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 "base/files/file_util.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdio.h>
10
11 #include <algorithm>
12 #include <fstream>
13 #include <initializer_list>
14 #include <memory>
15 #include <set>
16 #include <utility>
17 #include <vector>
18
19 #include "base/base_paths.h"
20 #include "base/bind.h"
21 #include "base/bind_helpers.h"
22 #include "base/callback_helpers.h"
23 #include "base/command_line.h"
24 #include "base/environment.h"
25 #include "base/files/file.h"
26 #include "base/files/file_enumerator.h"
27 #include "base/files/file_path.h"
28 #include "base/files/scoped_file.h"
29 #include "base/files/scoped_temp_dir.h"
30 #include "base/guid.h"
31 #include "base/path_service.h"
32 #include "base/stl_util.h"
33 #include "base/strings/string_util.h"
34 #include "base/strings/stringprintf.h"
35 #include "base/strings/utf_string_conversions.h"
36 #include "base/test/multiprocess_test.h"
37 #include "base/test/scoped_environment_variable_override.h"
38 #include "base/test/test_file_util.h"
39 #include "base/test/test_timeouts.h"
40 #include "base/threading/platform_thread.h"
41 #include "base/threading/thread.h"
42 #include "base/time/time.h"
43 #include "build/build_config.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45 #include "testing/multiprocess_func_list.h"
46 #include "testing/platform_test.h"
47
48 #if defined(OS_WIN)
49 #include <shellapi.h>
50 #include <shlobj.h>
51 #include <tchar.h>
52 #include <windows.h>
53 #include <winioctl.h>
54 #include "base/strings/string_number_conversions.h"
55 #include "base/win/scoped_handle.h"
56 #include "base/win/win_util.h"
57 #endif
58
59 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
60 #include <errno.h>
61 #include <fcntl.h>
62 #include <sys/ioctl.h>
63 #include <sys/types.h>
64 #include <unistd.h>
65 #endif
66
67 #if defined(OS_LINUX)
68 #include <linux/fs.h>
69 #endif
70
71 #if defined(OS_ANDROID)
72 #include "base/android/content_uri_utils.h"
73 #endif
74
75 // This macro helps avoid wrapped lines in the test structs.
76 #define FPL(x) FILE_PATH_LITERAL(x)
77
78 namespace base {
79
80 namespace {
81
82 const size_t kLargeFileSize = (1 << 16) + 3;
83
84 // To test that NormalizeFilePath() deals with NTFS reparse points correctly,
85 // we need functions to create and delete reparse points.
86 #if defined(OS_WIN)
87 typedef struct _REPARSE_DATA_BUFFER {
88 ULONG ReparseTag;
89 USHORT ReparseDataLength;
90 USHORT Reserved;
91 union {
92 struct {
93 USHORT SubstituteNameOffset;
94 USHORT SubstituteNameLength;
95 USHORT PrintNameOffset;
96 USHORT PrintNameLength;
97 ULONG Flags;
98 WCHAR PathBuffer[1];
99 } SymbolicLinkReparseBuffer;
100 struct {
101 USHORT SubstituteNameOffset;
102 USHORT SubstituteNameLength;
103 USHORT PrintNameOffset;
104 USHORT PrintNameLength;
105 WCHAR PathBuffer[1];
106 } MountPointReparseBuffer;
107 struct {
108 UCHAR DataBuffer[1];
109 } GenericReparseBuffer;
110 };
111 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
112
113 // Sets a reparse point. |source| will now point to |target|. Returns true if
114 // the call succeeds, false otherwise.
SetReparsePoint(HANDLE source,const FilePath & target_path)115 bool SetReparsePoint(HANDLE source, const FilePath& target_path) {
116 std::wstring kPathPrefix = FILE_PATH_LITERAL("\\??\\");
117 std::wstring target_str;
118 // The juction will not work if the target path does not start with \??\ .
119 if (kPathPrefix != target_path.value().substr(0, kPathPrefix.size()))
120 target_str += kPathPrefix;
121 target_str += target_path.value();
122 const wchar_t* target = target_str.c_str();
123 USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]);
124 char buffer[2000] = {0};
125 DWORD returned;
126
127 REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
128
129 data->ReparseTag = 0xa0000003;
130 memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
131
132 data->MountPointReparseBuffer.SubstituteNameLength = size_target;
133 data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
134 data->ReparseDataLength = size_target + 4 + 8;
135
136 int data_size = data->ReparseDataLength + 8;
137
138 if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size,
139 NULL, 0, &returned, NULL)) {
140 return false;
141 }
142 return true;
143 }
144
145 // Delete the reparse point referenced by |source|. Returns true if the call
146 // succeeds, false otherwise.
DeleteReparsePoint(HANDLE source)147 bool DeleteReparsePoint(HANDLE source) {
148 DWORD returned;
149 REPARSE_DATA_BUFFER data = {0};
150 data.ReparseTag = 0xa0000003;
151 if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
152 &returned, NULL)) {
153 return false;
154 }
155 return true;
156 }
157
158 // Method that wraps the win32 GetShortPathName API. Returns an empty path on
159 // error.
MakeShortFilePath(const FilePath & input)160 FilePath MakeShortFilePath(const FilePath& input) {
161 DWORD path_short_len = ::GetShortPathName(input.value().c_str(), nullptr, 0);
162 if (path_short_len == 0UL)
163 return FilePath();
164
165 std::wstring path_short_str;
166 path_short_len = ::GetShortPathName(
167 input.value().c_str(), WriteInto(&path_short_str, path_short_len),
168 path_short_len);
169 if (path_short_len == 0UL)
170 return FilePath();
171
172 return FilePath(path_short_str);
173 }
174
175 // Manages a reparse point for a test.
176 class ReparsePoint {
177 public:
178 // Creates a reparse point from |source| (an empty directory) to |target|.
ReparsePoint(const FilePath & source,const FilePath & target)179 ReparsePoint(const FilePath& source, const FilePath& target) {
180 dir_.Set(
181 ::CreateFile(source.value().c_str(), GENERIC_READ | GENERIC_WRITE,
182 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
183 NULL, OPEN_EXISTING,
184 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
185 NULL));
186 created_ = dir_.IsValid() && SetReparsePoint(dir_.Get(), target);
187 }
188
~ReparsePoint()189 ~ReparsePoint() {
190 if (created_)
191 DeleteReparsePoint(dir_.Get());
192 }
193
IsValid()194 bool IsValid() { return created_; }
195
196 private:
197 win::ScopedHandle dir_;
198 bool created_;
199 DISALLOW_COPY_AND_ASSIGN(ReparsePoint);
200 };
201
202 #endif
203
204 // Fuchsia doesn't support file permissions.
205 #if !defined(OS_FUCHSIA)
206 #if defined(OS_POSIX)
207 // Provide a simple way to change the permissions bits on |path| in tests.
208 // ASSERT failures will return, but not stop the test. Caller should wrap
209 // calls to this function in ASSERT_NO_FATAL_FAILURE().
ChangePosixFilePermissions(const FilePath & path,int mode_bits_to_set,int mode_bits_to_clear)210 void ChangePosixFilePermissions(const FilePath& path,
211 int mode_bits_to_set,
212 int mode_bits_to_clear) {
213 ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
214 << "Can't set and clear the same bits.";
215
216 int mode = 0;
217 ASSERT_TRUE(GetPosixFilePermissions(path, &mode));
218 mode |= mode_bits_to_set;
219 mode &= ~mode_bits_to_clear;
220 ASSERT_TRUE(SetPosixFilePermissions(path, mode));
221 }
222 #endif // defined(OS_POSIX)
223
224 // Sets the source file to read-only.
SetReadOnly(const FilePath & path,bool read_only)225 void SetReadOnly(const FilePath& path, bool read_only) {
226 #if defined(OS_WIN)
227 // On Windows, it involves setting/removing the 'readonly' bit.
228 DWORD attrs = GetFileAttributes(path.value().c_str());
229 ASSERT_NE(INVALID_FILE_ATTRIBUTES, attrs);
230 ASSERT_TRUE(SetFileAttributes(
231 path.value().c_str(), read_only ? (attrs | FILE_ATTRIBUTE_READONLY)
232 : (attrs & ~FILE_ATTRIBUTE_READONLY)));
233
234 DWORD expected =
235 read_only
236 ? ((attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY)) |
237 FILE_ATTRIBUTE_READONLY)
238 : (attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY));
239
240 // Ignore FILE_ATTRIBUTE_NOT_CONTENT_INDEXED and FILE_ATTRIBUTE_COMPRESSED
241 // if present. These flags are set by the operating system, depending on
242 // local configurations, such as compressing the file system. Not filtering
243 // out these flags could cause tests to fail even though they should pass.
244 attrs = GetFileAttributes(path.value().c_str()) &
245 ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_COMPRESSED);
246 ASSERT_EQ(expected, attrs);
247 #else
248 // On all other platforms, it involves removing/setting the write bit.
249 mode_t mode = read_only ? S_IRUSR : (S_IRUSR | S_IWUSR);
250 EXPECT_TRUE(SetPosixFilePermissions(
251 path, DirectoryExists(path) ? (mode | S_IXUSR) : mode));
252 #endif // defined(OS_WIN)
253 }
254
IsReadOnly(const FilePath & path)255 bool IsReadOnly(const FilePath& path) {
256 #if defined(OS_WIN)
257 DWORD attrs = GetFileAttributes(path.value().c_str());
258 EXPECT_NE(INVALID_FILE_ATTRIBUTES, attrs);
259 return attrs & FILE_ATTRIBUTE_READONLY;
260 #else
261 int mode = 0;
262 EXPECT_TRUE(GetPosixFilePermissions(path, &mode));
263 return !(mode & S_IWUSR);
264 #endif // defined(OS_WIN)
265 }
266
267 #endif // defined(OS_FUCHSIA)
268
269 const wchar_t bogus_content[] = L"I'm cannon fodder.";
270
271 const int FILES_AND_DIRECTORIES =
272 FileEnumerator::FILES | FileEnumerator::DIRECTORIES;
273
274 // file_util winds up using autoreleased objects on the Mac, so this needs
275 // to be a PlatformTest
276 class FileUtilTest : public PlatformTest {
277 protected:
SetUp()278 void SetUp() override {
279 PlatformTest::SetUp();
280 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
281 }
282
283 ScopedTempDir temp_dir_;
284 };
285
286 // Collects all the results from the given file enumerator, and provides an
287 // interface to query whether a given file is present.
288 class FindResultCollector {
289 public:
FindResultCollector(FileEnumerator * enumerator)290 explicit FindResultCollector(FileEnumerator* enumerator) {
291 FilePath cur_file;
292 while (!(cur_file = enumerator->Next()).value().empty()) {
293 FilePath::StringType path = cur_file.value();
294 // The file should not be returned twice.
295 EXPECT_TRUE(files_.end() == files_.find(path))
296 << "Same file returned twice";
297
298 // Save for later.
299 files_.insert(path);
300 }
301 }
302
303 // Returns true if the enumerator found the file.
HasFile(const FilePath & file) const304 bool HasFile(const FilePath& file) const {
305 return files_.find(file.value()) != files_.end();
306 }
307
size()308 int size() {
309 return static_cast<int>(files_.size());
310 }
311
312 private:
313 std::set<FilePath::StringType> files_;
314 };
315
316 // Simple function to dump some text into a new file.
CreateTextFile(const FilePath & filename,const std::wstring & contents)317 void CreateTextFile(const FilePath& filename,
318 const std::wstring& contents) {
319 std::wofstream file;
320 #if defined(OS_WIN)
321 file.open(filename.value().c_str());
322 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
323 file.open(filename.value());
324 #endif // OS_WIN
325 ASSERT_TRUE(file.is_open());
326 file << contents;
327 file.close();
328 }
329
330 // Simple function to take out some text from a file.
ReadTextFile(const FilePath & filename)331 std::wstring ReadTextFile(const FilePath& filename) {
332 wchar_t contents[64];
333 std::wifstream file;
334 #if defined(OS_WIN)
335 file.open(filename.value().c_str());
336 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
337 file.open(filename.value());
338 #endif // OS_WIN
339 EXPECT_TRUE(file.is_open());
340 file.getline(contents, size(contents));
341 file.close();
342 return std::wstring(contents);
343 }
344
345 // Sets |is_inheritable| to indicate whether or not |stream| is set up to be
346 // inerhited into child processes (i.e., HANDLE_FLAG_INHERIT is set on the
347 // underlying handle on Windows, or FD_CLOEXEC is not set on the underlying file
348 // descriptor on POSIX). Calls to this function must be wrapped with
349 // ASSERT_NO_FATAL_FAILURE to properly abort tests in case of fatal failure.
GetIsInheritable(FILE * stream,bool * is_inheritable)350 void GetIsInheritable(FILE* stream, bool* is_inheritable) {
351 #if defined(OS_WIN)
352 HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stream)));
353 ASSERT_NE(INVALID_HANDLE_VALUE, handle);
354
355 DWORD info = 0;
356 ASSERT_EQ(TRUE, ::GetHandleInformation(handle, &info));
357 *is_inheritable = ((info & HANDLE_FLAG_INHERIT) != 0);
358 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
359 int fd = fileno(stream);
360 ASSERT_NE(-1, fd);
361 int flags = fcntl(fd, F_GETFD, 0);
362 ASSERT_NE(-1, flags);
363 *is_inheritable = ((flags & FD_CLOEXEC) == 0);
364 #else
365 #error Not implemented
366 #endif
367 }
368
TEST_F(FileUtilTest,FileAndDirectorySize)369 TEST_F(FileUtilTest, FileAndDirectorySize) {
370 // Create three files of 20, 30 and 3 chars (utf8). ComputeDirectorySize
371 // should return 53 bytes.
372 FilePath file_01 = temp_dir_.GetPath().Append(FPL("The file 01.txt"));
373 CreateTextFile(file_01, L"12345678901234567890");
374 int64_t size_f1 = 0;
375 ASSERT_TRUE(GetFileSize(file_01, &size_f1));
376 EXPECT_EQ(20ll, size_f1);
377
378 FilePath subdir_path = temp_dir_.GetPath().Append(FPL("Level2"));
379 CreateDirectory(subdir_path);
380
381 FilePath file_02 = subdir_path.Append(FPL("The file 02.txt"));
382 CreateTextFile(file_02, L"123456789012345678901234567890");
383 int64_t size_f2 = 0;
384 ASSERT_TRUE(GetFileSize(file_02, &size_f2));
385 EXPECT_EQ(30ll, size_f2);
386
387 FilePath subsubdir_path = subdir_path.Append(FPL("Level3"));
388 CreateDirectory(subsubdir_path);
389
390 FilePath file_03 = subsubdir_path.Append(FPL("The file 03.txt"));
391 CreateTextFile(file_03, L"123");
392
393 int64_t computed_size = ComputeDirectorySize(temp_dir_.GetPath());
394 EXPECT_EQ(size_f1 + size_f2 + 3, computed_size);
395 }
396
TEST_F(FileUtilTest,NormalizeFilePathBasic)397 TEST_F(FileUtilTest, NormalizeFilePathBasic) {
398 // Create a directory under the test dir. Because we create it,
399 // we know it is not a link.
400 FilePath file_a_path = temp_dir_.GetPath().Append(FPL("file_a"));
401 FilePath dir_path = temp_dir_.GetPath().Append(FPL("dir"));
402 FilePath file_b_path = dir_path.Append(FPL("file_b"));
403 CreateDirectory(dir_path);
404
405 FilePath normalized_file_a_path, normalized_file_b_path;
406 ASSERT_FALSE(PathExists(file_a_path));
407 ASSERT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
408 << "NormalizeFilePath() should fail on nonexistent paths.";
409
410 CreateTextFile(file_a_path, bogus_content);
411 ASSERT_TRUE(PathExists(file_a_path));
412 ASSERT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
413
414 CreateTextFile(file_b_path, bogus_content);
415 ASSERT_TRUE(PathExists(file_b_path));
416 ASSERT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
417
418 // Because this test created |dir_path|, we know it is not a link
419 // or junction. So, the real path of the directory holding file a
420 // must be the parent of the path holding file b.
421 ASSERT_TRUE(normalized_file_a_path.DirName()
422 .IsParent(normalized_file_b_path.DirName()));
423 }
424
425 #if defined(OS_WIN)
426
TEST_F(FileUtilTest,NormalizeFileEmptyFile)427 TEST_F(FileUtilTest, NormalizeFileEmptyFile) {
428 // Create a directory under the test dir. Because we create it,
429 // we know it is not a link.
430 const wchar_t empty_content[] = L"";
431
432 FilePath file_a_path = temp_dir_.GetPath().Append(FPL("file_empty_a"));
433 FilePath dir_path = temp_dir_.GetPath().Append(FPL("dir"));
434 FilePath file_b_path = dir_path.Append(FPL("file_empty_b"));
435 ASSERT_TRUE(CreateDirectory(dir_path));
436
437 FilePath normalized_file_a_path, normalized_file_b_path;
438 ASSERT_FALSE(PathExists(file_a_path));
439 EXPECT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
440 << "NormalizeFilePath() should fail on nonexistent paths.";
441
442 CreateTextFile(file_a_path, empty_content);
443 ASSERT_TRUE(PathExists(file_a_path));
444 EXPECT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
445
446 CreateTextFile(file_b_path, empty_content);
447 ASSERT_TRUE(PathExists(file_b_path));
448 EXPECT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
449
450 // Because this test created |dir_path|, we know it is not a link
451 // or junction. So, the real path of the directory holding file a
452 // must be the parent of the path holding file b.
453 EXPECT_TRUE(normalized_file_a_path.DirName().IsParent(
454 normalized_file_b_path.DirName()));
455 }
456
TEST_F(FileUtilTest,NormalizeFilePathReparsePoints)457 TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) {
458 // Build the following directory structure:
459 //
460 // temp_dir
461 // |-> base_a
462 // | |-> sub_a
463 // | |-> file.txt
464 // | |-> long_name___... (Very long name.)
465 // | |-> sub_long
466 // | |-> deep.txt
467 // |-> base_b
468 // |-> to_sub_a (reparse point to temp_dir\base_a\sub_a)
469 // |-> to_base_b (reparse point to temp_dir\base_b)
470 // |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
471
472 FilePath base_a = temp_dir_.GetPath().Append(FPL("base_a"));
473 #if defined(OS_WIN)
474 // TEMP can have a lower case drive letter.
475 std::wstring temp_base_a = base_a.value();
476 ASSERT_FALSE(temp_base_a.empty());
477 temp_base_a[0] = ToUpperASCII(char16{temp_base_a[0]});
478 base_a = FilePath(temp_base_a);
479 #endif
480 ASSERT_TRUE(CreateDirectory(base_a));
481 #if defined(OS_WIN)
482 // TEMP might be a short name which is not normalized.
483 base_a = MakeLongFilePath(base_a);
484 #endif
485
486 FilePath sub_a = base_a.Append(FPL("sub_a"));
487 ASSERT_TRUE(CreateDirectory(sub_a));
488
489 FilePath file_txt = sub_a.Append(FPL("file.txt"));
490 CreateTextFile(file_txt, bogus_content);
491
492 // Want a directory whose name is long enough to make the path to the file
493 // inside just under MAX_PATH chars. This will be used to test that when
494 // a junction expands to a path over MAX_PATH chars in length,
495 // NormalizeFilePath() fails without crashing.
496 FilePath sub_long_rel(FPL("sub_long"));
497 FilePath deep_txt(FPL("deep.txt"));
498
499 int target_length = MAX_PATH;
500 target_length -= (sub_a.value().length() + 1); // +1 for the sepperator '\'.
501 target_length -= (sub_long_rel.Append(deep_txt).value().length() + 1);
502 // Without making the path a bit shorter, CreateDirectory() fails.
503 // the resulting path is still long enough to hit the failing case in
504 // NormalizePath().
505 const int kCreateDirLimit = 4;
506 target_length -= kCreateDirLimit;
507 FilePath::StringType long_name_str = FPL("long_name_");
508 long_name_str.resize(target_length, '_');
509
510 FilePath long_name = sub_a.Append(FilePath(long_name_str));
511 FilePath deep_file = long_name.Append(sub_long_rel).Append(deep_txt);
512 ASSERT_EQ(static_cast<size_t>(MAX_PATH - kCreateDirLimit),
513 deep_file.value().length());
514
515 FilePath sub_long = deep_file.DirName();
516 ASSERT_TRUE(CreateDirectory(sub_long));
517 CreateTextFile(deep_file, bogus_content);
518
519 FilePath base_b = temp_dir_.GetPath().Append(FPL("base_b"));
520 ASSERT_TRUE(CreateDirectory(base_b));
521 #if defined(OS_WIN)
522 // TEMP might be a short name which is not normalized.
523 base_b = MakeLongFilePath(base_b);
524 #endif
525
526 FilePath to_sub_a = base_b.Append(FPL("to_sub_a"));
527 ASSERT_TRUE(CreateDirectory(to_sub_a));
528 FilePath normalized_path;
529 {
530 ReparsePoint reparse_to_sub_a(to_sub_a, sub_a);
531 ASSERT_TRUE(reparse_to_sub_a.IsValid());
532
533 FilePath to_base_b = base_b.Append(FPL("to_base_b"));
534 ASSERT_TRUE(CreateDirectory(to_base_b));
535 ReparsePoint reparse_to_base_b(to_base_b, base_b);
536 ASSERT_TRUE(reparse_to_base_b.IsValid());
537
538 FilePath to_sub_long = base_b.Append(FPL("to_sub_long"));
539 ASSERT_TRUE(CreateDirectory(to_sub_long));
540 ReparsePoint reparse_to_sub_long(to_sub_long, sub_long);
541 ASSERT_TRUE(reparse_to_sub_long.IsValid());
542
543 // Normalize a junction free path: base_a\sub_a\file.txt .
544 ASSERT_TRUE(NormalizeFilePath(file_txt, &normalized_path));
545 ASSERT_EQ(file_txt.value(), normalized_path.value());
546
547 // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude
548 // the junction to_sub_a.
549 ASSERT_TRUE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
550 &normalized_path));
551 ASSERT_EQ(file_txt.value(), normalized_path.value());
552
553 // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be
554 // normalized to exclude junctions to_base_b and to_sub_a .
555 ASSERT_TRUE(NormalizeFilePath(base_b.Append(FPL("to_base_b"))
556 .Append(FPL("to_base_b"))
557 .Append(FPL("to_sub_a"))
558 .Append(FPL("file.txt")),
559 &normalized_path));
560 ASSERT_EQ(file_txt.value(), normalized_path.value());
561
562 // A long enough path will cause NormalizeFilePath() to fail. Make a long
563 // path using to_base_b many times, and check that paths long enough to fail
564 // do not cause a crash.
565 FilePath long_path = base_b;
566 const int kLengthLimit = MAX_PATH + 200;
567 while (long_path.value().length() <= kLengthLimit) {
568 long_path = long_path.Append(FPL("to_base_b"));
569 }
570 long_path = long_path.Append(FPL("to_sub_a"))
571 .Append(FPL("file.txt"));
572
573 ASSERT_FALSE(NormalizeFilePath(long_path, &normalized_path));
574
575 // Normalizing the junction to deep.txt should fail, because the expanded
576 // path to deep.txt is longer than MAX_PATH.
577 ASSERT_FALSE(NormalizeFilePath(to_sub_long.Append(deep_txt),
578 &normalized_path));
579
580 // Delete the reparse points, and see that NormalizeFilePath() fails
581 // to traverse them.
582 }
583
584 ASSERT_FALSE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
585 &normalized_path));
586 }
587
TEST_F(FileUtilTest,DevicePathToDriveLetter)588 TEST_F(FileUtilTest, DevicePathToDriveLetter) {
589 // Get a drive letter.
590 std::wstring real_drive_letter = AsWString(
591 ToUpperASCII(AsStringPiece16(temp_dir_.GetPath().value().substr(0, 2))));
592 if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
593 LOG(ERROR) << "Can't get a drive letter to test with.";
594 return;
595 }
596
597 // Get the NT style path to that drive.
598 wchar_t device_path[MAX_PATH] = {'\0'};
599 ASSERT_TRUE(
600 ::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH));
601 FilePath actual_device_path(device_path);
602 FilePath win32_path;
603
604 // Run DevicePathToDriveLetterPath() on the NT style path we got from
605 // QueryDosDevice(). Expect the drive letter we started with.
606 ASSERT_TRUE(DevicePathToDriveLetterPath(actual_device_path, &win32_path));
607 ASSERT_EQ(real_drive_letter, win32_path.value());
608
609 // Add some directories to the path. Expect those extra path componenets
610 // to be preserved.
611 FilePath kRelativePath(FPL("dir1\\dir2\\file.txt"));
612 ASSERT_TRUE(DevicePathToDriveLetterPath(
613 actual_device_path.Append(kRelativePath),
614 &win32_path));
615 EXPECT_EQ(FilePath(real_drive_letter + FILE_PATH_LITERAL("\\"))
616 .Append(kRelativePath)
617 .value(),
618 win32_path.value());
619
620 // Deform the real path so that it is invalid by removing the last four
621 // characters. The way windows names devices that are hard disks
622 // (\Device\HardDiskVolume${NUMBER}) guarantees that the string is longer
623 // than three characters. The only way the truncated string could be a
624 // real drive is if more than 10^3 disks are mounted:
625 // \Device\HardDiskVolume10000 would be truncated to \Device\HardDiskVolume1
626 // Check that DevicePathToDriveLetterPath fails.
627 size_t path_length = actual_device_path.value().length();
628 size_t new_length = path_length - 4;
629 ASSERT_GT(new_length, 0u);
630 FilePath prefix_of_real_device_path(
631 actual_device_path.value().substr(0, new_length));
632 ASSERT_FALSE(DevicePathToDriveLetterPath(prefix_of_real_device_path,
633 &win32_path));
634
635 ASSERT_FALSE(DevicePathToDriveLetterPath(
636 prefix_of_real_device_path.Append(kRelativePath),
637 &win32_path));
638
639 // Deform the real path so that it is invalid by adding some characters. For
640 // example, if C: maps to \Device\HardDiskVolume8, then we simulate a
641 // request for the drive letter whose native path is
642 // \Device\HardDiskVolume812345 . We assume such a device does not exist,
643 // because drives are numbered in order and mounting 112345 hard disks will
644 // never happen.
645 const FilePath::StringType kExtraChars = FPL("12345");
646
647 FilePath real_device_path_plus_numbers(
648 actual_device_path.value() + kExtraChars);
649
650 ASSERT_FALSE(DevicePathToDriveLetterPath(
651 real_device_path_plus_numbers,
652 &win32_path));
653
654 ASSERT_FALSE(DevicePathToDriveLetterPath(
655 real_device_path_plus_numbers.Append(kRelativePath),
656 &win32_path));
657 }
658
TEST_F(FileUtilTest,CreateTemporaryFileInDirLongPathTest)659 TEST_F(FileUtilTest, CreateTemporaryFileInDirLongPathTest) {
660 // Test that CreateTemporaryFileInDir() creates a path and returns a long path
661 // if it is available. This test requires that:
662 // - the filesystem at |temp_dir_| supports long filenames.
663 // - the account has FILE_LIST_DIRECTORY permission for all ancestor
664 // directories of |temp_dir_|.
665 constexpr FilePath::CharType kLongDirName[] = FPL("A long path");
666 constexpr FilePath::CharType kTestSubDirName[] = FPL("test");
667 FilePath long_test_dir = temp_dir_.GetPath().Append(kLongDirName);
668 ASSERT_TRUE(CreateDirectory(long_test_dir));
669
670 // kLongDirName is not a 8.3 component. So ::GetShortPathName() should give us
671 // a different short name.
672 FilePath short_test_dir = MakeShortFilePath(long_test_dir);
673 ASSERT_FALSE(short_test_dir.empty());
674 ASSERT_NE(kLongDirName, short_test_dir.BaseName().value());
675
676 FilePath temp_file;
677 ASSERT_TRUE(CreateTemporaryFileInDir(short_test_dir, &temp_file));
678 EXPECT_EQ(kLongDirName, temp_file.DirName().BaseName().value());
679 EXPECT_TRUE(PathExists(temp_file));
680
681 // Create a subdirectory of |long_test_dir| and make |long_test_dir|
682 // unreadable. We should still be able to create a temp file in the
683 // subdirectory, but we won't be able to determine the long path for it. This
684 // mimics the environment that some users run where their user profiles reside
685 // in a location where the don't have full access to the higher level
686 // directories. (Note that this assumption is true for NTFS, but not for some
687 // network file systems. E.g. AFS).
688 FilePath access_test_dir = long_test_dir.Append(kTestSubDirName);
689 ASSERT_TRUE(CreateDirectory(access_test_dir));
690 FilePermissionRestorer long_test_dir_restorer(long_test_dir);
691 ASSERT_TRUE(MakeFileUnreadable(long_test_dir));
692
693 // Use the short form of the directory to create a temporary filename.
694 ASSERT_TRUE(CreateTemporaryFileInDir(
695 short_test_dir.Append(kTestSubDirName), &temp_file));
696 EXPECT_TRUE(PathExists(temp_file));
697 EXPECT_TRUE(short_test_dir.IsParent(temp_file.DirName()));
698
699 // Check that the long path can't be determined for |temp_file|.
700 // Helper method base::MakeLongFilePath returns an empty path on error.
701 FilePath temp_file_long = MakeLongFilePath(temp_file);
702 ASSERT_TRUE(temp_file_long.empty());
703 }
704
TEST_F(FileUtilTest,MakeLongFilePathTest)705 TEST_F(FileUtilTest, MakeLongFilePathTest) {
706 // Tests helper function base::MakeLongFilePath
707
708 // If a username isn't a valid 8.3 short file name (even just a
709 // lengthy name like "user with long name"), Windows will set the TMP and TEMP
710 // environment variables to be 8.3 paths. ::GetTempPath (called in
711 // base::GetTempDir) just uses the value specified by TMP or TEMP, and so can
712 // return a short path. So from the start need to use MakeLongFilePath
713 // to normalize the path for such test environments.
714 FilePath temp_dir_long = MakeLongFilePath(temp_dir_.GetPath());
715 ASSERT_FALSE(temp_dir_long.empty());
716
717 FilePath long_test_dir = temp_dir_long.Append(FPL("A long directory name"));
718 ASSERT_TRUE(CreateDirectory(long_test_dir));
719
720 // Directory name is not a 8.3 component. So ::GetShortPathName() should give
721 // us a different short name.
722 FilePath short_test_dir = MakeShortFilePath(long_test_dir);
723 ASSERT_FALSE(short_test_dir.empty());
724
725 EXPECT_NE(long_test_dir, short_test_dir);
726 EXPECT_EQ(long_test_dir, MakeLongFilePath(short_test_dir));
727
728 FilePath long_test_file = long_test_dir.Append(FPL("A long file name.1234"));
729 CreateTextFile(long_test_file, bogus_content);
730 ASSERT_TRUE(PathExists(long_test_file));
731
732 // File name is not a 8.3 component. So ::GetShortPathName() should give us
733 // a different short name.
734 FilePath short_test_file = MakeShortFilePath(long_test_file);
735 ASSERT_FALSE(short_test_file.empty());
736
737 EXPECT_NE(long_test_file, short_test_file);
738 EXPECT_EQ(long_test_file, MakeLongFilePath(short_test_file));
739
740 // MakeLongFilePath should return empty path if file does not exist.
741 EXPECT_TRUE(DeleteFile(short_test_file, false));
742 EXPECT_TRUE(MakeLongFilePath(short_test_file).empty());
743
744 // MakeLongFilePath should return empty path if directory does not exist.
745 EXPECT_TRUE(DeleteFile(short_test_dir, false));
746 EXPECT_TRUE(MakeLongFilePath(short_test_dir).empty());
747 }
748
TEST_F(FileUtilTest,CreateWinHardlinkTest)749 TEST_F(FileUtilTest, CreateWinHardlinkTest) {
750 // Link to a different file name in a sub-directory of |temp_dir_|.
751 FilePath test_dir = temp_dir_.GetPath().Append(FPL("test"));
752 ASSERT_TRUE(CreateDirectory(test_dir));
753 FilePath temp_file;
754 ASSERT_TRUE(CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file));
755 FilePath link_to_file = test_dir.Append(FPL("linked_name"));
756 EXPECT_TRUE(CreateWinHardLink(link_to_file, temp_file));
757 EXPECT_TRUE(PathExists(link_to_file));
758
759 // Link two directories. This should fail. Verify that failure is returned
760 // by CreateWinHardLink.
761 EXPECT_FALSE(CreateWinHardLink(temp_dir_.GetPath(), test_dir));
762 }
763
764 #endif // defined(OS_WIN)
765
766 #if defined(OS_POSIX)
767
TEST_F(FileUtilTest,CreateAndReadSymlinks)768 TEST_F(FileUtilTest, CreateAndReadSymlinks) {
769 FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
770 FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
771 CreateTextFile(link_to, bogus_content);
772
773 ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
774 << "Failed to create file symlink.";
775
776 // If we created the link properly, we should be able to read the contents
777 // through it.
778 EXPECT_EQ(bogus_content, ReadTextFile(link_from));
779
780 FilePath result;
781 ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
782 EXPECT_EQ(link_to.value(), result.value());
783
784 // Link to a directory.
785 link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
786 link_to = temp_dir_.GetPath().Append(FPL("to_dir"));
787 ASSERT_TRUE(CreateDirectory(link_to));
788 ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
789 << "Failed to create directory symlink.";
790
791 // Test failures.
792 EXPECT_FALSE(CreateSymbolicLink(link_to, link_to));
793 EXPECT_FALSE(ReadSymbolicLink(link_to, &result));
794 FilePath missing = temp_dir_.GetPath().Append(FPL("missing"));
795 EXPECT_FALSE(ReadSymbolicLink(missing, &result));
796 }
797
798 // The following test of NormalizeFilePath() require that we create a symlink.
799 // This can not be done on Windows before Vista. On Vista, creating a symlink
800 // requires privilege "SeCreateSymbolicLinkPrivilege".
801 // TODO(skerner): Investigate the possibility of giving base_unittests the
802 // privileges required to create a symlink.
TEST_F(FileUtilTest,NormalizeFilePathSymlinks)803 TEST_F(FileUtilTest, NormalizeFilePathSymlinks) {
804 // Link one file to another.
805 FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
806 FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
807 CreateTextFile(link_to, bogus_content);
808
809 ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
810 << "Failed to create file symlink.";
811
812 // Check that NormalizeFilePath sees the link.
813 FilePath normalized_path;
814 ASSERT_TRUE(NormalizeFilePath(link_from, &normalized_path));
815 EXPECT_NE(link_from, link_to);
816 EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
817 EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
818
819 // Link to a directory.
820 link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
821 link_to = temp_dir_.GetPath().Append(FPL("to_dir"));
822 ASSERT_TRUE(CreateDirectory(link_to));
823 ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
824 << "Failed to create directory symlink.";
825
826 EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path))
827 << "Links to directories should return false.";
828
829 // Test that a loop in the links causes NormalizeFilePath() to return false.
830 link_from = temp_dir_.GetPath().Append(FPL("link_a"));
831 link_to = temp_dir_.GetPath().Append(FPL("link_b"));
832 ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
833 << "Failed to create loop symlink a.";
834 ASSERT_TRUE(CreateSymbolicLink(link_from, link_to))
835 << "Failed to create loop symlink b.";
836
837 // Infinite loop!
838 EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path));
839 }
840
TEST_F(FileUtilTest,DeleteSymlinkToExistentFile)841 TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) {
842 // Create a file.
843 FilePath file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 2.txt"));
844 CreateTextFile(file_name, bogus_content);
845 ASSERT_TRUE(PathExists(file_name));
846
847 // Create a symlink to the file.
848 FilePath file_link = temp_dir_.GetPath().Append("file_link_2");
849 ASSERT_TRUE(CreateSymbolicLink(file_name, file_link))
850 << "Failed to create symlink.";
851
852 // Delete the symbolic link.
853 EXPECT_TRUE(DeleteFile(file_link, false));
854
855 // Make sure original file is not deleted.
856 EXPECT_FALSE(PathExists(file_link));
857 EXPECT_TRUE(PathExists(file_name));
858 }
859
TEST_F(FileUtilTest,DeleteSymlinkToNonExistentFile)860 TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) {
861 // Create a non-existent file path.
862 FilePath non_existent =
863 temp_dir_.GetPath().Append(FPL("Test DeleteFile 3.txt"));
864 EXPECT_FALSE(PathExists(non_existent));
865
866 // Create a symlink to the non-existent file.
867 FilePath file_link = temp_dir_.GetPath().Append("file_link_3");
868 ASSERT_TRUE(CreateSymbolicLink(non_existent, file_link))
869 << "Failed to create symlink.";
870
871 // Make sure the symbolic link is exist.
872 EXPECT_TRUE(IsLink(file_link));
873 EXPECT_FALSE(PathExists(file_link));
874
875 // Delete the symbolic link.
876 EXPECT_TRUE(DeleteFile(file_link, false));
877
878 // Make sure the symbolic link is deleted.
879 EXPECT_FALSE(IsLink(file_link));
880 }
881
TEST_F(FileUtilTest,CopyFileFollowsSymlinks)882 TEST_F(FileUtilTest, CopyFileFollowsSymlinks) {
883 FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
884 FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
885 CreateTextFile(link_to, bogus_content);
886
887 ASSERT_TRUE(CreateSymbolicLink(link_to, link_from));
888
889 // If we created the link properly, we should be able to read the contents
890 // through it.
891 EXPECT_EQ(bogus_content, ReadTextFile(link_from));
892
893 FilePath result;
894 ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
895 EXPECT_EQ(link_to.value(), result.value());
896
897 // Create another file and copy it to |link_from|.
898 FilePath src_file = temp_dir_.GetPath().Append(FPL("src.txt"));
899 const std::wstring file_contents(L"Gooooooooooooooooooooogle");
900 CreateTextFile(src_file, file_contents);
901 ASSERT_TRUE(CopyFile(src_file, link_from));
902
903 // Make sure |link_from| is still a symlink, and |link_to| has been written to
904 // by CopyFile().
905 EXPECT_TRUE(IsLink(link_from));
906 EXPECT_EQ(file_contents, ReadTextFile(link_from));
907 EXPECT_EQ(file_contents, ReadTextFile(link_to));
908 }
909
TEST_F(FileUtilTest,ChangeFilePermissionsAndRead)910 TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
911 // Create a file path.
912 FilePath file_name =
913 temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
914 EXPECT_FALSE(PathExists(file_name));
915
916 static constexpr char kData[] = "hello";
917 static constexpr int kDataSize = sizeof(kData) - 1;
918 char buffer[kDataSize];
919
920 // Write file.
921 EXPECT_EQ(kDataSize, WriteFile(file_name, kData, kDataSize));
922 EXPECT_TRUE(PathExists(file_name));
923
924 // Make sure the file is readable.
925 int32_t mode = 0;
926 EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
927 EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
928
929 // Get rid of the read permission.
930 EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
931 EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
932 EXPECT_FALSE(mode & FILE_PERMISSION_READ_BY_USER);
933 // Make sure the file can't be read.
934 EXPECT_EQ(-1, ReadFile(file_name, buffer, kDataSize));
935
936 // Give the read permission.
937 EXPECT_TRUE(SetPosixFilePermissions(file_name, FILE_PERMISSION_READ_BY_USER));
938 EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
939 EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
940 // Make sure the file can be read.
941 EXPECT_EQ(kDataSize, ReadFile(file_name, buffer, kDataSize));
942
943 // Delete the file.
944 EXPECT_TRUE(DeleteFile(file_name, false));
945 EXPECT_FALSE(PathExists(file_name));
946 }
947
TEST_F(FileUtilTest,ChangeFilePermissionsAndWrite)948 TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) {
949 // Create a file path.
950 FilePath file_name =
951 temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
952 EXPECT_FALSE(PathExists(file_name));
953
954 const std::string kData("hello");
955
956 // Write file.
957 EXPECT_EQ(static_cast<int>(kData.length()),
958 WriteFile(file_name, kData.data(), kData.length()));
959 EXPECT_TRUE(PathExists(file_name));
960
961 // Make sure the file is writable.
962 int mode = 0;
963 EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
964 EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
965 EXPECT_TRUE(PathIsWritable(file_name));
966
967 // Get rid of the write permission.
968 EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
969 EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
970 EXPECT_FALSE(mode & FILE_PERMISSION_WRITE_BY_USER);
971 // Make sure the file can't be write.
972 EXPECT_EQ(-1, WriteFile(file_name, kData.data(), kData.length()));
973 EXPECT_FALSE(PathIsWritable(file_name));
974
975 // Give read permission.
976 EXPECT_TRUE(SetPosixFilePermissions(file_name,
977 FILE_PERMISSION_WRITE_BY_USER));
978 EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
979 EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
980 // Make sure the file can be write.
981 EXPECT_EQ(static_cast<int>(kData.length()),
982 WriteFile(file_name, kData.data(), kData.length()));
983 EXPECT_TRUE(PathIsWritable(file_name));
984
985 // Delete the file.
986 EXPECT_TRUE(DeleteFile(file_name, false));
987 EXPECT_FALSE(PathExists(file_name));
988 }
989
TEST_F(FileUtilTest,ChangeDirectoryPermissionsAndEnumerate)990 TEST_F(FileUtilTest, ChangeDirectoryPermissionsAndEnumerate) {
991 // Create a directory path.
992 FilePath subdir_path = temp_dir_.GetPath().Append(FPL("PermissionTest1"));
993 CreateDirectory(subdir_path);
994 ASSERT_TRUE(PathExists(subdir_path));
995
996 // Create a dummy file to enumerate.
997 FilePath file_name = subdir_path.Append(FPL("Test Readable File.txt"));
998 EXPECT_FALSE(PathExists(file_name));
999 const std::string kData("hello");
1000 EXPECT_EQ(static_cast<int>(kData.length()),
1001 WriteFile(file_name, kData.data(), kData.length()));
1002 EXPECT_TRUE(PathExists(file_name));
1003
1004 // Make sure the directory has the all permissions.
1005 int mode = 0;
1006 EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
1007 EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
1008
1009 // Get rid of the permissions from the directory.
1010 EXPECT_TRUE(SetPosixFilePermissions(subdir_path, 0u));
1011 EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
1012 EXPECT_FALSE(mode & FILE_PERMISSION_USER_MASK);
1013
1014 // Make sure the file in the directory can't be enumerated.
1015 FileEnumerator f1(subdir_path, true, FileEnumerator::FILES);
1016 EXPECT_TRUE(PathExists(subdir_path));
1017 FindResultCollector c1(&f1);
1018 EXPECT_EQ(0, c1.size());
1019 EXPECT_FALSE(GetPosixFilePermissions(file_name, &mode));
1020
1021 // Give the permissions to the directory.
1022 EXPECT_TRUE(SetPosixFilePermissions(subdir_path, FILE_PERMISSION_USER_MASK));
1023 EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
1024 EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
1025
1026 // Make sure the file in the directory can be enumerated.
1027 FileEnumerator f2(subdir_path, true, FileEnumerator::FILES);
1028 FindResultCollector c2(&f2);
1029 EXPECT_TRUE(c2.HasFile(file_name));
1030 EXPECT_EQ(1, c2.size());
1031
1032 // Delete the file.
1033 EXPECT_TRUE(DeleteFileRecursively(subdir_path));
1034 EXPECT_FALSE(PathExists(subdir_path));
1035 }
1036
TEST_F(FileUtilTest,ExecutableExistsInPath)1037 TEST_F(FileUtilTest, ExecutableExistsInPath) {
1038 // Create two directories that we will put in our PATH
1039 const FilePath::CharType kDir1[] = FPL("dir1");
1040 const FilePath::CharType kDir2[] = FPL("dir2");
1041
1042 FilePath dir1 = temp_dir_.GetPath().Append(kDir1);
1043 FilePath dir2 = temp_dir_.GetPath().Append(kDir2);
1044 ASSERT_TRUE(CreateDirectory(dir1));
1045 ASSERT_TRUE(CreateDirectory(dir2));
1046
1047 test::ScopedEnvironmentVariableOverride scoped_env(
1048 "PATH", dir1.value() + ":" + dir2.value());
1049 ASSERT_TRUE(scoped_env.IsOverridden());
1050
1051 const FilePath::CharType kRegularFileName[] = FPL("regular_file");
1052 const FilePath::CharType kExeFileName[] = FPL("exe");
1053 const FilePath::CharType kDneFileName[] = FPL("does_not_exist");
1054
1055 const FilePath kExePath = dir1.Append(kExeFileName);
1056 const FilePath kRegularFilePath = dir2.Append(kRegularFileName);
1057
1058 // Write file.
1059 const std::string kData("hello");
1060 ASSERT_EQ(static_cast<int>(kData.length()),
1061 WriteFile(kExePath, kData.data(), kData.length()));
1062 ASSERT_TRUE(PathExists(kExePath));
1063 ASSERT_EQ(static_cast<int>(kData.length()),
1064 WriteFile(kRegularFilePath, kData.data(), kData.length()));
1065 ASSERT_TRUE(PathExists(kRegularFilePath));
1066
1067 ASSERT_TRUE(SetPosixFilePermissions(dir1.Append(kExeFileName),
1068 FILE_PERMISSION_EXECUTE_BY_USER));
1069
1070 EXPECT_TRUE(ExecutableExistsInPath(scoped_env.GetEnv(), kExeFileName));
1071 EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kRegularFileName));
1072 EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kDneFileName));
1073 }
1074
TEST_F(FileUtilTest,CopyDirectoryPermissions)1075 TEST_F(FileUtilTest, CopyDirectoryPermissions) {
1076 // Create a directory.
1077 FilePath dir_name_from =
1078 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1079 CreateDirectory(dir_name_from);
1080 ASSERT_TRUE(PathExists(dir_name_from));
1081
1082 // Create some regular files under the directory with various permissions.
1083 FilePath file_name_from =
1084 dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1085 CreateTextFile(file_name_from, L"Mordecai");
1086 ASSERT_TRUE(PathExists(file_name_from));
1087 ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0755));
1088
1089 FilePath file2_name_from =
1090 dir_name_from.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
1091 CreateTextFile(file2_name_from, L"Rigby");
1092 ASSERT_TRUE(PathExists(file2_name_from));
1093 ASSERT_TRUE(SetPosixFilePermissions(file2_name_from, 0777));
1094
1095 FilePath file3_name_from =
1096 dir_name_from.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
1097 CreateTextFile(file3_name_from, L"Benson");
1098 ASSERT_TRUE(PathExists(file3_name_from));
1099 ASSERT_TRUE(SetPosixFilePermissions(file3_name_from, 0400));
1100
1101 // Copy the directory recursively.
1102 FilePath dir_name_to =
1103 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1104 FilePath file_name_to =
1105 dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1106 FilePath file2_name_to =
1107 dir_name_to.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
1108 FilePath file3_name_to =
1109 dir_name_to.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
1110
1111 ASSERT_FALSE(PathExists(dir_name_to));
1112
1113 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
1114 ASSERT_TRUE(PathExists(file_name_to));
1115 ASSERT_TRUE(PathExists(file2_name_to));
1116 ASSERT_TRUE(PathExists(file3_name_to));
1117
1118 int mode = 0;
1119 int expected_mode;
1120 ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
1121 #if defined(OS_MACOSX)
1122 expected_mode = 0755;
1123 #elif defined(OS_CHROMEOS)
1124 expected_mode = 0644;
1125 #else
1126 expected_mode = 0600;
1127 #endif
1128 EXPECT_EQ(expected_mode, mode);
1129
1130 ASSERT_TRUE(GetPosixFilePermissions(file2_name_to, &mode));
1131 #if defined(OS_MACOSX)
1132 expected_mode = 0755;
1133 #elif defined(OS_CHROMEOS)
1134 expected_mode = 0644;
1135 #else
1136 expected_mode = 0600;
1137 #endif
1138 EXPECT_EQ(expected_mode, mode);
1139
1140 ASSERT_TRUE(GetPosixFilePermissions(file3_name_to, &mode));
1141 #if defined(OS_MACOSX)
1142 expected_mode = 0600;
1143 #elif defined(OS_CHROMEOS)
1144 expected_mode = 0644;
1145 #else
1146 expected_mode = 0600;
1147 #endif
1148 EXPECT_EQ(expected_mode, mode);
1149 }
1150
TEST_F(FileUtilTest,CopyDirectoryPermissionsOverExistingFile)1151 TEST_F(FileUtilTest, CopyDirectoryPermissionsOverExistingFile) {
1152 // Create a directory.
1153 FilePath dir_name_from =
1154 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1155 CreateDirectory(dir_name_from);
1156 ASSERT_TRUE(PathExists(dir_name_from));
1157
1158 // Create a file under the directory.
1159 FilePath file_name_from =
1160 dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1161 CreateTextFile(file_name_from, L"Mordecai");
1162 ASSERT_TRUE(PathExists(file_name_from));
1163 ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0644));
1164
1165 // Create a directory.
1166 FilePath dir_name_to =
1167 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1168 CreateDirectory(dir_name_to);
1169 ASSERT_TRUE(PathExists(dir_name_to));
1170
1171 // Create a file under the directory with wider permissions.
1172 FilePath file_name_to =
1173 dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1174 CreateTextFile(file_name_to, L"Rigby");
1175 ASSERT_TRUE(PathExists(file_name_to));
1176 ASSERT_TRUE(SetPosixFilePermissions(file_name_to, 0777));
1177
1178 // Ensure that when we copy the directory, the file contents are copied
1179 // but the permissions on the destination are left alone.
1180 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
1181 ASSERT_TRUE(PathExists(file_name_to));
1182 ASSERT_EQ(L"Mordecai", ReadTextFile(file_name_to));
1183
1184 int mode = 0;
1185 ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
1186 EXPECT_EQ(0777, mode);
1187 }
1188
TEST_F(FileUtilTest,CopyDirectoryExclDoesNotOverwrite)1189 TEST_F(FileUtilTest, CopyDirectoryExclDoesNotOverwrite) {
1190 // Create source directory.
1191 FilePath dir_name_from =
1192 temp_dir_.GetPath().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("Reggy-1.txt"));
1199 CreateTextFile(file_name_from, L"Mordecai");
1200 ASSERT_TRUE(PathExists(file_name_from));
1201
1202 // Create destination directory.
1203 FilePath dir_name_to =
1204 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1205 CreateDirectory(dir_name_to);
1206 ASSERT_TRUE(PathExists(dir_name_to));
1207
1208 // Create a file under the directory with the same name.
1209 FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
1210 CreateTextFile(file_name_to, L"Rigby");
1211 ASSERT_TRUE(PathExists(file_name_to));
1212
1213 // Ensure that copying failed and the file was not overwritten.
1214 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
1215 ASSERT_TRUE(PathExists(file_name_to));
1216 ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to));
1217 }
1218
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverExistingFile)1219 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingFile) {
1220 // Create source directory.
1221 FilePath dir_name_from =
1222 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1223 CreateDirectory(dir_name_from);
1224 ASSERT_TRUE(PathExists(dir_name_from));
1225
1226 // Create a subdirectory.
1227 FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
1228 CreateDirectory(subdir_name_from);
1229 ASSERT_TRUE(PathExists(subdir_name_from));
1230
1231 // Create destination directory.
1232 FilePath dir_name_to =
1233 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1234 CreateDirectory(dir_name_to);
1235 ASSERT_TRUE(PathExists(dir_name_to));
1236
1237 // Create a regular file under the directory with the same name.
1238 FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
1239 CreateTextFile(file_name_to, L"Rigby");
1240 ASSERT_TRUE(PathExists(file_name_to));
1241
1242 // Ensure that copying failed and the file was not overwritten.
1243 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
1244 ASSERT_TRUE(PathExists(file_name_to));
1245 ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to));
1246 }
1247
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverExistingDirectory)1248 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingDirectory) {
1249 // Create source directory.
1250 FilePath dir_name_from =
1251 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1252 CreateDirectory(dir_name_from);
1253 ASSERT_TRUE(PathExists(dir_name_from));
1254
1255 // Create a subdirectory.
1256 FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
1257 CreateDirectory(subdir_name_from);
1258 ASSERT_TRUE(PathExists(subdir_name_from));
1259
1260 // Create destination directory.
1261 FilePath dir_name_to =
1262 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1263 CreateDirectory(dir_name_to);
1264 ASSERT_TRUE(PathExists(dir_name_to));
1265
1266 // Create a subdirectory under the directory with the same name.
1267 FilePath subdir_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
1268 CreateDirectory(subdir_name_to);
1269 ASSERT_TRUE(PathExists(subdir_name_to));
1270
1271 // Ensure that copying failed and the file was not overwritten.
1272 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
1273 }
1274
TEST_F(FileUtilTest,CopyFileExecutablePermission)1275 TEST_F(FileUtilTest, CopyFileExecutablePermission) {
1276 FilePath src = temp_dir_.GetPath().Append(FPL("src.txt"));
1277 const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1278 CreateTextFile(src, file_contents);
1279
1280 ASSERT_TRUE(SetPosixFilePermissions(src, 0755));
1281 int mode = 0;
1282 ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
1283 EXPECT_EQ(0755, mode);
1284
1285 FilePath dst = temp_dir_.GetPath().Append(FPL("dst.txt"));
1286 ASSERT_TRUE(CopyFile(src, dst));
1287 EXPECT_EQ(file_contents, ReadTextFile(dst));
1288
1289 ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1290 int expected_mode;
1291 #if defined(OS_MACOSX)
1292 expected_mode = 0755;
1293 #elif defined(OS_CHROMEOS)
1294 expected_mode = 0644;
1295 #else
1296 expected_mode = 0600;
1297 #endif
1298 EXPECT_EQ(expected_mode, mode);
1299 ASSERT_TRUE(DeleteFile(dst, false));
1300
1301 ASSERT_TRUE(SetPosixFilePermissions(src, 0777));
1302 ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
1303 EXPECT_EQ(0777, mode);
1304
1305 ASSERT_TRUE(CopyFile(src, dst));
1306 EXPECT_EQ(file_contents, ReadTextFile(dst));
1307
1308 ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1309 #if defined(OS_MACOSX)
1310 expected_mode = 0755;
1311 #elif defined(OS_CHROMEOS)
1312 expected_mode = 0644;
1313 #else
1314 expected_mode = 0600;
1315 #endif
1316 EXPECT_EQ(expected_mode, mode);
1317 ASSERT_TRUE(DeleteFile(dst, false));
1318
1319 ASSERT_TRUE(SetPosixFilePermissions(src, 0400));
1320 ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
1321 EXPECT_EQ(0400, mode);
1322
1323 ASSERT_TRUE(CopyFile(src, dst));
1324 EXPECT_EQ(file_contents, ReadTextFile(dst));
1325
1326 ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1327 #if defined(OS_MACOSX)
1328 expected_mode = 0600;
1329 #elif defined(OS_CHROMEOS)
1330 expected_mode = 0644;
1331 #else
1332 expected_mode = 0600;
1333 #endif
1334 EXPECT_EQ(expected_mode, mode);
1335
1336 // This time, do not delete |dst|. Instead set its permissions to 0777.
1337 ASSERT_TRUE(SetPosixFilePermissions(dst, 0777));
1338 ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1339 EXPECT_EQ(0777, mode);
1340
1341 // Overwrite it and check the permissions again.
1342 ASSERT_TRUE(CopyFile(src, dst));
1343 EXPECT_EQ(file_contents, ReadTextFile(dst));
1344 ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
1345 EXPECT_EQ(0777, mode);
1346 }
1347
1348 #endif // defined(OS_POSIX)
1349
1350 #if !defined(OS_FUCHSIA)
1351
TEST_F(FileUtilTest,CopyFileACL)1352 TEST_F(FileUtilTest, CopyFileACL) {
1353 // While FileUtilTest.CopyFile asserts the content is correctly copied over,
1354 // this test case asserts the access control bits are meeting expectations in
1355 // CopyFile().
1356 FilePath src = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("src.txt"));
1357 const std::wstring file_contents(L"Gooooooooooooooooooooogle");
1358 CreateTextFile(src, file_contents);
1359
1360 // Set the source file to read-only.
1361 ASSERT_FALSE(IsReadOnly(src));
1362 SetReadOnly(src, true);
1363 ASSERT_TRUE(IsReadOnly(src));
1364
1365 // Copy the file.
1366 FilePath dst = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("dst.txt"));
1367 ASSERT_TRUE(CopyFile(src, dst));
1368 EXPECT_EQ(file_contents, ReadTextFile(dst));
1369
1370 ASSERT_FALSE(IsReadOnly(dst));
1371 }
1372
TEST_F(FileUtilTest,CopyDirectoryACL)1373 TEST_F(FileUtilTest, CopyDirectoryACL) {
1374 // Create source directories.
1375 FilePath src = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("src"));
1376 FilePath src_subdir = src.Append(FILE_PATH_LITERAL("subdir"));
1377 CreateDirectory(src_subdir);
1378 ASSERT_TRUE(PathExists(src_subdir));
1379
1380 // Create a file under the directory.
1381 FilePath src_file = src.Append(FILE_PATH_LITERAL("src.txt"));
1382 CreateTextFile(src_file, L"Gooooooooooooooooooooogle");
1383 SetReadOnly(src_file, true);
1384 ASSERT_TRUE(IsReadOnly(src_file));
1385
1386 // Make directory read-only.
1387 SetReadOnly(src_subdir, true);
1388 ASSERT_TRUE(IsReadOnly(src_subdir));
1389
1390 // Copy the directory recursively.
1391 FilePath dst = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("dst"));
1392 FilePath dst_file = dst.Append(FILE_PATH_LITERAL("src.txt"));
1393 EXPECT_TRUE(CopyDirectory(src, dst, true));
1394
1395 FilePath dst_subdir = dst.Append(FILE_PATH_LITERAL("subdir"));
1396 ASSERT_FALSE(IsReadOnly(dst_subdir));
1397 ASSERT_FALSE(IsReadOnly(dst_file));
1398
1399 // Give write permissions to allow deletion.
1400 SetReadOnly(src_subdir, false);
1401 ASSERT_FALSE(IsReadOnly(src_subdir));
1402 }
1403
1404 #endif // !defined(OS_FUCHSIA)
1405
TEST_F(FileUtilTest,DeleteNonExistent)1406 TEST_F(FileUtilTest, DeleteNonExistent) {
1407 FilePath non_existent =
1408 temp_dir_.GetPath().AppendASCII("bogus_file_dne.foobar");
1409 ASSERT_FALSE(PathExists(non_existent));
1410
1411 EXPECT_TRUE(DeleteFile(non_existent, false));
1412 ASSERT_FALSE(PathExists(non_existent));
1413 EXPECT_TRUE(DeleteFileRecursively(non_existent));
1414 ASSERT_FALSE(PathExists(non_existent));
1415 }
1416
TEST_F(FileUtilTest,DeleteNonExistentWithNonExistentParent)1417 TEST_F(FileUtilTest, DeleteNonExistentWithNonExistentParent) {
1418 FilePath non_existent = temp_dir_.GetPath().AppendASCII("bogus_topdir");
1419 non_existent = non_existent.AppendASCII("bogus_subdir");
1420 ASSERT_FALSE(PathExists(non_existent));
1421
1422 EXPECT_TRUE(DeleteFile(non_existent, false));
1423 ASSERT_FALSE(PathExists(non_existent));
1424 EXPECT_TRUE(DeleteFileRecursively(non_existent));
1425 ASSERT_FALSE(PathExists(non_existent));
1426 }
1427
TEST_F(FileUtilTest,DeleteFile)1428 TEST_F(FileUtilTest, DeleteFile) {
1429 // Create a file
1430 FilePath file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 1.txt"));
1431 CreateTextFile(file_name, bogus_content);
1432 ASSERT_TRUE(PathExists(file_name));
1433
1434 // Make sure it's deleted
1435 EXPECT_TRUE(DeleteFile(file_name, false));
1436 EXPECT_FALSE(PathExists(file_name));
1437
1438 // Test recursive case, create a new file
1439 file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 2.txt"));
1440 CreateTextFile(file_name, bogus_content);
1441 ASSERT_TRUE(PathExists(file_name));
1442
1443 // Make sure it's deleted
1444 EXPECT_TRUE(DeleteFileRecursively(file_name));
1445 EXPECT_FALSE(PathExists(file_name));
1446 }
1447
1448 #if defined(OS_ANDROID)
TEST_F(FileUtilTest,DeleteContentUri)1449 TEST_F(FileUtilTest, DeleteContentUri) {
1450 // Get the path to the test file.
1451 FilePath data_dir;
1452 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
1453 data_dir = data_dir.Append(FPL("file_util"));
1454 ASSERT_TRUE(PathExists(data_dir));
1455 FilePath image_file = data_dir.Append(FPL("red.png"));
1456 ASSERT_TRUE(PathExists(image_file));
1457
1458 // Make a copy (we don't want to delete the original red.png when deleting the
1459 // content URI).
1460 FilePath image_copy = data_dir.Append(FPL("redcopy.png"));
1461 ASSERT_TRUE(CopyFile(image_file, image_copy));
1462
1463 // Insert the image into MediaStore and get a content URI.
1464 FilePath uri_path = InsertImageIntoMediaStore(image_copy);
1465 ASSERT_TRUE(uri_path.IsContentUri());
1466 ASSERT_TRUE(PathExists(uri_path));
1467
1468 // Try deleting the content URI.
1469 EXPECT_TRUE(DeleteFile(uri_path, false));
1470 EXPECT_FALSE(PathExists(image_copy));
1471 EXPECT_FALSE(PathExists(uri_path));
1472 }
1473 #endif // defined(OS_ANDROID)
1474
1475 #if defined(OS_WIN)
1476 // Tests that the Delete function works for wild cards, especially
1477 // with the recursion flag. Also coincidentally tests PathExists.
1478 // TODO(erikkay): see if anyone's actually using this feature of the API
TEST_F(FileUtilTest,DeleteWildCard)1479 TEST_F(FileUtilTest, DeleteWildCard) {
1480 // Create a file and a directory
1481 FilePath file_name =
1482 temp_dir_.GetPath().Append(FPL("Test DeleteWildCard.txt"));
1483 CreateTextFile(file_name, bogus_content);
1484 ASSERT_TRUE(PathExists(file_name));
1485
1486 FilePath subdir_path = temp_dir_.GetPath().Append(FPL("DeleteWildCardDir"));
1487 CreateDirectory(subdir_path);
1488 ASSERT_TRUE(PathExists(subdir_path));
1489
1490 // Create the wildcard path
1491 FilePath directory_contents = temp_dir_.GetPath();
1492 directory_contents = directory_contents.Append(FPL("*"));
1493
1494 // Delete non-recursively and check that only the file is deleted
1495 EXPECT_TRUE(DeleteFile(directory_contents, false));
1496 EXPECT_FALSE(PathExists(file_name));
1497 EXPECT_TRUE(PathExists(subdir_path));
1498
1499 // Delete recursively and make sure all contents are deleted
1500 EXPECT_TRUE(DeleteFileRecursively(directory_contents));
1501 EXPECT_FALSE(PathExists(file_name));
1502 EXPECT_FALSE(PathExists(subdir_path));
1503 }
1504
1505 // TODO(erikkay): see if anyone's actually using this feature of the API
TEST_F(FileUtilTest,DeleteNonExistantWildCard)1506 TEST_F(FileUtilTest, DeleteNonExistantWildCard) {
1507 // Create a file and a directory
1508 FilePath subdir_path =
1509 temp_dir_.GetPath().Append(FPL("DeleteNonExistantWildCard"));
1510 CreateDirectory(subdir_path);
1511 ASSERT_TRUE(PathExists(subdir_path));
1512
1513 // Create the wildcard path
1514 FilePath directory_contents = subdir_path;
1515 directory_contents = directory_contents.Append(FPL("*"));
1516
1517 // Delete non-recursively and check nothing got deleted
1518 EXPECT_TRUE(DeleteFile(directory_contents, false));
1519 EXPECT_TRUE(PathExists(subdir_path));
1520
1521 // Delete recursively and check nothing got deleted
1522 EXPECT_TRUE(DeleteFileRecursively(directory_contents));
1523 EXPECT_TRUE(PathExists(subdir_path));
1524 }
1525 #endif
1526
1527 // Tests non-recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirNonRecursive)1528 TEST_F(FileUtilTest, DeleteDirNonRecursive) {
1529 // Create a subdirectory and put a file and two directories inside.
1530 FilePath test_subdir =
1531 temp_dir_.GetPath().Append(FPL("DeleteDirNonRecursive"));
1532 CreateDirectory(test_subdir);
1533 ASSERT_TRUE(PathExists(test_subdir));
1534
1535 FilePath file_name = test_subdir.Append(FPL("Test DeleteDir.txt"));
1536 CreateTextFile(file_name, bogus_content);
1537 ASSERT_TRUE(PathExists(file_name));
1538
1539 FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
1540 CreateDirectory(subdir_path1);
1541 ASSERT_TRUE(PathExists(subdir_path1));
1542
1543 FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
1544 CreateDirectory(subdir_path2);
1545 ASSERT_TRUE(PathExists(subdir_path2));
1546
1547 // Delete non-recursively and check that the empty dir got deleted
1548 EXPECT_TRUE(DeleteFile(subdir_path2, false));
1549 EXPECT_FALSE(PathExists(subdir_path2));
1550
1551 // Delete non-recursively and check that nothing got deleted
1552 EXPECT_FALSE(DeleteFile(test_subdir, false));
1553 EXPECT_TRUE(PathExists(test_subdir));
1554 EXPECT_TRUE(PathExists(file_name));
1555 EXPECT_TRUE(PathExists(subdir_path1));
1556 }
1557
1558 // Tests recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirRecursive)1559 TEST_F(FileUtilTest, DeleteDirRecursive) {
1560 // Create a subdirectory and put a file and two directories inside.
1561 FilePath test_subdir = temp_dir_.GetPath().Append(FPL("DeleteDirRecursive"));
1562 CreateDirectory(test_subdir);
1563 ASSERT_TRUE(PathExists(test_subdir));
1564
1565 FilePath file_name = test_subdir.Append(FPL("Test DeleteDirRecursive.txt"));
1566 CreateTextFile(file_name, bogus_content);
1567 ASSERT_TRUE(PathExists(file_name));
1568
1569 FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
1570 CreateDirectory(subdir_path1);
1571 ASSERT_TRUE(PathExists(subdir_path1));
1572
1573 FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
1574 CreateDirectory(subdir_path2);
1575 ASSERT_TRUE(PathExists(subdir_path2));
1576
1577 // Delete recursively and check that the empty dir got deleted
1578 EXPECT_TRUE(DeleteFileRecursively(subdir_path2));
1579 EXPECT_FALSE(PathExists(subdir_path2));
1580
1581 // Delete recursively and check that everything got deleted
1582 EXPECT_TRUE(DeleteFileRecursively(test_subdir));
1583 EXPECT_FALSE(PathExists(file_name));
1584 EXPECT_FALSE(PathExists(subdir_path1));
1585 EXPECT_FALSE(PathExists(test_subdir));
1586 }
1587
1588 // Tests recursive Delete() for a directory.
TEST_F(FileUtilTest,DeleteDirRecursiveWithOpenFile)1589 TEST_F(FileUtilTest, DeleteDirRecursiveWithOpenFile) {
1590 // Create a subdirectory and put a file and two directories inside.
1591 FilePath test_subdir = temp_dir_.GetPath().Append(FPL("DeleteWithOpenFile"));
1592 CreateDirectory(test_subdir);
1593 ASSERT_TRUE(PathExists(test_subdir));
1594
1595 FilePath file_name1 = test_subdir.Append(FPL("Undeletebable File1.txt"));
1596 File file1(file_name1,
1597 File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
1598 ASSERT_TRUE(PathExists(file_name1));
1599
1600 FilePath file_name2 = test_subdir.Append(FPL("Deleteable File2.txt"));
1601 CreateTextFile(file_name2, bogus_content);
1602 ASSERT_TRUE(PathExists(file_name2));
1603
1604 FilePath file_name3 = test_subdir.Append(FPL("Undeletebable File3.txt"));
1605 File file3(file_name3,
1606 File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
1607 ASSERT_TRUE(PathExists(file_name3));
1608
1609 #if defined(OS_LINUX)
1610 // On Windows, holding the file open in sufficient to make it un-deletable.
1611 // The POSIX code is verifiable on Linux by creating an "immutable" file but
1612 // this is best-effort because it's not supported by all file systems. Both
1613 // files will have the same flags so no need to get them individually.
1614 int flags;
1615 bool file_attrs_supported =
1616 ioctl(file1.GetPlatformFile(), FS_IOC_GETFLAGS, &flags) == 0;
1617 // Some filesystems (e.g. tmpfs) don't support file attributes.
1618 if (file_attrs_supported) {
1619 flags |= FS_IMMUTABLE_FL;
1620 ioctl(file1.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
1621 ioctl(file3.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
1622 }
1623 #endif
1624
1625 // Delete recursively and check that at least the second file got deleted.
1626 // This ensures that un-deletable files don't impact those that can be.
1627 DeleteFileRecursively(test_subdir);
1628 EXPECT_FALSE(PathExists(file_name2));
1629
1630 #if defined(OS_LINUX)
1631 // Make sure that the test can clean up after itself.
1632 if (file_attrs_supported) {
1633 flags &= ~FS_IMMUTABLE_FL;
1634 ioctl(file1.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
1635 ioctl(file3.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
1636 }
1637 #endif
1638 }
1639
TEST_F(FileUtilTest,MoveFileNew)1640 TEST_F(FileUtilTest, MoveFileNew) {
1641 // Create a file
1642 FilePath file_name_from =
1643 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1644 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1645 ASSERT_TRUE(PathExists(file_name_from));
1646
1647 // The destination.
1648 FilePath file_name_to = temp_dir_.GetPath().Append(
1649 FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
1650 ASSERT_FALSE(PathExists(file_name_to));
1651
1652 EXPECT_TRUE(Move(file_name_from, file_name_to));
1653
1654 // Check everything has been moved.
1655 EXPECT_FALSE(PathExists(file_name_from));
1656 EXPECT_TRUE(PathExists(file_name_to));
1657 }
1658
TEST_F(FileUtilTest,MoveFileExists)1659 TEST_F(FileUtilTest, MoveFileExists) {
1660 // Create a file
1661 FilePath file_name_from =
1662 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1663 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1664 ASSERT_TRUE(PathExists(file_name_from));
1665
1666 // The destination name.
1667 FilePath file_name_to = temp_dir_.GetPath().Append(
1668 FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
1669 CreateTextFile(file_name_to, L"Old file content");
1670 ASSERT_TRUE(PathExists(file_name_to));
1671
1672 EXPECT_TRUE(Move(file_name_from, file_name_to));
1673
1674 // Check everything has been moved.
1675 EXPECT_FALSE(PathExists(file_name_from));
1676 EXPECT_TRUE(PathExists(file_name_to));
1677 EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
1678 }
1679
TEST_F(FileUtilTest,MoveFileDirExists)1680 TEST_F(FileUtilTest, MoveFileDirExists) {
1681 // Create a file
1682 FilePath file_name_from =
1683 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1684 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1685 ASSERT_TRUE(PathExists(file_name_from));
1686
1687 // The destination directory
1688 FilePath dir_name_to =
1689 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
1690 CreateDirectory(dir_name_to);
1691 ASSERT_TRUE(PathExists(dir_name_to));
1692
1693 EXPECT_FALSE(Move(file_name_from, dir_name_to));
1694 }
1695
1696
TEST_F(FileUtilTest,MoveNew)1697 TEST_F(FileUtilTest, MoveNew) {
1698 // Create a directory
1699 FilePath dir_name_from =
1700 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
1701 CreateDirectory(dir_name_from);
1702 ASSERT_TRUE(PathExists(dir_name_from));
1703
1704 // Create a file under the directory
1705 FilePath txt_file_name(FILE_PATH_LITERAL("Move_Test_File.txt"));
1706 FilePath file_name_from = dir_name_from.Append(txt_file_name);
1707 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1708 ASSERT_TRUE(PathExists(file_name_from));
1709
1710 // Move the directory.
1711 FilePath dir_name_to =
1712 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_To_Subdir"));
1713 FilePath file_name_to =
1714 dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1715
1716 ASSERT_FALSE(PathExists(dir_name_to));
1717
1718 EXPECT_TRUE(Move(dir_name_from, dir_name_to));
1719
1720 // Check everything has been moved.
1721 EXPECT_FALSE(PathExists(dir_name_from));
1722 EXPECT_FALSE(PathExists(file_name_from));
1723 EXPECT_TRUE(PathExists(dir_name_to));
1724 EXPECT_TRUE(PathExists(file_name_to));
1725
1726 // Test path traversal.
1727 file_name_from = dir_name_to.Append(txt_file_name);
1728 file_name_to = dir_name_to.Append(FILE_PATH_LITERAL(".."));
1729 file_name_to = file_name_to.Append(txt_file_name);
1730 EXPECT_FALSE(Move(file_name_from, file_name_to));
1731 EXPECT_TRUE(PathExists(file_name_from));
1732 EXPECT_FALSE(PathExists(file_name_to));
1733 EXPECT_TRUE(internal::MoveUnsafe(file_name_from, file_name_to));
1734 EXPECT_FALSE(PathExists(file_name_from));
1735 EXPECT_TRUE(PathExists(file_name_to));
1736 }
1737
TEST_F(FileUtilTest,MoveExist)1738 TEST_F(FileUtilTest, MoveExist) {
1739 // Create a directory
1740 FilePath dir_name_from =
1741 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
1742 CreateDirectory(dir_name_from);
1743 ASSERT_TRUE(PathExists(dir_name_from));
1744
1745 // Create a file under the directory
1746 FilePath file_name_from =
1747 dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1748 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1749 ASSERT_TRUE(PathExists(file_name_from));
1750
1751 // Move the directory
1752 FilePath dir_name_exists =
1753 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
1754
1755 FilePath dir_name_to =
1756 dir_name_exists.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
1757 FilePath file_name_to =
1758 dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
1759
1760 // Create the destination directory.
1761 CreateDirectory(dir_name_exists);
1762 ASSERT_TRUE(PathExists(dir_name_exists));
1763
1764 EXPECT_TRUE(Move(dir_name_from, dir_name_to));
1765
1766 // Check everything has been moved.
1767 EXPECT_FALSE(PathExists(dir_name_from));
1768 EXPECT_FALSE(PathExists(file_name_from));
1769 EXPECT_TRUE(PathExists(dir_name_to));
1770 EXPECT_TRUE(PathExists(file_name_to));
1771 }
1772
TEST_F(FileUtilTest,CopyDirectoryRecursivelyNew)1773 TEST_F(FileUtilTest, CopyDirectoryRecursivelyNew) {
1774 // Create a directory.
1775 FilePath dir_name_from =
1776 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1777 CreateDirectory(dir_name_from);
1778 ASSERT_TRUE(PathExists(dir_name_from));
1779
1780 // Create a file under the directory.
1781 FilePath file_name_from =
1782 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1783 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1784 ASSERT_TRUE(PathExists(file_name_from));
1785
1786 // Create a subdirectory.
1787 FilePath subdir_name_from =
1788 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1789 CreateDirectory(subdir_name_from);
1790 ASSERT_TRUE(PathExists(subdir_name_from));
1791
1792 // Create a file under the subdirectory.
1793 FilePath file_name2_from =
1794 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1795 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1796 ASSERT_TRUE(PathExists(file_name2_from));
1797
1798 // Copy the directory recursively.
1799 FilePath dir_name_to =
1800 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1801 FilePath file_name_to =
1802 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1803 FilePath subdir_name_to =
1804 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1805 FilePath file_name2_to =
1806 subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1807
1808 ASSERT_FALSE(PathExists(dir_name_to));
1809
1810 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
1811
1812 // Check everything has been copied.
1813 EXPECT_TRUE(PathExists(dir_name_from));
1814 EXPECT_TRUE(PathExists(file_name_from));
1815 EXPECT_TRUE(PathExists(subdir_name_from));
1816 EXPECT_TRUE(PathExists(file_name2_from));
1817 EXPECT_TRUE(PathExists(dir_name_to));
1818 EXPECT_TRUE(PathExists(file_name_to));
1819 EXPECT_TRUE(PathExists(subdir_name_to));
1820 EXPECT_TRUE(PathExists(file_name2_to));
1821 }
1822
TEST_F(FileUtilTest,CopyDirectoryRecursivelyExists)1823 TEST_F(FileUtilTest, CopyDirectoryRecursivelyExists) {
1824 // Create a directory.
1825 FilePath dir_name_from =
1826 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1827 CreateDirectory(dir_name_from);
1828 ASSERT_TRUE(PathExists(dir_name_from));
1829
1830 // Create a file under the directory.
1831 FilePath file_name_from =
1832 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1833 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1834 ASSERT_TRUE(PathExists(file_name_from));
1835
1836 // Create a subdirectory.
1837 FilePath subdir_name_from =
1838 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1839 CreateDirectory(subdir_name_from);
1840 ASSERT_TRUE(PathExists(subdir_name_from));
1841
1842 // Create a file under the subdirectory.
1843 FilePath file_name2_from =
1844 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1845 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1846 ASSERT_TRUE(PathExists(file_name2_from));
1847
1848 // Copy the directory recursively.
1849 FilePath dir_name_exists =
1850 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
1851
1852 FilePath dir_name_to =
1853 dir_name_exists.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1854 FilePath file_name_to =
1855 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1856 FilePath subdir_name_to =
1857 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1858 FilePath file_name2_to =
1859 subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1860
1861 // Create the destination directory.
1862 CreateDirectory(dir_name_exists);
1863 ASSERT_TRUE(PathExists(dir_name_exists));
1864
1865 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_exists, true));
1866
1867 // Check everything has been copied.
1868 EXPECT_TRUE(PathExists(dir_name_from));
1869 EXPECT_TRUE(PathExists(file_name_from));
1870 EXPECT_TRUE(PathExists(subdir_name_from));
1871 EXPECT_TRUE(PathExists(file_name2_from));
1872 EXPECT_TRUE(PathExists(dir_name_to));
1873 EXPECT_TRUE(PathExists(file_name_to));
1874 EXPECT_TRUE(PathExists(subdir_name_to));
1875 EXPECT_TRUE(PathExists(file_name2_to));
1876 }
1877
TEST_F(FileUtilTest,CopyDirectoryNew)1878 TEST_F(FileUtilTest, CopyDirectoryNew) {
1879 // Create a directory.
1880 FilePath dir_name_from =
1881 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1882 CreateDirectory(dir_name_from);
1883 ASSERT_TRUE(PathExists(dir_name_from));
1884
1885 // Create a file under the directory.
1886 FilePath file_name_from =
1887 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1888 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1889 ASSERT_TRUE(PathExists(file_name_from));
1890
1891 // Create a subdirectory.
1892 FilePath subdir_name_from =
1893 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1894 CreateDirectory(subdir_name_from);
1895 ASSERT_TRUE(PathExists(subdir_name_from));
1896
1897 // Create a file under the subdirectory.
1898 FilePath file_name2_from =
1899 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1900 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1901 ASSERT_TRUE(PathExists(file_name2_from));
1902
1903 // Copy the directory not recursively.
1904 FilePath dir_name_to =
1905 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1906 FilePath file_name_to =
1907 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1908 FilePath subdir_name_to =
1909 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1910
1911 ASSERT_FALSE(PathExists(dir_name_to));
1912
1913 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
1914
1915 // Check everything has been copied.
1916 EXPECT_TRUE(PathExists(dir_name_from));
1917 EXPECT_TRUE(PathExists(file_name_from));
1918 EXPECT_TRUE(PathExists(subdir_name_from));
1919 EXPECT_TRUE(PathExists(file_name2_from));
1920 EXPECT_TRUE(PathExists(dir_name_to));
1921 EXPECT_TRUE(PathExists(file_name_to));
1922 EXPECT_FALSE(PathExists(subdir_name_to));
1923 }
1924
TEST_F(FileUtilTest,CopyDirectoryExists)1925 TEST_F(FileUtilTest, CopyDirectoryExists) {
1926 // Create a directory.
1927 FilePath dir_name_from =
1928 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
1929 CreateDirectory(dir_name_from);
1930 ASSERT_TRUE(PathExists(dir_name_from));
1931
1932 // Create a file under the directory.
1933 FilePath file_name_from =
1934 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1935 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1936 ASSERT_TRUE(PathExists(file_name_from));
1937
1938 // Create a subdirectory.
1939 FilePath subdir_name_from =
1940 dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
1941 CreateDirectory(subdir_name_from);
1942 ASSERT_TRUE(PathExists(subdir_name_from));
1943
1944 // Create a file under the subdirectory.
1945 FilePath file_name2_from =
1946 subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1947 CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
1948 ASSERT_TRUE(PathExists(file_name2_from));
1949
1950 // Copy the directory not recursively.
1951 FilePath dir_name_to =
1952 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
1953 FilePath file_name_to =
1954 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1955 FilePath subdir_name_to =
1956 dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
1957
1958 // Create the destination directory.
1959 CreateDirectory(dir_name_to);
1960 ASSERT_TRUE(PathExists(dir_name_to));
1961
1962 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
1963
1964 // Check everything has been copied.
1965 EXPECT_TRUE(PathExists(dir_name_from));
1966 EXPECT_TRUE(PathExists(file_name_from));
1967 EXPECT_TRUE(PathExists(subdir_name_from));
1968 EXPECT_TRUE(PathExists(file_name2_from));
1969 EXPECT_TRUE(PathExists(dir_name_to));
1970 EXPECT_TRUE(PathExists(file_name_to));
1971 EXPECT_FALSE(PathExists(subdir_name_to));
1972 }
1973
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToNew)1974 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToNew) {
1975 // Create a file
1976 FilePath file_name_from =
1977 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1978 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1979 ASSERT_TRUE(PathExists(file_name_from));
1980
1981 // The destination name
1982 FilePath file_name_to = temp_dir_.GetPath().Append(
1983 FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
1984 ASSERT_FALSE(PathExists(file_name_to));
1985
1986 EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
1987
1988 // Check the has been copied
1989 EXPECT_TRUE(PathExists(file_name_to));
1990 }
1991
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToExisting)1992 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExisting) {
1993 // Create a file
1994 FilePath file_name_from =
1995 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
1996 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
1997 ASSERT_TRUE(PathExists(file_name_from));
1998
1999 // The destination name
2000 FilePath file_name_to = temp_dir_.GetPath().Append(
2001 FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
2002 CreateTextFile(file_name_to, L"Old file content");
2003 ASSERT_TRUE(PathExists(file_name_to));
2004
2005 EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
2006
2007 // Check the has been copied
2008 EXPECT_TRUE(PathExists(file_name_to));
2009 EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
2010 }
2011
TEST_F(FileUtilTest,CopyFileWithCopyDirectoryRecursiveToExistingDirectory)2012 TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExistingDirectory) {
2013 // Create a file
2014 FilePath file_name_from =
2015 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2016 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2017 ASSERT_TRUE(PathExists(file_name_from));
2018
2019 // The destination
2020 FilePath dir_name_to =
2021 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
2022 CreateDirectory(dir_name_to);
2023 ASSERT_TRUE(PathExists(dir_name_to));
2024 FilePath file_name_to =
2025 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2026
2027 EXPECT_TRUE(CopyDirectory(file_name_from, dir_name_to, true));
2028
2029 // Check the has been copied
2030 EXPECT_TRUE(PathExists(file_name_to));
2031 }
2032
TEST_F(FileUtilTest,CopyFileFailureWithCopyDirectoryExcl)2033 TEST_F(FileUtilTest, CopyFileFailureWithCopyDirectoryExcl) {
2034 // Create a file
2035 FilePath file_name_from =
2036 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2037 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2038 ASSERT_TRUE(PathExists(file_name_from));
2039
2040 // Make a destination file.
2041 FilePath file_name_to = temp_dir_.GetPath().Append(
2042 FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
2043 CreateTextFile(file_name_to, L"Old file content");
2044 ASSERT_TRUE(PathExists(file_name_to));
2045
2046 // Overwriting the destination should fail.
2047 EXPECT_FALSE(CopyDirectoryExcl(file_name_from, file_name_to, true));
2048 EXPECT_EQ(L"Old file content", ReadTextFile(file_name_to));
2049 }
2050
TEST_F(FileUtilTest,CopyDirectoryWithTrailingSeparators)2051 TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) {
2052 // Create a directory.
2053 FilePath dir_name_from =
2054 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2055 CreateDirectory(dir_name_from);
2056 ASSERT_TRUE(PathExists(dir_name_from));
2057
2058 // Create a file under the directory.
2059 FilePath file_name_from =
2060 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2061 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2062 ASSERT_TRUE(PathExists(file_name_from));
2063
2064 // Copy the directory recursively.
2065 FilePath dir_name_to =
2066 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2067 FilePath file_name_to =
2068 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2069
2070 // Create from path with trailing separators.
2071 #if defined(OS_WIN)
2072 FilePath from_path =
2073 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir\\\\\\"));
2074 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
2075 FilePath from_path =
2076 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir///"));
2077 #endif
2078
2079 EXPECT_TRUE(CopyDirectory(from_path, dir_name_to, true));
2080
2081 // Check everything has been copied.
2082 EXPECT_TRUE(PathExists(dir_name_from));
2083 EXPECT_TRUE(PathExists(file_name_from));
2084 EXPECT_TRUE(PathExists(dir_name_to));
2085 EXPECT_TRUE(PathExists(file_name_to));
2086 }
2087
2088 #if defined(OS_POSIX)
TEST_F(FileUtilTest,CopyDirectoryWithNonRegularFiles)2089 TEST_F(FileUtilTest, CopyDirectoryWithNonRegularFiles) {
2090 // Create a directory.
2091 FilePath dir_name_from =
2092 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2093 ASSERT_TRUE(CreateDirectory(dir_name_from));
2094 ASSERT_TRUE(PathExists(dir_name_from));
2095
2096 // Create a file under the directory.
2097 FilePath file_name_from =
2098 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2099 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2100 ASSERT_TRUE(PathExists(file_name_from));
2101
2102 // Create a symbolic link under the directory pointing to that file.
2103 FilePath symlink_name_from =
2104 dir_name_from.Append(FILE_PATH_LITERAL("Symlink"));
2105 ASSERT_TRUE(CreateSymbolicLink(file_name_from, symlink_name_from));
2106 ASSERT_TRUE(PathExists(symlink_name_from));
2107
2108 // Create a fifo under the directory.
2109 FilePath fifo_name_from =
2110 dir_name_from.Append(FILE_PATH_LITERAL("Fifo"));
2111 ASSERT_EQ(0, mkfifo(fifo_name_from.value().c_str(), 0644));
2112 ASSERT_TRUE(PathExists(fifo_name_from));
2113
2114 // Copy the directory.
2115 FilePath dir_name_to =
2116 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2117 FilePath file_name_to =
2118 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2119 FilePath symlink_name_to =
2120 dir_name_to.Append(FILE_PATH_LITERAL("Symlink"));
2121 FilePath fifo_name_to =
2122 dir_name_to.Append(FILE_PATH_LITERAL("Fifo"));
2123
2124 ASSERT_FALSE(PathExists(dir_name_to));
2125
2126 EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
2127
2128 // Check that only directories and regular files are copied.
2129 EXPECT_TRUE(PathExists(dir_name_from));
2130 EXPECT_TRUE(PathExists(file_name_from));
2131 EXPECT_TRUE(PathExists(symlink_name_from));
2132 EXPECT_TRUE(PathExists(fifo_name_from));
2133 EXPECT_TRUE(PathExists(dir_name_to));
2134 EXPECT_TRUE(PathExists(file_name_to));
2135 EXPECT_FALSE(PathExists(symlink_name_to));
2136 EXPECT_FALSE(PathExists(fifo_name_to));
2137 }
2138
TEST_F(FileUtilTest,CopyDirectoryExclFileOverSymlink)2139 TEST_F(FileUtilTest, CopyDirectoryExclFileOverSymlink) {
2140 // Create a directory.
2141 FilePath dir_name_from =
2142 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2143 ASSERT_TRUE(CreateDirectory(dir_name_from));
2144 ASSERT_TRUE(PathExists(dir_name_from));
2145
2146 // Create a file under the directory.
2147 FilePath file_name_from =
2148 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2149 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2150 ASSERT_TRUE(PathExists(file_name_from));
2151
2152 // Create a destination directory with a symlink of the same name.
2153 FilePath dir_name_to =
2154 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2155 ASSERT_TRUE(CreateDirectory(dir_name_to));
2156 ASSERT_TRUE(PathExists(dir_name_to));
2157
2158 FilePath symlink_target =
2159 dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
2160 CreateTextFile(symlink_target, L"asdf");
2161 ASSERT_TRUE(PathExists(symlink_target));
2162
2163 FilePath symlink_name_to =
2164 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2165 ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2166 ASSERT_TRUE(PathExists(symlink_name_to));
2167
2168 // Check that copying fails.
2169 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2170 }
2171
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverSymlink)2172 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverSymlink) {
2173 // Create a directory.
2174 FilePath dir_name_from =
2175 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2176 ASSERT_TRUE(CreateDirectory(dir_name_from));
2177 ASSERT_TRUE(PathExists(dir_name_from));
2178
2179 // Create a subdirectory.
2180 FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
2181 CreateDirectory(subdir_name_from);
2182 ASSERT_TRUE(PathExists(subdir_name_from));
2183
2184 // Create a destination directory with a symlink of the same name.
2185 FilePath dir_name_to =
2186 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2187 ASSERT_TRUE(CreateDirectory(dir_name_to));
2188 ASSERT_TRUE(PathExists(dir_name_to));
2189
2190 FilePath symlink_target = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
2191 CreateTextFile(symlink_target, L"asdf");
2192 ASSERT_TRUE(PathExists(symlink_target));
2193
2194 FilePath symlink_name_to =
2195 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2196 ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2197 ASSERT_TRUE(PathExists(symlink_name_to));
2198
2199 // Check that copying fails.
2200 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2201 }
2202
TEST_F(FileUtilTest,CopyDirectoryExclFileOverDanglingSymlink)2203 TEST_F(FileUtilTest, CopyDirectoryExclFileOverDanglingSymlink) {
2204 // Create a directory.
2205 FilePath dir_name_from =
2206 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2207 ASSERT_TRUE(CreateDirectory(dir_name_from));
2208 ASSERT_TRUE(PathExists(dir_name_from));
2209
2210 // Create a file under the directory.
2211 FilePath file_name_from =
2212 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2213 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2214 ASSERT_TRUE(PathExists(file_name_from));
2215
2216 // Create a destination directory with a dangling symlink of the same name.
2217 FilePath dir_name_to =
2218 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2219 ASSERT_TRUE(CreateDirectory(dir_name_to));
2220 ASSERT_TRUE(PathExists(dir_name_to));
2221
2222 FilePath symlink_target =
2223 dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
2224 CreateTextFile(symlink_target, L"asdf");
2225 ASSERT_TRUE(PathExists(symlink_target));
2226
2227 FilePath symlink_name_to =
2228 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2229 ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2230 ASSERT_TRUE(PathExists(symlink_name_to));
2231 ASSERT_TRUE(DeleteFile(symlink_target, false));
2232
2233 // Check that copying fails and that no file was created for the symlink's
2234 // referent.
2235 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2236 EXPECT_FALSE(PathExists(symlink_target));
2237 }
2238
TEST_F(FileUtilTest,CopyDirectoryExclDirectoryOverDanglingSymlink)2239 TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverDanglingSymlink) {
2240 // Create a directory.
2241 FilePath dir_name_from =
2242 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2243 ASSERT_TRUE(CreateDirectory(dir_name_from));
2244 ASSERT_TRUE(PathExists(dir_name_from));
2245
2246 // Create a subdirectory.
2247 FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
2248 CreateDirectory(subdir_name_from);
2249 ASSERT_TRUE(PathExists(subdir_name_from));
2250
2251 // Create a destination directory with a dangling symlink of the same name.
2252 FilePath dir_name_to =
2253 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2254 ASSERT_TRUE(CreateDirectory(dir_name_to));
2255 ASSERT_TRUE(PathExists(dir_name_to));
2256
2257 FilePath symlink_target =
2258 dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
2259 CreateTextFile(symlink_target, L"asdf");
2260 ASSERT_TRUE(PathExists(symlink_target));
2261
2262 FilePath symlink_name_to =
2263 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2264 ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
2265 ASSERT_TRUE(PathExists(symlink_name_to));
2266 ASSERT_TRUE(DeleteFile(symlink_target, false));
2267
2268 // Check that copying fails and that no directory was created for the
2269 // symlink's referent.
2270 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2271 EXPECT_FALSE(PathExists(symlink_target));
2272 }
2273
TEST_F(FileUtilTest,CopyDirectoryExclFileOverFifo)2274 TEST_F(FileUtilTest, CopyDirectoryExclFileOverFifo) {
2275 // Create a directory.
2276 FilePath dir_name_from =
2277 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2278 ASSERT_TRUE(CreateDirectory(dir_name_from));
2279 ASSERT_TRUE(PathExists(dir_name_from));
2280
2281 // Create a file under the directory.
2282 FilePath file_name_from =
2283 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2284 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2285 ASSERT_TRUE(PathExists(file_name_from));
2286
2287 // Create a destination directory with a fifo of the same name.
2288 FilePath dir_name_to =
2289 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
2290 ASSERT_TRUE(CreateDirectory(dir_name_to));
2291 ASSERT_TRUE(PathExists(dir_name_to));
2292
2293 FilePath fifo_name_to =
2294 dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2295 ASSERT_EQ(0, mkfifo(fifo_name_to.value().c_str(), 0644));
2296 ASSERT_TRUE(PathExists(fifo_name_to));
2297
2298 // Check that copying fails.
2299 EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
2300 }
2301 #endif // defined(OS_POSIX)
2302
TEST_F(FileUtilTest,CopyFile)2303 TEST_F(FileUtilTest, CopyFile) {
2304 // Create a directory
2305 FilePath dir_name_from =
2306 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
2307 ASSERT_TRUE(CreateDirectory(dir_name_from));
2308 ASSERT_TRUE(DirectoryExists(dir_name_from));
2309
2310 // Create a file under the directory
2311 FilePath file_name_from =
2312 dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
2313 const std::wstring file_contents(L"Gooooooooooooooooooooogle");
2314 CreateTextFile(file_name_from, file_contents);
2315 ASSERT_TRUE(PathExists(file_name_from));
2316
2317 // Copy the file.
2318 FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
2319 ASSERT_TRUE(CopyFile(file_name_from, dest_file));
2320
2321 // Try to copy the file to another location using '..' in the path.
2322 FilePath dest_file2(dir_name_from);
2323 dest_file2 = dest_file2.AppendASCII("..");
2324 dest_file2 = dest_file2.AppendASCII("DestFile.txt");
2325 ASSERT_FALSE(CopyFile(file_name_from, dest_file2));
2326
2327 FilePath dest_file2_test(dir_name_from);
2328 dest_file2_test = dest_file2_test.DirName();
2329 dest_file2_test = dest_file2_test.AppendASCII("DestFile.txt");
2330
2331 // Check expected copy results.
2332 EXPECT_TRUE(PathExists(file_name_from));
2333 EXPECT_TRUE(PathExists(dest_file));
2334 EXPECT_EQ(file_contents, ReadTextFile(dest_file));
2335 EXPECT_FALSE(PathExists(dest_file2_test));
2336 EXPECT_FALSE(PathExists(dest_file2));
2337
2338 // Change |file_name_from| contents.
2339 const std::wstring new_file_contents(L"Moogle");
2340 CreateTextFile(file_name_from, new_file_contents);
2341 ASSERT_TRUE(PathExists(file_name_from));
2342 EXPECT_EQ(new_file_contents, ReadTextFile(file_name_from));
2343
2344 // Overwrite |dest_file|.
2345 ASSERT_TRUE(CopyFile(file_name_from, dest_file));
2346 EXPECT_TRUE(PathExists(dest_file));
2347 EXPECT_EQ(new_file_contents, ReadTextFile(dest_file));
2348
2349 // Create another directory.
2350 FilePath dest_dir = temp_dir_.GetPath().Append(FPL("dest_dir"));
2351 ASSERT_TRUE(CreateDirectory(dest_dir));
2352 EXPECT_TRUE(DirectoryExists(dest_dir));
2353 EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
2354
2355 // Make sure CopyFile() cannot overwrite a directory.
2356 ASSERT_FALSE(CopyFile(file_name_from, dest_dir));
2357 EXPECT_TRUE(DirectoryExists(dest_dir));
2358 EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
2359 }
2360
2361 // file_util winds up using autoreleased objects on the Mac, so this needs
2362 // to be a PlatformTest.
2363 typedef PlatformTest ReadOnlyFileUtilTest;
2364
TEST_F(ReadOnlyFileUtilTest,ContentsEqual)2365 TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
2366 FilePath data_dir;
2367 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
2368 data_dir = data_dir.AppendASCII("file_util");
2369 ASSERT_TRUE(PathExists(data_dir));
2370
2371 FilePath original_file =
2372 data_dir.Append(FILE_PATH_LITERAL("original.txt"));
2373 FilePath same_file =
2374 data_dir.Append(FILE_PATH_LITERAL("same.txt"));
2375 FilePath same_length_file =
2376 data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
2377 FilePath different_file =
2378 data_dir.Append(FILE_PATH_LITERAL("different.txt"));
2379 FilePath different_first_file =
2380 data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
2381 FilePath different_last_file =
2382 data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
2383 FilePath empty1_file =
2384 data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
2385 FilePath empty2_file =
2386 data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
2387 FilePath shortened_file =
2388 data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
2389 FilePath binary_file =
2390 data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
2391 FilePath binary_file_same =
2392 data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
2393 FilePath binary_file_diff =
2394 data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
2395
2396 EXPECT_TRUE(ContentsEqual(original_file, original_file));
2397 EXPECT_TRUE(ContentsEqual(original_file, same_file));
2398 EXPECT_FALSE(ContentsEqual(original_file, same_length_file));
2399 EXPECT_FALSE(ContentsEqual(original_file, different_file));
2400 EXPECT_FALSE(ContentsEqual(FilePath(FILE_PATH_LITERAL("bogusname")),
2401 FilePath(FILE_PATH_LITERAL("bogusname"))));
2402 EXPECT_FALSE(ContentsEqual(original_file, different_first_file));
2403 EXPECT_FALSE(ContentsEqual(original_file, different_last_file));
2404 EXPECT_TRUE(ContentsEqual(empty1_file, empty2_file));
2405 EXPECT_FALSE(ContentsEqual(original_file, shortened_file));
2406 EXPECT_FALSE(ContentsEqual(shortened_file, original_file));
2407 EXPECT_TRUE(ContentsEqual(binary_file, binary_file_same));
2408 EXPECT_FALSE(ContentsEqual(binary_file, binary_file_diff));
2409 }
2410
TEST_F(ReadOnlyFileUtilTest,TextContentsEqual)2411 TEST_F(ReadOnlyFileUtilTest, TextContentsEqual) {
2412 FilePath data_dir;
2413 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
2414 data_dir = data_dir.AppendASCII("file_util");
2415 ASSERT_TRUE(PathExists(data_dir));
2416
2417 FilePath original_file =
2418 data_dir.Append(FILE_PATH_LITERAL("original.txt"));
2419 FilePath same_file =
2420 data_dir.Append(FILE_PATH_LITERAL("same.txt"));
2421 FilePath crlf_file =
2422 data_dir.Append(FILE_PATH_LITERAL("crlf.txt"));
2423 FilePath shortened_file =
2424 data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
2425 FilePath different_file =
2426 data_dir.Append(FILE_PATH_LITERAL("different.txt"));
2427 FilePath different_first_file =
2428 data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
2429 FilePath different_last_file =
2430 data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
2431 FilePath first1_file =
2432 data_dir.Append(FILE_PATH_LITERAL("first1.txt"));
2433 FilePath first2_file =
2434 data_dir.Append(FILE_PATH_LITERAL("first2.txt"));
2435 FilePath empty1_file =
2436 data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
2437 FilePath empty2_file =
2438 data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
2439 FilePath blank_line_file =
2440 data_dir.Append(FILE_PATH_LITERAL("blank_line.txt"));
2441 FilePath blank_line_crlf_file =
2442 data_dir.Append(FILE_PATH_LITERAL("blank_line_crlf.txt"));
2443
2444 EXPECT_TRUE(TextContentsEqual(original_file, same_file));
2445 EXPECT_TRUE(TextContentsEqual(original_file, crlf_file));
2446 EXPECT_FALSE(TextContentsEqual(original_file, shortened_file));
2447 EXPECT_FALSE(TextContentsEqual(original_file, different_file));
2448 EXPECT_FALSE(TextContentsEqual(original_file, different_first_file));
2449 EXPECT_FALSE(TextContentsEqual(original_file, different_last_file));
2450 EXPECT_FALSE(TextContentsEqual(first1_file, first2_file));
2451 EXPECT_TRUE(TextContentsEqual(empty1_file, empty2_file));
2452 EXPECT_FALSE(TextContentsEqual(original_file, empty1_file));
2453 EXPECT_TRUE(TextContentsEqual(blank_line_file, blank_line_crlf_file));
2454 }
2455
2456 // We don't need equivalent functionality outside of Windows.
2457 #if defined(OS_WIN)
TEST_F(FileUtilTest,CopyAndDeleteDirectoryTest)2458 TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) {
2459 // Create a directory
2460 FilePath dir_name_from = temp_dir_.GetPath().Append(
2461 FILE_PATH_LITERAL("CopyAndDelete_From_Subdir"));
2462 CreateDirectory(dir_name_from);
2463 ASSERT_TRUE(PathExists(dir_name_from));
2464
2465 // Create a file under the directory
2466 FilePath file_name_from =
2467 dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
2468 CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
2469 ASSERT_TRUE(PathExists(file_name_from));
2470
2471 // Move the directory by using CopyAndDeleteDirectory
2472 FilePath dir_name_to =
2473 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("CopyAndDelete_To_Subdir"));
2474 FilePath file_name_to =
2475 dir_name_to.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
2476
2477 ASSERT_FALSE(PathExists(dir_name_to));
2478
2479 EXPECT_TRUE(internal::CopyAndDeleteDirectory(dir_name_from,
2480 dir_name_to));
2481
2482 // Check everything has been moved.
2483 EXPECT_FALSE(PathExists(dir_name_from));
2484 EXPECT_FALSE(PathExists(file_name_from));
2485 EXPECT_TRUE(PathExists(dir_name_to));
2486 EXPECT_TRUE(PathExists(file_name_to));
2487 }
2488
TEST_F(FileUtilTest,GetTempDirTest)2489 TEST_F(FileUtilTest, GetTempDirTest) {
2490 static const TCHAR* kTmpKey = _T("TMP");
2491 static const TCHAR* kTmpValues[] = {
2492 _T(""), _T("C:"), _T("C:\\"), _T("C:\\tmp"), _T("C:\\tmp\\")
2493 };
2494 // Save the original $TMP.
2495 size_t original_tmp_size;
2496 TCHAR* original_tmp;
2497 ASSERT_EQ(0, ::_tdupenv_s(&original_tmp, &original_tmp_size, kTmpKey));
2498 // original_tmp may be NULL.
2499
2500 for (unsigned int i = 0; i < size(kTmpValues); ++i) {
2501 FilePath path;
2502 ::_tputenv_s(kTmpKey, kTmpValues[i]);
2503 GetTempDir(&path);
2504 EXPECT_TRUE(path.IsAbsolute()) << "$TMP=" << kTmpValues[i] <<
2505 " result=" << path.value();
2506 }
2507
2508 // Restore the original $TMP.
2509 if (original_tmp) {
2510 ::_tputenv_s(kTmpKey, original_tmp);
2511 free(original_tmp);
2512 } else {
2513 ::_tputenv_s(kTmpKey, _T(""));
2514 }
2515 }
2516 #endif // OS_WIN
2517
2518 // Test that files opened by OpenFile are not set up for inheritance into child
2519 // procs.
TEST_F(FileUtilTest,OpenFileNoInheritance)2520 TEST_F(FileUtilTest, OpenFileNoInheritance) {
2521 FilePath file_path(temp_dir_.GetPath().Append(FPL("a_file")));
2522
2523 // Character set handling is leaking according to ASAN. http://crbug.com/883698
2524 #if defined(ADDRESS_SANITIZER)
2525 static constexpr const char* modes[] = {"wb", "r"};
2526 #else
2527 static constexpr const char* modes[] = {"wb", "r,ccs=UTF-8"};
2528 #endif
2529
2530 for (const char* mode : modes) {
2531 SCOPED_TRACE(mode);
2532 ASSERT_NO_FATAL_FAILURE(CreateTextFile(file_path, L"Geepers"));
2533 FILE* file = OpenFile(file_path, mode);
2534 ASSERT_NE(nullptr, file);
2535 {
2536 ScopedClosureRunner file_closer(BindOnce(IgnoreResult(&CloseFile), file));
2537 bool is_inheritable = true;
2538 ASSERT_NO_FATAL_FAILURE(GetIsInheritable(file, &is_inheritable));
2539 EXPECT_FALSE(is_inheritable);
2540 }
2541 ASSERT_TRUE(DeleteFile(file_path, false));
2542 }
2543 }
2544
TEST_F(FileUtilTest,CreateTemporaryFileTest)2545 TEST_F(FileUtilTest, CreateTemporaryFileTest) {
2546 FilePath temp_files[3];
2547 for (auto& i : temp_files) {
2548 ASSERT_TRUE(CreateTemporaryFile(&i));
2549 EXPECT_TRUE(PathExists(i));
2550 EXPECT_FALSE(DirectoryExists(i));
2551 }
2552 for (int i = 0; i < 3; i++)
2553 EXPECT_FALSE(temp_files[i] == temp_files[(i+1)%3]);
2554 for (const auto& i : temp_files)
2555 EXPECT_TRUE(DeleteFile(i, false));
2556 }
2557
TEST_F(FileUtilTest,CreateAndOpenTemporaryFileTest)2558 TEST_F(FileUtilTest, CreateAndOpenTemporaryFileTest) {
2559 FilePath names[3];
2560 FILE* fps[3];
2561 int i;
2562
2563 // Create; make sure they are open and exist.
2564 for (i = 0; i < 3; ++i) {
2565 fps[i] = CreateAndOpenTemporaryFile(&(names[i]));
2566 ASSERT_TRUE(fps[i]);
2567 EXPECT_TRUE(PathExists(names[i]));
2568 }
2569
2570 // Make sure all names are unique.
2571 for (i = 0; i < 3; ++i) {
2572 EXPECT_FALSE(names[i] == names[(i+1)%3]);
2573 }
2574
2575 // Close and delete.
2576 for (i = 0; i < 3; ++i) {
2577 EXPECT_TRUE(CloseFile(fps[i]));
2578 EXPECT_TRUE(DeleteFile(names[i], false));
2579 }
2580 }
2581
TEST_F(FileUtilTest,GetUniquePathTest)2582 TEST_F(FileUtilTest, GetUniquePathTest) {
2583 // Create a unique temp directory and use it to generate a unique file path.
2584 base::ScopedTempDir temp_dir;
2585 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
2586 EXPECT_TRUE(temp_dir.IsValid());
2587 FilePath base_name(FILE_PATH_LITERAL("Unique_Base_Name.txt"));
2588 FilePath base_path = temp_dir.GetPath().Append(base_name);
2589 EXPECT_FALSE(PathExists(base_path));
2590
2591 // GetUniquePath() should return unchanged path if file does not exist.
2592 EXPECT_EQ(base_path, GetUniquePath(base_path));
2593
2594 // Create the file.
2595 {
2596 File file(base_path,
2597 File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
2598 EXPECT_TRUE(PathExists(base_path));
2599 }
2600
2601 static const FilePath::CharType* const kExpectedNames[] = {
2602 FILE_PATH_LITERAL("Unique_Base_Name (1).txt"),
2603 FILE_PATH_LITERAL("Unique_Base_Name (2).txt"),
2604 FILE_PATH_LITERAL("Unique_Base_Name (3).txt"),
2605 };
2606
2607 // Call GetUniquePath() three times against this existing file name.
2608 for (const FilePath::CharType* expected_name : kExpectedNames) {
2609 FilePath expected_path = temp_dir.GetPath().Append(expected_name);
2610 FilePath path = GetUniquePath(base_path);
2611 EXPECT_EQ(expected_path, path);
2612
2613 // Verify that a file with this path indeed does not exist on the file
2614 // system.
2615 EXPECT_FALSE(PathExists(path));
2616
2617 // Create the file so it exists for the next call to GetUniquePath() in the
2618 // loop.
2619 File file(path, File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
2620 EXPECT_TRUE(PathExists(path));
2621 }
2622 }
2623
TEST_F(FileUtilTest,FileToFILE)2624 TEST_F(FileUtilTest, FileToFILE) {
2625 File file;
2626 FILE* stream = FileToFILE(std::move(file), "w");
2627 EXPECT_FALSE(stream);
2628
2629 FilePath file_name = temp_dir_.GetPath().Append(FPL("The file.txt"));
2630 file = File(file_name, File::FLAG_CREATE | File::FLAG_WRITE);
2631 EXPECT_TRUE(file.IsValid());
2632
2633 stream = FileToFILE(std::move(file), "w");
2634 EXPECT_TRUE(stream);
2635 EXPECT_FALSE(file.IsValid());
2636 EXPECT_TRUE(CloseFile(stream));
2637 }
2638
TEST_F(FileUtilTest,CreateNewTempDirectoryTest)2639 TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
2640 FilePath temp_dir;
2641 ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
2642 EXPECT_TRUE(PathExists(temp_dir));
2643 EXPECT_TRUE(DeleteFile(temp_dir, false));
2644 }
2645
TEST_F(FileUtilTest,CreateNewTemporaryDirInDirTest)2646 TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) {
2647 FilePath new_dir;
2648 ASSERT_TRUE(CreateTemporaryDirInDir(
2649 temp_dir_.GetPath(), FILE_PATH_LITERAL("CreateNewTemporaryDirInDirTest"),
2650 &new_dir));
2651 EXPECT_TRUE(PathExists(new_dir));
2652 EXPECT_TRUE(temp_dir_.GetPath().IsParent(new_dir));
2653 EXPECT_TRUE(DeleteFile(new_dir, false));
2654 }
2655
2656 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
TEST_F(FileUtilTest,GetShmemTempDirTest)2657 TEST_F(FileUtilTest, GetShmemTempDirTest) {
2658 FilePath dir;
2659 EXPECT_TRUE(GetShmemTempDir(false, &dir));
2660 EXPECT_TRUE(DirectoryExists(dir));
2661 }
2662
TEST_F(FileUtilTest,AllocateFileRegionTest_ZeroOffset)2663 TEST_F(FileUtilTest, AllocateFileRegionTest_ZeroOffset) {
2664 const int kTestFileLength = 9;
2665 char test_data[] = "test_data";
2666 FilePath file_path = temp_dir_.GetPath().Append(
2667 FILE_PATH_LITERAL("allocate_file_region_test_zero_offset"));
2668 WriteFile(file_path, test_data, kTestFileLength);
2669
2670 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
2671 base::File::FLAG_WRITE);
2672 ASSERT_TRUE(file.IsValid());
2673 ASSERT_EQ(file.GetLength(), kTestFileLength);
2674
2675 const int kExtendedFileLength = 23;
2676 ASSERT_TRUE(AllocateFileRegion(&file, 0, kExtendedFileLength));
2677 EXPECT_EQ(file.GetLength(), kExtendedFileLength);
2678
2679 char data_read[32];
2680 int bytes_read = file.Read(0, data_read, kExtendedFileLength);
2681 EXPECT_EQ(bytes_read, kExtendedFileLength);
2682 for (int i = 0; i < kTestFileLength; ++i)
2683 EXPECT_EQ(test_data[i], data_read[i]);
2684 for (int i = kTestFileLength; i < kExtendedFileLength; ++i)
2685 EXPECT_EQ(0, data_read[i]);
2686 }
2687
TEST_F(FileUtilTest,AllocateFileRegionTest_NonZeroOffset)2688 TEST_F(FileUtilTest, AllocateFileRegionTest_NonZeroOffset) {
2689 const int kTestFileLength = 9;
2690 char test_data[] = "test_data";
2691 FilePath file_path = temp_dir_.GetPath().Append(
2692 FILE_PATH_LITERAL("allocate_file_region_test_non_zero_offset"));
2693 WriteFile(file_path, test_data, kTestFileLength);
2694
2695 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
2696 base::File::FLAG_WRITE);
2697 ASSERT_TRUE(file.IsValid());
2698 ASSERT_EQ(file.GetLength(), kTestFileLength);
2699
2700 const int kExtensionOffset = 5;
2701 const int kExtensionSize = 10;
2702 ASSERT_TRUE(AllocateFileRegion(&file, kExtensionOffset, kExtensionSize));
2703 const int kExtendedFileLength = kExtensionOffset + kExtensionSize;
2704 EXPECT_EQ(file.GetLength(), kExtendedFileLength);
2705
2706 char data_read[32];
2707 int bytes_read = file.Read(0, data_read, kExtendedFileLength);
2708 EXPECT_EQ(bytes_read, kExtendedFileLength);
2709 for (int i = 0; i < kTestFileLength; ++i)
2710 EXPECT_EQ(test_data[i], data_read[i]);
2711 for (int i = kTestFileLength; i < kExtendedFileLength; ++i)
2712 EXPECT_EQ(0, data_read[i]);
2713 }
2714
TEST_F(FileUtilTest,AllocateFileRegionTest_DontTruncate)2715 TEST_F(FileUtilTest, AllocateFileRegionTest_DontTruncate) {
2716 const int kTestFileLength = 9;
2717 char test_data[] = "test_data";
2718 FilePath file_path = temp_dir_.GetPath().Append(
2719 FILE_PATH_LITERAL("allocate_file_region_test_dont_truncate"));
2720 WriteFile(file_path, test_data, kTestFileLength);
2721
2722 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
2723 base::File::FLAG_WRITE);
2724 ASSERT_TRUE(file.IsValid());
2725 ASSERT_EQ(file.GetLength(), kTestFileLength);
2726
2727 const int kTruncatedFileLength = 4;
2728 ASSERT_TRUE(AllocateFileRegion(&file, 0, kTruncatedFileLength));
2729 EXPECT_EQ(file.GetLength(), kTestFileLength);
2730 }
2731 #endif
2732
TEST_F(FileUtilTest,GetHomeDirTest)2733 TEST_F(FileUtilTest, GetHomeDirTest) {
2734 #if !defined(OS_ANDROID) // Not implemented on Android.
2735 // We don't actually know what the home directory is supposed to be without
2736 // calling some OS functions which would just duplicate the implementation.
2737 // So here we just test that it returns something "reasonable".
2738 FilePath home = GetHomeDir();
2739 ASSERT_FALSE(home.empty());
2740 ASSERT_TRUE(home.IsAbsolute());
2741 #endif
2742 }
2743
TEST_F(FileUtilTest,CreateDirectoryTest)2744 TEST_F(FileUtilTest, CreateDirectoryTest) {
2745 FilePath test_root =
2746 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("create_directory_test"));
2747 #if defined(OS_WIN)
2748 FilePath test_path =
2749 test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
2750 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
2751 FilePath test_path =
2752 test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
2753 #endif
2754
2755 EXPECT_FALSE(PathExists(test_path));
2756 EXPECT_TRUE(CreateDirectory(test_path));
2757 EXPECT_TRUE(PathExists(test_path));
2758 // CreateDirectory returns true if the DirectoryExists returns true.
2759 EXPECT_TRUE(CreateDirectory(test_path));
2760
2761 // Doesn't work to create it on top of a non-dir
2762 test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
2763 EXPECT_FALSE(PathExists(test_path));
2764 CreateTextFile(test_path, L"test file");
2765 EXPECT_TRUE(PathExists(test_path));
2766 EXPECT_FALSE(CreateDirectory(test_path));
2767
2768 EXPECT_TRUE(DeleteFileRecursively(test_root));
2769 EXPECT_FALSE(PathExists(test_root));
2770 EXPECT_FALSE(PathExists(test_path));
2771
2772 // Verify assumptions made by the Windows implementation:
2773 // 1. The current directory always exists.
2774 // 2. The root directory always exists.
2775 ASSERT_TRUE(DirectoryExists(FilePath(FilePath::kCurrentDirectory)));
2776 FilePath top_level = test_root;
2777 while (top_level != top_level.DirName()) {
2778 top_level = top_level.DirName();
2779 }
2780 ASSERT_TRUE(DirectoryExists(top_level));
2781
2782 // Given these assumptions hold, it should be safe to
2783 // test that "creating" these directories succeeds.
2784 EXPECT_TRUE(CreateDirectory(
2785 FilePath(FilePath::kCurrentDirectory)));
2786 EXPECT_TRUE(CreateDirectory(top_level));
2787
2788 #if defined(OS_WIN)
2789 FilePath invalid_drive(FILE_PATH_LITERAL("o:\\"));
2790 FilePath invalid_path =
2791 invalid_drive.Append(FILE_PATH_LITERAL("some\\inaccessible\\dir"));
2792 if (!PathExists(invalid_drive)) {
2793 EXPECT_FALSE(CreateDirectory(invalid_path));
2794 }
2795 #endif
2796 }
2797
TEST_F(FileUtilTest,DetectDirectoryTest)2798 TEST_F(FileUtilTest, DetectDirectoryTest) {
2799 // Check a directory
2800 FilePath test_root =
2801 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("detect_directory_test"));
2802 EXPECT_FALSE(PathExists(test_root));
2803 EXPECT_TRUE(CreateDirectory(test_root));
2804 EXPECT_TRUE(PathExists(test_root));
2805 EXPECT_TRUE(DirectoryExists(test_root));
2806 // Check a file
2807 FilePath test_path =
2808 test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
2809 EXPECT_FALSE(PathExists(test_path));
2810 CreateTextFile(test_path, L"test file");
2811 EXPECT_TRUE(PathExists(test_path));
2812 EXPECT_FALSE(DirectoryExists(test_path));
2813 EXPECT_TRUE(DeleteFile(test_path, false));
2814
2815 EXPECT_TRUE(DeleteFileRecursively(test_root));
2816 }
2817
TEST_F(FileUtilTest,FileEnumeratorTest)2818 TEST_F(FileUtilTest, FileEnumeratorTest) {
2819 // Test an empty directory.
2820 FileEnumerator f0(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
2821 EXPECT_EQ(FPL(""), f0.Next().value());
2822 EXPECT_EQ(FPL(""), f0.Next().value());
2823
2824 // Test an empty directory, non-recursively, including "..".
2825 FileEnumerator f0_dotdot(
2826 temp_dir_.GetPath(), false,
2827 FILES_AND_DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
2828 EXPECT_EQ(temp_dir_.GetPath().Append(FPL("..")).value(),
2829 f0_dotdot.Next().value());
2830 EXPECT_EQ(FPL(""), f0_dotdot.Next().value());
2831
2832 // create the directories
2833 FilePath dir1 = temp_dir_.GetPath().Append(FPL("dir1"));
2834 EXPECT_TRUE(CreateDirectory(dir1));
2835 FilePath dir2 = temp_dir_.GetPath().Append(FPL("dir2"));
2836 EXPECT_TRUE(CreateDirectory(dir2));
2837 FilePath dir2inner = dir2.Append(FPL("inner"));
2838 EXPECT_TRUE(CreateDirectory(dir2inner));
2839
2840 // create the files
2841 FilePath dir2file = dir2.Append(FPL("dir2file.txt"));
2842 CreateTextFile(dir2file, std::wstring());
2843 FilePath dir2innerfile = dir2inner.Append(FPL("innerfile.txt"));
2844 CreateTextFile(dir2innerfile, std::wstring());
2845 FilePath file1 = temp_dir_.GetPath().Append(FPL("file1.txt"));
2846 CreateTextFile(file1, std::wstring());
2847 FilePath file2_rel = dir2.Append(FilePath::kParentDirectory)
2848 .Append(FPL("file2.txt"));
2849 CreateTextFile(file2_rel, std::wstring());
2850 FilePath file2_abs = temp_dir_.GetPath().Append(FPL("file2.txt"));
2851
2852 // Only enumerate files.
2853 FileEnumerator f1(temp_dir_.GetPath(), true, FileEnumerator::FILES);
2854 FindResultCollector c1(&f1);
2855 EXPECT_TRUE(c1.HasFile(file1));
2856 EXPECT_TRUE(c1.HasFile(file2_abs));
2857 EXPECT_TRUE(c1.HasFile(dir2file));
2858 EXPECT_TRUE(c1.HasFile(dir2innerfile));
2859 EXPECT_EQ(4, c1.size());
2860
2861 // Only enumerate directories.
2862 FileEnumerator f2(temp_dir_.GetPath(), true, FileEnumerator::DIRECTORIES);
2863 FindResultCollector c2(&f2);
2864 EXPECT_TRUE(c2.HasFile(dir1));
2865 EXPECT_TRUE(c2.HasFile(dir2));
2866 EXPECT_TRUE(c2.HasFile(dir2inner));
2867 EXPECT_EQ(3, c2.size());
2868
2869 // Only enumerate directories non-recursively.
2870 FileEnumerator f2_non_recursive(temp_dir_.GetPath(), false,
2871 FileEnumerator::DIRECTORIES);
2872 FindResultCollector c2_non_recursive(&f2_non_recursive);
2873 EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
2874 EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
2875 EXPECT_EQ(2, c2_non_recursive.size());
2876
2877 // Only enumerate directories, non-recursively, including "..".
2878 FileEnumerator f2_dotdot(
2879 temp_dir_.GetPath(), false,
2880 FileEnumerator::DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
2881 FindResultCollector c2_dotdot(&f2_dotdot);
2882 EXPECT_TRUE(c2_dotdot.HasFile(dir1));
2883 EXPECT_TRUE(c2_dotdot.HasFile(dir2));
2884 EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.GetPath().Append(FPL(".."))));
2885 EXPECT_EQ(3, c2_dotdot.size());
2886
2887 // Enumerate files and directories.
2888 FileEnumerator f3(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
2889 FindResultCollector c3(&f3);
2890 EXPECT_TRUE(c3.HasFile(dir1));
2891 EXPECT_TRUE(c3.HasFile(dir2));
2892 EXPECT_TRUE(c3.HasFile(file1));
2893 EXPECT_TRUE(c3.HasFile(file2_abs));
2894 EXPECT_TRUE(c3.HasFile(dir2file));
2895 EXPECT_TRUE(c3.HasFile(dir2inner));
2896 EXPECT_TRUE(c3.HasFile(dir2innerfile));
2897 EXPECT_EQ(7, c3.size());
2898
2899 // Non-recursive operation.
2900 FileEnumerator f4(temp_dir_.GetPath(), false, FILES_AND_DIRECTORIES);
2901 FindResultCollector c4(&f4);
2902 EXPECT_TRUE(c4.HasFile(dir2));
2903 EXPECT_TRUE(c4.HasFile(dir2));
2904 EXPECT_TRUE(c4.HasFile(file1));
2905 EXPECT_TRUE(c4.HasFile(file2_abs));
2906 EXPECT_EQ(4, c4.size());
2907
2908 // Enumerate with a pattern.
2909 FileEnumerator f5(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES,
2910 FPL("dir*"));
2911 FindResultCollector c5(&f5);
2912 EXPECT_TRUE(c5.HasFile(dir1));
2913 EXPECT_TRUE(c5.HasFile(dir2));
2914 EXPECT_TRUE(c5.HasFile(dir2file));
2915 EXPECT_TRUE(c5.HasFile(dir2inner));
2916 EXPECT_TRUE(c5.HasFile(dir2innerfile));
2917 EXPECT_EQ(5, c5.size());
2918
2919 #if defined(OS_WIN)
2920 {
2921 // Make dir1 point to dir2.
2922 ReparsePoint reparse_point(dir1, dir2);
2923 EXPECT_TRUE(reparse_point.IsValid());
2924
2925 // There can be a delay for the enumeration code to see the change on
2926 // the file system so skip this test for XP.
2927 // Enumerate the reparse point.
2928 FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES);
2929 FindResultCollector c6(&f6);
2930 FilePath inner2 = dir1.Append(FPL("inner"));
2931 EXPECT_TRUE(c6.HasFile(inner2));
2932 EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt"))));
2933 EXPECT_TRUE(c6.HasFile(dir1.Append(FPL("dir2file.txt"))));
2934 EXPECT_EQ(3, c6.size());
2935
2936 // No changes for non recursive operation.
2937 FileEnumerator f7(temp_dir_.GetPath(), false, FILES_AND_DIRECTORIES);
2938 FindResultCollector c7(&f7);
2939 EXPECT_TRUE(c7.HasFile(dir2));
2940 EXPECT_TRUE(c7.HasFile(dir2));
2941 EXPECT_TRUE(c7.HasFile(file1));
2942 EXPECT_TRUE(c7.HasFile(file2_abs));
2943 EXPECT_EQ(4, c7.size());
2944
2945 // Should not enumerate inside dir1 when using recursion.
2946 FileEnumerator f8(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
2947 FindResultCollector c8(&f8);
2948 EXPECT_TRUE(c8.HasFile(dir1));
2949 EXPECT_TRUE(c8.HasFile(dir2));
2950 EXPECT_TRUE(c8.HasFile(file1));
2951 EXPECT_TRUE(c8.HasFile(file2_abs));
2952 EXPECT_TRUE(c8.HasFile(dir2file));
2953 EXPECT_TRUE(c8.HasFile(dir2inner));
2954 EXPECT_TRUE(c8.HasFile(dir2innerfile));
2955 EXPECT_EQ(7, c8.size());
2956 }
2957 #endif
2958
2959 // Make sure the destructor closes the find handle while in the middle of a
2960 // query to allow TearDown to delete the directory.
2961 FileEnumerator f9(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
2962 EXPECT_FALSE(f9.Next().value().empty()); // Should have found something
2963 // (we don't care what).
2964 }
2965
TEST_F(FileUtilTest,AppendToFile)2966 TEST_F(FileUtilTest, AppendToFile) {
2967 FilePath data_dir =
2968 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("FilePathTest"));
2969
2970 // Create a fresh, empty copy of this directory.
2971 if (PathExists(data_dir)) {
2972 ASSERT_TRUE(DeleteFileRecursively(data_dir));
2973 }
2974 ASSERT_TRUE(CreateDirectory(data_dir));
2975
2976 // Create a fresh, empty copy of this directory.
2977 if (PathExists(data_dir)) {
2978 ASSERT_TRUE(DeleteFileRecursively(data_dir));
2979 }
2980 ASSERT_TRUE(CreateDirectory(data_dir));
2981 FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
2982
2983 std::string data("hello");
2984 EXPECT_FALSE(AppendToFile(foobar, data.c_str(), data.size()));
2985 EXPECT_EQ(static_cast<int>(data.length()),
2986 WriteFile(foobar, data.c_str(), data.length()));
2987 EXPECT_TRUE(AppendToFile(foobar, data.c_str(), data.size()));
2988
2989 const std::wstring read_content = ReadTextFile(foobar);
2990 EXPECT_EQ(L"hellohello", read_content);
2991 }
2992
TEST_F(FileUtilTest,ReadFile)2993 TEST_F(FileUtilTest, ReadFile) {
2994 // Create a test file to be read.
2995 const std::string kTestData("The quick brown fox jumps over the lazy dog.");
2996 FilePath file_path =
2997 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileTest"));
2998
2999 ASSERT_EQ(static_cast<int>(kTestData.size()),
3000 WriteFile(file_path, kTestData.data(), kTestData.size()));
3001
3002 // Make buffers with various size.
3003 std::vector<char> small_buffer(kTestData.size() / 2);
3004 std::vector<char> exact_buffer(kTestData.size());
3005 std::vector<char> large_buffer(kTestData.size() * 2);
3006
3007 // Read the file with smaller buffer.
3008 int bytes_read_small = ReadFile(
3009 file_path, &small_buffer[0], static_cast<int>(small_buffer.size()));
3010 EXPECT_EQ(static_cast<int>(small_buffer.size()), bytes_read_small);
3011 EXPECT_EQ(
3012 std::string(kTestData.begin(), kTestData.begin() + small_buffer.size()),
3013 std::string(small_buffer.begin(), small_buffer.end()));
3014
3015 // Read the file with buffer which have exactly same size.
3016 int bytes_read_exact = ReadFile(
3017 file_path, &exact_buffer[0], static_cast<int>(exact_buffer.size()));
3018 EXPECT_EQ(static_cast<int>(kTestData.size()), bytes_read_exact);
3019 EXPECT_EQ(kTestData, std::string(exact_buffer.begin(), exact_buffer.end()));
3020
3021 // Read the file with larger buffer.
3022 int bytes_read_large = ReadFile(
3023 file_path, &large_buffer[0], static_cast<int>(large_buffer.size()));
3024 EXPECT_EQ(static_cast<int>(kTestData.size()), bytes_read_large);
3025 EXPECT_EQ(kTestData, std::string(large_buffer.begin(),
3026 large_buffer.begin() + kTestData.size()));
3027
3028 // Make sure the return value is -1 if the file doesn't exist.
3029 FilePath file_path_not_exist =
3030 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileNotExistTest"));
3031 EXPECT_EQ(-1,
3032 ReadFile(file_path_not_exist,
3033 &exact_buffer[0],
3034 static_cast<int>(exact_buffer.size())));
3035 }
3036
TEST_F(FileUtilTest,ReadFileToString)3037 TEST_F(FileUtilTest, ReadFileToString) {
3038 const char kTestData[] = "0123";
3039 std::string data;
3040
3041 FilePath file_path =
3042 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3043 FilePath file_path_dangerous =
3044 temp_dir_.GetPath()
3045 .Append(FILE_PATH_LITERAL(".."))
3046 .Append(temp_dir_.GetPath().BaseName())
3047 .Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3048
3049 // Create test file.
3050 ASSERT_EQ(static_cast<int>(strlen(kTestData)),
3051 WriteFile(file_path, kTestData, strlen(kTestData)));
3052
3053 EXPECT_TRUE(ReadFileToString(file_path, &data));
3054 EXPECT_EQ(kTestData, data);
3055
3056 data = "temp";
3057 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
3058 EXPECT_EQ(0u, data.length());
3059
3060 data = "temp";
3061 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
3062 EXPECT_EQ("01", data);
3063
3064 data = "temp";
3065 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 3));
3066 EXPECT_EQ("012", data);
3067
3068 data = "temp";
3069 EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, &data, 4));
3070 EXPECT_EQ("0123", data);
3071
3072 data = "temp";
3073 EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, &data, 6));
3074 EXPECT_EQ("0123", data);
3075
3076 EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, nullptr, 6));
3077
3078 EXPECT_TRUE(ReadFileToString(file_path, nullptr));
3079
3080 data = "temp";
3081 EXPECT_FALSE(ReadFileToString(file_path_dangerous, &data));
3082 EXPECT_EQ(0u, data.length());
3083
3084 // Delete test file.
3085 EXPECT_TRUE(DeleteFile(file_path, false));
3086
3087 data = "temp";
3088 EXPECT_FALSE(ReadFileToString(file_path, &data));
3089 EXPECT_EQ(0u, data.length());
3090
3091 data = "temp";
3092 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 6));
3093 EXPECT_EQ(0u, data.length());
3094 }
3095
3096 #if !defined(OS_WIN)
TEST_F(FileUtilTest,ReadFileToStringWithUnknownFileSize)3097 TEST_F(FileUtilTest, ReadFileToStringWithUnknownFileSize) {
3098 FilePath file_path("/dev/zero");
3099 std::string data = "temp";
3100
3101 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
3102 EXPECT_EQ(0u, data.length());
3103
3104 data = "temp";
3105 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
3106 EXPECT_EQ(std::string(2, '\0'), data);
3107
3108 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 6));
3109
3110 // Read more than buffer size.
3111 data = "temp";
3112 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, kLargeFileSize));
3113 EXPECT_EQ(kLargeFileSize, data.length());
3114 EXPECT_EQ(std::string(kLargeFileSize, '\0'), data);
3115
3116 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, kLargeFileSize));
3117 }
3118 #endif // !defined(OS_WIN)
3119
3120 #if !defined(OS_WIN) && !defined(OS_NACL) && !defined(OS_FUCHSIA) && \
3121 !defined(OS_IOS)
3122 #define ChildMain WriteToPipeChildMain
3123 #define ChildMainString "WriteToPipeChildMain"
3124
MULTIPROCESS_TEST_MAIN(ChildMain)3125 MULTIPROCESS_TEST_MAIN(ChildMain) {
3126 const char kTestData[] = "0123";
3127 CommandLine* command_line = CommandLine::ForCurrentProcess();
3128 const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3129
3130 int fd = open(pipe_path.value().c_str(), O_WRONLY);
3131 CHECK_NE(-1, fd);
3132 size_t written = 0;
3133 while (written < strlen(kTestData)) {
3134 ssize_t res = write(fd, kTestData + written, strlen(kTestData) - written);
3135 if (res == -1)
3136 break;
3137 written += res;
3138 }
3139 CHECK_EQ(strlen(kTestData), written);
3140 CHECK_EQ(0, close(fd));
3141 return 0;
3142 }
3143
3144 #define MoreThanBufferSizeChildMain WriteToPipeMoreThanBufferSizeChildMain
3145 #define MoreThanBufferSizeChildMainString \
3146 "WriteToPipeMoreThanBufferSizeChildMain"
3147
MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain)3148 MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
3149 std::string data(kLargeFileSize, 'c');
3150 CommandLine* command_line = CommandLine::ForCurrentProcess();
3151 const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3152
3153 int fd = open(pipe_path.value().c_str(), O_WRONLY);
3154 CHECK_NE(-1, fd);
3155
3156 size_t written = 0;
3157 while (written < data.size()) {
3158 ssize_t res = write(fd, data.c_str() + written, data.size() - written);
3159 if (res == -1) {
3160 // We are unable to write because reading process has already read
3161 // requested number of bytes and closed pipe.
3162 break;
3163 }
3164 written += res;
3165 }
3166 CHECK_EQ(0, close(fd));
3167 return 0;
3168 }
3169
TEST_F(FileUtilTest,ReadFileToStringWithNamedPipe)3170 TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
3171 FilePath pipe_path =
3172 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("test_pipe"));
3173 ASSERT_EQ(0, mkfifo(pipe_path.value().c_str(), 0600));
3174
3175 CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
3176 child_command_line.AppendSwitchPath("pipe-path", pipe_path);
3177
3178 {
3179 Process child_process = SpawnMultiProcessTestChild(
3180 ChildMainString, child_command_line, LaunchOptions());
3181 ASSERT_TRUE(child_process.IsValid());
3182
3183 std::string data = "temp";
3184 EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
3185 EXPECT_EQ("01", data);
3186
3187 int rv = -1;
3188 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3189 child_process, TestTimeouts::action_timeout(), &rv));
3190 ASSERT_EQ(0, rv);
3191 }
3192 {
3193 Process child_process = SpawnMultiProcessTestChild(
3194 ChildMainString, child_command_line, LaunchOptions());
3195 ASSERT_TRUE(child_process.IsValid());
3196
3197 std::string data = "temp";
3198 EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3199 EXPECT_EQ("0123", data);
3200
3201 int rv = -1;
3202 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3203 child_process, TestTimeouts::action_timeout(), &rv));
3204 ASSERT_EQ(0, rv);
3205 }
3206 {
3207 Process child_process = SpawnMultiProcessTestChild(
3208 MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3209 ASSERT_TRUE(child_process.IsValid());
3210
3211 std::string data = "temp";
3212 EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3213 EXPECT_EQ("cccccc", data);
3214
3215 int rv = -1;
3216 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3217 child_process, TestTimeouts::action_timeout(), &rv));
3218 ASSERT_EQ(0, rv);
3219 }
3220 {
3221 Process child_process = SpawnMultiProcessTestChild(
3222 MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3223 ASSERT_TRUE(child_process.IsValid());
3224
3225 std::string data = "temp";
3226 EXPECT_FALSE(
3227 ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
3228 EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
3229
3230 int rv = -1;
3231 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3232 child_process, TestTimeouts::action_timeout(), &rv));
3233 ASSERT_EQ(0, rv);
3234 }
3235 {
3236 Process child_process = SpawnMultiProcessTestChild(
3237 MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3238 ASSERT_TRUE(child_process.IsValid());
3239
3240 std::string data = "temp";
3241 EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
3242 EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3243
3244 int rv = -1;
3245 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3246 child_process, TestTimeouts::action_timeout(), &rv));
3247 ASSERT_EQ(0, rv);
3248 }
3249 {
3250 Process child_process = SpawnMultiProcessTestChild(
3251 MoreThanBufferSizeChildMainString, child_command_line, LaunchOptions());
3252 ASSERT_TRUE(child_process.IsValid());
3253
3254 std::string data = "temp";
3255 EXPECT_TRUE(
3256 ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
3257 EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3258
3259 int rv = -1;
3260 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3261 child_process, TestTimeouts::action_timeout(), &rv));
3262 ASSERT_EQ(0, rv);
3263 }
3264
3265 ASSERT_EQ(0, unlink(pipe_path.value().c_str()));
3266 }
3267 #endif // !defined(OS_WIN) && !defined(OS_NACL) && !defined(OS_FUCHSIA) &&
3268 // !defined(OS_IOS)
3269
3270 #if defined(OS_WIN)
3271 #define ChildMain WriteToPipeChildMain
3272 #define ChildMainString "WriteToPipeChildMain"
3273
MULTIPROCESS_TEST_MAIN(ChildMain)3274 MULTIPROCESS_TEST_MAIN(ChildMain) {
3275 const char kTestData[] = "0123";
3276 CommandLine* command_line = CommandLine::ForCurrentProcess();
3277 const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3278 std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
3279 EXPECT_FALSE(switch_string.empty());
3280 unsigned int switch_uint = 0;
3281 EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
3282 win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
3283
3284 HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
3285 PIPE_WAIT, 1, 0, 0, 0, NULL);
3286 EXPECT_NE(ph, INVALID_HANDLE_VALUE);
3287 EXPECT_TRUE(SetEvent(sync_event.Get()));
3288 EXPECT_TRUE(ConnectNamedPipe(ph, NULL));
3289
3290 DWORD written;
3291 EXPECT_TRUE(::WriteFile(ph, kTestData, strlen(kTestData), &written, NULL));
3292 EXPECT_EQ(strlen(kTestData), written);
3293 CloseHandle(ph);
3294 return 0;
3295 }
3296
3297 #define MoreThanBufferSizeChildMain WriteToPipeMoreThanBufferSizeChildMain
3298 #define MoreThanBufferSizeChildMainString \
3299 "WriteToPipeMoreThanBufferSizeChildMain"
3300
MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain)3301 MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
3302 std::string data(kLargeFileSize, 'c');
3303 CommandLine* command_line = CommandLine::ForCurrentProcess();
3304 const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
3305 std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
3306 EXPECT_FALSE(switch_string.empty());
3307 unsigned int switch_uint = 0;
3308 EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
3309 win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
3310
3311 HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
3312 PIPE_WAIT, 1, data.size(), data.size(), 0, NULL);
3313 EXPECT_NE(ph, INVALID_HANDLE_VALUE);
3314 EXPECT_TRUE(SetEvent(sync_event.Get()));
3315 EXPECT_TRUE(ConnectNamedPipe(ph, NULL));
3316
3317 DWORD written;
3318 EXPECT_TRUE(::WriteFile(ph, data.c_str(), data.size(), &written, NULL));
3319 EXPECT_EQ(data.size(), written);
3320 CloseHandle(ph);
3321 return 0;
3322 }
3323
TEST_F(FileUtilTest,ReadFileToStringWithNamedPipe)3324 TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
3325 FilePath pipe_path(FILE_PATH_LITERAL("\\\\.\\pipe\\test_pipe"));
3326 win::ScopedHandle sync_event(CreateEvent(0, false, false, nullptr));
3327
3328 CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
3329 child_command_line.AppendSwitchPath("pipe-path", pipe_path);
3330 child_command_line.AppendSwitchASCII(
3331 "sync_event", NumberToString(win::HandleToUint32(sync_event.Get())));
3332
3333 LaunchOptions options;
3334 options.handles_to_inherit.push_back(sync_event.Get());
3335
3336 {
3337 Process child_process = SpawnMultiProcessTestChild(
3338 ChildMainString, child_command_line, options);
3339 ASSERT_TRUE(child_process.IsValid());
3340 // Wait for pipe creation in child process.
3341 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
3342
3343 std::string data = "temp";
3344 EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
3345 EXPECT_EQ("01", data);
3346
3347 int rv = -1;
3348 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3349 child_process, TestTimeouts::action_timeout(), &rv));
3350 ASSERT_EQ(0, rv);
3351 }
3352 {
3353 Process child_process = SpawnMultiProcessTestChild(
3354 ChildMainString, child_command_line, options);
3355 ASSERT_TRUE(child_process.IsValid());
3356 // Wait for pipe creation in child process.
3357 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
3358
3359 std::string data = "temp";
3360 EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3361 EXPECT_EQ("0123", data);
3362
3363 int rv = -1;
3364 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3365 child_process, TestTimeouts::action_timeout(), &rv));
3366 ASSERT_EQ(0, rv);
3367 }
3368 {
3369 Process child_process = SpawnMultiProcessTestChild(
3370 MoreThanBufferSizeChildMainString, child_command_line, options);
3371 ASSERT_TRUE(child_process.IsValid());
3372 // Wait for pipe creation in child process.
3373 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
3374
3375 std::string data = "temp";
3376 EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
3377 EXPECT_EQ("cccccc", data);
3378
3379 int rv = -1;
3380 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3381 child_process, TestTimeouts::action_timeout(), &rv));
3382 ASSERT_EQ(0, rv);
3383 }
3384 {
3385 Process child_process = SpawnMultiProcessTestChild(
3386 MoreThanBufferSizeChildMainString, child_command_line, options);
3387 ASSERT_TRUE(child_process.IsValid());
3388 // Wait for pipe creation in child process.
3389 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
3390
3391 std::string data = "temp";
3392 EXPECT_FALSE(
3393 ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
3394 EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
3395
3396 int rv = -1;
3397 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3398 child_process, TestTimeouts::action_timeout(), &rv));
3399 ASSERT_EQ(0, rv);
3400 }
3401 {
3402 Process child_process = SpawnMultiProcessTestChild(
3403 MoreThanBufferSizeChildMainString, child_command_line, options);
3404 ASSERT_TRUE(child_process.IsValid());
3405 // Wait for pipe creation in child process.
3406 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
3407
3408 std::string data = "temp";
3409 EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
3410 EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3411
3412 int rv = -1;
3413 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3414 child_process, TestTimeouts::action_timeout(), &rv));
3415 ASSERT_EQ(0, rv);
3416 }
3417 {
3418 Process child_process = SpawnMultiProcessTestChild(
3419 MoreThanBufferSizeChildMainString, child_command_line, options);
3420 ASSERT_TRUE(child_process.IsValid());
3421 // Wait for pipe creation in child process.
3422 EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
3423
3424 std::string data = "temp";
3425 EXPECT_TRUE(
3426 ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
3427 EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
3428
3429 int rv = -1;
3430 ASSERT_TRUE(WaitForMultiprocessTestChildExit(
3431 child_process, TestTimeouts::action_timeout(), &rv));
3432 ASSERT_EQ(0, rv);
3433 }
3434 }
3435 #endif // defined(OS_WIN)
3436
3437 #if defined(OS_POSIX) && !defined(OS_MACOSX)
TEST_F(FileUtilTest,ReadFileToStringWithProcFileSystem)3438 TEST_F(FileUtilTest, ReadFileToStringWithProcFileSystem) {
3439 FilePath file_path("/proc/cpuinfo");
3440 std::string data = "temp";
3441
3442 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
3443 EXPECT_EQ(0u, data.length());
3444
3445 data = "temp";
3446 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
3447 EXPECT_TRUE(EqualsCaseInsensitiveASCII("pr", data));
3448
3449 data = "temp";
3450 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 4));
3451 EXPECT_TRUE(EqualsCaseInsensitiveASCII("proc", data));
3452
3453 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 4));
3454 }
3455 #endif // defined(OS_POSIX) && !defined(OS_MACOSX)
3456
TEST_F(FileUtilTest,ReadFileToStringWithLargeFile)3457 TEST_F(FileUtilTest, ReadFileToStringWithLargeFile) {
3458 std::string data(kLargeFileSize, 'c');
3459
3460 FilePath file_path =
3461 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
3462
3463 // Create test file.
3464 ASSERT_EQ(static_cast<int>(kLargeFileSize),
3465 WriteFile(file_path, data.c_str(), kLargeFileSize));
3466
3467 std::string actual_data = "temp";
3468 EXPECT_TRUE(ReadFileToString(file_path, &actual_data));
3469 EXPECT_EQ(data, actual_data);
3470
3471 actual_data = "temp";
3472 EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &actual_data, 0));
3473 EXPECT_EQ(0u, actual_data.length());
3474
3475 // Read more than buffer size.
3476 actual_data = "temp";
3477 EXPECT_FALSE(
3478 ReadFileToStringWithMaxSize(file_path, &actual_data, kLargeFileSize - 1));
3479 EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), actual_data);
3480 }
3481
TEST_F(FileUtilTest,TouchFile)3482 TEST_F(FileUtilTest, TouchFile) {
3483 FilePath data_dir =
3484 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("FilePathTest"));
3485
3486 // Create a fresh, empty copy of this directory.
3487 if (PathExists(data_dir)) {
3488 ASSERT_TRUE(DeleteFileRecursively(data_dir));
3489 }
3490 ASSERT_TRUE(CreateDirectory(data_dir));
3491
3492 FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
3493 std::string data("hello");
3494 ASSERT_EQ(static_cast<int>(data.length()),
3495 WriteFile(foobar, data.c_str(), data.length()));
3496
3497 Time access_time;
3498 // This timestamp is divisible by one day (in local timezone),
3499 // to make it work on FAT too.
3500 ASSERT_TRUE(Time::FromString("Wed, 16 Nov 1994, 00:00:00",
3501 &access_time));
3502
3503 Time modification_time;
3504 // Note that this timestamp is divisible by two (seconds) - FAT stores
3505 // modification times with 2s resolution.
3506 ASSERT_TRUE(Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT",
3507 &modification_time));
3508
3509 ASSERT_TRUE(TouchFile(foobar, access_time, modification_time));
3510 File::Info file_info;
3511 ASSERT_TRUE(GetFileInfo(foobar, &file_info));
3512 #if !defined(OS_FUCHSIA)
3513 // Access time is not supported on Fuchsia, see https://crbug.com/735233.
3514 EXPECT_EQ(access_time.ToInternalValue(),
3515 file_info.last_accessed.ToInternalValue());
3516 #endif
3517 EXPECT_EQ(modification_time.ToInternalValue(),
3518 file_info.last_modified.ToInternalValue());
3519 }
3520
TEST_F(FileUtilTest,IsDirectoryEmpty)3521 TEST_F(FileUtilTest, IsDirectoryEmpty) {
3522 FilePath empty_dir =
3523 temp_dir_.GetPath().Append(FILE_PATH_LITERAL("EmptyDir"));
3524
3525 ASSERT_FALSE(PathExists(empty_dir));
3526
3527 ASSERT_TRUE(CreateDirectory(empty_dir));
3528
3529 EXPECT_TRUE(IsDirectoryEmpty(empty_dir));
3530
3531 FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt")));
3532 std::string bar("baz");
3533 ASSERT_EQ(static_cast<int>(bar.length()),
3534 WriteFile(foo, bar.c_str(), bar.length()));
3535
3536 EXPECT_FALSE(IsDirectoryEmpty(empty_dir));
3537 }
3538
3539 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
3540
TEST_F(FileUtilTest,SetNonBlocking)3541 TEST_F(FileUtilTest, SetNonBlocking) {
3542 const int kBogusFd = 99999;
3543 EXPECT_FALSE(SetNonBlocking(kBogusFd));
3544
3545 FilePath path;
3546 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &path));
3547 path = path.Append(FPL("file_util")).Append(FPL("original.txt"));
3548 ScopedFD fd(open(path.value().c_str(), O_RDONLY));
3549 ASSERT_GE(fd.get(), 0);
3550 EXPECT_TRUE(SetNonBlocking(fd.get()));
3551 }
3552
TEST_F(FileUtilTest,SetCloseOnExec)3553 TEST_F(FileUtilTest, SetCloseOnExec) {
3554 const int kBogusFd = 99999;
3555 EXPECT_FALSE(SetCloseOnExec(kBogusFd));
3556
3557 FilePath path;
3558 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &path));
3559 path = path.Append(FPL("file_util")).Append(FPL("original.txt"));
3560 ScopedFD fd(open(path.value().c_str(), O_RDONLY));
3561 ASSERT_GE(fd.get(), 0);
3562 EXPECT_TRUE(SetCloseOnExec(fd.get()));
3563 }
3564
3565 #endif
3566
3567 #if defined(OS_POSIX)
3568
3569 // Testing VerifyPathControlledByAdmin() is hard, because there is no
3570 // way a test can make a file owned by root, or change file paths
3571 // at the root of the file system. VerifyPathControlledByAdmin()
3572 // is implemented as a call to VerifyPathControlledByUser, which gives
3573 // us the ability to test with paths under the test's temp directory,
3574 // using a user id we control.
3575 // Pull tests of VerifyPathControlledByUserTest() into a separate test class
3576 // with a common SetUp() method.
3577 class VerifyPathControlledByUserTest : public FileUtilTest {
3578 protected:
SetUp()3579 void SetUp() override {
3580 FileUtilTest::SetUp();
3581
3582 // Create a basic structure used by each test.
3583 // base_dir_
3584 // |-> sub_dir_
3585 // |-> text_file_
3586
3587 base_dir_ = temp_dir_.GetPath().AppendASCII("base_dir");
3588 ASSERT_TRUE(CreateDirectory(base_dir_));
3589
3590 sub_dir_ = base_dir_.AppendASCII("sub_dir");
3591 ASSERT_TRUE(CreateDirectory(sub_dir_));
3592
3593 text_file_ = sub_dir_.AppendASCII("file.txt");
3594 CreateTextFile(text_file_, L"This text file has some text in it.");
3595
3596 // Get the user and group files are created with from |base_dir_|.
3597 stat_wrapper_t stat_buf;
3598 ASSERT_EQ(0, File::Stat(base_dir_.value().c_str(), &stat_buf));
3599 uid_ = stat_buf.st_uid;
3600 ok_gids_.insert(stat_buf.st_gid);
3601 bad_gids_.insert(stat_buf.st_gid + 1);
3602
3603 ASSERT_EQ(uid_, getuid()); // This process should be the owner.
3604
3605 // To ensure that umask settings do not cause the initial state
3606 // of permissions to be different from what we expect, explicitly
3607 // set permissions on the directories we create.
3608 // Make all files and directories non-world-writable.
3609
3610 // Users and group can read, write, traverse
3611 int enabled_permissions =
3612 FILE_PERMISSION_USER_MASK | FILE_PERMISSION_GROUP_MASK;
3613 // Other users can't read, write, traverse
3614 int disabled_permissions = FILE_PERMISSION_OTHERS_MASK;
3615
3616 ASSERT_NO_FATAL_FAILURE(
3617 ChangePosixFilePermissions(
3618 base_dir_, enabled_permissions, disabled_permissions));
3619 ASSERT_NO_FATAL_FAILURE(
3620 ChangePosixFilePermissions(
3621 sub_dir_, enabled_permissions, disabled_permissions));
3622 }
3623
3624 FilePath base_dir_;
3625 FilePath sub_dir_;
3626 FilePath text_file_;
3627 uid_t uid_;
3628
3629 std::set<gid_t> ok_gids_;
3630 std::set<gid_t> bad_gids_;
3631 };
3632
TEST_F(VerifyPathControlledByUserTest,BadPaths)3633 TEST_F(VerifyPathControlledByUserTest, BadPaths) {
3634 // File does not exist.
3635 FilePath does_not_exist = base_dir_.AppendASCII("does")
3636 .AppendASCII("not")
3637 .AppendASCII("exist");
3638 EXPECT_FALSE(
3639 VerifyPathControlledByUser(base_dir_, does_not_exist, uid_, ok_gids_));
3640
3641 // |base| not a subpath of |path|.
3642 EXPECT_FALSE(VerifyPathControlledByUser(sub_dir_, base_dir_, uid_, ok_gids_));
3643
3644 // An empty base path will fail to be a prefix for any path.
3645 FilePath empty;
3646 EXPECT_FALSE(VerifyPathControlledByUser(empty, base_dir_, uid_, ok_gids_));
3647
3648 // Finding that a bad call fails proves nothing unless a good call succeeds.
3649 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3650 }
3651
TEST_F(VerifyPathControlledByUserTest,Symlinks)3652 TEST_F(VerifyPathControlledByUserTest, Symlinks) {
3653 // Symlinks in the path should cause failure.
3654
3655 // Symlink to the file at the end of the path.
3656 FilePath file_link = base_dir_.AppendASCII("file_link");
3657 ASSERT_TRUE(CreateSymbolicLink(text_file_, file_link))
3658 << "Failed to create symlink.";
3659
3660 EXPECT_FALSE(
3661 VerifyPathControlledByUser(base_dir_, file_link, uid_, ok_gids_));
3662 EXPECT_FALSE(
3663 VerifyPathControlledByUser(file_link, file_link, uid_, ok_gids_));
3664
3665 // Symlink from one directory to another within the path.
3666 FilePath link_to_sub_dir = base_dir_.AppendASCII("link_to_sub_dir");
3667 ASSERT_TRUE(CreateSymbolicLink(sub_dir_, link_to_sub_dir))
3668 << "Failed to create symlink.";
3669
3670 FilePath file_path_with_link = link_to_sub_dir.AppendASCII("file.txt");
3671 ASSERT_TRUE(PathExists(file_path_with_link));
3672
3673 EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, file_path_with_link, uid_,
3674 ok_gids_));
3675
3676 EXPECT_FALSE(VerifyPathControlledByUser(link_to_sub_dir, file_path_with_link,
3677 uid_, ok_gids_));
3678
3679 // Symlinks in parents of base path are allowed.
3680 EXPECT_TRUE(VerifyPathControlledByUser(file_path_with_link,
3681 file_path_with_link, uid_, ok_gids_));
3682 }
3683
TEST_F(VerifyPathControlledByUserTest,OwnershipChecks)3684 TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
3685 // Get a uid that is not the uid of files we create.
3686 uid_t bad_uid = uid_ + 1;
3687
3688 // Make all files and directories non-world-writable.
3689 ASSERT_NO_FATAL_FAILURE(
3690 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
3691 ASSERT_NO_FATAL_FAILURE(
3692 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
3693 ASSERT_NO_FATAL_FAILURE(
3694 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
3695
3696 // We control these paths.
3697 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3698 EXPECT_TRUE(
3699 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3700 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3701
3702 // Another user does not control these paths.
3703 EXPECT_FALSE(
3704 VerifyPathControlledByUser(base_dir_, sub_dir_, bad_uid, ok_gids_));
3705 EXPECT_FALSE(
3706 VerifyPathControlledByUser(base_dir_, text_file_, bad_uid, ok_gids_));
3707 EXPECT_FALSE(
3708 VerifyPathControlledByUser(sub_dir_, text_file_, bad_uid, ok_gids_));
3709
3710 // Another group does not control the paths.
3711 EXPECT_FALSE(
3712 VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
3713 EXPECT_FALSE(
3714 VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
3715 EXPECT_FALSE(
3716 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
3717 }
3718
TEST_F(VerifyPathControlledByUserTest,GroupWriteTest)3719 TEST_F(VerifyPathControlledByUserTest, GroupWriteTest) {
3720 // Make all files and directories writable only by their owner.
3721 ASSERT_NO_FATAL_FAILURE(
3722 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH|S_IWGRP));
3723 ASSERT_NO_FATAL_FAILURE(
3724 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH|S_IWGRP));
3725 ASSERT_NO_FATAL_FAILURE(
3726 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH|S_IWGRP));
3727
3728 // Any group is okay because the path is not group-writable.
3729 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3730 EXPECT_TRUE(
3731 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3732 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3733
3734 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
3735 EXPECT_TRUE(
3736 VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
3737 EXPECT_TRUE(
3738 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
3739
3740 // No group is okay, because we don't check the group
3741 // if no group can write.
3742 std::set<gid_t> no_gids; // Empty set of gids.
3743 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, no_gids));
3744 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, text_file_, uid_, no_gids));
3745 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, no_gids));
3746
3747 // Make all files and directories writable by their group.
3748 ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, S_IWGRP, 0u));
3749 ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, S_IWGRP, 0u));
3750 ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, S_IWGRP, 0u));
3751
3752 // Now |ok_gids_| works, but |bad_gids_| fails.
3753 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3754 EXPECT_TRUE(
3755 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3756 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3757
3758 EXPECT_FALSE(
3759 VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
3760 EXPECT_FALSE(
3761 VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
3762 EXPECT_FALSE(
3763 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
3764
3765 // Because any group in the group set is allowed,
3766 // the union of good and bad gids passes.
3767
3768 std::set<gid_t> multiple_gids;
3769 std::set_union(
3770 ok_gids_.begin(), ok_gids_.end(),
3771 bad_gids_.begin(), bad_gids_.end(),
3772 std::inserter(multiple_gids, multiple_gids.begin()));
3773
3774 EXPECT_TRUE(
3775 VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, multiple_gids));
3776 EXPECT_TRUE(
3777 VerifyPathControlledByUser(base_dir_, text_file_, uid_, multiple_gids));
3778 EXPECT_TRUE(
3779 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, multiple_gids));
3780 }
3781
TEST_F(VerifyPathControlledByUserTest,WriteBitChecks)3782 TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
3783 // Make all files and directories non-world-writable.
3784 ASSERT_NO_FATAL_FAILURE(
3785 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
3786 ASSERT_NO_FATAL_FAILURE(
3787 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
3788 ASSERT_NO_FATAL_FAILURE(
3789 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
3790
3791 // Initialy, we control all parts of the path.
3792 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3793 EXPECT_TRUE(
3794 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3795 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3796
3797 // Make base_dir_ world-writable.
3798 ASSERT_NO_FATAL_FAILURE(
3799 ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
3800 EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3801 EXPECT_FALSE(
3802 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3803 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3804
3805 // Make sub_dir_ world writable.
3806 ASSERT_NO_FATAL_FAILURE(
3807 ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
3808 EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3809 EXPECT_FALSE(
3810 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3811 EXPECT_FALSE(
3812 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3813
3814 // Make text_file_ world writable.
3815 ASSERT_NO_FATAL_FAILURE(
3816 ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
3817 EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3818 EXPECT_FALSE(
3819 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3820 EXPECT_FALSE(
3821 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3822
3823 // Make sub_dir_ non-world writable.
3824 ASSERT_NO_FATAL_FAILURE(
3825 ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
3826 EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3827 EXPECT_FALSE(
3828 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3829 EXPECT_FALSE(
3830 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3831
3832 // Make base_dir_ non-world-writable.
3833 ASSERT_NO_FATAL_FAILURE(
3834 ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
3835 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3836 EXPECT_FALSE(
3837 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3838 EXPECT_FALSE(
3839 VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3840
3841 // Back to the initial state: Nothing is writable, so every path
3842 // should pass.
3843 ASSERT_NO_FATAL_FAILURE(
3844 ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
3845 EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
3846 EXPECT_TRUE(
3847 VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
3848 EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
3849 }
3850
3851 #endif // defined(OS_POSIX)
3852
3853 // Flaky test: crbug/1054637
3854 #if defined(OS_ANDROID)
TEST_F(FileUtilTest,DISABLED_ValidContentUriTest)3855 TEST_F(FileUtilTest, DISABLED_ValidContentUriTest) {
3856 // Get the test image path.
3857 FilePath data_dir;
3858 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
3859 data_dir = data_dir.AppendASCII("file_util");
3860 ASSERT_TRUE(PathExists(data_dir));
3861 FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
3862 int64_t image_size;
3863 GetFileSize(image_file, &image_size);
3864 ASSERT_GT(image_size, 0);
3865
3866 // Insert the image into MediaStore. MediaStore will do some conversions, and
3867 // return the content URI.
3868 FilePath path = InsertImageIntoMediaStore(image_file);
3869 EXPECT_TRUE(path.IsContentUri());
3870 EXPECT_TRUE(PathExists(path));
3871 // The file size may not equal to the input image as MediaStore may convert
3872 // the image.
3873 int64_t content_uri_size;
3874 GetFileSize(path, &content_uri_size);
3875 EXPECT_EQ(image_size, content_uri_size);
3876
3877 // We should be able to read the file.
3878 File file = OpenContentUriForRead(path);
3879 EXPECT_TRUE(file.IsValid());
3880 auto buffer = std::make_unique<char[]>(image_size);
3881 EXPECT_TRUE(file.ReadAtCurrentPos(buffer.get(), image_size));
3882 }
3883
TEST_F(FileUtilTest,NonExistentContentUriTest)3884 TEST_F(FileUtilTest, NonExistentContentUriTest) {
3885 FilePath path("content://foo.bar");
3886 EXPECT_TRUE(path.IsContentUri());
3887 EXPECT_FALSE(PathExists(path));
3888 // Size should be smaller than 0.
3889 int64_t size;
3890 EXPECT_FALSE(GetFileSize(path, &size));
3891
3892 // We should not be able to read the file.
3893 File file = OpenContentUriForRead(path);
3894 EXPECT_FALSE(file.IsValid());
3895 }
3896 #endif
3897
3898 #if !defined(OS_NACL_NONSFI)
TEST_F(FileUtilTest,GetUniquePathNumberNoFile)3899 TEST_F(FileUtilTest, GetUniquePathNumberNoFile) {
3900 // This file does not exist.
3901 const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
3902
3903 // The path is unique as-is.
3904 EXPECT_EQ(GetUniquePathNumber(some_file), 0);
3905 }
3906
TEST_F(FileUtilTest,GetUniquePathNumberFileExists)3907 TEST_F(FileUtilTest, GetUniquePathNumberFileExists) {
3908 // Create a file with the desired path.
3909 const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
3910 ASSERT_TRUE(File(some_file, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
3911
3912 // The file exists, so the number 1 is needed to make it unique.
3913 EXPECT_EQ(GetUniquePathNumber(some_file), 1);
3914 }
3915
TEST_F(FileUtilTest,GetUniquePathNumberFilesExist)3916 TEST_F(FileUtilTest, GetUniquePathNumberFilesExist) {
3917 // Create a file with the desired path and with it suffixed with " (1)"
3918 const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
3919 ASSERT_TRUE(File(some_file, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
3920 const FilePath some_file_one =
3921 temp_dir_.GetPath().Append(FPL("SomeFile (1).txt"));
3922 ASSERT_TRUE(
3923 File(some_file_one, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
3924
3925 // This time the number 2 is needed to make it unique.
3926 EXPECT_EQ(GetUniquePathNumber(some_file), 2);
3927 }
3928
TEST_F(FileUtilTest,GetUniquePathNumberTooManyFiles)3929 TEST_F(FileUtilTest, GetUniquePathNumberTooManyFiles) {
3930 // Create a file with the desired path.
3931 const FilePath some_file = temp_dir_.GetPath().Append(FPL("SomeFile.txt"));
3932 ASSERT_TRUE(File(some_file, File::FLAG_CREATE | File::FLAG_WRITE).IsValid());
3933
3934 // Now create 100 collisions.
3935 for (int i = 1; i <= kMaxUniqueFiles; ++i) {
3936 ASSERT_EQ(GetUniquePathNumber(some_file), i);
3937 ASSERT_TRUE(File(temp_dir_.GetPath().AppendASCII(
3938 StringPrintf("SomeFile (%d).txt", i)),
3939 File::FLAG_CREATE | File::FLAG_WRITE)
3940 .IsValid());
3941 }
3942
3943 // Verify that the limit has been reached.
3944 EXPECT_EQ(GetUniquePathNumber(some_file), -1);
3945 }
3946
TEST_F(FileUtilTest,PreReadFile_ExistingFile_NoSize)3947 TEST_F(FileUtilTest, PreReadFile_ExistingFile_NoSize) {
3948 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3949 CreateTextFile(text_file, bogus_content);
3950
3951 EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false));
3952 }
3953
TEST_F(FileUtilTest,PreReadFile_ExistingFile_ExactSize)3954 TEST_F(FileUtilTest, PreReadFile_ExistingFile_ExactSize) {
3955 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3956 CreateTextFile(text_file, bogus_content);
3957
3958 EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
3959 base::size(bogus_content)));
3960 }
3961
TEST_F(FileUtilTest,PreReadFile_ExistingFile_OverSized)3962 TEST_F(FileUtilTest, PreReadFile_ExistingFile_OverSized) {
3963 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3964 CreateTextFile(text_file, bogus_content);
3965
3966 EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
3967 base::size(bogus_content) * 2));
3968 }
3969
TEST_F(FileUtilTest,PreReadFile_ExistingFile_UnderSized)3970 TEST_F(FileUtilTest, PreReadFile_ExistingFile_UnderSized) {
3971 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3972 CreateTextFile(text_file, bogus_content);
3973
3974 EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false,
3975 base::size(bogus_content) / 2));
3976 }
3977
TEST_F(FileUtilTest,PreReadFile_ExistingFile_ZeroSize)3978 TEST_F(FileUtilTest, PreReadFile_ExistingFile_ZeroSize) {
3979 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3980 CreateTextFile(text_file, bogus_content);
3981
3982 EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false, /*max_bytes=*/0));
3983 }
3984
TEST_F(FileUtilTest,PreReadFile_ExistingEmptyFile_NoSize)3985 TEST_F(FileUtilTest, PreReadFile_ExistingEmptyFile_NoSize) {
3986 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3987 CreateTextFile(text_file, L"");
3988 // The test just asserts that this doesn't crash. The Windows implementation
3989 // fails in this case, due to the base::MemoryMappedFile implementation and
3990 // the limitations of ::MapViewOfFile().
3991 PreReadFile(text_file, /*is_executable=*/false);
3992 }
3993
TEST_F(FileUtilTest,PreReadFile_ExistingEmptyFile_ZeroSize)3994 TEST_F(FileUtilTest, PreReadFile_ExistingEmptyFile_ZeroSize) {
3995 FilePath text_file = temp_dir_.GetPath().Append(FPL("text_file"));
3996 CreateTextFile(text_file, L"");
3997 EXPECT_TRUE(PreReadFile(text_file, /*is_executable=*/false, /*max_bytes=*/0));
3998 }
3999
TEST_F(FileUtilTest,PreReadFile_InexistentFile)4000 TEST_F(FileUtilTest, PreReadFile_InexistentFile) {
4001 FilePath inexistent_file = temp_dir_.GetPath().Append(FPL("inexistent_file"));
4002 EXPECT_FALSE(PreReadFile(inexistent_file, /*is_executable=*/false));
4003 }
4004
4005 #endif // !defined(OS_NACL_NONSFI)
4006
4007 // Test that temp files obtained racily are all unique (no interference between
4008 // threads). Mimics file operations in DoLaunchChildTestProcess() to rule out
4009 // thread-safety issues @ https://crbug.com/826408#c17.
4010 #if defined(OS_FUCHSIA)
4011 // TODO(crbug.com/844416): Too slow to run on infra due to QEMU overloads.
4012 #define MAYBE_MultiThreadedTempFiles DISABLED_MultiThreadedTempFiles
4013 #else
4014 #define MAYBE_MultiThreadedTempFiles MultiThreadedTempFiles
4015 #endif
TEST(FileUtilMultiThreadedTest,MAYBE_MultiThreadedTempFiles)4016 TEST(FileUtilMultiThreadedTest, MAYBE_MultiThreadedTempFiles) {
4017 constexpr int kNumThreads = 64;
4018 constexpr int kNumWritesPerThread = 32;
4019
4020 std::unique_ptr<Thread> threads[kNumThreads];
4021 for (auto& thread : threads) {
4022 thread = std::make_unique<Thread>("test worker");
4023 thread->Start();
4024 }
4025
4026 // Wait until all threads are started for max parallelism.
4027 for (auto& thread : threads)
4028 thread->WaitUntilThreadStarted();
4029
4030 const RepeatingClosure open_write_close_read = BindRepeating([]() {
4031 FilePath output_filename;
4032 ScopedFILE output_file(CreateAndOpenTemporaryFile(&output_filename));
4033 EXPECT_TRUE(output_file);
4034
4035 const std::string content = GenerateGUID();
4036 #if defined(OS_WIN)
4037 HANDLE handle =
4038 reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(output_file.get())));
4039 DWORD bytes_written = 0;
4040 ::WriteFile(handle, content.c_str(), content.length(), &bytes_written,
4041 NULL);
4042 #else
4043 size_t bytes_written =
4044 ::write(::fileno(output_file.get()), content.c_str(), content.length());
4045 #endif
4046 EXPECT_EQ(content.length(), bytes_written);
4047 ::fflush(output_file.get());
4048 output_file.reset();
4049
4050 std::string output_file_contents;
4051 EXPECT_TRUE(ReadFileToString(output_filename, &output_file_contents))
4052 << output_filename;
4053
4054 EXPECT_EQ(content, output_file_contents);
4055
4056 DeleteFile(output_filename, false);
4057 });
4058
4059 // Post tasks to each thread in a round-robin fashion to ensure as much
4060 // parallelism as possible.
4061 for (int i = 0; i < kNumWritesPerThread; ++i) {
4062 for (auto& thread : threads) {
4063 thread->task_runner()->PostTask(FROM_HERE, open_write_close_read);
4064 }
4065 }
4066
4067 for (auto& thread : threads)
4068 thread->Stop();
4069 }
4070
4071 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
4072
TEST(ScopedFD,ScopedFDDoesClose)4073 TEST(ScopedFD, ScopedFDDoesClose) {
4074 int fds[2];
4075 char c = 0;
4076 ASSERT_EQ(0, pipe(fds));
4077 const int write_end = fds[1];
4078 ScopedFD read_end_closer(fds[0]);
4079 {
4080 ScopedFD write_end_closer(fds[1]);
4081 }
4082 // This is the only thread. This file descriptor should no longer be valid.
4083 int ret = close(write_end);
4084 EXPECT_EQ(-1, ret);
4085 EXPECT_EQ(EBADF, errno);
4086 // Make sure read(2) won't block.
4087 ASSERT_EQ(0, fcntl(fds[0], F_SETFL, O_NONBLOCK));
4088 // Reading the pipe should EOF.
4089 EXPECT_EQ(0, read(fds[0], &c, 1));
4090 }
4091
4092 #if defined(GTEST_HAS_DEATH_TEST)
CloseWithScopedFD(int fd)4093 void CloseWithScopedFD(int fd) {
4094 ScopedFD fd_closer(fd);
4095 }
4096 #endif
4097
TEST(ScopedFD,ScopedFDCrashesOnCloseFailure)4098 TEST(ScopedFD, ScopedFDCrashesOnCloseFailure) {
4099 int fds[2];
4100 ASSERT_EQ(0, pipe(fds));
4101 ScopedFD read_end_closer(fds[0]);
4102 EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
4103 #if defined(GTEST_HAS_DEATH_TEST)
4104 // This is the only thread. This file descriptor should no longer be valid.
4105 // Trying to close it should crash. This is important for security.
4106 EXPECT_DEATH(CloseWithScopedFD(fds[1]), "");
4107 #endif
4108 }
4109
4110 #endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
4111
4112 } // namespace
4113
4114 } // namespace base
4115