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 |