1// Copyright (c) 2012 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 <shellapi.h>
10#include <shlobj.h>
11#include <tchar.h>
12#include <winioctl.h>
13#endif
14
15#if defined(OS_POSIX)
16#include <errno.h>
17#include <fcntl.h>
18#include <unistd.h>
19#endif
20
21#include <algorithm>
22#include <fstream>
23#include <set>
24#include <vector>
25
26#include "base/base_paths.h"
27#include "base/files/file_enumerator.h"
28#include "base/files/file_path.h"
29#include "base/files/file_util.h"
30#include "base/files/scoped_file.h"
31#include "base/files/scoped_temp_dir.h"
32#include "base/path_service.h"
33#include "base/strings/utf_string_conversions.h"
34#include "base/test/test_file_util.h"
35#include "base/threading/platform_thread.h"
36#include "testing/gtest/include/gtest/gtest.h"
37#include "testing/platform_test.h"
38
39#if defined(OS_WIN)
40#include "base/win/scoped_handle.h"
41#include "base/win/windows_version.h"
42#endif
43
44#if defined(OS_ANDROID)
45#include "base/android/content_uri_utils.h"
46#endif
47
48// This macro helps avoid wrapped lines in the test structs.
49#define FPL(x) FILE_PATH_LITERAL(x)
50
51namespace base {
52
53namespace {
54
55// To test that NormalizeFilePath() deals with NTFS reparse points correctly,
56// we need functions to create and delete reparse points.
57#if defined(OS_WIN)
58typedef struct _REPARSE_DATA_BUFFER {
59  ULONG  ReparseTag;
60  USHORT  ReparseDataLength;
61  USHORT  Reserved;
62  union {
63    struct {
64      USHORT SubstituteNameOffset;
65      USHORT SubstituteNameLength;
66      USHORT PrintNameOffset;
67      USHORT PrintNameLength;
68      ULONG Flags;
69      WCHAR PathBuffer[1];
70    } SymbolicLinkReparseBuffer;
71    struct {
72      USHORT SubstituteNameOffset;
73      USHORT SubstituteNameLength;
74      USHORT PrintNameOffset;
75      USHORT PrintNameLength;
76      WCHAR PathBuffer[1];
77    } MountPointReparseBuffer;
78    struct {
79      UCHAR DataBuffer[1];
80    } GenericReparseBuffer;
81  };
82} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
83
84// Sets a reparse point. |source| will now point to |target|. Returns true if
85// the call succeeds, false otherwise.
86bool SetReparsePoint(HANDLE source, const FilePath& target_path) {
87  std::wstring kPathPrefix = L"\\??\\";
88  std::wstring target_str;
89  // The juction will not work if the target path does not start with \??\ .
90  if (kPathPrefix != target_path.value().substr(0, kPathPrefix.size()))
91    target_str += kPathPrefix;
92  target_str += target_path.value();
93  const wchar_t* target = target_str.c_str();
94  USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]);
95  char buffer[2000] = {0};
96  DWORD returned;
97
98  REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
99
100  data->ReparseTag = 0xa0000003;
101  memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
102
103  data->MountPointReparseBuffer.SubstituteNameLength = size_target;
104  data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
105  data->ReparseDataLength = size_target + 4 + 8;
106
107  int data_size = data->ReparseDataLength + 8;
108
109  if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size,
110                       NULL, 0, &returned, NULL)) {
111    return false;
112  }
113  return true;
114}
115
116// Delete the reparse point referenced by |source|. Returns true if the call
117// succeeds, false otherwise.
118bool DeleteReparsePoint(HANDLE source) {
119  DWORD returned;
120  REPARSE_DATA_BUFFER data = {0};
121  data.ReparseTag = 0xa0000003;
122  if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
123                       &returned, NULL)) {
124    return false;
125  }
126  return true;
127}
128
129// Manages a reparse point for a test.
130class ReparsePoint {
131 public:
132  // Creates a reparse point from |source| (an empty directory) to |target|.
133  ReparsePoint(const FilePath& source, const FilePath& target) {
134    dir_.Set(
135      ::CreateFile(source.value().c_str(),
136                   FILE_ALL_ACCESS,
137                   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
138                   NULL,
139                   OPEN_EXISTING,
140                   FILE_FLAG_BACKUP_SEMANTICS,  // Needed to open a directory.
141                   NULL));
142    created_ = dir_.IsValid() && SetReparsePoint(dir_.Get(), target);
143  }
144
145  ~ReparsePoint() {
146    if (created_)
147      DeleteReparsePoint(dir_.Get());
148  }
149
150  bool IsValid() { return created_; }
151
152 private:
153  win::ScopedHandle dir_;
154  bool created_;
155  DISALLOW_COPY_AND_ASSIGN(ReparsePoint);
156};
157
158#endif
159
160#if defined(OS_POSIX)
161// Provide a simple way to change the permissions bits on |path| in tests.
162// ASSERT failures will return, but not stop the test.  Caller should wrap
163// calls to this function in ASSERT_NO_FATAL_FAILURE().
164void ChangePosixFilePermissions(const FilePath& path,
165                                int mode_bits_to_set,
166                                int mode_bits_to_clear) {
167  ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
168      << "Can't set and clear the same bits.";
169
170  int mode = 0;
171  ASSERT_TRUE(GetPosixFilePermissions(path, &mode));
172  mode |= mode_bits_to_set;
173  mode &= ~mode_bits_to_clear;
174  ASSERT_TRUE(SetPosixFilePermissions(path, mode));
175}
176#endif  // defined(OS_POSIX)
177
178const wchar_t bogus_content[] = L"I'm cannon fodder.";
179
180const int FILES_AND_DIRECTORIES =
181    FileEnumerator::FILES | FileEnumerator::DIRECTORIES;
182
183// file_util winds up using autoreleased objects on the Mac, so this needs
184// to be a PlatformTest
185class FileUtilTest : public PlatformTest {
186 protected:
187  virtual void SetUp() OVERRIDE {
188    PlatformTest::SetUp();
189    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
190  }
191
192  ScopedTempDir temp_dir_;
193};
194
195// Collects all the results from the given file enumerator, and provides an
196// interface to query whether a given file is present.
197class FindResultCollector {
198 public:
199  explicit FindResultCollector(FileEnumerator& enumerator) {
200    FilePath cur_file;
201    while (!(cur_file = enumerator.Next()).value().empty()) {
202      FilePath::StringType path = cur_file.value();
203      // The file should not be returned twice.
204      EXPECT_TRUE(files_.end() == files_.find(path))
205          << "Same file returned twice";
206
207      // Save for later.
208      files_.insert(path);
209    }
210  }
211
212  // Returns true if the enumerator found the file.
213  bool HasFile(const FilePath& file) const {
214    return files_.find(file.value()) != files_.end();
215  }
216
217  int size() {
218    return static_cast<int>(files_.size());
219  }
220
221 private:
222  std::set<FilePath::StringType> files_;
223};
224
225// Simple function to dump some text into a new file.
226void CreateTextFile(const FilePath& filename,
227                    const std::wstring& contents) {
228  std::wofstream file;
229  file.open(filename.value().c_str());
230  ASSERT_TRUE(file.is_open());
231  file << contents;
232  file.close();
233}
234
235// Simple function to take out some text from a file.
236std::wstring ReadTextFile(const FilePath& filename) {
237  wchar_t contents[64];
238  std::wifstream file;
239  file.open(filename.value().c_str());
240  EXPECT_TRUE(file.is_open());
241  file.getline(contents, arraysize(contents));
242  file.close();
243  return std::wstring(contents);
244}
245
246#if defined(OS_WIN)
247uint64 FileTimeAsUint64(const FILETIME& ft) {
248  ULARGE_INTEGER u;
249  u.LowPart = ft.dwLowDateTime;
250  u.HighPart = ft.dwHighDateTime;
251  return u.QuadPart;
252}
253#endif
254
255TEST_F(FileUtilTest, FileAndDirectorySize) {
256  // Create three files of 20, 30 and 3 chars (utf8). ComputeDirectorySize
257  // should return 53 bytes.
258  FilePath file_01 = temp_dir_.path().Append(FPL("The file 01.txt"));
259  CreateTextFile(file_01, L"12345678901234567890");
260  int64 size_f1 = 0;
261  ASSERT_TRUE(GetFileSize(file_01, &size_f1));
262  EXPECT_EQ(20ll, size_f1);
263
264  FilePath subdir_path = temp_dir_.path().Append(FPL("Level2"));
265  CreateDirectory(subdir_path);
266
267  FilePath file_02 = subdir_path.Append(FPL("The file 02.txt"));
268  CreateTextFile(file_02, L"123456789012345678901234567890");
269  int64 size_f2 = 0;
270  ASSERT_TRUE(GetFileSize(file_02, &size_f2));
271  EXPECT_EQ(30ll, size_f2);
272
273  FilePath subsubdir_path = subdir_path.Append(FPL("Level3"));
274  CreateDirectory(subsubdir_path);
275
276  FilePath file_03 = subsubdir_path.Append(FPL("The file 03.txt"));
277  CreateTextFile(file_03, L"123");
278
279  int64 computed_size = ComputeDirectorySize(temp_dir_.path());
280  EXPECT_EQ(size_f1 + size_f2 + 3, computed_size);
281}
282
283TEST_F(FileUtilTest, NormalizeFilePathBasic) {
284  // Create a directory under the test dir.  Because we create it,
285  // we know it is not a link.
286  FilePath file_a_path = temp_dir_.path().Append(FPL("file_a"));
287  FilePath dir_path = temp_dir_.path().Append(FPL("dir"));
288  FilePath file_b_path = dir_path.Append(FPL("file_b"));
289  CreateDirectory(dir_path);
290
291  FilePath normalized_file_a_path, normalized_file_b_path;
292  ASSERT_FALSE(PathExists(file_a_path));
293  ASSERT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
294    << "NormalizeFilePath() should fail on nonexistent paths.";
295
296  CreateTextFile(file_a_path, bogus_content);
297  ASSERT_TRUE(PathExists(file_a_path));
298  ASSERT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
299
300  CreateTextFile(file_b_path, bogus_content);
301  ASSERT_TRUE(PathExists(file_b_path));
302  ASSERT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
303
304  // Beacuse this test created |dir_path|, we know it is not a link
305  // or junction.  So, the real path of the directory holding file a
306  // must be the parent of the path holding file b.
307  ASSERT_TRUE(normalized_file_a_path.DirName()
308      .IsParent(normalized_file_b_path.DirName()));
309}
310
311#if defined(OS_WIN)
312
313TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) {
314  // Build the following directory structure:
315  //
316  // temp_dir
317  // |-> base_a
318  // |   |-> sub_a
319  // |       |-> file.txt
320  // |       |-> long_name___... (Very long name.)
321  // |           |-> sub_long
322  // |              |-> deep.txt
323  // |-> base_b
324  //     |-> to_sub_a (reparse point to temp_dir\base_a\sub_a)
325  //     |-> to_base_b (reparse point to temp_dir\base_b)
326  //     |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
327
328  FilePath base_a = temp_dir_.path().Append(FPL("base_a"));
329  ASSERT_TRUE(CreateDirectory(base_a));
330
331  FilePath sub_a = base_a.Append(FPL("sub_a"));
332  ASSERT_TRUE(CreateDirectory(sub_a));
333
334  FilePath file_txt = sub_a.Append(FPL("file.txt"));
335  CreateTextFile(file_txt, bogus_content);
336
337  // Want a directory whose name is long enough to make the path to the file
338  // inside just under MAX_PATH chars.  This will be used to test that when
339  // a junction expands to a path over MAX_PATH chars in length,
340  // NormalizeFilePath() fails without crashing.
341  FilePath sub_long_rel(FPL("sub_long"));
342  FilePath deep_txt(FPL("deep.txt"));
343
344  int target_length = MAX_PATH;
345  target_length -= (sub_a.value().length() + 1);  // +1 for the sepperator '\'.
346  target_length -= (sub_long_rel.Append(deep_txt).value().length() + 1);
347  // Without making the path a bit shorter, CreateDirectory() fails.
348  // the resulting path is still long enough to hit the failing case in
349  // NormalizePath().
350  const int kCreateDirLimit = 4;
351  target_length -= kCreateDirLimit;
352  FilePath::StringType long_name_str = FPL("long_name_");
353  long_name_str.resize(target_length, '_');
354
355  FilePath long_name = sub_a.Append(FilePath(long_name_str));
356  FilePath deep_file = long_name.Append(sub_long_rel).Append(deep_txt);
357  ASSERT_EQ(MAX_PATH - kCreateDirLimit, deep_file.value().length());
358
359  FilePath sub_long = deep_file.DirName();
360  ASSERT_TRUE(CreateDirectory(sub_long));
361  CreateTextFile(deep_file, bogus_content);
362
363  FilePath base_b = temp_dir_.path().Append(FPL("base_b"));
364  ASSERT_TRUE(CreateDirectory(base_b));
365
366  FilePath to_sub_a = base_b.Append(FPL("to_sub_a"));
367  ASSERT_TRUE(CreateDirectory(to_sub_a));
368  FilePath normalized_path;
369  {
370    ReparsePoint reparse_to_sub_a(to_sub_a, sub_a);
371    ASSERT_TRUE(reparse_to_sub_a.IsValid());
372
373    FilePath to_base_b = base_b.Append(FPL("to_base_b"));
374    ASSERT_TRUE(CreateDirectory(to_base_b));
375    ReparsePoint reparse_to_base_b(to_base_b, base_b);
376    ASSERT_TRUE(reparse_to_base_b.IsValid());
377
378    FilePath to_sub_long = base_b.Append(FPL("to_sub_long"));
379    ASSERT_TRUE(CreateDirectory(to_sub_long));
380    ReparsePoint reparse_to_sub_long(to_sub_long, sub_long);
381    ASSERT_TRUE(reparse_to_sub_long.IsValid());
382
383    // Normalize a junction free path: base_a\sub_a\file.txt .
384    ASSERT_TRUE(NormalizeFilePath(file_txt, &normalized_path));
385    ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
386
387    // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude
388    // the junction to_sub_a.
389    ASSERT_TRUE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
390                                             &normalized_path));
391    ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
392
393    // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be
394    // normalized to exclude junctions to_base_b and to_sub_a .
395    ASSERT_TRUE(NormalizeFilePath(base_b.Append(FPL("to_base_b"))
396                                                   .Append(FPL("to_base_b"))
397                                                   .Append(FPL("to_sub_a"))
398                                                   .Append(FPL("file.txt")),
399                                             &normalized_path));
400    ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
401
402    // A long enough path will cause NormalizeFilePath() to fail.  Make a long
403    // path using to_base_b many times, and check that paths long enough to fail
404    // do not cause a crash.
405    FilePath long_path = base_b;
406    const int kLengthLimit = MAX_PATH + 200;
407    while (long_path.value().length() <= kLengthLimit) {
408      long_path = long_path.Append(FPL("to_base_b"));
409    }
410    long_path = long_path.Append(FPL("to_sub_a"))
411                         .Append(FPL("file.txt"));
412
413    ASSERT_FALSE(NormalizeFilePath(long_path, &normalized_path));
414
415    // Normalizing the junction to deep.txt should fail, because the expanded
416    // path to deep.txt is longer than MAX_PATH.
417    ASSERT_FALSE(NormalizeFilePath(to_sub_long.Append(deep_txt),
418                                              &normalized_path));
419
420    // Delete the reparse points, and see that NormalizeFilePath() fails
421    // to traverse them.
422  }
423
424  ASSERT_FALSE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
425                                            &normalized_path));
426}
427
428TEST_F(FileUtilTest, DevicePathToDriveLetter) {
429  // Get a drive letter.
430  std::wstring real_drive_letter = temp_dir_.path().value().substr(0, 2);
431  if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
432    LOG(ERROR) << "Can't get a drive letter to test with.";
433    return;
434  }
435
436  // Get the NT style path to that drive.
437  wchar_t device_path[MAX_PATH] = {'\0'};
438  ASSERT_TRUE(
439      ::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH));
440  FilePath actual_device_path(device_path);
441  FilePath win32_path;
442
443  // Run DevicePathToDriveLetterPath() on the NT style path we got from
444  // QueryDosDevice().  Expect the drive letter we started with.
445  ASSERT_TRUE(DevicePathToDriveLetterPath(actual_device_path, &win32_path));
446  ASSERT_EQ(real_drive_letter, win32_path.value());
447
448  // Add some directories to the path.  Expect those extra path componenets
449  // to be preserved.
450  FilePath kRelativePath(FPL("dir1\\dir2\\file.txt"));
451  ASSERT_TRUE(DevicePathToDriveLetterPath(
452      actual_device_path.Append(kRelativePath),
453      &win32_path));
454  EXPECT_EQ(FilePath(real_drive_letter + L"\\").Append(kRelativePath).value(),
455            win32_path.value());
456
457  // Deform the real path so that it is invalid by removing the last four
458  // characters.  The way windows names devices that are hard disks
459  // (\Device\HardDiskVolume${NUMBER}) guarantees that the string is longer
460  // than three characters.  The only way the truncated string could be a
461  // real drive is if more than 10^3 disks are mounted:
462  // \Device\HardDiskVolume10000 would be truncated to \Device\HardDiskVolume1
463  // Check that DevicePathToDriveLetterPath fails.
464  int path_length = actual_device_path.value().length();
465  int new_length = path_length - 4;
466  ASSERT_LT(0, new_length);
467  FilePath prefix_of_real_device_path(
468      actual_device_path.value().substr(0, new_length));
469  ASSERT_FALSE(DevicePathToDriveLetterPath(prefix_of_real_device_path,
470                                           &win32_path));
471
472  ASSERT_FALSE(DevicePathToDriveLetterPath(
473      prefix_of_real_device_path.Append(kRelativePath),
474      &win32_path));
475
476  // Deform the real path so that it is invalid by adding some characters. For
477  // example, if C: maps to \Device\HardDiskVolume8, then we simulate a
478  // request for the drive letter whose native path is
479  // \Device\HardDiskVolume812345 .  We assume such a device does not exist,
480  // because drives are numbered in order and mounting 112345 hard disks will
481  // never happen.
482  const FilePath::StringType kExtraChars = FPL("12345");
483
484  FilePath real_device_path_plus_numbers(
485      actual_device_path.value() + kExtraChars);
486
487  ASSERT_FALSE(DevicePathToDriveLetterPath(
488      real_device_path_plus_numbers,
489      &win32_path));
490
491  ASSERT_FALSE(DevicePathToDriveLetterPath(
492      real_device_path_plus_numbers.Append(kRelativePath),
493      &win32_path));
494}
495
496TEST_F(FileUtilTest, CreateTemporaryFileInDirLongPathTest) {
497  // Test that CreateTemporaryFileInDir() creates a path and returns a long path
498  // if it is available. This test requires that:
499  // - the filesystem at |temp_dir_| supports long filenames.
500  // - the account has FILE_LIST_DIRECTORY permission for all ancestor
501  //   directories of |temp_dir_|.
502  const FilePath::CharType kLongDirName[] = FPL("A long path");
503  const FilePath::CharType kTestSubDirName[] = FPL("test");
504  FilePath long_test_dir = temp_dir_.path().Append(kLongDirName);
505  ASSERT_TRUE(CreateDirectory(long_test_dir));
506
507  // kLongDirName is not a 8.3 component. So GetShortName() should give us a
508  // different short name.
509  WCHAR path_buffer[MAX_PATH];
510  DWORD path_buffer_length = GetShortPathName(long_test_dir.value().c_str(),
511                                              path_buffer, MAX_PATH);
512  ASSERT_LT(path_buffer_length, DWORD(MAX_PATH));
513  ASSERT_NE(DWORD(0), path_buffer_length);
514  FilePath short_test_dir(path_buffer);
515  ASSERT_STRNE(kLongDirName, short_test_dir.BaseName().value().c_str());
516
517  FilePath temp_file;
518  ASSERT_TRUE(CreateTemporaryFileInDir(short_test_dir, &temp_file));
519  EXPECT_STREQ(kLongDirName, temp_file.DirName().BaseName().value().c_str());
520  EXPECT_TRUE(PathExists(temp_file));
521
522  // Create a subdirectory of |long_test_dir| and make |long_test_dir|
523  // unreadable. We should still be able to create a temp file in the
524  // subdirectory, but we won't be able to determine the long path for it. This
525  // mimics the environment that some users run where their user profiles reside
526  // in a location where the don't have full access to the higher level
527  // directories. (Note that this assumption is true for NTFS, but not for some
528  // network file systems. E.g. AFS).
529  FilePath access_test_dir = long_test_dir.Append(kTestSubDirName);
530  ASSERT_TRUE(CreateDirectory(access_test_dir));
531  base::FilePermissionRestorer long_test_dir_restorer(long_test_dir);
532  ASSERT_TRUE(base::MakeFileUnreadable(long_test_dir));
533
534  // Use the short form of the directory to create a temporary filename.
535  ASSERT_TRUE(CreateTemporaryFileInDir(
536      short_test_dir.Append(kTestSubDirName), &temp_file));
537  EXPECT_TRUE(PathExists(temp_file));
538  EXPECT_TRUE(short_test_dir.IsParent(temp_file.DirName()));
539
540  // Check that the long path can't be determined for |temp_file|.
541  path_buffer_length = GetLongPathName(temp_file.value().c_str(),
542                                       path_buffer, MAX_PATH);
543  EXPECT_EQ(DWORD(0), path_buffer_length);
544}
545
546#endif  // defined(OS_WIN)
547
548#if defined(OS_POSIX)
549
550TEST_F(FileUtilTest, CreateAndReadSymlinks) {
551  FilePath link_from = temp_dir_.path().Append(FPL("from_file"));
552  FilePath link_to = temp_dir_.path().Append(FPL("to_file"));
553  CreateTextFile(link_to, bogus_content);
554
555  ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
556    << "Failed to create file symlink.";
557
558  // If we created the link properly, we should be able to read the contents
559  // through it.
560  std::wstring contents = ReadTextFile(link_from);
561  EXPECT_EQ(bogus_content, contents);
562
563  FilePath result;
564  ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
565  EXPECT_EQ(link_to.value(), result.value());
566
567  // Link to a directory.
568  link_from = temp_dir_.path().Append(FPL("from_dir"));
569  link_to = temp_dir_.path().Append(FPL("to_dir"));
570  ASSERT_TRUE(CreateDirectory(link_to));
571  ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
572    << "Failed to create directory symlink.";
573
574  // Test failures.
575  EXPECT_FALSE(CreateSymbolicLink(link_to, link_to));
576  EXPECT_FALSE(ReadSymbolicLink(link_to, &result));
577  FilePath missing = temp_dir_.path().Append(FPL("missing"));
578  EXPECT_FALSE(ReadSymbolicLink(missing, &result));
579}
580
581// The following test of NormalizeFilePath() require that we create a symlink.
582// This can not be done on Windows before Vista.  On Vista, creating a symlink
583// requires privilege "SeCreateSymbolicLinkPrivilege".
584// TODO(skerner): Investigate the possibility of giving base_unittests the
585// privileges required to create a symlink.
586TEST_F(FileUtilTest, NormalizeFilePathSymlinks) {
587  // Link one file to another.
588  FilePath link_from = temp_dir_.path().Append(FPL("from_file"));
589  FilePath link_to = temp_dir_.path().Append(FPL("to_file"));
590  CreateTextFile(link_to, bogus_content);
591
592  ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
593    << "Failed to create file symlink.";
594
595  // Check that NormalizeFilePath sees the link.
596  FilePath normalized_path;
597  ASSERT_TRUE(NormalizeFilePath(link_from, &normalized_path));
598  EXPECT_NE(link_from, link_to);
599  EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
600  EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
601
602  // Link to a directory.
603  link_from = temp_dir_.path().Append(FPL("from_dir"));
604  link_to = temp_dir_.path().Append(FPL("to_dir"));
605  ASSERT_TRUE(CreateDirectory(link_to));
606  ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
607    << "Failed to create directory symlink.";
608
609  EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path))
610    << "Links to directories should return false.";
611
612  // Test that a loop in the links causes NormalizeFilePath() to return false.
613  link_from = temp_dir_.path().Append(FPL("link_a"));
614  link_to = temp_dir_.path().Append(FPL("link_b"));
615  ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
616    << "Failed to create loop symlink a.";
617  ASSERT_TRUE(CreateSymbolicLink(link_from, link_to))
618    << "Failed to create loop symlink b.";
619
620  // Infinite loop!
621  EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path));
622}
623#endif  // defined(OS_POSIX)
624
625TEST_F(FileUtilTest, DeleteNonExistent) {
626  FilePath non_existent = temp_dir_.path().AppendASCII("bogus_file_dne.foobar");
627  ASSERT_FALSE(PathExists(non_existent));
628
629  EXPECT_TRUE(DeleteFile(non_existent, false));
630  ASSERT_FALSE(PathExists(non_existent));
631  EXPECT_TRUE(DeleteFile(non_existent, true));
632  ASSERT_FALSE(PathExists(non_existent));
633}
634
635TEST_F(FileUtilTest, DeleteNonExistentWithNonExistentParent) {
636  FilePath non_existent = temp_dir_.path().AppendASCII("bogus_topdir");
637  non_existent = non_existent.AppendASCII("bogus_subdir");
638  ASSERT_FALSE(PathExists(non_existent));
639
640  EXPECT_TRUE(DeleteFile(non_existent, false));
641  ASSERT_FALSE(PathExists(non_existent));
642  EXPECT_TRUE(DeleteFile(non_existent, true));
643  ASSERT_FALSE(PathExists(non_existent));
644}
645
646TEST_F(FileUtilTest, DeleteFile) {
647  // Create a file
648  FilePath file_name = temp_dir_.path().Append(FPL("Test DeleteFile 1.txt"));
649  CreateTextFile(file_name, bogus_content);
650  ASSERT_TRUE(PathExists(file_name));
651
652  // Make sure it's deleted
653  EXPECT_TRUE(DeleteFile(file_name, false));
654  EXPECT_FALSE(PathExists(file_name));
655
656  // Test recursive case, create a new file
657  file_name = temp_dir_.path().Append(FPL("Test DeleteFile 2.txt"));
658  CreateTextFile(file_name, bogus_content);
659  ASSERT_TRUE(PathExists(file_name));
660
661  // Make sure it's deleted
662  EXPECT_TRUE(DeleteFile(file_name, true));
663  EXPECT_FALSE(PathExists(file_name));
664}
665
666#if defined(OS_POSIX)
667TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) {
668  // Create a file.
669  FilePath file_name = temp_dir_.path().Append(FPL("Test DeleteFile 2.txt"));
670  CreateTextFile(file_name, bogus_content);
671  ASSERT_TRUE(PathExists(file_name));
672
673  // Create a symlink to the file.
674  FilePath file_link = temp_dir_.path().Append("file_link_2");
675  ASSERT_TRUE(CreateSymbolicLink(file_name, file_link))
676      << "Failed to create symlink.";
677
678  // Delete the symbolic link.
679  EXPECT_TRUE(DeleteFile(file_link, false));
680
681  // Make sure original file is not deleted.
682  EXPECT_FALSE(PathExists(file_link));
683  EXPECT_TRUE(PathExists(file_name));
684}
685
686TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) {
687  // Create a non-existent file path.
688  FilePath non_existent = temp_dir_.path().Append(FPL("Test DeleteFile 3.txt"));
689  EXPECT_FALSE(PathExists(non_existent));
690
691  // Create a symlink to the non-existent file.
692  FilePath file_link = temp_dir_.path().Append("file_link_3");
693  ASSERT_TRUE(CreateSymbolicLink(non_existent, file_link))
694      << "Failed to create symlink.";
695
696  // Make sure the symbolic link is exist.
697  EXPECT_TRUE(IsLink(file_link));
698  EXPECT_FALSE(PathExists(file_link));
699
700  // Delete the symbolic link.
701  EXPECT_TRUE(DeleteFile(file_link, false));
702
703  // Make sure the symbolic link is deleted.
704  EXPECT_FALSE(IsLink(file_link));
705}
706
707TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
708  // Create a file path.
709  FilePath file_name = temp_dir_.path().Append(FPL("Test Readable File.txt"));
710  EXPECT_FALSE(PathExists(file_name));
711
712  const std::string kData("hello");
713
714  int buffer_size = kData.length();
715  char* buffer = new char[buffer_size];
716
717  // Write file.
718  EXPECT_EQ(static_cast<int>(kData.length()),
719            WriteFile(file_name, kData.data(), kData.length()));
720  EXPECT_TRUE(PathExists(file_name));
721
722  // Make sure the file is readable.
723  int32 mode = 0;
724  EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
725  EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
726
727  // Get rid of the read permission.
728  EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
729  EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
730  EXPECT_FALSE(mode & FILE_PERMISSION_READ_BY_USER);
731  // Make sure the file can't be read.
732  EXPECT_EQ(-1, ReadFile(file_name, buffer, buffer_size));
733
734  // Give the read permission.
735  EXPECT_TRUE(SetPosixFilePermissions(file_name, FILE_PERMISSION_READ_BY_USER));
736  EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
737  EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
738  // Make sure the file can be read.
739  EXPECT_EQ(static_cast<int>(kData.length()),
740            ReadFile(file_name, buffer, buffer_size));
741
742  // Delete the file.
743  EXPECT_TRUE(DeleteFile(file_name, false));
744  EXPECT_FALSE(PathExists(file_name));
745
746  delete[] buffer;
747}
748
749TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) {
750  // Create a file path.
751  FilePath file_name = temp_dir_.path().Append(FPL("Test Readable File.txt"));
752  EXPECT_FALSE(PathExists(file_name));
753
754  const std::string kData("hello");
755
756  // Write file.
757  EXPECT_EQ(static_cast<int>(kData.length()),
758            WriteFile(file_name, kData.data(), kData.length()));
759  EXPECT_TRUE(PathExists(file_name));
760
761  // Make sure the file is writable.
762  int mode = 0;
763  EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
764  EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
765  EXPECT_TRUE(PathIsWritable(file_name));
766
767  // Get rid of the write permission.
768  EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
769  EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
770  EXPECT_FALSE(mode & FILE_PERMISSION_WRITE_BY_USER);
771  // Make sure the file can't be write.
772  EXPECT_EQ(-1, WriteFile(file_name, kData.data(), kData.length()));
773  EXPECT_FALSE(PathIsWritable(file_name));
774
775  // Give read permission.
776  EXPECT_TRUE(SetPosixFilePermissions(file_name,
777                                      FILE_PERMISSION_WRITE_BY_USER));
778  EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
779  EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
780  // Make sure the file can be write.
781  EXPECT_EQ(static_cast<int>(kData.length()),
782            WriteFile(file_name, kData.data(), kData.length()));
783  EXPECT_TRUE(PathIsWritable(file_name));
784
785  // Delete the file.
786  EXPECT_TRUE(DeleteFile(file_name, false));
787  EXPECT_FALSE(PathExists(file_name));
788}
789
790TEST_F(FileUtilTest, ChangeDirectoryPermissionsAndEnumerate) {
791  // Create a directory path.
792  FilePath subdir_path =
793      temp_dir_.path().Append(FPL("PermissionTest1"));
794  CreateDirectory(subdir_path);
795  ASSERT_TRUE(PathExists(subdir_path));
796
797  // Create a dummy file to enumerate.
798  FilePath file_name = subdir_path.Append(FPL("Test Readable File.txt"));
799  EXPECT_FALSE(PathExists(file_name));
800  const std::string kData("hello");
801  EXPECT_EQ(static_cast<int>(kData.length()),
802            WriteFile(file_name, kData.data(), kData.length()));
803  EXPECT_TRUE(PathExists(file_name));
804
805  // Make sure the directory has the all permissions.
806  int mode = 0;
807  EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
808  EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
809
810  // Get rid of the permissions from the directory.
811  EXPECT_TRUE(SetPosixFilePermissions(subdir_path, 0u));
812  EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
813  EXPECT_FALSE(mode & FILE_PERMISSION_USER_MASK);
814
815  // Make sure the file in the directory can't be enumerated.
816  FileEnumerator f1(subdir_path, true, FileEnumerator::FILES);
817  EXPECT_TRUE(PathExists(subdir_path));
818  FindResultCollector c1(f1);
819  EXPECT_EQ(0, c1.size());
820  EXPECT_FALSE(GetPosixFilePermissions(file_name, &mode));
821
822  // Give the permissions to the directory.
823  EXPECT_TRUE(SetPosixFilePermissions(subdir_path, FILE_PERMISSION_USER_MASK));
824  EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
825  EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
826
827  // Make sure the file in the directory can be enumerated.
828  FileEnumerator f2(subdir_path, true, FileEnumerator::FILES);
829  FindResultCollector c2(f2);
830  EXPECT_TRUE(c2.HasFile(file_name));
831  EXPECT_EQ(1, c2.size());
832
833  // Delete the file.
834  EXPECT_TRUE(DeleteFile(subdir_path, true));
835  EXPECT_FALSE(PathExists(subdir_path));
836}
837
838#endif  // defined(OS_POSIX)
839
840#if defined(OS_WIN)
841// Tests that the Delete function works for wild cards, especially
842// with the recursion flag.  Also coincidentally tests PathExists.
843// TODO(erikkay): see if anyone's actually using this feature of the API
844TEST_F(FileUtilTest, DeleteWildCard) {
845  // Create a file and a directory
846  FilePath file_name = temp_dir_.path().Append(FPL("Test DeleteWildCard.txt"));
847  CreateTextFile(file_name, bogus_content);
848  ASSERT_TRUE(PathExists(file_name));
849
850  FilePath subdir_path = temp_dir_.path().Append(FPL("DeleteWildCardDir"));
851  CreateDirectory(subdir_path);
852  ASSERT_TRUE(PathExists(subdir_path));
853
854  // Create the wildcard path
855  FilePath directory_contents = temp_dir_.path();
856  directory_contents = directory_contents.Append(FPL("*"));
857
858  // Delete non-recursively and check that only the file is deleted
859  EXPECT_TRUE(DeleteFile(directory_contents, false));
860  EXPECT_FALSE(PathExists(file_name));
861  EXPECT_TRUE(PathExists(subdir_path));
862
863  // Delete recursively and make sure all contents are deleted
864  EXPECT_TRUE(DeleteFile(directory_contents, true));
865  EXPECT_FALSE(PathExists(file_name));
866  EXPECT_FALSE(PathExists(subdir_path));
867}
868
869// TODO(erikkay): see if anyone's actually using this feature of the API
870TEST_F(FileUtilTest, DeleteNonExistantWildCard) {
871  // Create a file and a directory
872  FilePath subdir_path =
873      temp_dir_.path().Append(FPL("DeleteNonExistantWildCard"));
874  CreateDirectory(subdir_path);
875  ASSERT_TRUE(PathExists(subdir_path));
876
877  // Create the wildcard path
878  FilePath directory_contents = subdir_path;
879  directory_contents = directory_contents.Append(FPL("*"));
880
881  // Delete non-recursively and check nothing got deleted
882  EXPECT_TRUE(DeleteFile(directory_contents, false));
883  EXPECT_TRUE(PathExists(subdir_path));
884
885  // Delete recursively and check nothing got deleted
886  EXPECT_TRUE(DeleteFile(directory_contents, true));
887  EXPECT_TRUE(PathExists(subdir_path));
888}
889#endif
890
891// Tests non-recursive Delete() for a directory.
892TEST_F(FileUtilTest, DeleteDirNonRecursive) {
893  // Create a subdirectory and put a file and two directories inside.
894  FilePath test_subdir = temp_dir_.path().Append(FPL("DeleteDirNonRecursive"));
895  CreateDirectory(test_subdir);
896  ASSERT_TRUE(PathExists(test_subdir));
897
898  FilePath file_name = test_subdir.Append(FPL("Test DeleteDir.txt"));
899  CreateTextFile(file_name, bogus_content);
900  ASSERT_TRUE(PathExists(file_name));
901
902  FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
903  CreateDirectory(subdir_path1);
904  ASSERT_TRUE(PathExists(subdir_path1));
905
906  FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
907  CreateDirectory(subdir_path2);
908  ASSERT_TRUE(PathExists(subdir_path2));
909
910  // Delete non-recursively and check that the empty dir got deleted
911  EXPECT_TRUE(DeleteFile(subdir_path2, false));
912  EXPECT_FALSE(PathExists(subdir_path2));
913
914  // Delete non-recursively and check that nothing got deleted
915  EXPECT_FALSE(DeleteFile(test_subdir, false));
916  EXPECT_TRUE(PathExists(test_subdir));
917  EXPECT_TRUE(PathExists(file_name));
918  EXPECT_TRUE(PathExists(subdir_path1));
919}
920
921// Tests recursive Delete() for a directory.
922TEST_F(FileUtilTest, DeleteDirRecursive) {
923  // Create a subdirectory and put a file and two directories inside.
924  FilePath test_subdir = temp_dir_.path().Append(FPL("DeleteDirRecursive"));
925  CreateDirectory(test_subdir);
926  ASSERT_TRUE(PathExists(test_subdir));
927
928  FilePath file_name = test_subdir.Append(FPL("Test DeleteDirRecursive.txt"));
929  CreateTextFile(file_name, bogus_content);
930  ASSERT_TRUE(PathExists(file_name));
931
932  FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
933  CreateDirectory(subdir_path1);
934  ASSERT_TRUE(PathExists(subdir_path1));
935
936  FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
937  CreateDirectory(subdir_path2);
938  ASSERT_TRUE(PathExists(subdir_path2));
939
940  // Delete recursively and check that the empty dir got deleted
941  EXPECT_TRUE(DeleteFile(subdir_path2, true));
942  EXPECT_FALSE(PathExists(subdir_path2));
943
944  // Delete recursively and check that everything got deleted
945  EXPECT_TRUE(DeleteFile(test_subdir, true));
946  EXPECT_FALSE(PathExists(file_name));
947  EXPECT_FALSE(PathExists(subdir_path1));
948  EXPECT_FALSE(PathExists(test_subdir));
949}
950
951TEST_F(FileUtilTest, MoveFileNew) {
952  // Create a file
953  FilePath file_name_from =
954      temp_dir_.path().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
955  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
956  ASSERT_TRUE(PathExists(file_name_from));
957
958  // The destination.
959  FilePath file_name_to = temp_dir_.path().Append(
960      FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
961  ASSERT_FALSE(PathExists(file_name_to));
962
963  EXPECT_TRUE(Move(file_name_from, file_name_to));
964
965  // Check everything has been moved.
966  EXPECT_FALSE(PathExists(file_name_from));
967  EXPECT_TRUE(PathExists(file_name_to));
968}
969
970TEST_F(FileUtilTest, MoveFileExists) {
971  // Create a file
972  FilePath file_name_from =
973      temp_dir_.path().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
974  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
975  ASSERT_TRUE(PathExists(file_name_from));
976
977  // The destination name.
978  FilePath file_name_to = temp_dir_.path().Append(
979      FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
980  CreateTextFile(file_name_to, L"Old file content");
981  ASSERT_TRUE(PathExists(file_name_to));
982
983  EXPECT_TRUE(Move(file_name_from, file_name_to));
984
985  // Check everything has been moved.
986  EXPECT_FALSE(PathExists(file_name_from));
987  EXPECT_TRUE(PathExists(file_name_to));
988  EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
989}
990
991TEST_F(FileUtilTest, MoveFileDirExists) {
992  // Create a file
993  FilePath file_name_from =
994      temp_dir_.path().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
995  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
996  ASSERT_TRUE(PathExists(file_name_from));
997
998  // The destination directory
999  FilePath dir_name_to =
1000      temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
1001  CreateDirectory(dir_name_to);
1002  ASSERT_TRUE(PathExists(dir_name_to));
1003
1004  EXPECT_FALSE(Move(file_name_from, dir_name_to));
1005}
1006
1007
1008TEST_F(FileUtilTest, MoveNew) {
1009  // Create a directory
1010  FilePath dir_name_from =
1011      temp_dir_.path().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
1012  CreateDirectory(dir_name_from);
1013  ASSERT_TRUE(PathExists(dir_name_from));
1014
1015  // Create a file under the directory
1016  FilePath txt_file_name(FILE_PATH_LITERAL("Move_Test_File.txt"));
1017  FilePath file_name_from = dir_name_from.Append(txt_file_name);
1018  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1019  ASSERT_TRUE(PathExists(file_name_from));
1020
1021  // Move the directory.
1022  FilePath dir_name_to =
1023      temp_dir_.path().Append(FILE_PATH_LITERAL("Move_To_Subdir"));
1024  FilePath file_name_to =
1025      dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1026
1027  ASSERT_FALSE(PathExists(dir_name_to));
1028
1029  EXPECT_TRUE(Move(dir_name_from, dir_name_to));
1030
1031  // Check everything has been moved.
1032  EXPECT_FALSE(PathExists(dir_name_from));
1033  EXPECT_FALSE(PathExists(file_name_from));
1034  EXPECT_TRUE(PathExists(dir_name_to));
1035  EXPECT_TRUE(PathExists(file_name_to));
1036
1037  // Test path traversal.
1038  file_name_from = dir_name_to.Append(txt_file_name);
1039  file_name_to = dir_name_to.Append(FILE_PATH_LITERAL(".."));
1040  file_name_to = file_name_to.Append(txt_file_name);
1041  EXPECT_FALSE(Move(file_name_from, file_name_to));
1042  EXPECT_TRUE(PathExists(file_name_from));
1043  EXPECT_FALSE(PathExists(file_name_to));
1044  EXPECT_TRUE(internal::MoveUnsafe(file_name_from, file_name_to));
1045  EXPECT_FALSE(PathExists(file_name_from));
1046  EXPECT_TRUE(PathExists(file_name_to));
1047}
1048
1049TEST_F(FileUtilTest, MoveExist) {
1050  // Create a directory
1051  FilePath dir_name_from =
1052      temp_dir_.path().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
1053  CreateDirectory(dir_name_from);
1054  ASSERT_TRUE(PathExists(dir_name_from));
1055
1056  // Create a file under the directory
1057  FilePath file_name_from =
1058      dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1059  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1060  ASSERT_TRUE(PathExists(file_name_from));
1061
1062  // Move the directory
1063  FilePath dir_name_exists =
1064      temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
1065
1066  FilePath dir_name_to =
1067      dir_name_exists.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
1068  FilePath file_name_to =
1069      dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1070
1071  // Create the destination directory.
1072  CreateDirectory(dir_name_exists);
1073  ASSERT_TRUE(PathExists(dir_name_exists));
1074
1075  EXPECT_TRUE(Move(dir_name_from, dir_name_to));
1076
1077  // Check everything has been moved.
1078  EXPECT_FALSE(PathExists(dir_name_from));
1079  EXPECT_FALSE(PathExists(file_name_from));
1080  EXPECT_TRUE(PathExists(dir_name_to));
1081  EXPECT_TRUE(PathExists(file_name_to));
1082}
1083
1084TEST_F(FileUtilTest, CopyDirectoryRecursivelyNew) {
1085  // Create a directory.
1086  FilePath dir_name_from =
1087      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1088  CreateDirectory(dir_name_from);
1089  ASSERT_TRUE(PathExists(dir_name_from));
1090
1091  // Create a file under the directory.
1092  FilePath file_name_from =
1093      dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1094  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1095  ASSERT_TRUE(PathExists(file_name_from));
1096
1097  // Create a subdirectory.
1098  FilePath subdir_name_from =
1099      dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1100  CreateDirectory(subdir_name_from);
1101  ASSERT_TRUE(PathExists(subdir_name_from));
1102
1103  // Create a file under the subdirectory.
1104  FilePath file_name2_from =
1105      subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1106  CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1107  ASSERT_TRUE(PathExists(file_name2_from));
1108
1109  // Copy the directory recursively.
1110  FilePath dir_name_to =
1111      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1112  FilePath file_name_to =
1113      dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1114  FilePath subdir_name_to =
1115      dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1116  FilePath file_name2_to =
1117      subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1118
1119  ASSERT_FALSE(PathExists(dir_name_to));
1120
1121  EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
1122
1123  // Check everything has been copied.
1124  EXPECT_TRUE(PathExists(dir_name_from));
1125  EXPECT_TRUE(PathExists(file_name_from));
1126  EXPECT_TRUE(PathExists(subdir_name_from));
1127  EXPECT_TRUE(PathExists(file_name2_from));
1128  EXPECT_TRUE(PathExists(dir_name_to));
1129  EXPECT_TRUE(PathExists(file_name_to));
1130  EXPECT_TRUE(PathExists(subdir_name_to));
1131  EXPECT_TRUE(PathExists(file_name2_to));
1132}
1133
1134TEST_F(FileUtilTest, CopyDirectoryRecursivelyExists) {
1135  // Create a directory.
1136  FilePath dir_name_from =
1137      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1138  CreateDirectory(dir_name_from);
1139  ASSERT_TRUE(PathExists(dir_name_from));
1140
1141  // Create a file under the directory.
1142  FilePath file_name_from =
1143      dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1144  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1145  ASSERT_TRUE(PathExists(file_name_from));
1146
1147  // Create a subdirectory.
1148  FilePath subdir_name_from =
1149      dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1150  CreateDirectory(subdir_name_from);
1151  ASSERT_TRUE(PathExists(subdir_name_from));
1152
1153  // Create a file under the subdirectory.
1154  FilePath file_name2_from =
1155      subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1156  CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1157  ASSERT_TRUE(PathExists(file_name2_from));
1158
1159  // Copy the directory recursively.
1160  FilePath dir_name_exists =
1161      temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
1162
1163  FilePath dir_name_to =
1164      dir_name_exists.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1165  FilePath file_name_to =
1166      dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1167  FilePath subdir_name_to =
1168      dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1169  FilePath file_name2_to =
1170      subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1171
1172  // Create the destination directory.
1173  CreateDirectory(dir_name_exists);
1174  ASSERT_TRUE(PathExists(dir_name_exists));
1175
1176  EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_exists, true));
1177
1178  // Check everything has been copied.
1179  EXPECT_TRUE(PathExists(dir_name_from));
1180  EXPECT_TRUE(PathExists(file_name_from));
1181  EXPECT_TRUE(PathExists(subdir_name_from));
1182  EXPECT_TRUE(PathExists(file_name2_from));
1183  EXPECT_TRUE(PathExists(dir_name_to));
1184  EXPECT_TRUE(PathExists(file_name_to));
1185  EXPECT_TRUE(PathExists(subdir_name_to));
1186  EXPECT_TRUE(PathExists(file_name2_to));
1187}
1188
1189TEST_F(FileUtilTest, CopyDirectoryNew) {
1190  // Create a directory.
1191  FilePath dir_name_from =
1192      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1193  CreateDirectory(dir_name_from);
1194  ASSERT_TRUE(PathExists(dir_name_from));
1195
1196  // Create a file under the directory.
1197  FilePath file_name_from =
1198      dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1199  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1200  ASSERT_TRUE(PathExists(file_name_from));
1201
1202  // Create a subdirectory.
1203  FilePath subdir_name_from =
1204      dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1205  CreateDirectory(subdir_name_from);
1206  ASSERT_TRUE(PathExists(subdir_name_from));
1207
1208  // Create a file under the subdirectory.
1209  FilePath file_name2_from =
1210      subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1211  CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1212  ASSERT_TRUE(PathExists(file_name2_from));
1213
1214  // Copy the directory not recursively.
1215  FilePath dir_name_to =
1216      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1217  FilePath file_name_to =
1218      dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1219  FilePath subdir_name_to =
1220      dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1221
1222  ASSERT_FALSE(PathExists(dir_name_to));
1223
1224  EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
1225
1226  // Check everything has been copied.
1227  EXPECT_TRUE(PathExists(dir_name_from));
1228  EXPECT_TRUE(PathExists(file_name_from));
1229  EXPECT_TRUE(PathExists(subdir_name_from));
1230  EXPECT_TRUE(PathExists(file_name2_from));
1231  EXPECT_TRUE(PathExists(dir_name_to));
1232  EXPECT_TRUE(PathExists(file_name_to));
1233  EXPECT_FALSE(PathExists(subdir_name_to));
1234}
1235
1236TEST_F(FileUtilTest, CopyDirectoryExists) {
1237  // Create a directory.
1238  FilePath dir_name_from =
1239      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1240  CreateDirectory(dir_name_from);
1241  ASSERT_TRUE(PathExists(dir_name_from));
1242
1243  // Create a file under the directory.
1244  FilePath file_name_from =
1245      dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1246  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1247  ASSERT_TRUE(PathExists(file_name_from));
1248
1249  // Create a subdirectory.
1250  FilePath subdir_name_from =
1251      dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1252  CreateDirectory(subdir_name_from);
1253  ASSERT_TRUE(PathExists(subdir_name_from));
1254
1255  // Create a file under the subdirectory.
1256  FilePath file_name2_from =
1257      subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1258  CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1259  ASSERT_TRUE(PathExists(file_name2_from));
1260
1261  // Copy the directory not recursively.
1262  FilePath dir_name_to =
1263      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1264  FilePath file_name_to =
1265      dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1266  FilePath subdir_name_to =
1267      dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1268
1269  // Create the destination directory.
1270  CreateDirectory(dir_name_to);
1271  ASSERT_TRUE(PathExists(dir_name_to));
1272
1273  EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
1274
1275  // Check everything has been copied.
1276  EXPECT_TRUE(PathExists(dir_name_from));
1277  EXPECT_TRUE(PathExists(file_name_from));
1278  EXPECT_TRUE(PathExists(subdir_name_from));
1279  EXPECT_TRUE(PathExists(file_name2_from));
1280  EXPECT_TRUE(PathExists(dir_name_to));
1281  EXPECT_TRUE(PathExists(file_name_to));
1282  EXPECT_FALSE(PathExists(subdir_name_to));
1283}
1284
1285TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToNew) {
1286  // Create a file
1287  FilePath file_name_from =
1288      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1289  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1290  ASSERT_TRUE(PathExists(file_name_from));
1291
1292  // The destination name
1293  FilePath file_name_to = temp_dir_.path().Append(
1294      FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
1295  ASSERT_FALSE(PathExists(file_name_to));
1296
1297  EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
1298
1299  // Check the has been copied
1300  EXPECT_TRUE(PathExists(file_name_to));
1301}
1302
1303TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExisting) {
1304  // Create a file
1305  FilePath file_name_from =
1306      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1307  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1308  ASSERT_TRUE(PathExists(file_name_from));
1309
1310  // The destination name
1311  FilePath file_name_to = temp_dir_.path().Append(
1312      FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
1313  CreateTextFile(file_name_to, L"Old file content");
1314  ASSERT_TRUE(PathExists(file_name_to));
1315
1316  EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
1317
1318  // Check the has been copied
1319  EXPECT_TRUE(PathExists(file_name_to));
1320  EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
1321}
1322
1323TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExistingDirectory) {
1324  // Create a file
1325  FilePath file_name_from =
1326      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1327  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1328  ASSERT_TRUE(PathExists(file_name_from));
1329
1330  // The destination
1331  FilePath dir_name_to =
1332      temp_dir_.path().Append(FILE_PATH_LITERAL("Destination"));
1333  CreateDirectory(dir_name_to);
1334  ASSERT_TRUE(PathExists(dir_name_to));
1335  FilePath file_name_to =
1336      dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1337
1338  EXPECT_TRUE(CopyDirectory(file_name_from, dir_name_to, true));
1339
1340  // Check the has been copied
1341  EXPECT_TRUE(PathExists(file_name_to));
1342}
1343
1344TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) {
1345  // Create a directory.
1346  FilePath dir_name_from =
1347      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1348  CreateDirectory(dir_name_from);
1349  ASSERT_TRUE(PathExists(dir_name_from));
1350
1351  // Create a file under the directory.
1352  FilePath file_name_from =
1353      dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1354  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1355  ASSERT_TRUE(PathExists(file_name_from));
1356
1357  // Copy the directory recursively.
1358  FilePath dir_name_to =
1359      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1360  FilePath file_name_to =
1361      dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1362
1363  // Create from path with trailing separators.
1364#if defined(OS_WIN)
1365  FilePath from_path =
1366      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir\\\\\\"));
1367#elif defined (OS_POSIX)
1368  FilePath from_path =
1369      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir///"));
1370#endif
1371
1372  EXPECT_TRUE(CopyDirectory(from_path, dir_name_to, true));
1373
1374  // Check everything has been copied.
1375  EXPECT_TRUE(PathExists(dir_name_from));
1376  EXPECT_TRUE(PathExists(file_name_from));
1377  EXPECT_TRUE(PathExists(dir_name_to));
1378  EXPECT_TRUE(PathExists(file_name_to));
1379}
1380
1381// Sets the source file to read-only.
1382void SetReadOnly(const FilePath& path) {
1383#if defined(OS_WIN)
1384  // On Windows, it involves setting a bit.
1385  DWORD attrs = GetFileAttributes(path.value().c_str());
1386  ASSERT_NE(INVALID_FILE_ATTRIBUTES, attrs);
1387  ASSERT_TRUE(SetFileAttributes(
1388      path.value().c_str(), attrs | FILE_ATTRIBUTE_READONLY));
1389  attrs = GetFileAttributes(path.value().c_str());
1390  // Files in the temporary directory should not be indexed ever. If this
1391  // assumption change, fix this unit test accordingly.
1392  // FILE_ATTRIBUTE_NOT_CONTENT_INDEXED doesn't exist on XP.
1393  DWORD expected = FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY;
1394  if (win::GetVersion() >= win::VERSION_VISTA)
1395    expected |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
1396  ASSERT_EQ(expected, attrs);
1397#else
1398  // On all other platforms, it involves removing the write bit.
1399  EXPECT_TRUE(SetPosixFilePermissions(path, S_IRUSR));
1400#endif
1401}
1402
1403bool IsReadOnly(const FilePath& path) {
1404#if defined(OS_WIN)
1405  DWORD attrs = GetFileAttributes(path.value().c_str());
1406  EXPECT_NE(INVALID_FILE_ATTRIBUTES, attrs);
1407  return attrs & FILE_ATTRIBUTE_READONLY;
1408#else
1409  int mode = 0;
1410  EXPECT_TRUE(GetPosixFilePermissions(path, &mode));
1411  return !(mode & S_IWUSR);
1412#endif
1413}
1414
1415TEST_F(FileUtilTest, CopyDirectoryACL) {
1416  // Create a directory.
1417  FilePath src = temp_dir_.path().Append(FILE_PATH_LITERAL("src"));
1418  CreateDirectory(src);
1419  ASSERT_TRUE(PathExists(src));
1420
1421  // Create a file under the directory.
1422  FilePath src_file = src.Append(FILE_PATH_LITERAL("src.txt"));
1423  CreateTextFile(src_file, L"Gooooooooooooooooooooogle");
1424  SetReadOnly(src_file);
1425  ASSERT_TRUE(IsReadOnly(src_file));
1426
1427  // Copy the directory recursively.
1428  FilePath dst = temp_dir_.path().Append(FILE_PATH_LITERAL("dst"));
1429  FilePath dst_file = dst.Append(FILE_PATH_LITERAL("src.txt"));
1430  EXPECT_TRUE(CopyDirectory(src, dst, true));
1431
1432  ASSERT_FALSE(IsReadOnly(dst_file));
1433}
1434
1435TEST_F(FileUtilTest, CopyFile) {
1436  // Create a directory
1437  FilePath dir_name_from =
1438      temp_dir_.path().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1439  CreateDirectory(dir_name_from);
1440  ASSERT_TRUE(PathExists(dir_name_from));
1441
1442  // Create a file under the directory
1443  FilePath file_name_from =
1444      dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1445  const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1446  CreateTextFile(file_name_from, file_contents);
1447  ASSERT_TRUE(PathExists(file_name_from));
1448
1449  // Copy the file.
1450  FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
1451  ASSERT_TRUE(CopyFile(file_name_from, dest_file));
1452
1453  // Copy the file to another location using '..' in the path.
1454  FilePath dest_file2(dir_name_from);
1455  dest_file2 = dest_file2.AppendASCII("..");
1456  dest_file2 = dest_file2.AppendASCII("DestFile.txt");
1457  ASSERT_FALSE(CopyFile(file_name_from, dest_file2));
1458  ASSERT_TRUE(internal::CopyFileUnsafe(file_name_from, dest_file2));
1459
1460  FilePath dest_file2_test(dir_name_from);
1461  dest_file2_test = dest_file2_test.DirName();
1462  dest_file2_test = dest_file2_test.AppendASCII("DestFile.txt");
1463
1464  // Check everything has been copied.
1465  EXPECT_TRUE(PathExists(file_name_from));
1466  EXPECT_TRUE(PathExists(dest_file));
1467  const std::wstring read_contents = ReadTextFile(dest_file);
1468  EXPECT_EQ(file_contents, read_contents);
1469  EXPECT_TRUE(PathExists(dest_file2_test));
1470  EXPECT_TRUE(PathExists(dest_file2));
1471}
1472
1473TEST_F(FileUtilTest, CopyFileACL) {
1474  // While FileUtilTest.CopyFile asserts the content is correctly copied over,
1475  // this test case asserts the access control bits are meeting expectations in
1476  // CopyFileUnsafe().
1477  FilePath src = temp_dir_.path().Append(FILE_PATH_LITERAL("src.txt"));
1478  const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1479  CreateTextFile(src, file_contents);
1480
1481  // Set the source file to read-only.
1482  ASSERT_FALSE(IsReadOnly(src));
1483  SetReadOnly(src);
1484  ASSERT_TRUE(IsReadOnly(src));
1485
1486  // Copy the file.
1487  FilePath dst = temp_dir_.path().Append(FILE_PATH_LITERAL("dst.txt"));
1488  ASSERT_TRUE(CopyFile(src, dst));
1489  EXPECT_EQ(file_contents, ReadTextFile(dst));
1490
1491  ASSERT_FALSE(IsReadOnly(dst));
1492}
1493
1494// file_util winds up using autoreleased objects on the Mac, so this needs
1495// to be a PlatformTest.
1496typedef PlatformTest ReadOnlyFileUtilTest;
1497
1498TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
1499  FilePath data_dir;
1500  ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
1501  data_dir = data_dir.AppendASCII("file_util");
1502  ASSERT_TRUE(PathExists(data_dir));
1503
1504  FilePath original_file =
1505      data_dir.Append(FILE_PATH_LITERAL("original.txt"));
1506  FilePath same_file =
1507      data_dir.Append(FILE_PATH_LITERAL("same.txt"));
1508  FilePath same_length_file =
1509      data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
1510  FilePath different_file =
1511      data_dir.Append(FILE_PATH_LITERAL("different.txt"));
1512  FilePath different_first_file =
1513      data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
1514  FilePath different_last_file =
1515      data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
1516  FilePath empty1_file =
1517      data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
1518  FilePath empty2_file =
1519      data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
1520  FilePath shortened_file =
1521      data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
1522  FilePath binary_file =
1523      data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
1524  FilePath binary_file_same =
1525      data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
1526  FilePath binary_file_diff =
1527      data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
1528
1529  EXPECT_TRUE(ContentsEqual(original_file, original_file));
1530  EXPECT_TRUE(ContentsEqual(original_file, same_file));
1531  EXPECT_FALSE(ContentsEqual(original_file, same_length_file));
1532  EXPECT_FALSE(ContentsEqual(original_file, different_file));
1533  EXPECT_FALSE(ContentsEqual(FilePath(FILE_PATH_LITERAL("bogusname")),
1534                             FilePath(FILE_PATH_LITERAL("bogusname"))));
1535  EXPECT_FALSE(ContentsEqual(original_file, different_first_file));
1536  EXPECT_FALSE(ContentsEqual(original_file, different_last_file));
1537  EXPECT_TRUE(ContentsEqual(empty1_file, empty2_file));
1538  EXPECT_FALSE(ContentsEqual(original_file, shortened_file));
1539  EXPECT_FALSE(ContentsEqual(shortened_file, original_file));
1540  EXPECT_TRUE(ContentsEqual(binary_file, binary_file_same));
1541  EXPECT_FALSE(ContentsEqual(binary_file, binary_file_diff));
1542}
1543
1544TEST_F(ReadOnlyFileUtilTest, TextContentsEqual) {
1545  FilePath data_dir;
1546  ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
1547  data_dir = data_dir.AppendASCII("file_util");
1548  ASSERT_TRUE(PathExists(data_dir));
1549
1550  FilePath original_file =
1551      data_dir.Append(FILE_PATH_LITERAL("original.txt"));
1552  FilePath same_file =
1553      data_dir.Append(FILE_PATH_LITERAL("same.txt"));
1554  FilePath crlf_file =
1555      data_dir.Append(FILE_PATH_LITERAL("crlf.txt"));
1556  FilePath shortened_file =
1557      data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
1558  FilePath different_file =
1559      data_dir.Append(FILE_PATH_LITERAL("different.txt"));
1560  FilePath different_first_file =
1561      data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
1562  FilePath different_last_file =
1563      data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
1564  FilePath first1_file =
1565      data_dir.Append(FILE_PATH_LITERAL("first1.txt"));
1566  FilePath first2_file =
1567      data_dir.Append(FILE_PATH_LITERAL("first2.txt"));
1568  FilePath empty1_file =
1569      data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
1570  FilePath empty2_file =
1571      data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
1572  FilePath blank_line_file =
1573      data_dir.Append(FILE_PATH_LITERAL("blank_line.txt"));
1574  FilePath blank_line_crlf_file =
1575      data_dir.Append(FILE_PATH_LITERAL("blank_line_crlf.txt"));
1576
1577  EXPECT_TRUE(TextContentsEqual(original_file, same_file));
1578  EXPECT_TRUE(TextContentsEqual(original_file, crlf_file));
1579  EXPECT_FALSE(TextContentsEqual(original_file, shortened_file));
1580  EXPECT_FALSE(TextContentsEqual(original_file, different_file));
1581  EXPECT_FALSE(TextContentsEqual(original_file, different_first_file));
1582  EXPECT_FALSE(TextContentsEqual(original_file, different_last_file));
1583  EXPECT_FALSE(TextContentsEqual(first1_file, first2_file));
1584  EXPECT_TRUE(TextContentsEqual(empty1_file, empty2_file));
1585  EXPECT_FALSE(TextContentsEqual(original_file, empty1_file));
1586  EXPECT_TRUE(TextContentsEqual(blank_line_file, blank_line_crlf_file));
1587}
1588
1589// We don't need equivalent functionality outside of Windows.
1590#if defined(OS_WIN)
1591TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) {
1592  // Create a directory
1593  FilePath dir_name_from =
1594      temp_dir_.path().Append(FILE_PATH_LITERAL("CopyAndDelete_From_Subdir"));
1595  CreateDirectory(dir_name_from);
1596  ASSERT_TRUE(PathExists(dir_name_from));
1597
1598  // Create a file under the directory
1599  FilePath file_name_from =
1600      dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
1601  CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1602  ASSERT_TRUE(PathExists(file_name_from));
1603
1604  // Move the directory by using CopyAndDeleteDirectory
1605  FilePath dir_name_to = temp_dir_.path().Append(
1606      FILE_PATH_LITERAL("CopyAndDelete_To_Subdir"));
1607  FilePath file_name_to =
1608      dir_name_to.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
1609
1610  ASSERT_FALSE(PathExists(dir_name_to));
1611
1612  EXPECT_TRUE(internal::CopyAndDeleteDirectory(dir_name_from,
1613                                                     dir_name_to));
1614
1615  // Check everything has been moved.
1616  EXPECT_FALSE(PathExists(dir_name_from));
1617  EXPECT_FALSE(PathExists(file_name_from));
1618  EXPECT_TRUE(PathExists(dir_name_to));
1619  EXPECT_TRUE(PathExists(file_name_to));
1620}
1621
1622TEST_F(FileUtilTest, GetTempDirTest) {
1623  static const TCHAR* kTmpKey = _T("TMP");
1624  static const TCHAR* kTmpValues[] = {
1625    _T(""), _T("C:"), _T("C:\\"), _T("C:\\tmp"), _T("C:\\tmp\\")
1626  };
1627  // Save the original $TMP.
1628  size_t original_tmp_size;
1629  TCHAR* original_tmp;
1630  ASSERT_EQ(0, ::_tdupenv_s(&original_tmp, &original_tmp_size, kTmpKey));
1631  // original_tmp may be NULL.
1632
1633  for (unsigned int i = 0; i < arraysize(kTmpValues); ++i) {
1634    FilePath path;
1635    ::_tputenv_s(kTmpKey, kTmpValues[i]);
1636    GetTempDir(&path);
1637    EXPECT_TRUE(path.IsAbsolute()) << "$TMP=" << kTmpValues[i] <<
1638        " result=" << path.value();
1639  }
1640
1641  // Restore the original $TMP.
1642  if (original_tmp) {
1643    ::_tputenv_s(kTmpKey, original_tmp);
1644    free(original_tmp);
1645  } else {
1646    ::_tputenv_s(kTmpKey, _T(""));
1647  }
1648}
1649#endif  // OS_WIN
1650
1651TEST_F(FileUtilTest, CreateTemporaryFileTest) {
1652  FilePath temp_files[3];
1653  for (int i = 0; i < 3; i++) {
1654    ASSERT_TRUE(CreateTemporaryFile(&(temp_files[i])));
1655    EXPECT_TRUE(PathExists(temp_files[i]));
1656    EXPECT_FALSE(DirectoryExists(temp_files[i]));
1657  }
1658  for (int i = 0; i < 3; i++)
1659    EXPECT_FALSE(temp_files[i] == temp_files[(i+1)%3]);
1660  for (int i = 0; i < 3; i++)
1661    EXPECT_TRUE(DeleteFile(temp_files[i], false));
1662}
1663
1664TEST_F(FileUtilTest, CreateAndOpenTemporaryFileTest) {
1665  FilePath names[3];
1666  FILE* fps[3];
1667  int i;
1668
1669  // Create; make sure they are open and exist.
1670  for (i = 0; i < 3; ++i) {
1671    fps[i] = CreateAndOpenTemporaryFile(&(names[i]));
1672    ASSERT_TRUE(fps[i]);
1673    EXPECT_TRUE(PathExists(names[i]));
1674  }
1675
1676  // Make sure all names are unique.
1677  for (i = 0; i < 3; ++i) {
1678    EXPECT_FALSE(names[i] == names[(i+1)%3]);
1679  }
1680
1681  // Close and delete.
1682  for (i = 0; i < 3; ++i) {
1683    EXPECT_TRUE(CloseFile(fps[i]));
1684    EXPECT_TRUE(DeleteFile(names[i], false));
1685  }
1686}
1687
1688TEST_F(FileUtilTest, FileToFILE) {
1689  File file;
1690  FILE* stream = FileToFILE(file.Pass(), "w");
1691  EXPECT_FALSE(stream);
1692
1693  FilePath file_name = temp_dir_.path().Append(FPL("The file.txt"));
1694  file = File(file_name, File::FLAG_CREATE | File::FLAG_WRITE);
1695  EXPECT_TRUE(file.IsValid());
1696
1697  stream = FileToFILE(file.Pass(), "w");
1698  EXPECT_TRUE(stream);
1699  EXPECT_FALSE(file.IsValid());
1700  EXPECT_TRUE(CloseFile(stream));
1701}
1702
1703TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
1704  FilePath temp_dir;
1705  ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
1706  EXPECT_TRUE(PathExists(temp_dir));
1707  EXPECT_TRUE(DeleteFile(temp_dir, false));
1708}
1709
1710TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) {
1711  FilePath new_dir;
1712  ASSERT_TRUE(CreateTemporaryDirInDir(
1713                  temp_dir_.path(),
1714                  FILE_PATH_LITERAL("CreateNewTemporaryDirInDirTest"),
1715                  &new_dir));
1716  EXPECT_TRUE(PathExists(new_dir));
1717  EXPECT_TRUE(temp_dir_.path().IsParent(new_dir));
1718  EXPECT_TRUE(DeleteFile(new_dir, false));
1719}
1720
1721#if defined(OS_POSIX)
1722TEST_F(FileUtilTest, GetShmemTempDirTest) {
1723  FilePath dir;
1724  EXPECT_TRUE(GetShmemTempDir(false, &dir));
1725  EXPECT_TRUE(DirectoryExists(dir));
1726}
1727#endif
1728
1729TEST_F(FileUtilTest, GetHomeDirTest) {
1730#if !defined(OS_ANDROID)  // Not implemented on Android.
1731  // We don't actually know what the home directory is supposed to be without
1732  // calling some OS functions which would just duplicate the implementation.
1733  // So here we just test that it returns something "reasonable".
1734  FilePath home = GetHomeDir();
1735  ASSERT_FALSE(home.empty());
1736  ASSERT_TRUE(home.IsAbsolute());
1737#endif
1738}
1739
1740TEST_F(FileUtilTest, CreateDirectoryTest) {
1741  FilePath test_root =
1742      temp_dir_.path().Append(FILE_PATH_LITERAL("create_directory_test"));
1743#if defined(OS_WIN)
1744  FilePath test_path =
1745      test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
1746#elif defined(OS_POSIX)
1747  FilePath test_path =
1748      test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
1749#endif
1750
1751  EXPECT_FALSE(PathExists(test_path));
1752  EXPECT_TRUE(CreateDirectory(test_path));
1753  EXPECT_TRUE(PathExists(test_path));
1754  // CreateDirectory returns true if the DirectoryExists returns true.
1755  EXPECT_TRUE(CreateDirectory(test_path));
1756
1757  // Doesn't work to create it on top of a non-dir
1758  test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
1759  EXPECT_FALSE(PathExists(test_path));
1760  CreateTextFile(test_path, L"test file");
1761  EXPECT_TRUE(PathExists(test_path));
1762  EXPECT_FALSE(CreateDirectory(test_path));
1763
1764  EXPECT_TRUE(DeleteFile(test_root, true));
1765  EXPECT_FALSE(PathExists(test_root));
1766  EXPECT_FALSE(PathExists(test_path));
1767
1768  // Verify assumptions made by the Windows implementation:
1769  // 1. The current directory always exists.
1770  // 2. The root directory always exists.
1771  ASSERT_TRUE(DirectoryExists(FilePath(FilePath::kCurrentDirectory)));
1772  FilePath top_level = test_root;
1773  while (top_level != top_level.DirName()) {
1774    top_level = top_level.DirName();
1775  }
1776  ASSERT_TRUE(DirectoryExists(top_level));
1777
1778  // Given these assumptions hold, it should be safe to
1779  // test that "creating" these directories succeeds.
1780  EXPECT_TRUE(CreateDirectory(
1781      FilePath(FilePath::kCurrentDirectory)));
1782  EXPECT_TRUE(CreateDirectory(top_level));
1783
1784#if defined(OS_WIN)
1785  FilePath invalid_drive(FILE_PATH_LITERAL("o:\\"));
1786  FilePath invalid_path =
1787      invalid_drive.Append(FILE_PATH_LITERAL("some\\inaccessible\\dir"));
1788  if (!PathExists(invalid_drive)) {
1789    EXPECT_FALSE(CreateDirectory(invalid_path));
1790  }
1791#endif
1792}
1793
1794TEST_F(FileUtilTest, DetectDirectoryTest) {
1795  // Check a directory
1796  FilePath test_root =
1797      temp_dir_.path().Append(FILE_PATH_LITERAL("detect_directory_test"));
1798  EXPECT_FALSE(PathExists(test_root));
1799  EXPECT_TRUE(CreateDirectory(test_root));
1800  EXPECT_TRUE(PathExists(test_root));
1801  EXPECT_TRUE(DirectoryExists(test_root));
1802  // Check a file
1803  FilePath test_path =
1804      test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
1805  EXPECT_FALSE(PathExists(test_path));
1806  CreateTextFile(test_path, L"test file");
1807  EXPECT_TRUE(PathExists(test_path));
1808  EXPECT_FALSE(DirectoryExists(test_path));
1809  EXPECT_TRUE(DeleteFile(test_path, false));
1810
1811  EXPECT_TRUE(DeleteFile(test_root, true));
1812}
1813
1814TEST_F(FileUtilTest, FileEnumeratorTest) {
1815  // Test an empty directory.
1816  FileEnumerator f0(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1817  EXPECT_EQ(FPL(""), f0.Next().value());
1818  EXPECT_EQ(FPL(""), f0.Next().value());
1819
1820  // Test an empty directory, non-recursively, including "..".
1821  FileEnumerator f0_dotdot(temp_dir_.path(), false,
1822      FILES_AND_DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
1823  EXPECT_EQ(temp_dir_.path().Append(FPL("..")).value(),
1824            f0_dotdot.Next().value());
1825  EXPECT_EQ(FPL(""), f0_dotdot.Next().value());
1826
1827  // create the directories
1828  FilePath dir1 = temp_dir_.path().Append(FPL("dir1"));
1829  EXPECT_TRUE(CreateDirectory(dir1));
1830  FilePath dir2 = temp_dir_.path().Append(FPL("dir2"));
1831  EXPECT_TRUE(CreateDirectory(dir2));
1832  FilePath dir2inner = dir2.Append(FPL("inner"));
1833  EXPECT_TRUE(CreateDirectory(dir2inner));
1834
1835  // create the files
1836  FilePath dir2file = dir2.Append(FPL("dir2file.txt"));
1837  CreateTextFile(dir2file, std::wstring());
1838  FilePath dir2innerfile = dir2inner.Append(FPL("innerfile.txt"));
1839  CreateTextFile(dir2innerfile, std::wstring());
1840  FilePath file1 = temp_dir_.path().Append(FPL("file1.txt"));
1841  CreateTextFile(file1, std::wstring());
1842  FilePath file2_rel = dir2.Append(FilePath::kParentDirectory)
1843      .Append(FPL("file2.txt"));
1844  CreateTextFile(file2_rel, std::wstring());
1845  FilePath file2_abs = temp_dir_.path().Append(FPL("file2.txt"));
1846
1847  // Only enumerate files.
1848  FileEnumerator f1(temp_dir_.path(), true, FileEnumerator::FILES);
1849  FindResultCollector c1(f1);
1850  EXPECT_TRUE(c1.HasFile(file1));
1851  EXPECT_TRUE(c1.HasFile(file2_abs));
1852  EXPECT_TRUE(c1.HasFile(dir2file));
1853  EXPECT_TRUE(c1.HasFile(dir2innerfile));
1854  EXPECT_EQ(4, c1.size());
1855
1856  // Only enumerate directories.
1857  FileEnumerator f2(temp_dir_.path(), true, FileEnumerator::DIRECTORIES);
1858  FindResultCollector c2(f2);
1859  EXPECT_TRUE(c2.HasFile(dir1));
1860  EXPECT_TRUE(c2.HasFile(dir2));
1861  EXPECT_TRUE(c2.HasFile(dir2inner));
1862  EXPECT_EQ(3, c2.size());
1863
1864  // Only enumerate directories non-recursively.
1865  FileEnumerator f2_non_recursive(
1866      temp_dir_.path(), false, FileEnumerator::DIRECTORIES);
1867  FindResultCollector c2_non_recursive(f2_non_recursive);
1868  EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
1869  EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
1870  EXPECT_EQ(2, c2_non_recursive.size());
1871
1872  // Only enumerate directories, non-recursively, including "..".
1873  FileEnumerator f2_dotdot(temp_dir_.path(), false,
1874                           FileEnumerator::DIRECTORIES |
1875                           FileEnumerator::INCLUDE_DOT_DOT);
1876  FindResultCollector c2_dotdot(f2_dotdot);
1877  EXPECT_TRUE(c2_dotdot.HasFile(dir1));
1878  EXPECT_TRUE(c2_dotdot.HasFile(dir2));
1879  EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.path().Append(FPL(".."))));
1880  EXPECT_EQ(3, c2_dotdot.size());
1881
1882  // Enumerate files and directories.
1883  FileEnumerator f3(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1884  FindResultCollector c3(f3);
1885  EXPECT_TRUE(c3.HasFile(dir1));
1886  EXPECT_TRUE(c3.HasFile(dir2));
1887  EXPECT_TRUE(c3.HasFile(file1));
1888  EXPECT_TRUE(c3.HasFile(file2_abs));
1889  EXPECT_TRUE(c3.HasFile(dir2file));
1890  EXPECT_TRUE(c3.HasFile(dir2inner));
1891  EXPECT_TRUE(c3.HasFile(dir2innerfile));
1892  EXPECT_EQ(7, c3.size());
1893
1894  // Non-recursive operation.
1895  FileEnumerator f4(temp_dir_.path(), false, FILES_AND_DIRECTORIES);
1896  FindResultCollector c4(f4);
1897  EXPECT_TRUE(c4.HasFile(dir2));
1898  EXPECT_TRUE(c4.HasFile(dir2));
1899  EXPECT_TRUE(c4.HasFile(file1));
1900  EXPECT_TRUE(c4.HasFile(file2_abs));
1901  EXPECT_EQ(4, c4.size());
1902
1903  // Enumerate with a pattern.
1904  FileEnumerator f5(temp_dir_.path(), true, FILES_AND_DIRECTORIES, FPL("dir*"));
1905  FindResultCollector c5(f5);
1906  EXPECT_TRUE(c5.HasFile(dir1));
1907  EXPECT_TRUE(c5.HasFile(dir2));
1908  EXPECT_TRUE(c5.HasFile(dir2file));
1909  EXPECT_TRUE(c5.HasFile(dir2inner));
1910  EXPECT_TRUE(c5.HasFile(dir2innerfile));
1911  EXPECT_EQ(5, c5.size());
1912
1913#if defined(OS_WIN)
1914  {
1915    // Make dir1 point to dir2.
1916    ReparsePoint reparse_point(dir1, dir2);
1917    EXPECT_TRUE(reparse_point.IsValid());
1918
1919    if ((win::GetVersion() >= win::VERSION_VISTA)) {
1920      // There can be a delay for the enumeration code to see the change on
1921      // the file system so skip this test for XP.
1922      // Enumerate the reparse point.
1923      FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES);
1924      FindResultCollector c6(f6);
1925      FilePath inner2 = dir1.Append(FPL("inner"));
1926      EXPECT_TRUE(c6.HasFile(inner2));
1927      EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt"))));
1928      EXPECT_TRUE(c6.HasFile(dir1.Append(FPL("dir2file.txt"))));
1929      EXPECT_EQ(3, c6.size());
1930    }
1931
1932    // No changes for non recursive operation.
1933    FileEnumerator f7(temp_dir_.path(), false, FILES_AND_DIRECTORIES);
1934    FindResultCollector c7(f7);
1935    EXPECT_TRUE(c7.HasFile(dir2));
1936    EXPECT_TRUE(c7.HasFile(dir2));
1937    EXPECT_TRUE(c7.HasFile(file1));
1938    EXPECT_TRUE(c7.HasFile(file2_abs));
1939    EXPECT_EQ(4, c7.size());
1940
1941    // Should not enumerate inside dir1 when using recursion.
1942    FileEnumerator f8(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1943    FindResultCollector c8(f8);
1944    EXPECT_TRUE(c8.HasFile(dir1));
1945    EXPECT_TRUE(c8.HasFile(dir2));
1946    EXPECT_TRUE(c8.HasFile(file1));
1947    EXPECT_TRUE(c8.HasFile(file2_abs));
1948    EXPECT_TRUE(c8.HasFile(dir2file));
1949    EXPECT_TRUE(c8.HasFile(dir2inner));
1950    EXPECT_TRUE(c8.HasFile(dir2innerfile));
1951    EXPECT_EQ(7, c8.size());
1952  }
1953#endif
1954
1955  // Make sure the destructor closes the find handle while in the middle of a
1956  // query to allow TearDown to delete the directory.
1957  FileEnumerator f9(temp_dir_.path(), true, FILES_AND_DIRECTORIES);
1958  EXPECT_FALSE(f9.Next().value().empty());  // Should have found something
1959                                            // (we don't care what).
1960}
1961
1962TEST_F(FileUtilTest, AppendToFile) {
1963  FilePath data_dir =
1964      temp_dir_.path().Append(FILE_PATH_LITERAL("FilePathTest"));
1965
1966  // Create a fresh, empty copy of this directory.
1967  if (PathExists(data_dir)) {
1968    ASSERT_TRUE(DeleteFile(data_dir, true));
1969  }
1970  ASSERT_TRUE(CreateDirectory(data_dir));
1971
1972  // Create a fresh, empty copy of this directory.
1973  if (PathExists(data_dir)) {
1974    ASSERT_TRUE(DeleteFile(data_dir, true));
1975  }
1976  ASSERT_TRUE(CreateDirectory(data_dir));
1977  FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
1978
1979  std::string data("hello");
1980  EXPECT_EQ(-1, AppendToFile(foobar, data.c_str(), data.length()));
1981  EXPECT_EQ(static_cast<int>(data.length()),
1982            WriteFile(foobar, data.c_str(), data.length()));
1983  EXPECT_EQ(static_cast<int>(data.length()),
1984            AppendToFile(foobar, data.c_str(), data.length()));
1985
1986  const std::wstring read_content = ReadTextFile(foobar);
1987  EXPECT_EQ(L"hellohello", read_content);
1988}
1989
1990TEST_F(FileUtilTest, ReadFile) {
1991  // Create a test file to be read.
1992  const std::string kTestData("The quick brown fox jumps over the lazy dog.");
1993  FilePath file_path =
1994      temp_dir_.path().Append(FILE_PATH_LITERAL("ReadFileTest"));
1995
1996  ASSERT_EQ(static_cast<int>(kTestData.size()),
1997            WriteFile(file_path, kTestData.data(), kTestData.size()));
1998
1999  // Make buffers with various size.
2000  std::vector<char> small_buffer(kTestData.size() / 2);
2001  std::vector<char> exact_buffer(kTestData.size());
2002  std::vector<char> large_buffer(kTestData.size() * 2);
2003
2004  // Read the file with smaller buffer.
2005  int bytes_read_small = ReadFile(
2006      file_path, &small_buffer[0], static_cast<int>(small_buffer.size()));
2007  EXPECT_EQ(static_cast<int>(small_buffer.size()), bytes_read_small);
2008  EXPECT_EQ(
2009      std::string(kTestData.begin(), kTestData.begin() + small_buffer.size()),
2010      std::string(small_buffer.begin(), small_buffer.end()));
2011
2012  // Read the file with buffer which have exactly same size.
2013  int bytes_read_exact = ReadFile(
2014      file_path, &exact_buffer[0], static_cast<int>(exact_buffer.size()));
2015  EXPECT_EQ(static_cast<int>(kTestData.size()), bytes_read_exact);
2016  EXPECT_EQ(kTestData, std::string(exact_buffer.begin(), exact_buffer.end()));
2017
2018  // Read the file with larger buffer.
2019  int bytes_read_large = ReadFile(
2020      file_path, &large_buffer[0], static_cast<int>(large_buffer.size()));
2021  EXPECT_EQ(static_cast<int>(kTestData.size()), bytes_read_large);
2022  EXPECT_EQ(kTestData, std::string(large_buffer.begin(),
2023                                   large_buffer.begin() + kTestData.size()));
2024
2025  // Make sure the return value is -1 if the file doesn't exist.
2026  FilePath file_path_not_exist =
2027      temp_dir_.path().Append(FILE_PATH_LITERAL("ReadFileNotExistTest"));
2028  EXPECT_EQ(-1,
2029            ReadFile(file_path_not_exist,
2030                     &exact_buffer[0],
2031                     static_cast<int>(exact_buffer.size())));
2032}
2033
2034TEST_F(FileUtilTest, ReadFileToString) {
2035  const char kTestData[] = "0123";
2036  std::string data;
2037
2038  FilePath file_path =
2039      temp_dir_.path().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
2040  FilePath file_path_dangerous =
2041      temp_dir_.path().Append(FILE_PATH_LITERAL("..")).
2042      Append(temp_dir_.path().BaseName()).
2043      Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
2044
2045  // Create test file.
2046  ASSERT_EQ(4, WriteFile(file_path, kTestData, 4));
2047
2048  EXPECT_TRUE(ReadFileToString(file_path, &data));
2049  EXPECT_EQ(kTestData, data);
2050
2051  data = "temp";
2052  EXPECT_FALSE(ReadFileToString(file_path, &data, 0));
2053  EXPECT_EQ(0u, data.length());
2054
2055  data = "temp";
2056  EXPECT_FALSE(ReadFileToString(file_path, &data, 2));
2057  EXPECT_EQ("01", data);
2058
2059  data.clear();
2060  EXPECT_FALSE(ReadFileToString(file_path, &data, 3));
2061  EXPECT_EQ("012", data);
2062
2063  data.clear();
2064  EXPECT_TRUE(ReadFileToString(file_path, &data, 4));
2065  EXPECT_EQ("0123", data);
2066
2067  data.clear();
2068  EXPECT_TRUE(ReadFileToString(file_path, &data, 6));
2069  EXPECT_EQ("0123", data);
2070
2071  EXPECT_TRUE(ReadFileToString(file_path, NULL, 6));
2072
2073  EXPECT_TRUE(ReadFileToString(file_path, NULL));
2074
2075  data = "temp";
2076  EXPECT_FALSE(ReadFileToString(file_path_dangerous, &data));
2077  EXPECT_EQ(0u, data.length());
2078
2079  // Delete test file.
2080  EXPECT_TRUE(base::DeleteFile(file_path, false));
2081
2082  data = "temp";
2083  EXPECT_FALSE(ReadFileToString(file_path, &data));
2084  EXPECT_EQ(0u, data.length());
2085
2086  data = "temp";
2087  EXPECT_FALSE(ReadFileToString(file_path, &data, 6));
2088  EXPECT_EQ(0u, data.length());
2089}
2090
2091TEST_F(FileUtilTest, TouchFile) {
2092  FilePath data_dir =
2093      temp_dir_.path().Append(FILE_PATH_LITERAL("FilePathTest"));
2094
2095  // Create a fresh, empty copy of this directory.
2096  if (PathExists(data_dir)) {
2097    ASSERT_TRUE(DeleteFile(data_dir, true));
2098  }
2099  ASSERT_TRUE(CreateDirectory(data_dir));
2100
2101  FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
2102  std::string data("hello");
2103  ASSERT_TRUE(WriteFile(foobar, data.c_str(), data.length()));
2104
2105  Time access_time;
2106  // This timestamp is divisible by one day (in local timezone),
2107  // to make it work on FAT too.
2108  ASSERT_TRUE(Time::FromString("Wed, 16 Nov 1994, 00:00:00",
2109                               &access_time));
2110
2111  Time modification_time;
2112  // Note that this timestamp is divisible by two (seconds) - FAT stores
2113  // modification times with 2s resolution.
2114  ASSERT_TRUE(Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT",
2115              &modification_time));
2116
2117  ASSERT_TRUE(TouchFile(foobar, access_time, modification_time));
2118  File::Info file_info;
2119  ASSERT_TRUE(GetFileInfo(foobar, &file_info));
2120  EXPECT_EQ(access_time.ToInternalValue(),
2121            file_info.last_accessed.ToInternalValue());
2122  EXPECT_EQ(modification_time.ToInternalValue(),
2123            file_info.last_modified.ToInternalValue());
2124}
2125
2126TEST_F(FileUtilTest, IsDirectoryEmpty) {
2127  FilePath empty_dir = temp_dir_.path().Append(FILE_PATH_LITERAL("EmptyDir"));
2128
2129  ASSERT_FALSE(PathExists(empty_dir));
2130
2131  ASSERT_TRUE(CreateDirectory(empty_dir));
2132
2133  EXPECT_TRUE(IsDirectoryEmpty(empty_dir));
2134
2135  FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt")));
2136  std::string bar("baz");
2137  ASSERT_TRUE(WriteFile(foo, bar.c_str(), bar.length()));
2138
2139  EXPECT_FALSE(IsDirectoryEmpty(empty_dir));
2140}
2141
2142#if defined(OS_POSIX)
2143
2144// Testing VerifyPathControlledByAdmin() is hard, because there is no
2145// way a test can make a file owned by root, or change file paths
2146// at the root of the file system.  VerifyPathControlledByAdmin()
2147// is implemented as a call to VerifyPathControlledByUser, which gives
2148// us the ability to test with paths under the test's temp directory,
2149// using a user id we control.
2150// Pull tests of VerifyPathControlledByUserTest() into a separate test class
2151// with a common SetUp() method.
2152class VerifyPathControlledByUserTest : public FileUtilTest {
2153 protected:
2154  virtual void SetUp() OVERRIDE {
2155    FileUtilTest::SetUp();
2156
2157    // Create a basic structure used by each test.
2158    // base_dir_
2159    //  |-> sub_dir_
2160    //       |-> text_file_
2161
2162    base_dir_ = temp_dir_.path().AppendASCII("base_dir");
2163    ASSERT_TRUE(CreateDirectory(base_dir_));
2164
2165    sub_dir_ = base_dir_.AppendASCII("sub_dir");
2166    ASSERT_TRUE(CreateDirectory(sub_dir_));
2167
2168    text_file_ = sub_dir_.AppendASCII("file.txt");
2169    CreateTextFile(text_file_, L"This text file has some text in it.");
2170
2171    // Get the user and group files are created with from |base_dir_|.
2172    struct stat stat_buf;
2173    ASSERT_EQ(0, stat(base_dir_.value().c_str(), &stat_buf));
2174    uid_ = stat_buf.st_uid;
2175    ok_gids_.insert(stat_buf.st_gid);
2176    bad_gids_.insert(stat_buf.st_gid + 1);
2177
2178    ASSERT_EQ(uid_, getuid());  // This process should be the owner.
2179
2180    // To ensure that umask settings do not cause the initial state
2181    // of permissions to be different from what we expect, explicitly
2182    // set permissions on the directories we create.
2183    // Make all files and directories non-world-writable.
2184
2185    // Users and group can read, write, traverse
2186    int enabled_permissions =
2187        FILE_PERMISSION_USER_MASK | FILE_PERMISSION_GROUP_MASK;
2188    // Other users can't read, write, traverse
2189    int disabled_permissions = FILE_PERMISSION_OTHERS_MASK;
2190
2191    ASSERT_NO_FATAL_FAILURE(
2192        ChangePosixFilePermissions(
2193            base_dir_, enabled_permissions, disabled_permissions));
2194    ASSERT_NO_FATAL_FAILURE(
2195        ChangePosixFilePermissions(
2196            sub_dir_, enabled_permissions, disabled_permissions));
2197  }
2198
2199  FilePath base_dir_;
2200  FilePath sub_dir_;
2201  FilePath text_file_;
2202  uid_t uid_;
2203
2204  std::set<gid_t> ok_gids_;
2205  std::set<gid_t> bad_gids_;
2206};
2207
2208TEST_F(VerifyPathControlledByUserTest, BadPaths) {
2209  // File does not exist.
2210  FilePath does_not_exist = base_dir_.AppendASCII("does")
2211                                     .AppendASCII("not")
2212                                     .AppendASCII("exist");
2213  EXPECT_FALSE(
2214      base::VerifyPathControlledByUser(
2215          base_dir_, does_not_exist, uid_, ok_gids_));
2216
2217  // |base| not a subpath of |path|.
2218  EXPECT_FALSE(
2219      base::VerifyPathControlledByUser(
2220          sub_dir_, base_dir_, uid_, ok_gids_));
2221
2222  // An empty base path will fail to be a prefix for any path.
2223  FilePath empty;
2224  EXPECT_FALSE(
2225      base::VerifyPathControlledByUser(
2226          empty, base_dir_, uid_, ok_gids_));
2227
2228  // Finding that a bad call fails proves nothing unless a good call succeeds.
2229  EXPECT_TRUE(
2230      base::VerifyPathControlledByUser(
2231          base_dir_, sub_dir_, uid_, ok_gids_));
2232}
2233
2234TEST_F(VerifyPathControlledByUserTest, Symlinks) {
2235  // Symlinks in the path should cause failure.
2236
2237  // Symlink to the file at the end of the path.
2238  FilePath file_link =  base_dir_.AppendASCII("file_link");
2239  ASSERT_TRUE(CreateSymbolicLink(text_file_, file_link))
2240      << "Failed to create symlink.";
2241
2242  EXPECT_FALSE(
2243      base::VerifyPathControlledByUser(
2244          base_dir_, file_link, uid_, ok_gids_));
2245  EXPECT_FALSE(
2246      base::VerifyPathControlledByUser(
2247          file_link, file_link, uid_, ok_gids_));
2248
2249  // Symlink from one directory to another within the path.
2250  FilePath link_to_sub_dir =  base_dir_.AppendASCII("link_to_sub_dir");
2251  ASSERT_TRUE(CreateSymbolicLink(sub_dir_, link_to_sub_dir))
2252    << "Failed to create symlink.";
2253
2254  FilePath file_path_with_link = link_to_sub_dir.AppendASCII("file.txt");
2255  ASSERT_TRUE(PathExists(file_path_with_link));
2256
2257  EXPECT_FALSE(
2258      base::VerifyPathControlledByUser(
2259          base_dir_, file_path_with_link, uid_, ok_gids_));
2260
2261  EXPECT_FALSE(
2262      base::VerifyPathControlledByUser(
2263          link_to_sub_dir, file_path_with_link, uid_, ok_gids_));
2264
2265  // Symlinks in parents of base path are allowed.
2266  EXPECT_TRUE(
2267      base::VerifyPathControlledByUser(
2268          file_path_with_link, file_path_with_link, uid_, ok_gids_));
2269}
2270
2271TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
2272  // Get a uid that is not the uid of files we create.
2273  uid_t bad_uid = uid_ + 1;
2274
2275  // Make all files and directories non-world-writable.
2276  ASSERT_NO_FATAL_FAILURE(
2277      ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
2278  ASSERT_NO_FATAL_FAILURE(
2279      ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
2280  ASSERT_NO_FATAL_FAILURE(
2281      ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
2282
2283  // We control these paths.
2284  EXPECT_TRUE(
2285      base::VerifyPathControlledByUser(
2286          base_dir_, sub_dir_, uid_, ok_gids_));
2287  EXPECT_TRUE(
2288      base::VerifyPathControlledByUser(
2289          base_dir_, text_file_, uid_, ok_gids_));
2290  EXPECT_TRUE(
2291      base::VerifyPathControlledByUser(
2292          sub_dir_, text_file_, uid_, ok_gids_));
2293
2294  // Another user does not control these paths.
2295  EXPECT_FALSE(
2296      base::VerifyPathControlledByUser(
2297          base_dir_, sub_dir_, bad_uid, ok_gids_));
2298  EXPECT_FALSE(
2299      base::VerifyPathControlledByUser(
2300          base_dir_, text_file_, bad_uid, ok_gids_));
2301  EXPECT_FALSE(
2302      base::VerifyPathControlledByUser(
2303          sub_dir_, text_file_, bad_uid, ok_gids_));
2304
2305  // Another group does not control the paths.
2306  EXPECT_FALSE(
2307      base::VerifyPathControlledByUser(
2308          base_dir_, sub_dir_, uid_, bad_gids_));
2309  EXPECT_FALSE(
2310      base::VerifyPathControlledByUser(
2311          base_dir_, text_file_, uid_, bad_gids_));
2312  EXPECT_FALSE(
2313      base::VerifyPathControlledByUser(
2314          sub_dir_, text_file_, uid_, bad_gids_));
2315}
2316
2317TEST_F(VerifyPathControlledByUserTest, GroupWriteTest) {
2318  // Make all files and directories writable only by their owner.
2319  ASSERT_NO_FATAL_FAILURE(
2320      ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH|S_IWGRP));
2321  ASSERT_NO_FATAL_FAILURE(
2322      ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH|S_IWGRP));
2323  ASSERT_NO_FATAL_FAILURE(
2324      ChangePosixFilePermissions(text_file_, 0u, S_IWOTH|S_IWGRP));
2325
2326  // Any group is okay because the path is not group-writable.
2327  EXPECT_TRUE(
2328      base::VerifyPathControlledByUser(
2329          base_dir_, sub_dir_, uid_, ok_gids_));
2330  EXPECT_TRUE(
2331      base::VerifyPathControlledByUser(
2332          base_dir_, text_file_, uid_, ok_gids_));
2333  EXPECT_TRUE(
2334      base::VerifyPathControlledByUser(
2335          sub_dir_, text_file_, uid_, ok_gids_));
2336
2337  EXPECT_TRUE(
2338      base::VerifyPathControlledByUser(
2339          base_dir_, sub_dir_, uid_, bad_gids_));
2340  EXPECT_TRUE(
2341      base::VerifyPathControlledByUser(
2342          base_dir_, text_file_, uid_, bad_gids_));
2343  EXPECT_TRUE(
2344      base::VerifyPathControlledByUser(
2345          sub_dir_, text_file_, uid_, bad_gids_));
2346
2347  // No group is okay, because we don't check the group
2348  // if no group can write.
2349  std::set<gid_t> no_gids;  // Empty set of gids.
2350  EXPECT_TRUE(
2351      base::VerifyPathControlledByUser(
2352          base_dir_, sub_dir_, uid_, no_gids));
2353  EXPECT_TRUE(
2354      base::VerifyPathControlledByUser(
2355          base_dir_, text_file_, uid_, no_gids));
2356  EXPECT_TRUE(
2357      base::VerifyPathControlledByUser(
2358          sub_dir_, text_file_, uid_, no_gids));
2359
2360
2361  // Make all files and directories writable by their group.
2362  ASSERT_NO_FATAL_FAILURE(
2363      ChangePosixFilePermissions(base_dir_, S_IWGRP, 0u));
2364  ASSERT_NO_FATAL_FAILURE(
2365      ChangePosixFilePermissions(sub_dir_, S_IWGRP, 0u));
2366  ASSERT_NO_FATAL_FAILURE(
2367      ChangePosixFilePermissions(text_file_, S_IWGRP, 0u));
2368
2369  // Now |ok_gids_| works, but |bad_gids_| fails.
2370  EXPECT_TRUE(
2371      base::VerifyPathControlledByUser(
2372          base_dir_, sub_dir_, uid_, ok_gids_));
2373  EXPECT_TRUE(
2374      base::VerifyPathControlledByUser(
2375          base_dir_, text_file_, uid_, ok_gids_));
2376  EXPECT_TRUE(
2377      base::VerifyPathControlledByUser(
2378          sub_dir_, text_file_, uid_, ok_gids_));
2379
2380  EXPECT_FALSE(
2381      base::VerifyPathControlledByUser(
2382          base_dir_, sub_dir_, uid_, bad_gids_));
2383  EXPECT_FALSE(
2384      base::VerifyPathControlledByUser(
2385          base_dir_, text_file_, uid_, bad_gids_));
2386  EXPECT_FALSE(
2387      base::VerifyPathControlledByUser(
2388          sub_dir_, text_file_, uid_, bad_gids_));
2389
2390  // Because any group in the group set is allowed,
2391  // the union of good and bad gids passes.
2392
2393  std::set<gid_t> multiple_gids;
2394  std::set_union(
2395      ok_gids_.begin(), ok_gids_.end(),
2396      bad_gids_.begin(), bad_gids_.end(),
2397      std::inserter(multiple_gids, multiple_gids.begin()));
2398
2399  EXPECT_TRUE(
2400      base::VerifyPathControlledByUser(
2401          base_dir_, sub_dir_, uid_, multiple_gids));
2402  EXPECT_TRUE(
2403      base::VerifyPathControlledByUser(
2404          base_dir_, text_file_, uid_, multiple_gids));
2405  EXPECT_TRUE(
2406      base::VerifyPathControlledByUser(
2407          sub_dir_, text_file_, uid_, multiple_gids));
2408}
2409
2410TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
2411  // Make all files and directories non-world-writable.
2412  ASSERT_NO_FATAL_FAILURE(
2413      ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
2414  ASSERT_NO_FATAL_FAILURE(
2415      ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
2416  ASSERT_NO_FATAL_FAILURE(
2417      ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
2418
2419  // Initialy, we control all parts of the path.
2420  EXPECT_TRUE(
2421      base::VerifyPathControlledByUser(
2422          base_dir_, sub_dir_, uid_, ok_gids_));
2423  EXPECT_TRUE(
2424      base::VerifyPathControlledByUser(
2425          base_dir_, text_file_, uid_, ok_gids_));
2426  EXPECT_TRUE(
2427      base::VerifyPathControlledByUser(
2428          sub_dir_, text_file_, uid_, ok_gids_));
2429
2430  // Make base_dir_ world-writable.
2431  ASSERT_NO_FATAL_FAILURE(
2432      ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
2433  EXPECT_FALSE(
2434      base::VerifyPathControlledByUser(
2435          base_dir_, sub_dir_, uid_, ok_gids_));
2436  EXPECT_FALSE(
2437      base::VerifyPathControlledByUser(
2438          base_dir_, text_file_, uid_, ok_gids_));
2439  EXPECT_TRUE(
2440      base::VerifyPathControlledByUser(
2441          sub_dir_, text_file_, uid_, ok_gids_));
2442
2443  // Make sub_dir_ world writable.
2444  ASSERT_NO_FATAL_FAILURE(
2445      ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
2446  EXPECT_FALSE(
2447      base::VerifyPathControlledByUser(
2448          base_dir_, sub_dir_, uid_, ok_gids_));
2449  EXPECT_FALSE(
2450      base::VerifyPathControlledByUser(
2451          base_dir_, text_file_, uid_, ok_gids_));
2452  EXPECT_FALSE(
2453      base::VerifyPathControlledByUser(
2454          sub_dir_, text_file_, uid_, ok_gids_));
2455
2456  // Make text_file_ world writable.
2457  ASSERT_NO_FATAL_FAILURE(
2458      ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
2459  EXPECT_FALSE(
2460      base::VerifyPathControlledByUser(
2461          base_dir_, sub_dir_, uid_, ok_gids_));
2462  EXPECT_FALSE(
2463      base::VerifyPathControlledByUser(
2464          base_dir_, text_file_, uid_, ok_gids_));
2465  EXPECT_FALSE(
2466      base::VerifyPathControlledByUser(
2467          sub_dir_, text_file_, uid_, ok_gids_));
2468
2469  // Make sub_dir_ non-world writable.
2470  ASSERT_NO_FATAL_FAILURE(
2471      ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
2472  EXPECT_FALSE(
2473      base::VerifyPathControlledByUser(
2474          base_dir_, sub_dir_, uid_, ok_gids_));
2475  EXPECT_FALSE(
2476      base::VerifyPathControlledByUser(
2477          base_dir_, text_file_, uid_, ok_gids_));
2478  EXPECT_FALSE(
2479      base::VerifyPathControlledByUser(
2480          sub_dir_, text_file_, uid_, ok_gids_));
2481
2482  // Make base_dir_ non-world-writable.
2483  ASSERT_NO_FATAL_FAILURE(
2484      ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
2485  EXPECT_TRUE(
2486      base::VerifyPathControlledByUser(
2487          base_dir_, sub_dir_, uid_, ok_gids_));
2488  EXPECT_FALSE(
2489      base::VerifyPathControlledByUser(
2490          base_dir_, text_file_, uid_, ok_gids_));
2491  EXPECT_FALSE(
2492      base::VerifyPathControlledByUser(
2493          sub_dir_, text_file_, uid_, ok_gids_));
2494
2495  // Back to the initial state: Nothing is writable, so every path
2496  // should pass.
2497  ASSERT_NO_FATAL_FAILURE(
2498      ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
2499  EXPECT_TRUE(
2500      base::VerifyPathControlledByUser(
2501          base_dir_, sub_dir_, uid_, ok_gids_));
2502  EXPECT_TRUE(
2503      base::VerifyPathControlledByUser(
2504          base_dir_, text_file_, uid_, ok_gids_));
2505  EXPECT_TRUE(
2506      base::VerifyPathControlledByUser(
2507          sub_dir_, text_file_, uid_, ok_gids_));
2508}
2509
2510#if defined(OS_ANDROID)
2511TEST_F(FileUtilTest, ValidContentUriTest) {
2512  // Get the test image path.
2513  FilePath data_dir;
2514  ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
2515  data_dir = data_dir.AppendASCII("file_util");
2516  ASSERT_TRUE(PathExists(data_dir));
2517  FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
2518  int64 image_size;
2519  GetFileSize(image_file, &image_size);
2520  EXPECT_LT(0, image_size);
2521
2522  // Insert the image into MediaStore. MediaStore will do some conversions, and
2523  // return the content URI.
2524  FilePath path = base::InsertImageIntoMediaStore(image_file);
2525  EXPECT_TRUE(path.IsContentUri());
2526  EXPECT_TRUE(PathExists(path));
2527  // The file size may not equal to the input image as MediaStore may convert
2528  // the image.
2529  int64 content_uri_size;
2530  GetFileSize(path, &content_uri_size);
2531  EXPECT_EQ(image_size, content_uri_size);
2532
2533  // We should be able to read the file.
2534  char* buffer = new char[image_size];
2535  File file = OpenContentUriForRead(path);
2536  EXPECT_TRUE(file.IsValid());
2537  EXPECT_TRUE(file.ReadAtCurrentPos(buffer, image_size));
2538  delete[] buffer;
2539}
2540
2541TEST_F(FileUtilTest, NonExistentContentUriTest) {
2542  FilePath path("content://foo.bar");
2543  EXPECT_TRUE(path.IsContentUri());
2544  EXPECT_FALSE(PathExists(path));
2545  // Size should be smaller than 0.
2546  int64 size;
2547  EXPECT_FALSE(GetFileSize(path, &size));
2548
2549  // We should not be able to read the file.
2550  File file = OpenContentUriForRead(path);
2551  EXPECT_FALSE(file.IsValid());
2552}
2553#endif
2554
2555TEST(ScopedFD, ScopedFDDoesClose) {
2556  int fds[2];
2557  char c = 0;
2558  ASSERT_EQ(0, pipe(fds));
2559  const int write_end = fds[1];
2560  base::ScopedFD read_end_closer(fds[0]);
2561  {
2562    base::ScopedFD write_end_closer(fds[1]);
2563  }
2564  // This is the only thread. This file descriptor should no longer be valid.
2565  int ret = close(write_end);
2566  EXPECT_EQ(-1, ret);
2567  EXPECT_EQ(EBADF, errno);
2568  // Make sure read(2) won't block.
2569  ASSERT_EQ(0, fcntl(fds[0], F_SETFL, O_NONBLOCK));
2570  // Reading the pipe should EOF.
2571  EXPECT_EQ(0, read(fds[0], &c, 1));
2572}
2573
2574#if defined(GTEST_HAS_DEATH_TEST)
2575void CloseWithScopedFD(int fd) {
2576  base::ScopedFD fd_closer(fd);
2577}
2578#endif
2579
2580TEST(ScopedFD, ScopedFDCrashesOnCloseFailure) {
2581  int fds[2];
2582  ASSERT_EQ(0, pipe(fds));
2583  base::ScopedFD read_end_closer(fds[0]);
2584  EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
2585#if defined(GTEST_HAS_DEATH_TEST)
2586  // This is the only thread. This file descriptor should no longer be valid.
2587  // Trying to close it should crash. This is important for security.
2588  EXPECT_DEATH(CloseWithScopedFD(fds[1]), "");
2589#endif
2590}
2591
2592#endif  // defined(OS_POSIX)
2593
2594}  // namespace
2595
2596}  // namespace base
2597