file_util_unittest.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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
36namespace {
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)
41typedef 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.
69bool 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.
101bool 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
113const wchar_t bogus_content[] = L"I'm cannon fodder.";
114
115const 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
122class FileUtilTest : public PlatformTest {
123 protected:
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.
134class FindResultCollector {
135 public:
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.
150  bool HasFile(const FilePath& file) const {
151    return files_.find(file.value()) != files_.end();
152  }
153
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.
163void 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.
173std::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)
184uint64 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
192const 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.
218TEST_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
232static 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
258static 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.
286TEST_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
296static 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
322TEST_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
354TEST_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
389TEST_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
422TEST_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
566TEST_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.
604TEST_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
645TEST_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
655TEST_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
679TEST_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
705TEST_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.
727TEST_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.
757TEST_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
786TEST_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
805TEST_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
826TEST_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
843TEST_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
873TEST_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
908TEST_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
958TEST_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
1013TEST_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
1060TEST_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
1109TEST_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
1127TEST_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
1147TEST_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
1168TEST_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)
1207TEST_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.
1242typedef PlatformTest ReadOnlyFileUtilTest;
1243
1244TEST_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
1293TEST_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)
1345TEST_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
1388TEST_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
1409TEST_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
1439TEST_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
1468TEST_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
1481TEST_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
1505TEST_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
1513TEST_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
1524TEST_F(FileUtilTest, GetShmemTempDirTest) {
1525  FilePath dir;
1526  EXPECT_TRUE(file_util::GetShmemTempDir(&dir));
1527  EXPECT_TRUE(file_util::DirectoryExists(dir));
1528}
1529
1530TEST_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
1585TEST_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
1606TEST_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
1721TEST_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
1765TEST_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
1800TEST_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