1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "build/build_config.h"
6
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #include <winioctl.h>
10 #include <shellapi.h>
11 #include <shlobj.h>
12 #include <tchar.h>
13 #endif
14
15 #include <fstream>
16 #include <set>
17
18 #include "base/base_paths.h"
19 #include "base/file_path.h"
20 #include "base/file_util.h"
21 #include "base/memory/scoped_temp_dir.h"
22 #include "base/path_service.h"
23 #include "base/threading/platform_thread.h"
24 #include "base/time.h"
25 #include "base/utf_string_conversions.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "testing/platform_test.h"
28
29 #if defined(OS_WIN)
30 #include "base/win/scoped_handle.h"
31 #endif
32
33 // This macro helps avoid wrapped lines in the test structs.
34 #define FPL(x) FILE_PATH_LITERAL(x)
35
36 namespace {
37
38 // To test that file_util::Normalize FilePath() deals with NTFS reparse points
39 // correctly, we need functions to create and delete reparse points.
40 #if defined(OS_WIN)
41 typedef struct _REPARSE_DATA_BUFFER {
42 ULONG ReparseTag;
43 USHORT ReparseDataLength;
44 USHORT Reserved;
45 union {
46 struct {
47 USHORT SubstituteNameOffset;
48 USHORT SubstituteNameLength;
49 USHORT PrintNameOffset;
50 USHORT PrintNameLength;
51 ULONG Flags;
52 WCHAR PathBuffer[1];
53 } SymbolicLinkReparseBuffer;
54 struct {
55 USHORT SubstituteNameOffset;
56 USHORT SubstituteNameLength;
57 USHORT PrintNameOffset;
58 USHORT PrintNameLength;
59 WCHAR PathBuffer[1];
60 } MountPointReparseBuffer;
61 struct {
62 UCHAR DataBuffer[1];
63 } GenericReparseBuffer;
64 };
65 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
66
67 // Sets a reparse point. |source| will now point to |target|. Returns true if
68 // the call succeeds, false otherwise.
SetReparsePoint(HANDLE source,const FilePath & target_path)69 bool SetReparsePoint(HANDLE source, const FilePath& target_path) {
70 std::wstring kPathPrefix = L"\\??\\";
71 std::wstring target_str;
72 // The juction will not work if the target path does not start with \??\ .
73 if (kPathPrefix != target_path.value().substr(0, kPathPrefix.size()))
74 target_str += kPathPrefix;
75 target_str += target_path.value();
76 const wchar_t* target = target_str.c_str();
77 USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]);
78 char buffer[2000] = {0};
79 DWORD returned;
80
81 REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
82
83 data->ReparseTag = 0xa0000003;
84 memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
85
86 data->MountPointReparseBuffer.SubstituteNameLength = size_target;
87 data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
88 data->ReparseDataLength = size_target + 4 + 8;
89
90 int data_size = data->ReparseDataLength + 8;
91
92 if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size,
93 NULL, 0, &returned, NULL)) {
94 return false;
95 }
96 return true;
97 }
98
99 // Delete the reparse point referenced by |source|. Returns true if the call
100 // succeeds, false otherwise.
DeleteReparsePoint(HANDLE source)101 bool DeleteReparsePoint(HANDLE source) {
102 DWORD returned;
103 REPARSE_DATA_BUFFER data = {0};
104 data.ReparseTag = 0xa0000003;
105 if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
106 &returned, NULL)) {
107 return false;
108 }
109 return true;
110 }
111 #endif
112
113 const wchar_t bogus_content[] = L"I'm cannon fodder.";
114
115 const file_util::FileEnumerator::FILE_TYPE FILES_AND_DIRECTORIES =
116 static_cast<file_util::FileEnumerator::FILE_TYPE>(
117 file_util::FileEnumerator::FILES |
118 file_util::FileEnumerator::DIRECTORIES);
119
120 // file_util winds up using autoreleased objects on the Mac, so this needs
121 // to be a PlatformTest
122 class FileUtilTest : public PlatformTest {
123 protected:
SetUp()124 virtual void SetUp() {
125 PlatformTest::SetUp();
126 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
127 }
128
129 ScopedTempDir temp_dir_;
130 };
131
132 // Collects all the results from the given file enumerator, and provides an
133 // interface to query whether a given file is present.
134 class FindResultCollector {
135 public:
FindResultCollector(file_util::FileEnumerator & enumerator)136 explicit FindResultCollector(file_util::FileEnumerator& enumerator) {
137 FilePath cur_file;
138 while (!(cur_file = enumerator.Next()).value().empty()) {
139 FilePath::StringType path = cur_file.value();
140 // The file should not be returned twice.
141 EXPECT_TRUE(files_.end() == files_.find(path))
142 << "Same file returned twice";
143
144 // Save for later.
145 files_.insert(path);
146 }
147 }
148
149 // Returns true if the enumerator found the file.
HasFile(const FilePath & file) const150 bool HasFile(const FilePath& file) const {
151 return files_.find(file.value()) != files_.end();
152 }
153
size()154 int size() {
155 return static_cast<int>(files_.size());
156 }
157
158 private:
159 std::set<FilePath::StringType> files_;
160 };
161
162 // Simple function to dump some text into a new file.
CreateTextFile(const FilePath & filename,const std::wstring & contents)163 void CreateTextFile(const FilePath& filename,
164 const std::wstring& contents) {
165 std::wofstream file;
166 file.open(filename.value().c_str());
167 ASSERT_TRUE(file.is_open());
168 file << contents;
169 file.close();
170 }
171
172 // Simple function to take out some text from a file.
ReadTextFile(const FilePath & filename)173 std::wstring ReadTextFile(const FilePath& filename) {
174 wchar_t contents[64];
175 std::wifstream file;
176 file.open(filename.value().c_str());
177 EXPECT_TRUE(file.is_open());
178 file.getline(contents, arraysize(contents));
179 file.close();
180 return std::wstring(contents);
181 }
182
183 #if defined(OS_WIN)
FileTimeAsUint64(const FILETIME & ft)184 uint64 FileTimeAsUint64(const FILETIME& ft) {
185 ULARGE_INTEGER u;
186 u.LowPart = ft.dwLowDateTime;
187 u.HighPart = ft.dwHighDateTime;
188 return u.QuadPart;
189 }
190 #endif
191
192 const struct append_case {
193 const wchar_t* path;
194 const wchar_t* ending;
195 const wchar_t* result;
196 } append_cases[] = {
197 #if defined(OS_WIN)
198 {L"c:\\colon\\backslash", L"path", L"c:\\colon\\backslash\\path"},
199 {L"c:\\colon\\backslash\\", L"path", L"c:\\colon\\backslash\\path"},
200 {L"c:\\colon\\backslash\\\\", L"path", L"c:\\colon\\backslash\\\\path"},
201 {L"c:\\colon\\backslash\\", L"", L"c:\\colon\\backslash\\"},
202 {L"c:\\colon\\backslash", L"", L"c:\\colon\\backslash\\"},
203 {L"", L"path", L"\\path"},
204 {L"", L"", L"\\"},
205 #elif defined(OS_POSIX)
206 {L"/foo/bar", L"path", L"/foo/bar/path"},
207 {L"/foo/bar/", L"path", L"/foo/bar/path"},
208 {L"/foo/bar//", L"path", L"/foo/bar//path"},
209 {L"/foo/bar/", L"", L"/foo/bar/"},
210 {L"/foo/bar", L"", L"/foo/bar/"},
211 {L"", L"path", L"/path"},
212 {L"", L"", L"/"},
213 #endif
214 };
215
216 #if defined(OS_WIN)
217 // This function is deprecated, but still used on Windows.
TEST_F(FileUtilTest,AppendToPath)218 TEST_F(FileUtilTest, AppendToPath) {
219 for (unsigned int i = 0; i < arraysize(append_cases); ++i) {
220 const append_case& value = append_cases[i];
221 std::wstring result = value.path;
222 file_util::AppendToPath(&result, value.ending);
223 EXPECT_EQ(value.result, result);
224 }
225
226 #ifdef NDEBUG
227 file_util::AppendToPath(NULL, L"path"); // asserts in debug mode
228 #endif
229 }
230 #endif // defined(OS_WIN)
231
232 static const struct filename_case {
233 const wchar_t* path;
234 const wchar_t* filename;
235 } filename_cases[] = {
236 #if defined(OS_WIN)
237 {L"c:\\colon\\backslash", L"backslash"},
238 {L"c:\\colon\\backslash\\", L""},
239 {L"\\\\filename.exe", L"filename.exe"},
240 {L"filename.exe", L"filename.exe"},
241 {L"", L""},
242 {L"\\\\\\", L""},
243 {L"c:/colon/backslash", L"backslash"},
244 {L"c:/colon/backslash/", L""},
245 {L"//////", L""},
246 {L"///filename.exe", L"filename.exe"},
247 #elif defined(OS_POSIX)
248 {L"/foo/bar", L"bar"},
249 {L"/foo/bar/", L""},
250 {L"/filename.exe", L"filename.exe"},
251 {L"filename.exe", L"filename.exe"},
252 {L"", L""},
253 {L"/", L""},
254 #endif
255 };
256
257 // Test finding the file type from a path name
258 static const struct extension_case {
259 const wchar_t* path;
260 const wchar_t* extension;
261 } extension_cases[] = {
262 #if defined(OS_WIN)
263 {L"C:\\colon\\backslash\\filename.extension", L"extension"},
264 {L"C:\\colon\\backslash\\filename.", L""},
265 {L"C:\\colon\\backslash\\filename", L""},
266 {L"C:\\colon\\backslash\\", L""},
267 {L"C:\\colon\\backslash.\\", L""},
268 {L"C:\\colon\\backslash\filename.extension.extension2", L"extension2"},
269 #elif defined(OS_POSIX)
270 {L"/foo/bar/filename.extension", L"extension"},
271 {L"/foo/bar/filename.", L""},
272 {L"/foo/bar/filename", L""},
273 {L"/foo/bar/", L""},
274 {L"/foo/bar./", L""},
275 {L"/foo/bar/filename.extension.extension2", L"extension2"},
276 {L".", L""},
277 {L"..", L""},
278 {L"./foo", L""},
279 {L"./foo.extension", L"extension"},
280 {L"/foo.extension1/bar.extension2", L"extension2"},
281 #endif
282 };
283
284 #if defined(OS_WIN)
285 // This function has been deprecated on non-Windows.
TEST_F(FileUtilTest,GetFileExtensionFromPath)286 TEST_F(FileUtilTest, GetFileExtensionFromPath) {
287 for (unsigned int i = 0; i < arraysize(extension_cases); ++i) {
288 const extension_case& ext = extension_cases[i];
289 const std::wstring fext = file_util::GetFileExtensionFromPath(ext.path);
290 EXPECT_EQ(ext.extension, fext);
291 }
292 }
293 #endif
294
295 // Test finding the directory component of a path
296 static const struct dir_case {
297 const wchar_t* full_path;
298 const wchar_t* directory;
299 } dir_cases[] = {
300 #if defined(OS_WIN)
301 {L"C:\\WINDOWS\\system32\\gdi32.dll", L"C:\\WINDOWS\\system32"},
302 {L"C:\\WINDOWS\\system32\\not_exist_thx_1138", L"C:\\WINDOWS\\system32"},
303 {L"C:\\WINDOWS\\system32\\", L"C:\\WINDOWS\\system32"},
304 {L"C:\\WINDOWS\\system32\\\\", L"C:\\WINDOWS\\system32"},
305 {L"C:\\WINDOWS\\system32", L"C:\\WINDOWS"},
306 {L"C:\\WINDOWS\\system32.\\", L"C:\\WINDOWS\\system32."},
307 {L"C:\\", L"C:\\"},
308 #elif defined(OS_POSIX)
309 {L"/foo/bar/gdi32.dll", L"/foo/bar"},
310 {L"/foo/bar/not_exist_thx_1138", L"/foo/bar"},
311 {L"/foo/bar/", L"/foo/bar"},
312 {L"/foo/bar//", L"/foo/bar"},
313 {L"/foo/bar", L"/foo"},
314 {L"/foo/bar./", L"/foo/bar."},
315 {L"/", L"/"},
316 {L".", L"."},
317 {L"..", L"."}, // yes, ".." technically lives in "."
318 #endif
319 };
320
321 // Flaky, http://crbug.com/46246
TEST_F(FileUtilTest,FLAKY_CountFilesCreatedAfter)322 TEST_F(FileUtilTest, FLAKY_CountFilesCreatedAfter) {
323 // Create old file (that we don't want to count)
324 FilePath old_file_name =
325 temp_dir_.path().Append(FILE_PATH_LITERAL("Old File.txt"));
326 CreateTextFile(old_file_name, L"Just call me Mr. Creakybits");
327
328 // Age to perfection
329 #if defined(OS_WIN)
330 base::PlatformThread::Sleep(100);
331 #elif defined(OS_POSIX)
332 // We need to wait at least one second here because the precision of
333 // file creation time is one second.
334 base::PlatformThread::Sleep(1500);
335 #endif
336
337 // Establish our cutoff time
338 base::Time now(base::Time::NowFromSystemTime());
339 EXPECT_EQ(0, file_util::CountFilesCreatedAfter(temp_dir_.path(), now));
340
341 // Create a new file (that we do want to count)
342 FilePath new_file_name =
343 temp_dir_.path().Append(FILE_PATH_LITERAL("New File.txt"));
344 CreateTextFile(new_file_name, L"Waaaaaaaaaaaaaah.");
345
346 // We should see only the new file.
347 EXPECT_EQ(1, file_util::CountFilesCreatedAfter(temp_dir_.path(), now));
348
349 // Delete new file, we should see no files after cutoff now
350 EXPECT_TRUE(file_util::Delete(new_file_name, false));
351 EXPECT_EQ(0, file_util::CountFilesCreatedAfter(temp_dir_.path(), now));
352 }
353
TEST_F(FileUtilTest,FileAndDirectorySize)354 TEST_F(FileUtilTest, FileAndDirectorySize) {
355 // Create three files of 20, 30 and 3 chars (utf8). ComputeDirectorySize
356 // should return 53 bytes.
357 FilePath file_01 = temp_dir_.path().Append(FPL("The file 01.txt"));
358 CreateTextFile(file_01, L"12345678901234567890");
359 int64 size_f1 = 0;
360 ASSERT_TRUE(file_util::GetFileSize(file_01, &size_f1));
361 EXPECT_EQ(20ll, size_f1);
362
363 FilePath subdir_path = temp_dir_.path().Append(FPL("Level2"));
364 file_util::CreateDirectory(subdir_path);
365
366 FilePath file_02 = subdir_path.Append(FPL("The file 02.txt"));
367 CreateTextFile(file_02, L"123456789012345678901234567890");
368 int64 size_f2 = 0;
369 ASSERT_TRUE(file_util::GetFileSize(file_02, &size_f2));
370 EXPECT_EQ(30ll, size_f2);
371
372 FilePath subsubdir_path = subdir_path.Append(FPL("Level3"));
373 file_util::CreateDirectory(subsubdir_path);
374
375 FilePath file_03 = subsubdir_path.Append(FPL("The file 03.txt"));
376 CreateTextFile(file_03, L"123");
377
378 int64 computed_size = file_util::ComputeDirectorySize(temp_dir_.path());
379 EXPECT_EQ(size_f1 + size_f2 + 3, computed_size);
380
381 computed_size =
382 file_util::ComputeFilesSize(temp_dir_.path(), FPL("The file*"));
383 EXPECT_EQ(size_f1, computed_size);
384
385 computed_size = file_util::ComputeFilesSize(temp_dir_.path(), FPL("bla*"));
386 EXPECT_EQ(0, computed_size);
387 }
388
TEST_F(FileUtilTest,NormalizeFilePathBasic)389 TEST_F(FileUtilTest, NormalizeFilePathBasic) {
390 // Create a directory under the test dir. Because we create it,
391 // we know it is not a link.
392 FilePath file_a_path = temp_dir_.path().Append(FPL("file_a"));
393 FilePath dir_path = temp_dir_.path().Append(FPL("dir"));
394 FilePath file_b_path = dir_path.Append(FPL("file_b"));
395 file_util::CreateDirectory(dir_path);
396
397 FilePath normalized_file_a_path, normalized_file_b_path;
398 ASSERT_FALSE(file_util::PathExists(file_a_path));
399 ASSERT_FALSE(file_util::NormalizeFilePath(file_a_path,
400 &normalized_file_a_path))
401 << "NormalizeFilePath() should fail on nonexistent paths.";
402
403 CreateTextFile(file_a_path, bogus_content);
404 ASSERT_TRUE(file_util::PathExists(file_a_path));
405 ASSERT_TRUE(file_util::NormalizeFilePath(file_a_path,
406 &normalized_file_a_path));
407
408 CreateTextFile(file_b_path, bogus_content);
409 ASSERT_TRUE(file_util::PathExists(file_b_path));
410 ASSERT_TRUE(file_util::NormalizeFilePath(file_b_path,
411 &normalized_file_b_path));
412
413 // Beacuse this test created |dir_path|, we know it is not a link
414 // or junction. So, the real path of the directory holding file a
415 // must be the parent of the path holding file b.
416 ASSERT_TRUE(normalized_file_a_path.DirName()
417 .IsParent(normalized_file_b_path.DirName()));
418 }
419
420 #if defined(OS_WIN)
421
TEST_F(FileUtilTest,NormalizeFilePathReparsePoints)422 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) {
423 // Build the following directory structure:
424 //
425 // temp_dir
426 // |-> base_a
427 // | |-> sub_a
428 // | |-> file.txt
429 // | |-> long_name___... (Very long name.)
430 // | |-> sub_long
431 // | |-> deep.txt
432 // |-> base_b
433 // |-> to_sub_a (reparse point to temp_dir\base_a\sub_a)
434 // |-> to_base_b (reparse point to temp_dir\base_b)
435 // |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
436
437 FilePath base_a = temp_dir_.path().Append(FPL("base_a"));
438 ASSERT_TRUE(file_util::CreateDirectory(base_a));
439
440 FilePath sub_a = base_a.Append(FPL("sub_a"));
441 ASSERT_TRUE(file_util::CreateDirectory(sub_a));
442
443 FilePath file_txt = sub_a.Append(FPL("file.txt"));
444 CreateTextFile(file_txt, bogus_content);
445
446 // Want a directory whose name is long enough to make the path to the file
447 // inside just under MAX_PATH chars. This will be used to test that when
448 // a junction expands to a path over MAX_PATH chars in length,
449 // NormalizeFilePath() fails without crashing.
450 FilePath sub_long_rel(FPL("sub_long"));
451 FilePath deep_txt(FPL("deep.txt"));
452
453 int target_length = MAX_PATH;
454 target_length -= (sub_a.value().length() + 1); // +1 for the sepperator '\'.
455 target_length -= (sub_long_rel.Append(deep_txt).value().length() + 1);
456 // Without making the path a bit shorter, CreateDirectory() fails.
457 // the resulting path is still long enough to hit the failing case in
458 // NormalizePath().
459 const int kCreateDirLimit = 4;
460 target_length -= kCreateDirLimit;
461 FilePath::StringType long_name_str = FPL("long_name_");
462 long_name_str.resize(target_length, '_');
463
464 FilePath long_name = sub_a.Append(FilePath(long_name_str));
465 FilePath deep_file = long_name.Append(sub_long_rel).Append(deep_txt);
466 ASSERT_EQ(MAX_PATH - kCreateDirLimit, deep_file.value().length());
467
468 FilePath sub_long = deep_file.DirName();
469 ASSERT_TRUE(file_util::CreateDirectory(sub_long));
470 CreateTextFile(deep_file, bogus_content);
471
472 FilePath base_b = temp_dir_.path().Append(FPL("base_b"));
473 ASSERT_TRUE(file_util::CreateDirectory(base_b));
474
475 FilePath to_sub_a = base_b.Append(FPL("to_sub_a"));
476 ASSERT_TRUE(file_util::CreateDirectory(to_sub_a));
477 base::win::ScopedHandle reparse_to_sub_a(
478 ::CreateFile(to_sub_a.value().c_str(),
479 FILE_ALL_ACCESS,
480 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
481 NULL,
482 OPEN_EXISTING,
483 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
484 NULL));
485 ASSERT_TRUE(reparse_to_sub_a.IsValid());
486 ASSERT_TRUE(SetReparsePoint(reparse_to_sub_a, sub_a));
487
488 FilePath to_base_b = base_b.Append(FPL("to_base_b"));
489 ASSERT_TRUE(file_util::CreateDirectory(to_base_b));
490 base::win::ScopedHandle reparse_to_base_b(
491 ::CreateFile(to_base_b.value().c_str(),
492 FILE_ALL_ACCESS,
493 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
494 NULL,
495 OPEN_EXISTING,
496 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
497 NULL));
498 ASSERT_TRUE(reparse_to_base_b.IsValid());
499 ASSERT_TRUE(SetReparsePoint(reparse_to_base_b, base_b));
500
501 FilePath to_sub_long = base_b.Append(FPL("to_sub_long"));
502 ASSERT_TRUE(file_util::CreateDirectory(to_sub_long));
503 base::win::ScopedHandle reparse_to_sub_long(
504 ::CreateFile(to_sub_long.value().c_str(),
505 FILE_ALL_ACCESS,
506 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
507 NULL,
508 OPEN_EXISTING,
509 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
510 NULL));
511 ASSERT_TRUE(reparse_to_sub_long.IsValid());
512 ASSERT_TRUE(SetReparsePoint(reparse_to_sub_long, sub_long));
513
514 // Normalize a junction free path: base_a\sub_a\file.txt .
515 FilePath normalized_path;
516 ASSERT_TRUE(file_util::NormalizeFilePath(file_txt, &normalized_path));
517 ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
518
519 // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude
520 // the junction to_sub_a.
521 ASSERT_TRUE(file_util::NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
522 &normalized_path));
523 ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
524
525 // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be
526 // normalized to exclude junctions to_base_b and to_sub_a .
527 ASSERT_TRUE(file_util::NormalizeFilePath(base_b.Append(FPL("to_base_b"))
528 .Append(FPL("to_base_b"))
529 .Append(FPL("to_sub_a"))
530 .Append(FPL("file.txt")),
531 &normalized_path));
532 ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
533
534 // A long enough path will cause NormalizeFilePath() to fail. Make a long
535 // path using to_base_b many times, and check that paths long enough to fail
536 // do not cause a crash.
537 FilePath long_path = base_b;
538 const int kLengthLimit = MAX_PATH + 200;
539 while (long_path.value().length() <= kLengthLimit) {
540 long_path = long_path.Append(FPL("to_base_b"));
541 }
542 long_path = long_path.Append(FPL("to_sub_a"))
543 .Append(FPL("file.txt"));
544
545 ASSERT_FALSE(file_util::NormalizeFilePath(long_path, &normalized_path));
546
547 // Normalizing the junction to deep.txt should fail, because the expanded
548 // path to deep.txt is longer than MAX_PATH.
549 ASSERT_FALSE(file_util::NormalizeFilePath(to_sub_long.Append(deep_txt),
550 &normalized_path));
551
552 // Delete the reparse points, and see that NormalizeFilePath() fails
553 // to traverse them.
554 ASSERT_TRUE(DeleteReparsePoint(reparse_to_sub_a));
555 ASSERT_TRUE(DeleteReparsePoint(reparse_to_base_b));
556 ASSERT_TRUE(DeleteReparsePoint(reparse_to_sub_long));
557
558 ASSERT_FALSE(file_util::NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
559 &normalized_path));
560 }
561
562 #endif // defined(OS_WIN)
563
564 #if defined(OS_POSIX)
565
TEST_F(FileUtilTest,CreateAndReadSymlinks)566 TEST_F(FileUtilTest, CreateAndReadSymlinks) {
567 FilePath link_from = temp_dir_.path().Append(FPL("from_file"));
568 FilePath link_to = temp_dir_.path().Append(FPL("to_file"));
569 CreateTextFile(link_to, bogus_content);
570
571 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from))
572 << "Failed to create file symlink.";
573
574 // If we created the link properly, we should be able to read the
575 // contents through it.
576 std::wstring contents = ReadTextFile(link_from);
577 ASSERT_EQ(contents, bogus_content);
578
579 FilePath result;
580 ASSERT_TRUE(file_util::ReadSymbolicLink(link_from, &result));
581 ASSERT_EQ(link_to.value(), result.value());
582
583 // Link to a directory.
584 link_from = temp_dir_.path().Append(FPL("from_dir"));
585 link_to = temp_dir_.path().Append(FPL("to_dir"));
586 file_util::CreateDirectory(link_to);
587
588 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from))
589 << "Failed to create directory symlink.";
590
591 // Test failures.
592 ASSERT_FALSE(file_util::CreateSymbolicLink(link_to, link_to));
593 ASSERT_FALSE(file_util::ReadSymbolicLink(link_to, &result));
594 FilePath missing = temp_dir_.path().Append(FPL("missing"));
595 ASSERT_FALSE(file_util::ReadSymbolicLink(missing, &result));
596 }
597
598
599 // The following test of NormalizeFilePath() require that we create a symlink.
600 // This can not be done on Windows before Vista. On Vista, creating a symlink
601 // requires privilege "SeCreateSymbolicLinkPrivilege".
602 // TODO(skerner): Investigate the possibility of giving base_unittests the
603 // privileges required to create a symlink.
TEST_F(FileUtilTest,NormalizeFilePathSymlinks)604 TEST_F(FileUtilTest, NormalizeFilePathSymlinks) {
605 FilePath normalized_path;
606
607 // Link one file to another.
608 FilePath link_from = temp_dir_.path().Append(FPL("from_file"));
609 FilePath link_to = temp_dir_.path().Append(FPL("to_file"));
610 CreateTextFile(link_to, bogus_content);
611
612 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from))
613 << "Failed to create file symlink.";
614
615 // Check that NormalizeFilePath sees the link.
616 ASSERT_TRUE(file_util::NormalizeFilePath(link_from, &normalized_path));
617 ASSERT_TRUE(link_to != link_from);
618 ASSERT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
619 ASSERT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
620
621 // Link to a directory.
622 link_from = temp_dir_.path().Append(FPL("from_dir"));
623 link_to = temp_dir_.path().Append(FPL("to_dir"));
624 file_util::CreateDirectory(link_to);
625
626 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from))
627 << "Failed to create directory symlink.";
628
629 ASSERT_FALSE(file_util::NormalizeFilePath(link_from, &normalized_path))
630 << "Links to directories should return false.";
631
632 // Test that a loop in the links causes NormalizeFilePath() to return false.
633 link_from = temp_dir_.path().Append(FPL("link_a"));
634 link_to = temp_dir_.path().Append(FPL("link_b"));
635 ASSERT_TRUE(file_util::CreateSymbolicLink(link_to, link_from))
636 << "Failed to create loop symlink a.";
637 ASSERT_TRUE(file_util::CreateSymbolicLink(link_from, link_to))
638 << "Failed to create loop symlink b.";
639
640 // Infinite loop!
641 ASSERT_FALSE(file_util::NormalizeFilePath(link_from, &normalized_path));
642 }
643 #endif // defined(OS_POSIX)
644
TEST_F(FileUtilTest,DeleteNonExistent)645 TEST_F(FileUtilTest, DeleteNonExistent) {
646 FilePath non_existent = temp_dir_.path().AppendASCII("bogus_file_dne.foobar");
647 ASSERT_FALSE(file_util::PathExists(non_existent));
648
649 EXPECT_TRUE(file_util::Delete(non_existent, false));
650 ASSERT_FALSE(file_util::PathExists(non_existent));
651 EXPECT_TRUE(file_util::Delete(non_existent, true));
652 ASSERT_FALSE(file_util::PathExists(non_existent));
653 }
654
TEST_F(FileUtilTest,DeleteFile)655 TEST_F(FileUtilTest, DeleteFile) {
656 // Create a file
657 FilePath file_name = temp_dir_.path().Append(FPL("Test DeleteFile 1.txt"));
658 CreateTextFile(file_name, bogus_content);
659 ASSERT_TRUE(file_util::PathExists(file_name));
660
661 // Make sure it's deleted
662 EXPECT_TRUE(file_util::Delete(file_name, false));
663 EXPECT_FALSE(file_util::PathExists(file_name));
664
665 // Test recursive case, create a new file
666 file_name = temp_dir_.path().Append(FPL("Test DeleteFile 2.txt"));
667 CreateTextFile(file_name, bogus_content);
668 ASSERT_TRUE(file_util::PathExists(file_name));
669
670 // Make sure it's deleted
671 EXPECT_TRUE(file_util::Delete(file_name, true));
672 EXPECT_FALSE(file_util::PathExists(file_name));
673 }
674
675 #if defined(OS_WIN)
676 // Tests that the Delete function works for wild cards, especially
677 // with the recursion flag. Also coincidentally tests PathExists.
678 // TODO(erikkay): see if anyone's actually using this feature of the API
TEST_F(FileUtilTest,DeleteWildCard)679 TEST_F(FileUtilTest, DeleteWildCard) {
680 // Create a file and a directory
681 FilePath file_name = temp_dir_.path().Append(FPL("Test DeleteWildCard.txt"));
682 CreateTextFile(file_name, bogus_content);
683 ASSERT_TRUE(file_util::PathExists(file_name));
684
685 FilePath subdir_path = temp_dir_.path().Append(FPL("DeleteWildCardDir"));
686 file_util::CreateDirectory(subdir_path);
687 ASSERT_TRUE(file_util::PathExists(subdir_path));
688
689 // Create the wildcard path
690 FilePath directory_contents = temp_dir_.path();
691 directory_contents = directory_contents.Append(FPL("*"));
692
693 // Delete non-recursively and check that only the file is deleted
694 EXPECT_TRUE(file_util::Delete(directory_contents, false));
695 EXPECT_FALSE(file_util::PathExists(file_name));
696 EXPECT_TRUE(file_util::PathExists(subdir_path));
697
698 // Delete recursively and make sure all contents are deleted
699 EXPECT_TRUE(file_util::Delete(directory_contents, true));
700 EXPECT_FALSE(file_util::PathExists(file_name));
701 EXPECT_FALSE(file_util::PathExists(subdir_path));
702 }
703
704 // TODO(erikkay): see if anyone's actually using this feature of the API
TEST_F(FileUtilTest,DeleteNonExistantWildCard)705 TEST_F(FileUtilTest, DeleteNonExistantWildCard) {
706 // Create a file and a directory
707 FilePath subdir_path =
708 temp_dir_.path().Append(FPL("DeleteNonExistantWildCard"));
709 file_util::CreateDirectory(subdir_path);
710 ASSERT_TRUE(file_util::PathExists(subdir_path));
711
712 // Create the wildcard path
713 FilePath directory_contents = subdir_path;
714 directory_contents = directory_contents.Append(FPL("*"));
715
716 // Delete non-recursively and check nothing got deleted
717 EXPECT_TRUE(file_util::Delete(directory_contents, false));
718 EXPECT_TRUE(file_util::PathExists(subdir_path));
719
720 // Delete recursively and check nothing got deleted
721 EXPECT_TRUE(file_util::Delete(directory_contents, true));
722 EXPECT_TRUE(file_util::PathExists(subdir_path));
723 }
724 #endif
725
726 // Tests non-recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirNonRecursive)727 TEST_F(FileUtilTest, DeleteDirNonRecursive) {
728 // Create a subdirectory and put a file and two directories inside.
729 FilePath test_subdir = temp_dir_.path().Append(FPL("DeleteDirNonRecursive"));
730 file_util::CreateDirectory(test_subdir);
731 ASSERT_TRUE(file_util::PathExists(test_subdir));
732
733 FilePath file_name = test_subdir.Append(FPL("Test DeleteDir.txt"));
734 CreateTextFile(file_name, bogus_content);
735 ASSERT_TRUE(file_util::PathExists(file_name));
736
737 FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
738 file_util::CreateDirectory(subdir_path1);
739 ASSERT_TRUE(file_util::PathExists(subdir_path1));
740
741 FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
742 file_util::CreateDirectory(subdir_path2);
743 ASSERT_TRUE(file_util::PathExists(subdir_path2));
744
745 // Delete non-recursively and check that the empty dir got deleted
746 EXPECT_TRUE(file_util::Delete(subdir_path2, false));
747 EXPECT_FALSE(file_util::PathExists(subdir_path2));
748
749 // Delete non-recursively and check that nothing got deleted
750 EXPECT_FALSE(file_util::Delete(test_subdir, false));
751 EXPECT_TRUE(file_util::PathExists(test_subdir));
752 EXPECT_TRUE(file_util::PathExists(file_name));
753 EXPECT_TRUE(file_util::PathExists(subdir_path1));
754 }
755
756 // Tests recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirRecursive)757 TEST_F(FileUtilTest, DeleteDirRecursive) {
758 // Create a subdirectory and put a file and two directories inside.
759 FilePath test_subdir = temp_dir_.path().Append(FPL("DeleteDirRecursive"));
760 file_util::CreateDirectory(test_subdir);
761 ASSERT_TRUE(file_util::PathExists(test_subdir));
762
763 FilePath file_name = test_subdir.Append(FPL("Test DeleteDirRecursive.txt"));
764 CreateTextFile(file_name, bogus_content);
765 ASSERT_TRUE(file_util::PathExists(file_name));
766
767 FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
768 file_util::CreateDirectory(subdir_path1);
769 ASSERT_TRUE(file_util::PathExists(subdir_path1));
770
771 FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
772 file_util::CreateDirectory(subdir_path2);
773 ASSERT_TRUE(file_util::PathExists(subdir_path2));
774
775 // Delete recursively and check that the empty dir got deleted
776 EXPECT_TRUE(file_util::Delete(subdir_path2, true));
777 EXPECT_FALSE(file_util::PathExists(subdir_path2));
778
779 // Delete recursively and check that everything got deleted
780 EXPECT_TRUE(file_util::Delete(test_subdir, true));
781 EXPECT_FALSE(file_util::PathExists(file_name));
782 EXPECT_FALSE(file_util::PathExists(subdir_path1));
783 EXPECT_FALSE(file_util::PathExists(test_subdir));
784 }
785
TEST_F(FileUtilTest,MoveFileNew)786 TEST_F(FileUtilTest, MoveFileNew) {
787 // Create a file
788 FilePath file_name_from =
789 temp_dir_.path().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
790 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
791 ASSERT_TRUE(file_util::PathExists(file_name_from));
792
793 // The destination.
794 FilePath file_name_to = temp_dir_.path().Append(
795 FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
796 ASSERT_FALSE(file_util::PathExists(file_name_to));
797
798 EXPECT_TRUE(file_util::Move(file_name_from, file_name_to));
799
800 // Check everything has been moved.
801 EXPECT_FALSE(file_util::PathExists(file_name_from));
802 EXPECT_TRUE(file_util::PathExists(file_name_to));
803 }
804
TEST_F(FileUtilTest,MoveFileExists)805 TEST_F(FileUtilTest, MoveFileExists) {
806 // Create a file
807 FilePath file_name_from =
808 temp_dir_.path().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
809 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
810 ASSERT_TRUE(file_util::PathExists(file_name_from));
811
812 // The destination name.
813 FilePath file_name_to = temp_dir_.path().Append(
814 FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
815 CreateTextFile(file_name_to, L"Old file content");
816 ASSERT_TRUE(file_util::PathExists(file_name_to));
817
818 EXPECT_TRUE(file_util::Move(file_name_from, file_name_to));
819
820 // Check everything has been moved.
821 EXPECT_FALSE(file_util::PathExists(file_name_from));
822 EXPECT_TRUE(file_util::PathExists(file_name_to));
823 EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
824 }
825
TEST_F(FileUtilTest,MoveFileDirExists)826 TEST_F(FileUtilTest, MoveFileDirExists) {
827 // Create a file
828 FilePath file_name_from =
829 temp_dir_.path().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
830 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
831 ASSERT_TRUE(file_util::PathExists(file_name_from));
832
833 // The destination directory
834 FilePath dir_name_to =
835 temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
836 file_util::CreateDirectory(dir_name_to);
837 ASSERT_TRUE(file_util::PathExists(dir_name_to));
838
839 EXPECT_FALSE(file_util::Move(file_name_from, dir_name_to));
840 }
841
842
TEST_F(FileUtilTest,MoveNew)843 TEST_F(FileUtilTest, MoveNew) {
844 // Create a directory
845 FilePath dir_name_from =
846 temp_dir_.path().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
847 file_util::CreateDirectory(dir_name_from);
848 ASSERT_TRUE(file_util::PathExists(dir_name_from));
849
850 // Create a file under the directory
851 FilePath file_name_from =
852 dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
853 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
854 ASSERT_TRUE(file_util::PathExists(file_name_from));
855
856 // Move the directory.
857 FilePath dir_name_to =
858 temp_dir_.path().Append(FILE_PATH_LITERAL("Move_To_Subdir"));
859 FilePath file_name_to =
860 dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
861
862 ASSERT_FALSE(file_util::PathExists(dir_name_to));
863
864 EXPECT_TRUE(file_util::Move(dir_name_from, dir_name_to));
865
866 // Check everything has been moved.
867 EXPECT_FALSE(file_util::PathExists(dir_name_from));
868 EXPECT_FALSE(file_util::PathExists(file_name_from));
869 EXPECT_TRUE(file_util::PathExists(dir_name_to));
870 EXPECT_TRUE(file_util::PathExists(file_name_to));
871 }
872
TEST_F(FileUtilTest,MoveExist)873 TEST_F(FileUtilTest, MoveExist) {
874 // Create a directory
875 FilePath dir_name_from =
876 temp_dir_.path().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
877 file_util::CreateDirectory(dir_name_from);
878 ASSERT_TRUE(file_util::PathExists(dir_name_from));
879
880 // Create a file under the directory
881 FilePath file_name_from =
882 dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
883 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
884 ASSERT_TRUE(file_util::PathExists(file_name_from));
885
886 // Move the directory
887 FilePath dir_name_exists =
888 temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
889
890 FilePath dir_name_to =
891 dir_name_exists.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
892 FilePath file_name_to =
893 dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
894
895 // Create the destination directory.
896 file_util::CreateDirectory(dir_name_exists);
897 ASSERT_TRUE(file_util::PathExists(dir_name_exists));
898
899 EXPECT_TRUE(file_util::Move(dir_name_from, dir_name_to));
900
901 // Check everything has been moved.
902 EXPECT_FALSE(file_util::PathExists(dir_name_from));
903 EXPECT_FALSE(file_util::PathExists(file_name_from));
904 EXPECT_TRUE(file_util::PathExists(dir_name_to));
905 EXPECT_TRUE(file_util::PathExists(file_name_to));
906 }
907
TEST_F(FileUtilTest,CopyDirectoryRecursivelyNew)908 TEST_F(FileUtilTest, CopyDirectoryRecursivelyNew) {
909 // Create a directory.
910 FilePath dir_name_from =
911 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
912 file_util::CreateDirectory(dir_name_from);
913 ASSERT_TRUE(file_util::PathExists(dir_name_from));
914
915 // Create a file under the directory.
916 FilePath file_name_from =
917 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
918 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
919 ASSERT_TRUE(file_util::PathExists(file_name_from));
920
921 // Create a subdirectory.
922 FilePath subdir_name_from =
923 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
924 file_util::CreateDirectory(subdir_name_from);
925 ASSERT_TRUE(file_util::PathExists(subdir_name_from));
926
927 // Create a file under the subdirectory.
928 FilePath file_name2_from =
929 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
930 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
931 ASSERT_TRUE(file_util::PathExists(file_name2_from));
932
933 // Copy the directory recursively.
934 FilePath dir_name_to =
935 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
936 FilePath file_name_to =
937 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
938 FilePath subdir_name_to =
939 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
940 FilePath file_name2_to =
941 subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
942
943 ASSERT_FALSE(file_util::PathExists(dir_name_to));
944
945 EXPECT_TRUE(file_util::CopyDirectory(dir_name_from, dir_name_to, true));
946
947 // Check everything has been copied.
948 EXPECT_TRUE(file_util::PathExists(dir_name_from));
949 EXPECT_TRUE(file_util::PathExists(file_name_from));
950 EXPECT_TRUE(file_util::PathExists(subdir_name_from));
951 EXPECT_TRUE(file_util::PathExists(file_name2_from));
952 EXPECT_TRUE(file_util::PathExists(dir_name_to));
953 EXPECT_TRUE(file_util::PathExists(file_name_to));
954 EXPECT_TRUE(file_util::PathExists(subdir_name_to));
955 EXPECT_TRUE(file_util::PathExists(file_name2_to));
956 }
957
TEST_F(FileUtilTest,CopyDirectoryRecursivelyExists)958 TEST_F(FileUtilTest, CopyDirectoryRecursivelyExists) {
959 // Create a directory.
960 FilePath dir_name_from =
961 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
962 file_util::CreateDirectory(dir_name_from);
963 ASSERT_TRUE(file_util::PathExists(dir_name_from));
964
965 // Create a file under the directory.
966 FilePath file_name_from =
967 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
968 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
969 ASSERT_TRUE(file_util::PathExists(file_name_from));
970
971 // Create a subdirectory.
972 FilePath subdir_name_from =
973 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
974 file_util::CreateDirectory(subdir_name_from);
975 ASSERT_TRUE(file_util::PathExists(subdir_name_from));
976
977 // Create a file under the subdirectory.
978 FilePath file_name2_from =
979 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
980 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
981 ASSERT_TRUE(file_util::PathExists(file_name2_from));
982
983 // Copy the directory recursively.
984 FilePath dir_name_exists =
985 temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
986
987 FilePath dir_name_to =
988 dir_name_exists.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
989 FilePath file_name_to =
990 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
991 FilePath subdir_name_to =
992 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
993 FilePath file_name2_to =
994 subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
995
996 // Create the destination directory.
997 file_util::CreateDirectory(dir_name_exists);
998 ASSERT_TRUE(file_util::PathExists(dir_name_exists));
999
1000 EXPECT_TRUE(file_util::CopyDirectory(dir_name_from, dir_name_exists, true));
1001
1002 // Check everything has been copied.
1003 EXPECT_TRUE(file_util::PathExists(dir_name_from));
1004 EXPECT_TRUE(file_util::PathExists(file_name_from));
1005 EXPECT_TRUE(file_util::PathExists(subdir_name_from));
1006 EXPECT_TRUE(file_util::PathExists(file_name2_from));
1007 EXPECT_TRUE(file_util::PathExists(dir_name_to));
1008 EXPECT_TRUE(file_util::PathExists(file_name_to));
1009 EXPECT_TRUE(file_util::PathExists(subdir_name_to));
1010 EXPECT_TRUE(file_util::PathExists(file_name2_to));
1011 }
1012
TEST_F(FileUtilTest,CopyDirectoryNew)1013 TEST_F(FileUtilTest, CopyDirectoryNew) {
1014 // Create a directory.
1015 FilePath dir_name_from =
1016 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1017 file_util::CreateDirectory(dir_name_from);
1018 ASSERT_TRUE(file_util::PathExists(dir_name_from));
1019
1020 // Create a file under the directory.
1021 FilePath file_name_from =
1022 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1023 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1024 ASSERT_TRUE(file_util::PathExists(file_name_from));
1025
1026 // Create a subdirectory.
1027 FilePath subdir_name_from =
1028 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1029 file_util::CreateDirectory(subdir_name_from);
1030 ASSERT_TRUE(file_util::PathExists(subdir_name_from));
1031
1032 // Create a file under the subdirectory.
1033 FilePath file_name2_from =
1034 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1035 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1036 ASSERT_TRUE(file_util::PathExists(file_name2_from));
1037
1038 // Copy the directory not recursively.
1039 FilePath dir_name_to =
1040 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1041 FilePath file_name_to =
1042 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1043 FilePath subdir_name_to =
1044 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1045
1046 ASSERT_FALSE(file_util::PathExists(dir_name_to));
1047
1048 EXPECT_TRUE(file_util::CopyDirectory(dir_name_from, dir_name_to, false));
1049
1050 // Check everything has been copied.
1051 EXPECT_TRUE(file_util::PathExists(dir_name_from));
1052 EXPECT_TRUE(file_util::PathExists(file_name_from));
1053 EXPECT_TRUE(file_util::PathExists(subdir_name_from));
1054 EXPECT_TRUE(file_util::PathExists(file_name2_from));
1055 EXPECT_TRUE(file_util::PathExists(dir_name_to));
1056 EXPECT_TRUE(file_util::PathExists(file_name_to));
1057 EXPECT_FALSE(file_util::PathExists(subdir_name_to));
1058 }
1059
TEST_F(FileUtilTest,CopyDirectoryExists)1060 TEST_F(FileUtilTest, CopyDirectoryExists) {
1061 // Create a directory.
1062 FilePath dir_name_from =
1063 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1064 file_util::CreateDirectory(dir_name_from);
1065 ASSERT_TRUE(file_util::PathExists(dir_name_from));
1066
1067 // Create a file under the directory.
1068 FilePath file_name_from =
1069 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1070 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1071 ASSERT_TRUE(file_util::PathExists(file_name_from));
1072
1073 // Create a subdirectory.
1074 FilePath subdir_name_from =
1075 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1076 file_util::CreateDirectory(subdir_name_from);
1077 ASSERT_TRUE(file_util::PathExists(subdir_name_from));
1078
1079 // Create a file under the subdirectory.
1080 FilePath file_name2_from =
1081 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1082 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1083 ASSERT_TRUE(file_util::PathExists(file_name2_from));
1084
1085 // Copy the directory not recursively.
1086 FilePath dir_name_to =
1087 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1088 FilePath file_name_to =
1089 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1090 FilePath subdir_name_to =
1091 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1092
1093 // Create the destination directory.
1094 file_util::CreateDirectory(dir_name_to);
1095 ASSERT_TRUE(file_util::PathExists(dir_name_to));
1096
1097 EXPECT_TRUE(file_util::CopyDirectory(dir_name_from, dir_name_to, false));
1098
1099 // Check everything has been copied.
1100 EXPECT_TRUE(file_util::PathExists(dir_name_from));
1101 EXPECT_TRUE(file_util::PathExists(file_name_from));
1102 EXPECT_TRUE(file_util::PathExists(subdir_name_from));
1103 EXPECT_TRUE(file_util::PathExists(file_name2_from));
1104 EXPECT_TRUE(file_util::PathExists(dir_name_to));
1105 EXPECT_TRUE(file_util::PathExists(file_name_to));
1106 EXPECT_FALSE(file_util::PathExists(subdir_name_to));
1107 }
1108
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToNew)1109 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToNew) {
1110 // Create a file
1111 FilePath file_name_from =
1112 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1113 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1114 ASSERT_TRUE(file_util::PathExists(file_name_from));
1115
1116 // The destination name
1117 FilePath file_name_to = temp_dir_.path().Append(
1118 FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
1119 ASSERT_FALSE(file_util::PathExists(file_name_to));
1120
1121 EXPECT_TRUE(file_util::CopyDirectory(file_name_from, file_name_to, true));
1122
1123 // Check the has been copied
1124 EXPECT_TRUE(file_util::PathExists(file_name_to));
1125 }
1126
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToExisting)1127 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExisting) {
1128 // Create a file
1129 FilePath file_name_from =
1130 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1131 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1132 ASSERT_TRUE(file_util::PathExists(file_name_from));
1133
1134 // The destination name
1135 FilePath file_name_to = temp_dir_.path().Append(
1136 FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
1137 CreateTextFile(file_name_to, L"Old file content");
1138 ASSERT_TRUE(file_util::PathExists(file_name_to));
1139
1140 EXPECT_TRUE(file_util::CopyDirectory(file_name_from, file_name_to, true));
1141
1142 // Check the has been copied
1143 EXPECT_TRUE(file_util::PathExists(file_name_to));
1144 EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
1145 }
1146
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToExistingDirectory)1147 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExistingDirectory) {
1148 // Create a file
1149 FilePath file_name_from =
1150 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1151 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1152 ASSERT_TRUE(file_util::PathExists(file_name_from));
1153
1154 // The destination
1155 FilePath dir_name_to =
1156 temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
1157 file_util::CreateDirectory(dir_name_to);
1158 ASSERT_TRUE(file_util::PathExists(dir_name_to));
1159 FilePath file_name_to =
1160 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1161
1162 EXPECT_TRUE(file_util::CopyDirectory(file_name_from, dir_name_to, true));
1163
1164 // Check the has been copied
1165 EXPECT_TRUE(file_util::PathExists(file_name_to));
1166 }
1167
TEST_F(FileUtilTest,CopyFile)1168 TEST_F(FileUtilTest, CopyFile) {
1169 // Create a directory
1170 FilePath dir_name_from =
1171 temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1172 file_util::CreateDirectory(dir_name_from);
1173 ASSERT_TRUE(file_util::PathExists(dir_name_from));
1174
1175 // Create a file under the directory
1176 FilePath file_name_from =
1177 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1178 const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1179 CreateTextFile(file_name_from, file_contents);
1180 ASSERT_TRUE(file_util::PathExists(file_name_from));
1181
1182 // Copy the file.
1183 FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
1184 ASSERT_TRUE(file_util::CopyFile(file_name_from, dest_file));
1185
1186 // Copy the file to another location using '..' in the path.
1187 FilePath dest_file2(dir_name_from);
1188 dest_file2 = dest_file2.AppendASCII("..");
1189 dest_file2 = dest_file2.AppendASCII("DestFile.txt");
1190 ASSERT_TRUE(file_util::CopyFile(file_name_from, dest_file2));
1191
1192 FilePath dest_file2_test(dir_name_from);
1193 dest_file2_test = dest_file2_test.DirName();
1194 dest_file2_test = dest_file2_test.AppendASCII("DestFile.txt");
1195
1196 // Check everything has been copied.
1197 EXPECT_TRUE(file_util::PathExists(file_name_from));
1198 EXPECT_TRUE(file_util::PathExists(dest_file));
1199 const std::wstring read_contents = ReadTextFile(dest_file);
1200 EXPECT_EQ(file_contents, read_contents);
1201 EXPECT_TRUE(file_util::PathExists(dest_file2_test));
1202 EXPECT_TRUE(file_util::PathExists(dest_file2));
1203 }
1204
1205 // TODO(erikkay): implement
1206 #if defined(OS_WIN)
TEST_F(FileUtilTest,GetFileCreationLocalTime)1207 TEST_F(FileUtilTest, GetFileCreationLocalTime) {
1208 FilePath file_name = temp_dir_.path().Append(L"Test File.txt");
1209
1210 SYSTEMTIME start_time;
1211 GetLocalTime(&start_time);
1212 Sleep(100);
1213 CreateTextFile(file_name, L"New file!");
1214 Sleep(100);
1215 SYSTEMTIME end_time;
1216 GetLocalTime(&end_time);
1217
1218 SYSTEMTIME file_creation_time;
1219 file_util::GetFileCreationLocalTime(file_name.value(), &file_creation_time);
1220
1221 FILETIME start_filetime;
1222 SystemTimeToFileTime(&start_time, &start_filetime);
1223 FILETIME end_filetime;
1224 SystemTimeToFileTime(&end_time, &end_filetime);
1225 FILETIME file_creation_filetime;
1226 SystemTimeToFileTime(&file_creation_time, &file_creation_filetime);
1227
1228 EXPECT_EQ(-1, CompareFileTime(&start_filetime, &file_creation_filetime)) <<
1229 "start time: " << FileTimeAsUint64(start_filetime) << ", " <<
1230 "creation time: " << FileTimeAsUint64(file_creation_filetime);
1231
1232 EXPECT_EQ(-1, CompareFileTime(&file_creation_filetime, &end_filetime)) <<
1233 "creation time: " << FileTimeAsUint64(file_creation_filetime) << ", " <<
1234 "end time: " << FileTimeAsUint64(end_filetime);
1235
1236 ASSERT_TRUE(DeleteFile(file_name.value().c_str()));
1237 }
1238 #endif
1239
1240 // file_util winds up using autoreleased objects on the Mac, so this needs
1241 // to be a PlatformTest.
1242 typedef PlatformTest ReadOnlyFileUtilTest;
1243
TEST_F(ReadOnlyFileUtilTest,ContentsEqual)1244 TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
1245 FilePath data_dir;
1246 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
1247 data_dir = data_dir.Append(FILE_PATH_LITERAL("base"))
1248 .Append(FILE_PATH_LITERAL("data"))
1249 .Append(FILE_PATH_LITERAL("file_util_unittest"));
1250 ASSERT_TRUE(file_util::PathExists(data_dir));
1251
1252 FilePath original_file =
1253 data_dir.Append(FILE_PATH_LITERAL("original.txt"));
1254 FilePath same_file =
1255 data_dir.Append(FILE_PATH_LITERAL("same.txt"));
1256 FilePath same_length_file =
1257 data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
1258 FilePath different_file =
1259 data_dir.Append(FILE_PATH_LITERAL("different.txt"));
1260 FilePath different_first_file =
1261 data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
1262 FilePath different_last_file =
1263 data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
1264 FilePath empty1_file =
1265 data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
1266 FilePath empty2_file =
1267 data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
1268 FilePath shortened_file =
1269 data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
1270 FilePath binary_file =
1271 data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
1272 FilePath binary_file_same =
1273 data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
1274 FilePath binary_file_diff =
1275 data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
1276
1277 EXPECT_TRUE(file_util::ContentsEqual(original_file, original_file));
1278 EXPECT_TRUE(file_util::ContentsEqual(original_file, same_file));
1279 EXPECT_FALSE(file_util::ContentsEqual(original_file, same_length_file));
1280 EXPECT_FALSE(file_util::ContentsEqual(original_file, different_file));
1281 EXPECT_FALSE(file_util::ContentsEqual(
1282 FilePath(FILE_PATH_LITERAL("bogusname")),
1283 FilePath(FILE_PATH_LITERAL("bogusname"))));
1284 EXPECT_FALSE(file_util::ContentsEqual(original_file, different_first_file));
1285 EXPECT_FALSE(file_util::ContentsEqual(original_file, different_last_file));
1286 EXPECT_TRUE(file_util::ContentsEqual(empty1_file, empty2_file));
1287 EXPECT_FALSE(file_util::ContentsEqual(original_file, shortened_file));
1288 EXPECT_FALSE(file_util::ContentsEqual(shortened_file, original_file));
1289 EXPECT_TRUE(file_util::ContentsEqual(binary_file, binary_file_same));
1290 EXPECT_FALSE(file_util::ContentsEqual(binary_file, binary_file_diff));
1291 }
1292
TEST_F(ReadOnlyFileUtilTest,TextContentsEqual)1293 TEST_F(ReadOnlyFileUtilTest, TextContentsEqual) {
1294 FilePath data_dir;
1295 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
1296 data_dir = data_dir.Append(FILE_PATH_LITERAL("base"))
1297 .Append(FILE_PATH_LITERAL("data"))
1298 .Append(FILE_PATH_LITERAL("file_util_unittest"));
1299 ASSERT_TRUE(file_util::PathExists(data_dir));
1300
1301 FilePath original_file =
1302 data_dir.Append(FILE_PATH_LITERAL("original.txt"));
1303 FilePath same_file =
1304 data_dir.Append(FILE_PATH_LITERAL("same.txt"));
1305 FilePath crlf_file =
1306 data_dir.Append(FILE_PATH_LITERAL("crlf.txt"));
1307 FilePath shortened_file =
1308 data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
1309 FilePath different_file =
1310 data_dir.Append(FILE_PATH_LITERAL("different.txt"));
1311 FilePath different_first_file =
1312 data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
1313 FilePath different_last_file =
1314 data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
1315 FilePath first1_file =
1316 data_dir.Append(FILE_PATH_LITERAL("first1.txt"));
1317 FilePath first2_file =
1318 data_dir.Append(FILE_PATH_LITERAL("first2.txt"));
1319 FilePath empty1_file =
1320 data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
1321 FilePath empty2_file =
1322 data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
1323 FilePath blank_line_file =
1324 data_dir.Append(FILE_PATH_LITERAL("blank_line.txt"));
1325 FilePath blank_line_crlf_file =
1326 data_dir.Append(FILE_PATH_LITERAL("blank_line_crlf.txt"));
1327
1328 EXPECT_TRUE(file_util::TextContentsEqual(original_file, same_file));
1329 EXPECT_TRUE(file_util::TextContentsEqual(original_file, crlf_file));
1330 EXPECT_FALSE(file_util::TextContentsEqual(original_file, shortened_file));
1331 EXPECT_FALSE(file_util::TextContentsEqual(original_file, different_file));
1332 EXPECT_FALSE(file_util::TextContentsEqual(original_file,
1333 different_first_file));
1334 EXPECT_FALSE(file_util::TextContentsEqual(original_file,
1335 different_last_file));
1336 EXPECT_FALSE(file_util::TextContentsEqual(first1_file, first2_file));
1337 EXPECT_TRUE(file_util::TextContentsEqual(empty1_file, empty2_file));
1338 EXPECT_FALSE(file_util::TextContentsEqual(original_file, empty1_file));
1339 EXPECT_TRUE(file_util::TextContentsEqual(blank_line_file,
1340 blank_line_crlf_file));
1341 }
1342
1343 // We don't need equivalent functionality outside of Windows.
1344 #if defined(OS_WIN)
TEST_F(FileUtilTest,ResolveShortcutTest)1345 TEST_F(FileUtilTest, ResolveShortcutTest) {
1346 FilePath target_file = temp_dir_.path().Append(L"Target.txt");
1347 CreateTextFile(target_file, L"This is the target.");
1348
1349 FilePath link_file = temp_dir_.path().Append(L"Link.lnk");
1350
1351 HRESULT result;
1352 IShellLink *shell = NULL;
1353 IPersistFile *persist = NULL;
1354
1355 CoInitialize(NULL);
1356 // Temporarily create a shortcut for test
1357 result = CoCreateInstance(CLSID_ShellLink, NULL,
1358 CLSCTX_INPROC_SERVER, IID_IShellLink,
1359 reinterpret_cast<LPVOID*>(&shell));
1360 EXPECT_TRUE(SUCCEEDED(result));
1361 result = shell->QueryInterface(IID_IPersistFile,
1362 reinterpret_cast<LPVOID*>(&persist));
1363 EXPECT_TRUE(SUCCEEDED(result));
1364 result = shell->SetPath(target_file.value().c_str());
1365 EXPECT_TRUE(SUCCEEDED(result));
1366 result = shell->SetDescription(L"ResolveShortcutTest");
1367 EXPECT_TRUE(SUCCEEDED(result));
1368 result = persist->Save(link_file.value().c_str(), TRUE);
1369 EXPECT_TRUE(SUCCEEDED(result));
1370 if (persist)
1371 persist->Release();
1372 if (shell)
1373 shell->Release();
1374
1375 bool is_solved;
1376 is_solved = file_util::ResolveShortcut(&link_file);
1377 EXPECT_TRUE(is_solved);
1378 std::wstring contents;
1379 contents = ReadTextFile(link_file);
1380 EXPECT_EQ(L"This is the target.", contents);
1381
1382 // Cleaning
1383 DeleteFile(target_file.value().c_str());
1384 DeleteFile(link_file.value().c_str());
1385 CoUninitialize();
1386 }
1387
TEST_F(FileUtilTest,CreateShortcutTest)1388 TEST_F(FileUtilTest, CreateShortcutTest) {
1389 const wchar_t file_contents[] = L"This is another target.";
1390 FilePath target_file = temp_dir_.path().Append(L"Target1.txt");
1391 CreateTextFile(target_file, file_contents);
1392
1393 FilePath link_file = temp_dir_.path().Append(L"Link1.lnk");
1394
1395 CoInitialize(NULL);
1396 EXPECT_TRUE(file_util::CreateShortcutLink(target_file.value().c_str(),
1397 link_file.value().c_str(),
1398 NULL, NULL, NULL, NULL, 0, NULL));
1399 FilePath resolved_name = link_file;
1400 EXPECT_TRUE(file_util::ResolveShortcut(&resolved_name));
1401 std::wstring read_contents = ReadTextFile(resolved_name);
1402 EXPECT_EQ(file_contents, read_contents);
1403
1404 DeleteFile(target_file.value().c_str());
1405 DeleteFile(link_file.value().c_str());
1406 CoUninitialize();
1407 }
1408
TEST_F(FileUtilTest,CopyAndDeleteDirectoryTest)1409 TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) {
1410 // Create a directory
1411 FilePath dir_name_from =
1412 temp_dir_.path().Append(FILE_PATH_LITERAL("CopyAndDelete_From_Subdir"));
1413 file_util::CreateDirectory(dir_name_from);
1414 ASSERT_TRUE(file_util::PathExists(dir_name_from));
1415
1416 // Create a file under the directory
1417 FilePath file_name_from =
1418 dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
1419 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1420 ASSERT_TRUE(file_util::PathExists(file_name_from));
1421
1422 // Move the directory by using CopyAndDeleteDirectory
1423 FilePath dir_name_to = temp_dir_.path().Append(
1424 FILE_PATH_LITERAL("CopyAndDelete_To_Subdir"));
1425 FilePath file_name_to =
1426 dir_name_to.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
1427
1428 ASSERT_FALSE(file_util::PathExists(dir_name_to));
1429
1430 EXPECT_TRUE(file_util::CopyAndDeleteDirectory(dir_name_from, dir_name_to));
1431
1432 // Check everything has been moved.
1433 EXPECT_FALSE(file_util::PathExists(dir_name_from));
1434 EXPECT_FALSE(file_util::PathExists(file_name_from));
1435 EXPECT_TRUE(file_util::PathExists(dir_name_to));
1436 EXPECT_TRUE(file_util::PathExists(file_name_to));
1437 }
1438
TEST_F(FileUtilTest,GetTempDirTest)1439 TEST_F(FileUtilTest, GetTempDirTest) {
1440 static const TCHAR* kTmpKey = _T("TMP");
1441 static const TCHAR* kTmpValues[] = {
1442 _T(""), _T("C:"), _T("C:\\"), _T("C:\\tmp"), _T("C:\\tmp\\")
1443 };
1444 // Save the original $TMP.
1445 size_t original_tmp_size;
1446 TCHAR* original_tmp;
1447 ASSERT_EQ(0, ::_tdupenv_s(&original_tmp, &original_tmp_size, kTmpKey));
1448 // original_tmp may be NULL.
1449
1450 for (unsigned int i = 0; i < arraysize(kTmpValues); ++i) {
1451 FilePath path;
1452 ::_tputenv_s(kTmpKey, kTmpValues[i]);
1453 file_util::GetTempDir(&path);
1454 EXPECT_TRUE(path.IsAbsolute()) << "$TMP=" << kTmpValues[i] <<
1455 " result=" << path.value();
1456 }
1457
1458 // Restore the original $TMP.
1459 if (original_tmp) {
1460 ::_tputenv_s(kTmpKey, original_tmp);
1461 free(original_tmp);
1462 } else {
1463 ::_tputenv_s(kTmpKey, _T(""));
1464 }
1465 }
1466 #endif // OS_WIN
1467
TEST_F(FileUtilTest,CreateTemporaryFileTest)1468 TEST_F(FileUtilTest, CreateTemporaryFileTest) {
1469 FilePath temp_files[3];
1470 for (int i = 0; i < 3; i++) {
1471 ASSERT_TRUE(file_util::CreateTemporaryFile(&(temp_files[i])));
1472 EXPECT_TRUE(file_util::PathExists(temp_files[i]));
1473 EXPECT_FALSE(file_util::DirectoryExists(temp_files[i]));
1474 }
1475 for (int i = 0; i < 3; i++)
1476 EXPECT_FALSE(temp_files[i] == temp_files[(i+1)%3]);
1477 for (int i = 0; i < 3; i++)
1478 EXPECT_TRUE(file_util::Delete(temp_files[i], false));
1479 }
1480
TEST_F(FileUtilTest,CreateAndOpenTemporaryFileTest)1481 TEST_F(FileUtilTest, CreateAndOpenTemporaryFileTest) {
1482 FilePath names[3];
1483 FILE *fps[3];
1484 int i;
1485
1486 // Create; make sure they are open and exist.
1487 for (i = 0; i < 3; ++i) {
1488 fps[i] = file_util::CreateAndOpenTemporaryFile(&(names[i]));
1489 ASSERT_TRUE(fps[i]);
1490 EXPECT_TRUE(file_util::PathExists(names[i]));
1491 }
1492
1493 // Make sure all names are unique.
1494 for (i = 0; i < 3; ++i) {
1495 EXPECT_FALSE(names[i] == names[(i+1)%3]);
1496 }
1497
1498 // Close and delete.
1499 for (i = 0; i < 3; ++i) {
1500 EXPECT_TRUE(file_util::CloseFile(fps[i]));
1501 EXPECT_TRUE(file_util::Delete(names[i], false));
1502 }
1503 }
1504
TEST_F(FileUtilTest,CreateNewTempDirectoryTest)1505 TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
1506 FilePath temp_dir;
1507 ASSERT_TRUE(file_util::CreateNewTempDirectory(FilePath::StringType(),
1508 &temp_dir));
1509 EXPECT_TRUE(file_util::PathExists(temp_dir));
1510 EXPECT_TRUE(file_util::Delete(temp_dir, false));
1511 }
1512
TEST_F(FileUtilTest,CreateNewTemporaryDirInDirTest)1513 TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) {
1514 FilePath new_dir;
1515 ASSERT_TRUE(file_util::CreateTemporaryDirInDir(
1516 temp_dir_.path(),
1517 FILE_PATH_LITERAL("CreateNewTemporaryDirInDirTest"),
1518 &new_dir));
1519 EXPECT_TRUE(file_util::PathExists(new_dir));
1520 EXPECT_TRUE(temp_dir_.path().IsParent(new_dir));
1521 EXPECT_TRUE(file_util::Delete(new_dir, false));
1522 }
1523
TEST_F(FileUtilTest,GetShmemTempDirTest)1524 TEST_F(FileUtilTest, GetShmemTempDirTest) {
1525 FilePath dir;
1526 EXPECT_TRUE(file_util::GetShmemTempDir(&dir));
1527 EXPECT_TRUE(file_util::DirectoryExists(dir));
1528 }
1529
TEST_F(FileUtilTest,CreateDirectoryTest)1530 TEST_F(FileUtilTest, CreateDirectoryTest) {
1531 FilePath test_root =
1532 temp_dir_.path().Append(FILE_PATH_LITERAL("create_directory_test"));
1533 #if defined(OS_WIN)
1534 FilePath test_path =
1535 test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
1536 #elif defined(OS_POSIX)
1537 FilePath test_path =
1538 test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
1539 #endif
1540
1541 EXPECT_FALSE(file_util::PathExists(test_path));
1542 EXPECT_TRUE(file_util::CreateDirectory(test_path));
1543 EXPECT_TRUE(file_util::PathExists(test_path));
1544 // CreateDirectory returns true if the DirectoryExists returns true.
1545 EXPECT_TRUE(file_util::CreateDirectory(test_path));
1546
1547 // Doesn't work to create it on top of a non-dir
1548 test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
1549 EXPECT_FALSE(file_util::PathExists(test_path));
1550 CreateTextFile(test_path, L"test file");
1551 EXPECT_TRUE(file_util::PathExists(test_path));
1552 EXPECT_FALSE(file_util::CreateDirectory(test_path));
1553
1554 EXPECT_TRUE(file_util::Delete(test_root, true));
1555 EXPECT_FALSE(file_util::PathExists(test_root));
1556 EXPECT_FALSE(file_util::PathExists(test_path));
1557
1558 // Verify assumptions made by the Windows implementation:
1559 // 1. The current directory always exists.
1560 // 2. The root directory always exists.
1561 ASSERT_TRUE(file_util::DirectoryExists(
1562 FilePath(FilePath::kCurrentDirectory)));
1563 FilePath top_level = test_root;
1564 while (top_level != top_level.DirName()) {
1565 top_level = top_level.DirName();
1566 }
1567 ASSERT_TRUE(file_util::DirectoryExists(top_level));
1568
1569 // Given these assumptions hold, it should be safe to
1570 // test that "creating" these directories succeeds.
1571 EXPECT_TRUE(file_util::CreateDirectory(
1572 FilePath(FilePath::kCurrentDirectory)));
1573 EXPECT_TRUE(file_util::CreateDirectory(top_level));
1574
1575 #if defined(OS_WIN)
1576 FilePath invalid_drive(FILE_PATH_LITERAL("o:\\"));
1577 FilePath invalid_path =
1578 invalid_drive.Append(FILE_PATH_LITERAL("some\\inaccessible\\dir"));
1579 if (!file_util::PathExists(invalid_drive)) {
1580 EXPECT_FALSE(file_util::CreateDirectory(invalid_path));
1581 }
1582 #endif
1583 }
1584
TEST_F(FileUtilTest,DetectDirectoryTest)1585 TEST_F(FileUtilTest, DetectDirectoryTest) {
1586 // Check a directory
1587 FilePath test_root =
1588 temp_dir_.path().Append(FILE_PATH_LITERAL("detect_directory_test"));
1589 EXPECT_FALSE(file_util::PathExists(test_root));
1590 EXPECT_TRUE(file_util::CreateDirectory(test_root));
1591 EXPECT_TRUE(file_util::PathExists(test_root));
1592 EXPECT_TRUE(file_util::DirectoryExists(test_root));
1593
1594 // Check a file
1595 FilePath test_path =
1596 test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
1597 EXPECT_FALSE(file_util::PathExists(test_path));
1598 CreateTextFile(test_path, L"test file");
1599 EXPECT_TRUE(file_util::PathExists(test_path));
1600 EXPECT_FALSE(file_util::DirectoryExists(test_path));
1601 EXPECT_TRUE(file_util::Delete(test_path, false));
1602
1603 EXPECT_TRUE(file_util::Delete(test_root, true));
1604 }
1605
TEST_F(FileUtilTest,FileEnumeratorTest)1606 TEST_F(FileUtilTest, FileEnumeratorTest) {
1607 // Test an empty directory.
1608 file_util::FileEnumerator f0(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1609 EXPECT_EQ(f0.Next().value(), FILE_PATH_LITERAL(""));
1610 EXPECT_EQ(f0.Next().value(), FILE_PATH_LITERAL(""));
1611
1612 // Test an empty directory, non-recursively, including "..".
1613 file_util::FileEnumerator f0_dotdot(temp_dir_.path(), false,
1614 static_cast<file_util::FileEnumerator::FILE_TYPE>(
1615 FILES_AND_DIRECTORIES | file_util::FileEnumerator::INCLUDE_DOT_DOT));
1616 EXPECT_EQ(temp_dir_.path().Append(FILE_PATH_LITERAL("..")).value(),
1617 f0_dotdot.Next().value());
1618 EXPECT_EQ(FILE_PATH_LITERAL(""),
1619 f0_dotdot.Next().value());
1620
1621 // create the directories
1622 FilePath dir1 = temp_dir_.path().Append(FILE_PATH_LITERAL("dir1"));
1623 EXPECT_TRUE(file_util::CreateDirectory(dir1));
1624 FilePath dir2 = temp_dir_.path().Append(FILE_PATH_LITERAL("dir2"));
1625 EXPECT_TRUE(file_util::CreateDirectory(dir2));
1626 FilePath dir2inner = dir2.Append(FILE_PATH_LITERAL("inner"));
1627 EXPECT_TRUE(file_util::CreateDirectory(dir2inner));
1628
1629 // create the files
1630 FilePath dir2file = dir2.Append(FILE_PATH_LITERAL("dir2file.txt"));
1631 CreateTextFile(dir2file, L"");
1632 FilePath dir2innerfile = dir2inner.Append(FILE_PATH_LITERAL("innerfile.txt"));
1633 CreateTextFile(dir2innerfile, L"");
1634 FilePath file1 = temp_dir_.path().Append(FILE_PATH_LITERAL("file1.txt"));
1635 CreateTextFile(file1, L"");
1636 FilePath file2_rel =
1637 dir2.Append(FilePath::kParentDirectory)
1638 .Append(FILE_PATH_LITERAL("file2.txt"));
1639 CreateTextFile(file2_rel, L"");
1640 FilePath file2_abs = temp_dir_.path().Append(FILE_PATH_LITERAL("file2.txt"));
1641
1642 // Only enumerate files.
1643 file_util::FileEnumerator f1(temp_dir_.path(), true,
1644 file_util::FileEnumerator::FILES);
1645 FindResultCollector c1(f1);
1646 EXPECT_TRUE(c1.HasFile(file1));
1647 EXPECT_TRUE(c1.HasFile(file2_abs));
1648 EXPECT_TRUE(c1.HasFile(dir2file));
1649 EXPECT_TRUE(c1.HasFile(dir2innerfile));
1650 EXPECT_EQ(c1.size(), 4);
1651
1652 // Only enumerate directories.
1653 file_util::FileEnumerator f2(temp_dir_.path(), true,
1654 file_util::FileEnumerator::DIRECTORIES);
1655 FindResultCollector c2(f2);
1656 EXPECT_TRUE(c2.HasFile(dir1));
1657 EXPECT_TRUE(c2.HasFile(dir2));
1658 EXPECT_TRUE(c2.HasFile(dir2inner));
1659 EXPECT_EQ(c2.size(), 3);
1660
1661 // Only enumerate directories non-recursively.
1662 file_util::FileEnumerator f2_non_recursive(
1663 temp_dir_.path(), false, file_util::FileEnumerator::DIRECTORIES);
1664 FindResultCollector c2_non_recursive(f2_non_recursive);
1665 EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
1666 EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
1667 EXPECT_EQ(c2_non_recursive.size(), 2);
1668
1669 // Only enumerate directories, non-recursively, including "..".
1670 file_util::FileEnumerator f2_dotdot(
1671 temp_dir_.path(), false,
1672 static_cast<file_util::FileEnumerator::FILE_TYPE>(
1673 file_util::FileEnumerator::DIRECTORIES |
1674 file_util::FileEnumerator::INCLUDE_DOT_DOT));
1675 FindResultCollector c2_dotdot(f2_dotdot);
1676 EXPECT_TRUE(c2_dotdot.HasFile(dir1));
1677 EXPECT_TRUE(c2_dotdot.HasFile(dir2));
1678 EXPECT_TRUE(c2_dotdot.HasFile(
1679 temp_dir_.path().Append(FILE_PATH_LITERAL(".."))));
1680 EXPECT_EQ(c2_dotdot.size(), 3);
1681
1682 // Enumerate files and directories.
1683 file_util::FileEnumerator f3(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1684 FindResultCollector c3(f3);
1685 EXPECT_TRUE(c3.HasFile(dir1));
1686 EXPECT_TRUE(c3.HasFile(dir2));
1687 EXPECT_TRUE(c3.HasFile(file1));
1688 EXPECT_TRUE(c3.HasFile(file2_abs));
1689 EXPECT_TRUE(c3.HasFile(dir2file));
1690 EXPECT_TRUE(c3.HasFile(dir2inner));
1691 EXPECT_TRUE(c3.HasFile(dir2innerfile));
1692 EXPECT_EQ(c3.size(), 7);
1693
1694 // Non-recursive operation.
1695 file_util::FileEnumerator f4(temp_dir_.path(), false, FILES_AND_DIRECTORIES);
1696 FindResultCollector c4(f4);
1697 EXPECT_TRUE(c4.HasFile(dir2));
1698 EXPECT_TRUE(c4.HasFile(dir2));
1699 EXPECT_TRUE(c4.HasFile(file1));
1700 EXPECT_TRUE(c4.HasFile(file2_abs));
1701 EXPECT_EQ(c4.size(), 4);
1702
1703 // Enumerate with a pattern.
1704 file_util::FileEnumerator f5(temp_dir_.path(), true, FILES_AND_DIRECTORIES,
1705 FILE_PATH_LITERAL("dir*"));
1706 FindResultCollector c5(f5);
1707 EXPECT_TRUE(c5.HasFile(dir1));
1708 EXPECT_TRUE(c5.HasFile(dir2));
1709 EXPECT_TRUE(c5.HasFile(dir2file));
1710 EXPECT_TRUE(c5.HasFile(dir2inner));
1711 EXPECT_TRUE(c5.HasFile(dir2innerfile));
1712 EXPECT_EQ(c5.size(), 5);
1713
1714 // Make sure the destructor closes the find handle while in the middle of a
1715 // query to allow TearDown to delete the directory.
1716 file_util::FileEnumerator f6(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1717 EXPECT_FALSE(f6.Next().value().empty()); // Should have found something
1718 // (we don't care what).
1719 }
1720
TEST_F(FileUtilTest,Contains)1721 TEST_F(FileUtilTest, Contains) {
1722 FilePath data_dir =
1723 temp_dir_.path().Append(FILE_PATH_LITERAL("FilePathTest"));
1724
1725 // Create a fresh, empty copy of this directory.
1726 if (file_util::PathExists(data_dir)) {
1727 ASSERT_TRUE(file_util::Delete(data_dir, true));
1728 }
1729 ASSERT_TRUE(file_util::CreateDirectory(data_dir));
1730
1731 FilePath foo(data_dir.Append(FILE_PATH_LITERAL("foo")));
1732 FilePath bar(foo.Append(FILE_PATH_LITERAL("bar.txt")));
1733 FilePath baz(data_dir.Append(FILE_PATH_LITERAL("baz.txt")));
1734 FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
1735
1736 // Annoyingly, the directories must actually exist in order for realpath(),
1737 // which Contains() relies on in posix, to work.
1738 ASSERT_TRUE(file_util::CreateDirectory(foo));
1739 std::string data("hello");
1740 ASSERT_TRUE(file_util::WriteFile(bar, data.c_str(), data.length()));
1741 ASSERT_TRUE(file_util::WriteFile(baz, data.c_str(), data.length()));
1742 ASSERT_TRUE(file_util::WriteFile(foobar, data.c_str(), data.length()));
1743
1744 EXPECT_TRUE(file_util::ContainsPath(foo, bar));
1745 EXPECT_FALSE(file_util::ContainsPath(foo, baz));
1746 EXPECT_FALSE(file_util::ContainsPath(foo, foobar));
1747 EXPECT_FALSE(file_util::ContainsPath(foo, foo));
1748
1749 // Platform-specific concerns.
1750 FilePath foo_caps(data_dir.Append(FILE_PATH_LITERAL("FOO")));
1751 #if defined(OS_WIN)
1752 EXPECT_TRUE(file_util::ContainsPath(foo,
1753 foo_caps.Append(FILE_PATH_LITERAL("bar.txt"))));
1754 EXPECT_TRUE(file_util::ContainsPath(foo,
1755 FilePath(foo.value() + FILE_PATH_LITERAL("/bar.txt"))));
1756 #elif defined(OS_MACOSX)
1757 // We can't really do this test on OS X since the case-sensitivity of the
1758 // filesystem is configurable.
1759 #elif defined(OS_POSIX)
1760 EXPECT_FALSE(file_util::ContainsPath(foo,
1761 foo_caps.Append(FILE_PATH_LITERAL("bar.txt"))));
1762 #endif
1763 }
1764
TEST_F(FileUtilTest,TouchFile)1765 TEST_F(FileUtilTest, TouchFile) {
1766 FilePath data_dir =
1767 temp_dir_.path().Append(FILE_PATH_LITERAL("FilePathTest"));
1768
1769 // Create a fresh, empty copy of this directory.
1770 if (file_util::PathExists(data_dir)) {
1771 ASSERT_TRUE(file_util::Delete(data_dir, true));
1772 }
1773 ASSERT_TRUE(file_util::CreateDirectory(data_dir));
1774
1775 FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
1776 std::string data("hello");
1777 ASSERT_TRUE(file_util::WriteFile(foobar, data.c_str(), data.length()));
1778
1779 base::Time access_time;
1780 // This timestamp is divisible by one day (in local timezone),
1781 // to make it work on FAT too.
1782 ASSERT_TRUE(base::Time::FromString(L"Wed, 16 Nov 1994, 00:00:00",
1783 &access_time));
1784
1785 base::Time modification_time;
1786 // Note that this timestamp is divisible by two (seconds) - FAT stores
1787 // modification times with 2s resolution.
1788 ASSERT_TRUE(base::Time::FromString(L"Tue, 15 Nov 1994, 12:45:26 GMT",
1789 &modification_time));
1790
1791 ASSERT_TRUE(file_util::TouchFile(foobar, access_time, modification_time));
1792 base::PlatformFileInfo file_info;
1793 ASSERT_TRUE(file_util::GetFileInfo(foobar, &file_info));
1794 EXPECT_EQ(file_info.last_accessed.ToInternalValue(),
1795 access_time.ToInternalValue());
1796 EXPECT_EQ(file_info.last_modified.ToInternalValue(),
1797 modification_time.ToInternalValue());
1798 }
1799
TEST_F(FileUtilTest,IsDirectoryEmpty)1800 TEST_F(FileUtilTest, IsDirectoryEmpty) {
1801 FilePath empty_dir = temp_dir_.path().Append(FILE_PATH_LITERAL("EmptyDir"));
1802
1803 ASSERT_FALSE(file_util::PathExists(empty_dir));
1804
1805 ASSERT_TRUE(file_util::CreateDirectory(empty_dir));
1806
1807 EXPECT_TRUE(file_util::IsDirectoryEmpty(empty_dir));
1808
1809 FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt")));
1810 std::string bar("baz");
1811 ASSERT_TRUE(file_util::WriteFile(foo, bar.c_str(), bar.length()));
1812
1813 EXPECT_FALSE(file_util::IsDirectoryEmpty(empty_dir));
1814 }
1815
1816 } // namespace
1817