| OLD | NEW |
| (Empty) |
| 1 // Copyright 2007-2010 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 // | |
| 16 // Path-utility unit tests. | |
| 17 | |
| 18 #include <vector> | |
| 19 #include "omaha/base/file.h" | |
| 20 #include "omaha/base/path.h" | |
| 21 #include "omaha/base/utils.h" | |
| 22 #include "omaha/testing/unit_test.h" | |
| 23 | |
| 24 namespace omaha { | |
| 25 | |
| 26 TEST(PathTest, IsAbsolutePath) { | |
| 27 ASSERT_TRUE(IsAbsolutePath(L"C:\\Foo.bar")); | |
| 28 ASSERT_TRUE(IsAbsolutePath(L"\\\\user-laptop1\\path")); | |
| 29 ASSERT_FALSE(IsAbsolutePath(L"windows\\system32")); | |
| 30 } | |
| 31 | |
| 32 // EnclosePath is overzealous and quotes a path even though no spaces exists. | |
| 33 TEST(PathTest, EnclosePath) { | |
| 34 CString path; | |
| 35 EnclosePath(&path); | |
| 36 EXPECT_STREQ(_T(""), path); | |
| 37 | |
| 38 path = _T(""); | |
| 39 EnclosePath(&path); | |
| 40 EXPECT_STREQ(_T(""), path); | |
| 41 | |
| 42 path = _T("a"); | |
| 43 EnclosePath(&path); | |
| 44 EXPECT_STREQ(_T("\"a\""), path); | |
| 45 | |
| 46 path = _T("a b"); | |
| 47 EnclosePath(&path); | |
| 48 EXPECT_STREQ(_T("\"a b\""), path); | |
| 49 | |
| 50 path = " a b "; | |
| 51 EnclosePath(&path); | |
| 52 EXPECT_STREQ(_T("\" a b \""), path); | |
| 53 | |
| 54 path = _T("\"a b\""); | |
| 55 EnclosePath(&path); | |
| 56 EXPECT_STREQ(_T("\"a b\""), path); | |
| 57 | |
| 58 path = _T("c:\\Windows\\notepad.exe"); | |
| 59 EnclosePath(&path); | |
| 60 EXPECT_STREQ(_T("\"c:\\Windows\\notepad.exe\""), path); | |
| 61 | |
| 62 path = _T("c:\\Program Files\\Google\\Common\\Google Update"); | |
| 63 EnclosePath(&path); | |
| 64 EXPECT_STREQ(_T("\"c:\\Program Files\\Google\\Common\\Google Update\""), | |
| 65 path); | |
| 66 } | |
| 67 | |
| 68 // EnclosePath encloses a string that has a quote only at the beginning or end. | |
| 69 TEST(PathTest, EnclosePath_OnlyOneQuote) { | |
| 70 ExpectAsserts expect_asserts; | |
| 71 CString path = _T("\"a b"); | |
| 72 EnclosePath(&path); | |
| 73 EXPECT_STREQ(_T("\"\"a b\""), path); | |
| 74 | |
| 75 path = _T("a b\""); | |
| 76 EnclosePath(&path); | |
| 77 EXPECT_STREQ(_T("\"a b\"\""), path); | |
| 78 } | |
| 79 | |
| 80 // EnclosePath does not look at the middle of the string. | |
| 81 TEST(PathTest, EnclosePath_QuoteInMiddle) { | |
| 82 CString path = _T("a\" b"); | |
| 83 EnclosePath(&path); | |
| 84 EXPECT_STREQ(_T("\"a\" b\""), path); | |
| 85 } | |
| 86 | |
| 87 TEST(PathTest, EnclosePath_SingleQuotes) { | |
| 88 CString path = _T("'foo'"); | |
| 89 EnclosePath(&path); | |
| 90 EXPECT_STREQ(_T("\"'foo'\""), path); | |
| 91 } | |
| 92 | |
| 93 TEST(PathTest, EnclosePathIfExe) { | |
| 94 CString original_path; | |
| 95 CString new_path; | |
| 96 new_path = EnclosePathIfExe(original_path); | |
| 97 EXPECT_STREQ(original_path, new_path); | |
| 98 | |
| 99 original_path = _T(""); | |
| 100 new_path = EnclosePathIfExe(original_path); | |
| 101 EXPECT_STREQ(original_path, new_path); | |
| 102 | |
| 103 original_path = _T("a"); | |
| 104 new_path = EnclosePathIfExe(original_path); | |
| 105 EXPECT_STREQ(original_path, new_path); | |
| 106 | |
| 107 original_path = _T("a b"); | |
| 108 new_path = EnclosePathIfExe(original_path); | |
| 109 EXPECT_STREQ(original_path, new_path); | |
| 110 | |
| 111 original_path = " a b "; | |
| 112 new_path = EnclosePathIfExe(original_path); | |
| 113 EXPECT_STREQ(original_path, new_path); | |
| 114 | |
| 115 original_path = _T("\"a b\""); | |
| 116 new_path = EnclosePathIfExe(original_path); | |
| 117 EXPECT_STREQ(original_path, new_path); | |
| 118 | |
| 119 original_path = _T("c:\\Windows\\notepad.exe"); | |
| 120 new_path = EnclosePathIfExe(original_path); | |
| 121 EXPECT_STREQ(_T("\"c:\\Windows\\notepad.exe\""), new_path); | |
| 122 | |
| 123 original_path = _T("c:\\Program Files\\Google\\Update"); | |
| 124 new_path = EnclosePathIfExe(original_path); | |
| 125 EXPECT_STREQ(original_path, new_path); | |
| 126 | |
| 127 original_path = _T("c:\\Progra Files\\Google\\Update\\1.1.1.1\\goopdate.dll"); | |
| 128 new_path = EnclosePathIfExe(original_path); | |
| 129 EXPECT_STREQ(original_path, new_path); | |
| 130 | |
| 131 original_path = _T("c:\\Prog F\\Googl\\Update\\GoogleUpdate.exe"); | |
| 132 new_path = EnclosePathIfExe(original_path); | |
| 133 EXPECT_STREQ(_T("\"c:\\Prog F\\Googl\\Update\\GoogleUpdate.exe\""), new_path); | |
| 134 } | |
| 135 | |
| 136 TEST(PathTest, ConcatenatePath) { | |
| 137 CString expected_path("C:\\first\\part\\second\\part"); | |
| 138 | |
| 139 CString start("C:\\first\\part"); | |
| 140 CString start_slash("C:\\first\\part\\"); | |
| 141 CString end("second\\part"); | |
| 142 CString end_slash("\\second\\part"); | |
| 143 | |
| 144 EXPECT_STREQ(expected_path, ConcatenatePath(start, end)); | |
| 145 EXPECT_STREQ(expected_path, ConcatenatePath(start_slash, end)); | |
| 146 EXPECT_STREQ(expected_path, ConcatenatePath(start, end_slash)); | |
| 147 EXPECT_STREQ(expected_path, ConcatenatePath(start_slash, end_slash)); | |
| 148 } | |
| 149 | |
| 150 TEST(PathTest, ConcatenatePath_PathTooLong) { | |
| 151 CString two_hundred_char_root_path(_T("C:\\reallllllllllllllllllllllllllllllll
llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllly\\looooooooooooooo
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
ong")); // NOLINT | |
| 152 CString two_hundred_char_path(_T("realllllllllllllllllllllllllllllllllllllllll
llllllllllllllllllllllllllllllllllllllllllllllllllllllly\\looooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"))
; // NOLINT | |
| 153 EXPECT_EQ(200, two_hundred_char_root_path.GetLength()); | |
| 154 CString fifty_eight_char_name( | |
| 155 _T("filenaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaame")); | |
| 156 EXPECT_EQ(58, fifty_eight_char_name.GetLength()); | |
| 157 CString fifty_nine_char_name( | |
| 158 _T("filenaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaame")); | |
| 159 EXPECT_EQ(59, fifty_nine_char_name.GetLength()); | |
| 160 CString sixty_char_name( | |
| 161 _T("filenaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaame")); | |
| 162 EXPECT_EQ(60, sixty_char_name.GetLength()); | |
| 163 | |
| 164 // Adding the '\' makes it 259 chars. | |
| 165 CString result = ConcatenatePath(two_hundred_char_root_path, | |
| 166 fifty_eight_char_name); | |
| 167 EXPECT_STREQ(_T("C:\\reallllllllllllllllllllllllllllllllllllllllllllllllllllll
llllllllllllllllllllllllllllllllllllllly\\looooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\\filenaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaame"), // NOLINT | |
| 168 result); | |
| 169 | |
| 170 // Adding the '\' makes it 260 chars. | |
| 171 ExpectAsserts expect_asserts; | |
| 172 result = ConcatenatePath(two_hundred_char_root_path, | |
| 173 fifty_nine_char_name); | |
| 174 EXPECT_TRUE(result.IsEmpty()); | |
| 175 | |
| 176 // Adding the '\' makes it 261 chars. | |
| 177 result = ConcatenatePath(two_hundred_char_root_path, sixty_char_name); | |
| 178 EXPECT_TRUE(result.IsEmpty()); | |
| 179 | |
| 180 // Test for buffer overflow on long strings. | |
| 181 } | |
| 182 | |
| 183 TEST(PathTest, ConcatenatePath_EmptyString) { | |
| 184 EXPECT_STREQ(_T("bar.exe"), ConcatenatePath(_T(""), _T("bar.exe"))); | |
| 185 EXPECT_STREQ(_T("foo"), ConcatenatePath(_T("foo"), _T(""))); | |
| 186 // This is not what I would expect, but it is what the API does. | |
| 187 EXPECT_STREQ(_T("\\"), ConcatenatePath(_T(""), _T(""))); | |
| 188 } | |
| 189 | |
| 190 // TODO(omaha): The expected and actual values are reversed throughout. | |
| 191 | |
| 192 TEST(PathTest, ShortPathToLongPath) { | |
| 193 CString expected_path("C:\\Program Files"); | |
| 194 CString short_path("C:\\Progra~1"); | |
| 195 | |
| 196 CString long_path; | |
| 197 ASSERT_SUCCEEDED(ShortPathToLongPath(short_path, &long_path)); | |
| 198 ASSERT_STREQ(expected_path, long_path); | |
| 199 } | |
| 200 | |
| 201 TEST(PathTest, FindFilesTest) { | |
| 202 GUID guid = GUID_NULL; | |
| 203 ASSERT_SUCCEEDED(::CoCreateGuid(&guid)); | |
| 204 | |
| 205 TCHAR path[MAX_PATH] = {0}; | |
| 206 ASSERT_NE(::GetTempPath(MAX_PATH, path), 0); | |
| 207 | |
| 208 CString dir = ConcatenatePath(path, GuidToString(guid)); | |
| 209 EXPECT_FALSE(dir.IsEmpty()); | |
| 210 EXPECT_FALSE(File::Exists(dir)); | |
| 211 | |
| 212 // Test with non-existent dir. | |
| 213 std::vector<CString> files; | |
| 214 EXPECT_FAILED(FindFiles(dir, _T("*.txt"), &files)); | |
| 215 EXPECT_EQ(files.size(), 0); | |
| 216 | |
| 217 // Test with empty dir. | |
| 218 EXPECT_NE(::CreateDirectory(dir, NULL), 0); | |
| 219 files.clear(); | |
| 220 EXPECT_EQ(FindFiles(dir, _T("asdf.txt"), &files), 0x80070002); | |
| 221 EXPECT_EQ(files.size(), 0); | |
| 222 | |
| 223 CString filename1 = _T("one.txt"); | |
| 224 CString filepath1 = ConcatenatePath(dir, filename1); | |
| 225 CString filename2 = _T("two_en.txt"); | |
| 226 CString filepath2 = ConcatenatePath(dir, filename2); | |
| 227 | |
| 228 // Test with dir containing one file. | |
| 229 scoped_hfile handle1(::CreateFile(filepath1, GENERIC_READ, FILE_SHARE_READ, | |
| 230 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, | |
| 231 NULL)); | |
| 232 EXPECT_TRUE(valid(handle1)); | |
| 233 files.clear(); | |
| 234 EXPECT_SUCCEEDED(FindFiles(dir, _T("*.txt"), &files)); | |
| 235 EXPECT_EQ(files.size(), 1); | |
| 236 EXPECT_STREQ(files[0], filename1); | |
| 237 | |
| 238 files.clear(); | |
| 239 EXPECT_SUCCEEDED(FindFiles(dir, _T("o*.txt"), &files)); | |
| 240 EXPECT_EQ(files.size(), 1); | |
| 241 EXPECT_STREQ(files[0], filename1); | |
| 242 | |
| 243 files.clear(); | |
| 244 EXPECT_SUCCEEDED(FindFiles(dir, filepath1, &files)); | |
| 245 EXPECT_EQ(files.size(), 1); | |
| 246 EXPECT_STREQ(files[0], filename1); | |
| 247 | |
| 248 files.clear(); | |
| 249 EXPECT_EQ(FindFiles(dir, _T("t*.txt"), &files), 0x80070002); | |
| 250 EXPECT_EQ(files.size(), 0); | |
| 251 | |
| 252 // Test with dir containing two files. | |
| 253 scoped_hfile handle2(::CreateFile(filepath2, GENERIC_READ, FILE_SHARE_READ, | |
| 254 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, | |
| 255 NULL)); | |
| 256 EXPECT_TRUE(valid(handle2)); | |
| 257 files.clear(); | |
| 258 EXPECT_SUCCEEDED(FindFiles(dir, _T("*.txt"), &files)); | |
| 259 EXPECT_EQ(files.size(), 2); | |
| 260 EXPECT_STREQ(files[0], filename1); | |
| 261 EXPECT_STREQ(files[1], filename2); | |
| 262 | |
| 263 files.clear(); | |
| 264 EXPECT_SUCCEEDED(FindFiles(dir, _T("o*.txt"), &files)); | |
| 265 EXPECT_EQ(files.size(), 1); | |
| 266 EXPECT_STREQ(files[0], filename1); | |
| 267 | |
| 268 files.clear(); | |
| 269 EXPECT_SUCCEEDED(FindFiles(dir, _T("t*.txt"), &files)); | |
| 270 EXPECT_EQ(files.size(), 1); | |
| 271 EXPECT_STREQ(files[0], filename2); | |
| 272 | |
| 273 files.clear(); | |
| 274 EXPECT_EQ(FindFiles(dir, _T("asdf.txt"), &files), 0x80070002); | |
| 275 EXPECT_EQ(files.size(), 0); | |
| 276 | |
| 277 reset(handle1); | |
| 278 EXPECT_SUCCEEDED(File::Remove(filepath1)); | |
| 279 reset(handle2); | |
| 280 EXPECT_SUCCEEDED(File::Remove(filepath2)); | |
| 281 EXPECT_NE(::RemoveDirectory(dir), 0); | |
| 282 } | |
| 283 | |
| 284 namespace detail { | |
| 285 | |
| 286 struct Directory { | |
| 287 Directory() {} | |
| 288 explicit Directory(const CString& name) : dir_name(name) {} | |
| 289 | |
| 290 CString dir_name; | |
| 291 std::vector<Directory> sub_dirs; | |
| 292 std::vector<CString> files; | |
| 293 }; | |
| 294 | |
| 295 void ConvertDirectoryStructureToFiles(const Directory& directory, | |
| 296 const CString& dir_path, | |
| 297 std::vector<CString>* files) { | |
| 298 ASSERT_TRUE(files != NULL); | |
| 299 ASSERT_HRESULT_SUCCEEDED(CreateDir(dir_path, NULL)); | |
| 300 | |
| 301 for (size_t i = 0; i < directory.files.size(); ++i) { | |
| 302 const CString& file = ConcatenatePath(dir_path, directory.files[i]); | |
| 303 scoped_hfile handle(::CreateFile(file, GENERIC_READ, FILE_SHARE_READ, | |
| 304 NULL, CREATE_ALWAYS, | |
| 305 FILE_ATTRIBUTE_NORMAL, | |
| 306 NULL)); | |
| 307 EXPECT_TRUE(valid(handle)); | |
| 308 files->push_back(file); | |
| 309 } | |
| 310 | |
| 311 for (size_t i = 0; i < directory.sub_dirs.size(); ++i) { | |
| 312 ConvertDirectoryStructureToFiles( | |
| 313 directory.sub_dirs[i], | |
| 314 ConcatenatePath(dir_path, directory.sub_dirs[i].dir_name), | |
| 315 files); | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 void CreateTestDirectoryStructure(Directory* root_dir) { | |
| 320 EXPECT_TRUE(root_dir != NULL); | |
| 321 GUID guid = GUID_NULL; | |
| 322 ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&guid)); | |
| 323 | |
| 324 TCHAR path[MAX_PATH] = {0}; | |
| 325 ASSERT_NE(0, ::GetTempPath(MAX_PATH, path)); | |
| 326 | |
| 327 CString dir = ConcatenatePath(path, GuidToString(guid)); | |
| 328 EXPECT_FALSE(dir.IsEmpty()); | |
| 329 EXPECT_FALSE(File::Exists(dir)); | |
| 330 | |
| 331 root_dir->dir_name = dir; | |
| 332 root_dir->files.push_back(_T("test1.txt")); | |
| 333 root_dir->files.push_back(_T("test2.txt")); | |
| 334 | |
| 335 Directory sub_dir1_level1(_T("sub_dir1_level1")); | |
| 336 sub_dir1_level1.files.push_back(_T("sub_dir1_level1_test1.txt")); | |
| 337 Directory sub_dir1_level2(_T("sub_dir1_level2")); | |
| 338 sub_dir1_level2.files.push_back(_T("sub_dir1_level2_test1.txt")); | |
| 339 sub_dir1_level1.sub_dirs.push_back(sub_dir1_level2); | |
| 340 root_dir->sub_dirs.push_back(sub_dir1_level1); | |
| 341 | |
| 342 Directory sub_dir2_level1(_T("sub_dir2_level1")); | |
| 343 sub_dir2_level1.files.push_back(_T("sub_dir2_level1_test1.txt")); | |
| 344 root_dir->sub_dirs.push_back(sub_dir2_level1); | |
| 345 } | |
| 346 } // detail. | |
| 347 | |
| 348 TEST(PathTest, FindFileRecursiveTest) { | |
| 349 detail::Directory dir; | |
| 350 detail::CreateTestDirectoryStructure(&dir); | |
| 351 | |
| 352 std::vector<CString> expected_files; | |
| 353 detail::ConvertDirectoryStructureToFiles(dir, dir.dir_name, &expected_files); | |
| 354 | |
| 355 // Call the test method. | |
| 356 std::vector<CString> files; | |
| 357 ASSERT_HRESULT_SUCCEEDED(FindFileRecursive(dir.dir_name, | |
| 358 _T("*test*.txt"), | |
| 359 &files)); | |
| 360 | |
| 361 // Validate the results. | |
| 362 ASSERT_EQ(expected_files.size(), files.size()); | |
| 363 for (size_t i = 0; i < expected_files.size(); ++i) { | |
| 364 EXPECT_STREQ(expected_files[i], files[i]); | |
| 365 } | |
| 366 | |
| 367 // Cleanup. | |
| 368 ASSERT_HRESULT_SUCCEEDED(DeleteDirectory(dir.dir_name)); | |
| 369 } | |
| 370 | |
| 371 TEST(PathTest, FindFileRecursiveTest_Empty) { | |
| 372 GUID guid = GUID_NULL; | |
| 373 ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&guid)); | |
| 374 | |
| 375 TCHAR path[MAX_PATH] = {0}; | |
| 376 ASSERT_NE(0, ::GetTempPath(MAX_PATH, path)); | |
| 377 | |
| 378 CString dir = ConcatenatePath(path, GuidToString(guid)); | |
| 379 EXPECT_FALSE(dir.IsEmpty()); | |
| 380 EXPECT_FALSE(File::Exists(dir)); | |
| 381 | |
| 382 ASSERT_HRESULT_SUCCEEDED(CreateDir(dir, NULL)); | |
| 383 | |
| 384 // Call the test method. | |
| 385 std::vector<CString> files; | |
| 386 ASSERT_HRESULT_SUCCEEDED(FindFileRecursive(dir, _T("*test*.txt"), | |
| 387 &files)); | |
| 388 | |
| 389 // Validate results. | |
| 390 ASSERT_EQ(0, files.size()); | |
| 391 | |
| 392 // Cleanup. | |
| 393 ASSERT_HRESULT_SUCCEEDED(DeleteDirectory(dir)); | |
| 394 } | |
| 395 | |
| 396 TEST(PathTest, FindFileRecursiveTest_DirNotCreated) { | |
| 397 GUID guid = GUID_NULL; | |
| 398 ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&guid)); | |
| 399 | |
| 400 TCHAR path[MAX_PATH] = {0}; | |
| 401 ASSERT_NE(0, ::GetTempPath(MAX_PATH, path)); | |
| 402 | |
| 403 CString dir = ConcatenatePath(path, GuidToString(guid)); | |
| 404 EXPECT_FALSE(dir.IsEmpty()); | |
| 405 EXPECT_FALSE(File::Exists(dir)); | |
| 406 | |
| 407 // Call the test method. | |
| 408 std::vector<CString> files; | |
| 409 ASSERT_HRESULT_FAILED(FindFileRecursive(dir, _T("*test*.txt"), &files)); | |
| 410 } | |
| 411 | |
| 412 } // namespace omaha | |
| 413 | |
| OLD | NEW |