| OLD | NEW |
| (Empty) |
| 1 // Copyright 2003-2009 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 // File unittest | |
| 17 | |
| 18 #include "omaha/base/file.h" | |
| 19 #include "omaha/base/logging.h" | |
| 20 #include "omaha/base/string.h" | |
| 21 #include "omaha/base/timer.h" | |
| 22 #include "omaha/base/tr_rand.h" | |
| 23 #include "omaha/base/utils.h" | |
| 24 #include "omaha/testing/unit_test.h" | |
| 25 | |
| 26 namespace omaha { | |
| 27 | |
| 28 // TODO(omaha): test error-prone functions such as ReadLineAnsi | |
| 29 | |
| 30 namespace { | |
| 31 | |
| 32 #define kIEBrowserExe \ | |
| 33 _T("C:\\PROGRAM FILES\\Internet Explorer\\iexplore.exe") | |
| 34 | |
| 35 #define kIEBrowserQuotedExe \ | |
| 36 _T("\"") kIEBrowserExe _T("\"") | |
| 37 | |
| 38 } // namespace | |
| 39 | |
| 40 void SimpleTest(bool async) { | |
| 41 File f; | |
| 42 | |
| 43 char buf[1000] = "test"; | |
| 44 uint32 len1 = 4; | |
| 45 | |
| 46 char buf2[1000] = "aaaa"; | |
| 47 uint32 len2 = 4; | |
| 48 | |
| 49 char buf3[1000] = "bbbb"; | |
| 50 uint32 len3 = 4; | |
| 51 | |
| 52 char buf4[1000] = " "; | |
| 53 uint32 len4 = 4; | |
| 54 | |
| 55 CString s(_T("test")); | |
| 56 CString testfile(_T("testfile.1")); | |
| 57 | |
| 58 ASSERT_SUCCEEDED(f.Open(testfile, true, async)); | |
| 59 uint32 pos = 0; | |
| 60 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 61 reinterpret_cast<byte*>(buf), | |
| 62 len1, | |
| 63 0, | |
| 64 NULL)); | |
| 65 pos += len1; | |
| 66 | |
| 67 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 68 reinterpret_cast<byte*>(buf3), | |
| 69 len3, | |
| 70 0, | |
| 71 NULL)); | |
| 72 pos += len3; | |
| 73 | |
| 74 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 75 reinterpret_cast<byte*>(buf3), | |
| 76 len3, | |
| 77 0, | |
| 78 NULL)); | |
| 79 pos += len3; | |
| 80 | |
| 81 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 82 reinterpret_cast<byte*>(buf3), | |
| 83 len3, | |
| 84 0, | |
| 85 NULL)); | |
| 86 pos += len3; | |
| 87 | |
| 88 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 89 reinterpret_cast<byte*>(buf3), | |
| 90 len3, | |
| 91 0, | |
| 92 NULL)); | |
| 93 pos += len3; | |
| 94 | |
| 95 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 96 reinterpret_cast<byte*>(buf3), | |
| 97 len3, | |
| 98 0, | |
| 99 NULL)); | |
| 100 pos += len3; | |
| 101 | |
| 102 ASSERT_SUCCEEDED(f.WriteAt(pos, | |
| 103 reinterpret_cast<byte*>(buf3), | |
| 104 len3, | |
| 105 0, | |
| 106 NULL)); | |
| 107 pos += len3; | |
| 108 | |
| 109 ASSERT_SUCCEEDED(f.ReadAt(0, reinterpret_cast<byte*>(buf4), len1, 0, NULL)); | |
| 110 ASSERT_STREQ(buf, buf4); | |
| 111 | |
| 112 ASSERT_SUCCEEDED(f.ReadAt(4, reinterpret_cast<byte*>(buf4), len3, 0, NULL)); | |
| 113 ASSERT_STREQ(buf3, buf4); | |
| 114 | |
| 115 ASSERT_SUCCEEDED(f.WriteAt(1, reinterpret_cast<byte*>(buf3), 2, 0, NULL)); | |
| 116 | |
| 117 ASSERT_SUCCEEDED(f.WriteAt(20, reinterpret_cast<byte*>(buf), 2, 0, NULL)); | |
| 118 ASSERT_SUCCEEDED(f.ReadAt(20, reinterpret_cast<byte*>(buf), 2, 0, NULL)); | |
| 119 | |
| 120 ASSERT_SUCCEEDED(f.WriteAt(30, reinterpret_cast<byte*>(buf), 2, 0, NULL)); | |
| 121 | |
| 122 ASSERT_SUCCEEDED(f.SeekFromBegin(0)); | |
| 123 | |
| 124 ASSERT_SUCCEEDED(f.ReadAt(30, reinterpret_cast<byte*>(buf), 2, 0, NULL)); | |
| 125 | |
| 126 ASSERT_SUCCEEDED(f.Close()); | |
| 127 | |
| 128 ASSERT_SUCCEEDED(f.Open(L"testfile.1", false, false)); | |
| 129 ASSERT_SUCCEEDED(f.ReadAt(0, reinterpret_cast<byte*>(buf), 16, 0, NULL)); | |
| 130 buf[17] = '\0'; | |
| 131 | |
| 132 uint64 size_on_disk = 0; | |
| 133 ASSERT_SUCCEEDED(f.GetSizeOnDisk(&size_on_disk)); | |
| 134 ASSERT_EQ(size_on_disk, 32); | |
| 135 | |
| 136 ASSERT_SUCCEEDED(f.Close()); | |
| 137 | |
| 138 ASSERT_TRUE(File::Exists(testfile)); | |
| 139 ASSERT_SUCCEEDED(File::Remove(testfile)); | |
| 140 ASSERT_FALSE(File::Exists(testfile)); | |
| 141 } | |
| 142 | |
| 143 void FileWriteCreate(uint32 file_size) { | |
| 144 Timer time(true); | |
| 145 CString testfile; | |
| 146 testfile.Format(L"testfile%u", file_size); | |
| 147 | |
| 148 File f; | |
| 149 ASSERT_SUCCEEDED(f.Open(testfile, true, false)); | |
| 150 ASSERT_SUCCEEDED(f.SetLength(file_size, false)); | |
| 151 | |
| 152 uint32 write_size = 512; | |
| 153 | |
| 154 byte *buf2 = new byte[write_size]; | |
| 155 | |
| 156 for (uint32 j = 0; j < file_size - write_size; j += write_size) { | |
| 157 for (uint32 i = 0; i < write_size; i++) { | |
| 158 buf2[i] = static_cast<byte>(tr_rand() % 255); | |
| 159 } | |
| 160 ASSERT_SUCCEEDED(f.WriteAt(j, buf2, write_size, 0, NULL)); | |
| 161 } | |
| 162 | |
| 163 f.Sync(); | |
| 164 f.Close(); | |
| 165 | |
| 166 EXPECT_SUCCEEDED(File::Remove(testfile)); | |
| 167 } | |
| 168 | |
| 169 void FileWriteTimeTest(uint32 file_size, | |
| 170 uint32 number_writes, | |
| 171 uint32 write_size) { | |
| 172 Timer time(true); | |
| 173 CString testfile; | |
| 174 testfile.Format(L"testfile%u", file_size); | |
| 175 | |
| 176 File f; | |
| 177 ASSERT_SUCCEEDED(f.Open(testfile, true, false)); | |
| 178 | |
| 179 byte *buf = new byte[write_size]; | |
| 180 | |
| 181 for (uint32 i = 0; i < number_writes; i++) { | |
| 182 for (uint32 j = 0; j < write_size; j++) { | |
| 183 buf[j] = static_cast<byte>(tr_rand() % 255); | |
| 184 } | |
| 185 uint32 pos = (tr_rand() * 65536 + tr_rand()) % (file_size - write_size); | |
| 186 ASSERT_SUCCEEDED(f.WriteAt(pos, buf, write_size, 0, NULL)); | |
| 187 } | |
| 188 | |
| 189 delete[] buf; | |
| 190 | |
| 191 ASSERT_SUCCEEDED(f.Sync()); | |
| 192 ASSERT_SUCCEEDED(f.Close()); | |
| 193 | |
| 194 EXPECT_SUCCEEDED(File::Remove(testfile)); | |
| 195 } | |
| 196 | |
| 197 TEST(FileTest, File) { | |
| 198 const TCHAR* const kTestFileName = L"testfile.3"; | |
| 199 | |
| 200 SimpleTest(false); | |
| 201 | |
| 202 int header = 123; | |
| 203 int header2 = 0; | |
| 204 | |
| 205 File f2; | |
| 206 ASSERT_SUCCEEDED(f2.Open(kTestFileName, true, false)); | |
| 207 ASSERT_SUCCEEDED(f2.WriteAt(0, | |
| 208 reinterpret_cast<byte*>(&header), | |
| 209 sizeof(header), | |
| 210 0, | |
| 211 NULL)); | |
| 212 ASSERT_SUCCEEDED(f2.ReadAt(0, | |
| 213 reinterpret_cast<byte*>(&header2), | |
| 214 sizeof(header), | |
| 215 0, | |
| 216 NULL)); | |
| 217 ASSERT_EQ(header, header2); | |
| 218 | |
| 219 uint64 size_on_disk = 0; | |
| 220 | |
| 221 ASSERT_SUCCEEDED(f2.GetSizeOnDisk(&size_on_disk)); | |
| 222 ASSERT_EQ(size_on_disk, sizeof(header)); | |
| 223 ASSERT_SUCCEEDED(f2.Close()); | |
| 224 | |
| 225 const int kLevel = 1; | |
| 226 for (uint32 file_size = 2 * 1024 * 1024; | |
| 227 file_size <= 2 * 1024 * 1024; | |
| 228 file_size *= 2) { | |
| 229 for (uint32 number_writes = 100; | |
| 230 number_writes <= (300 * static_cast<uint32>(kLevel)); | |
| 231 number_writes *= 2) { | |
| 232 uint32 write_size = 128; | |
| 233 FileWriteTimeTest(file_size, number_writes, write_size); | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 // Test File::Copy, File::Move, File::CopyWildcards | |
| 238 { | |
| 239 CString windows_dir; | |
| 240 CString temp_dir; | |
| 241 DWORD dw = ::GetEnvironmentVariable( | |
| 242 L"SystemRoot", | |
| 243 windows_dir.GetBufferSetLength(MAX_PATH), | |
| 244 MAX_PATH); | |
| 245 windows_dir.ReleaseBuffer(); | |
| 246 ASSERT_TRUE(dw); | |
| 247 dw = ::GetEnvironmentVariable(L"TEMP", | |
| 248 temp_dir.GetBufferSetLength(MAX_PATH), | |
| 249 MAX_PATH); | |
| 250 temp_dir.ReleaseBuffer(); | |
| 251 ASSERT_TRUE(dw); | |
| 252 CString known_file1(windows_dir + L"\\NOTEPAD.EXE"); | |
| 253 CString known_file2(windows_dir + L"\\REGEDIT.EXE"); | |
| 254 CString temp_file1(temp_dir + L"\\FOO.TMP"); | |
| 255 CString temp_file2(temp_dir + L"\\BAR.TMP"); | |
| 256 uint32 known_size1 = 0; | |
| 257 uint32 known_size2 = 0; | |
| 258 uint32 temp_size1 = 0; | |
| 259 | |
| 260 // Start with neither file existing | |
| 261 if (File::Exists(temp_file1)) | |
| 262 File::Remove(temp_file1); | |
| 263 if (File::Exists(temp_file2)) | |
| 264 File::Remove(temp_file2); | |
| 265 ASSERT_FALSE(File::Exists(temp_file1)); | |
| 266 ASSERT_FALSE(File::Exists(temp_file2)); | |
| 267 ASSERT_SUCCEEDED(File::GetFileSizeUnopen(known_file1, &known_size1)); | |
| 268 ASSERT_SUCCEEDED(File::GetFileSizeUnopen(known_file2, &known_size2)); | |
| 269 ASSERT_NE(known_size1, known_size2); | |
| 270 | |
| 271 // Copy to create a file, move it to 2nd file, then remove 2nd file | |
| 272 ASSERT_SUCCEEDED(File::Copy(known_file1, temp_file1, false)); | |
| 273 ASSERT_TRUE(File::Exists(temp_file1)); | |
| 274 ASSERT_SUCCEEDED(File::Move(temp_file1, temp_file2, false)); | |
| 275 ASSERT_FALSE(File::Exists(temp_file1)); | |
| 276 ASSERT_TRUE(File::Exists(temp_file2)); | |
| 277 ASSERT_SUCCEEDED(File::Remove(temp_file2)); | |
| 278 ASSERT_FALSE(File::Exists(temp_file2)); | |
| 279 | |
| 280 // Try copying a file on top of a file - with and without | |
| 281 // replace_existing_file=true | |
| 282 ASSERT_SUCCEEDED(File::Copy(known_file1, temp_file1, false)); | |
| 283 ASSERT_SUCCEEDED(File::GetFileSizeUnopen(temp_file1, &temp_size1)); | |
| 284 ASSERT_EQ(temp_size1, known_size1); | |
| 285 ASSERT_SUCCEEDED(File::Copy(known_file2, temp_file1, false)); | |
| 286 ASSERT_TRUE(File::Exists(temp_file1)); | |
| 287 ASSERT_SUCCEEDED(File::GetFileSizeUnopen(temp_file1, &temp_size1)); | |
| 288 ASSERT_EQ(temp_size1, known_size1); | |
| 289 ASSERT_SUCCEEDED(File::Copy(known_file2, temp_file1, true)); | |
| 290 ASSERT_TRUE(File::Exists(temp_file1)); | |
| 291 ASSERT_SUCCEEDED(File::GetFileSizeUnopen(temp_file1, &temp_size1)); | |
| 292 ASSERT_EQ(temp_size1, known_size2); | |
| 293 ASSERT_SUCCEEDED(File::Remove(temp_file1)); | |
| 294 | |
| 295 // Try copying a bunch of files | |
| 296 CString known_file3(windows_dir + L"\\twunk_32.exe"); | |
| 297 CString known_file4(windows_dir + L"\\twunk_16.exe"); | |
| 298 CString temp_file3(temp_dir + L"\\twunk_32.exe"); | |
| 299 CString temp_file4(temp_dir + L"\\twunk_16.exe"); | |
| 300 if (File::Exists(temp_file3)) | |
| 301 File::Remove(temp_file3); | |
| 302 if (File::Exists(temp_file4)) | |
| 303 File::Remove(temp_file4); | |
| 304 ASSERT_TRUE(File::Exists(known_file3)); | |
| 305 ASSERT_TRUE(File::Exists(known_file4)); | |
| 306 ASSERT_FALSE(File::Exists(temp_file3)); | |
| 307 ASSERT_FALSE(File::Exists(temp_file4)); | |
| 308 ASSERT_SUCCEEDED(File::CopyWildcards(windows_dir, | |
| 309 temp_dir, | |
| 310 L"twunk*.exe", | |
| 311 true)); | |
| 312 ASSERT_TRUE(File::Exists(temp_file3)); | |
| 313 ASSERT_TRUE(File::Exists(temp_file4)); | |
| 314 ASSERT_SUCCEEDED(File::Remove(temp_file3)); | |
| 315 ASSERT_SUCCEEDED(File::Remove(temp_file4)); | |
| 316 | |
| 317 std::vector<CString> matching_files; | |
| 318 ASSERT_SUCCEEDED(File::GetWildcards(windows_dir, | |
| 319 L"twunk*.exe", | |
| 320 &matching_files)); | |
| 321 ASSERT_EQ(matching_files.size(), 2); | |
| 322 ASSERT_TRUE(matching_files[0] == known_file3 || | |
| 323 matching_files[0] == known_file4); | |
| 324 ASSERT_TRUE(matching_files[1] == known_file3 || | |
| 325 matching_files[1] == known_file4); | |
| 326 ASSERT_TRUE(matching_files[0] != matching_files[1]); | |
| 327 } | |
| 328 | |
| 329 EXPECT_SUCCEEDED(File::Remove(kTestFileName)); | |
| 330 } | |
| 331 | |
| 332 | |
| 333 TEST(FileTest, FileChangeWatcher) { | |
| 334 CString temp_dir; | |
| 335 ASSERT_TRUE(::GetEnvironmentVariable(L"TEMP", | |
| 336 temp_dir.GetBufferSetLength(MAX_PATH), | |
| 337 MAX_PATH) != 0); | |
| 338 temp_dir.ReleaseBuffer(); | |
| 339 temp_dir = String_MakeEndWith(temp_dir, _T("\\"), false /* ignore_case */); | |
| 340 temp_dir = temp_dir + _T("omaha_unittest") + itostr(tr_rand() % 255); | |
| 341 EXPECT_SUCCEEDED(CreateDir(temp_dir, 0)); | |
| 342 | |
| 343 // watch the directory for changes | |
| 344 FileWatcher watcher(temp_dir, false, FILE_NOTIFY_CHANGE_LAST_WRITE); | |
| 345 EXPECT_SUCCEEDED(watcher.EnsureEventSetup()); | |
| 346 EXPECT_FALSE(watcher.HasChangeOccurred()); | |
| 347 | |
| 348 // | |
| 349 // verify that the watcher got set-up correctly the first time | |
| 350 // | |
| 351 | |
| 352 // do something in the dir | |
| 353 File f; | |
| 354 int header1 = 94; | |
| 355 ASSERT_SUCCEEDED(f.Open(temp_dir + _T("\\testfile.1"), true, false)); | |
| 356 ASSERT_SUCCEEDED(f.WriteAt(0, reinterpret_cast<byte*>(&header1), | |
| 357 sizeof(header1), 0, NULL)); | |
| 358 ASSERT_SUCCEEDED(f.Sync()); | |
| 359 ASSERT_SUCCEEDED(f.Close()); | |
| 360 | |
| 361 // Did we noticed that something happened? | |
| 362 EXPECT_TRUE(watcher.HasChangeOccurred()); | |
| 363 EXPECT_SUCCEEDED(watcher.EnsureEventSetup()); | |
| 364 EXPECT_FALSE(watcher.HasChangeOccurred()); | |
| 365 | |
| 366 // | |
| 367 // verify that the watcher got set-up correctly the second time | |
| 368 // | |
| 369 | |
| 370 // do something in the dir | |
| 371 byte header2 = 2; | |
| 372 ASSERT_SUCCEEDED(f.Open(temp_dir + _T("\\testfile.2"), true, false)); | |
| 373 ASSERT_SUCCEEDED(f.WriteAt(0, reinterpret_cast<byte*>(&header2), | |
| 374 sizeof(header2), 0, NULL)); | |
| 375 ASSERT_SUCCEEDED(f.Sync()); | |
| 376 ASSERT_SUCCEEDED(f.Close()); | |
| 377 | |
| 378 // Did we noticed that something happened? | |
| 379 EXPECT_TRUE(watcher.HasChangeOccurred()); | |
| 380 EXPECT_SUCCEEDED(watcher.EnsureEventSetup()); | |
| 381 EXPECT_FALSE(watcher.HasChangeOccurred()); | |
| 382 | |
| 383 EXPECT_SUCCEEDED(DeleteDirectory(temp_dir)); | |
| 384 } | |
| 385 | |
| 386 TEST(FileTest, Exists_UnQuoted) { | |
| 387 EXPECT_TRUE(File::Exists(kIEBrowserExe)); | |
| 388 EXPECT_FALSE(File::Exists(_T("C:\\foo\\does not exist.exe"))); | |
| 389 EXPECT_FALSE(File::Exists(_T("Z:\\foo\\does not exist.exe"))); | |
| 390 if (ShouldRunLargeTest()) { | |
| 391 EXPECT_FALSE(File::Exists(_T("\\\\foo\\does not exist.exe"))); | |
| 392 } | |
| 393 } | |
| 394 | |
| 395 // File::Exists() expects unquoted paths. | |
| 396 TEST(FileTest, Exists_Quoted) { | |
| 397 EXPECT_FALSE(File::Exists(kIEBrowserQuotedExe)); | |
| 398 EXPECT_FALSE(File::Exists(_T("\"C:\\foo\\does not exist.exe\""))); | |
| 399 EXPECT_FALSE(File::Exists(_T("\"Z:\\foo\\does not exist.exe\""))); | |
| 400 if (ShouldRunLargeTest()) { | |
| 401 EXPECT_FALSE(File::Exists(_T("\"\\\\foo\\does not exist.exe\""))); | |
| 402 } | |
| 403 } | |
| 404 | |
| 405 // File::Exists() handles trailing spaces but not leading whitespace, tabs, or | |
| 406 // enclosed paths. | |
| 407 TEST(FileTest, Exists_ExtraWhitespace) { | |
| 408 EXPECT_TRUE(File::Exists(kIEBrowserExe _T(" "))); | |
| 409 EXPECT_TRUE(File::Exists(kIEBrowserExe _T(" "))); | |
| 410 EXPECT_FALSE(File::Exists(_T(" ") kIEBrowserExe)); | |
| 411 EXPECT_FALSE(File::Exists(kIEBrowserExe _T("\t"))); | |
| 412 | |
| 413 EXPECT_FALSE(File::Exists(kIEBrowserQuotedExe _T(" "))); | |
| 414 EXPECT_FALSE(File::Exists(kIEBrowserQuotedExe _T(" "))); | |
| 415 EXPECT_FALSE(File::Exists(_T(" ") kIEBrowserQuotedExe)); | |
| 416 EXPECT_FALSE(File::Exists(kIEBrowserQuotedExe _T("\t"))); | |
| 417 | |
| 418 EXPECT_FALSE(File::Exists(_T("\"") kIEBrowserExe _T(" \""))); | |
| 419 EXPECT_FALSE(File::Exists(_T("\"") kIEBrowserExe _T(" \""))); | |
| 420 EXPECT_FALSE(File::Exists(_T("\" ") kIEBrowserExe _T("\"") )); | |
| 421 EXPECT_FALSE(File::Exists(_T("\"") kIEBrowserExe _T("\t\""))); | |
| 422 | |
| 423 EXPECT_FALSE(File::Exists(_T("\"") kIEBrowserExe _T(" \" "))); | |
| 424 } | |
| 425 | |
| 426 TEST(FileTest, AreFilesIdentical) { | |
| 427 CString windows_dir; | |
| 428 ASSERT_TRUE(::GetEnvironmentVariable(_T("SystemRoot"), | |
| 429 CStrBuf(windows_dir, MAX_PATH), | |
| 430 MAX_PATH)); | |
| 431 | |
| 432 CString known_file1(windows_dir + _T("\\NOTEPAD.EXE")); | |
| 433 CString known_file2(windows_dir + _T("\\REGEDIT.EXE")); | |
| 434 | |
| 435 EXPECT_TRUE(File::AreFilesIdentical(known_file1, known_file1)); | |
| 436 EXPECT_FALSE(File::AreFilesIdentical(known_file1, known_file2)); | |
| 437 } | |
| 438 | |
| 439 } // namespace omaha | |
| OLD | NEW |