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.h"
6 
7 #include <stdint.h>
8 
9 #include <utility>
10 
11 #include "base/files/file_util.h"
12 #include "base/files/memory_mapped_file.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/time/time.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 using base::File;
19 using base::FilePath;
20 
TEST(FileTest,Create)21 TEST(FileTest, Create) {
22   base::ScopedTempDir temp_dir;
23   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
24   FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
25 
26   {
27     // Don't create a File at all.
28     File file;
29     EXPECT_FALSE(file.IsValid());
30     EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
31 
32     File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
33     EXPECT_FALSE(file2.IsValid());
34     EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
35   }
36 
37   {
38     // Open a file that doesn't exist.
39     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
40     EXPECT_FALSE(file.IsValid());
41     EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
42     EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, base::File::GetLastFileError());
43   }
44 
45   {
46     // Open or create a file.
47     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
48     EXPECT_TRUE(file.IsValid());
49     EXPECT_TRUE(file.created());
50     EXPECT_EQ(base::File::FILE_OK, file.error_details());
51   }
52 
53   {
54     // Open an existing file.
55     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
56     EXPECT_TRUE(file.IsValid());
57     EXPECT_FALSE(file.created());
58     EXPECT_EQ(base::File::FILE_OK, file.error_details());
59 
60     // This time verify closing the file.
61     file.Close();
62     EXPECT_FALSE(file.IsValid());
63   }
64 
65   {
66     // Open an existing file through Initialize
67     File file;
68     file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
69     EXPECT_TRUE(file.IsValid());
70     EXPECT_FALSE(file.created());
71     EXPECT_EQ(base::File::FILE_OK, file.error_details());
72 
73     // This time verify closing the file.
74     file.Close();
75     EXPECT_FALSE(file.IsValid());
76   }
77 
78   {
79     // Create a file that exists.
80     File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
81     EXPECT_FALSE(file.IsValid());
82     EXPECT_FALSE(file.created());
83     EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
84     EXPECT_EQ(base::File::FILE_ERROR_EXISTS, base::File::GetLastFileError());
85   }
86 
87   {
88     // Create or overwrite a file.
89     File file(file_path,
90               base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
91     EXPECT_TRUE(file.IsValid());
92     EXPECT_TRUE(file.created());
93     EXPECT_EQ(base::File::FILE_OK, file.error_details());
94   }
95 
96   {
97     // Create a delete-on-close file.
98     file_path = temp_dir.GetPath().AppendASCII("create_file_2");
99     File file(file_path,
100               base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
101                   base::File::FLAG_DELETE_ON_CLOSE);
102     EXPECT_TRUE(file.IsValid());
103     EXPECT_TRUE(file.created());
104     EXPECT_EQ(base::File::FILE_OK, file.error_details());
105   }
106 
107   EXPECT_FALSE(base::PathExists(file_path));
108 }
109 
TEST(FileTest,SelfSwap)110 TEST(FileTest, SelfSwap) {
111   base::ScopedTempDir temp_dir;
112   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
113   FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
114   File file(file_path,
115             base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_DELETE_ON_CLOSE);
116   std::swap(file, file);
117   EXPECT_TRUE(file.IsValid());
118 }
119 
TEST(FileTest,Async)120 TEST(FileTest, Async) {
121   base::ScopedTempDir temp_dir;
122   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
123   FilePath file_path = temp_dir.GetPath().AppendASCII("create_file");
124 
125   {
126     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC);
127     EXPECT_TRUE(file.IsValid());
128     EXPECT_TRUE(file.async());
129   }
130 
131   {
132     File file(file_path, base::File::FLAG_OPEN_ALWAYS);
133     EXPECT_TRUE(file.IsValid());
134     EXPECT_FALSE(file.async());
135   }
136 }
137 
TEST(FileTest,DeleteOpenFile)138 TEST(FileTest, DeleteOpenFile) {
139   base::ScopedTempDir temp_dir;
140   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
141   FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
142 
143   // Create a file.
144   File file(file_path,
145             base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
146                 base::File::FLAG_SHARE_DELETE);
147   EXPECT_TRUE(file.IsValid());
148   EXPECT_TRUE(file.created());
149   EXPECT_EQ(base::File::FILE_OK, file.error_details());
150 
151   // Open an existing file and mark it as delete on close.
152   File same_file(file_path,
153                  base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
154                      base::File::FLAG_READ);
155   EXPECT_TRUE(file.IsValid());
156   EXPECT_FALSE(same_file.created());
157   EXPECT_EQ(base::File::FILE_OK, same_file.error_details());
158 
159   // Close both handles and check that the file is gone.
160   file.Close();
161   same_file.Close();
162   EXPECT_FALSE(base::PathExists(file_path));
163 }
164 
TEST(FileTest,ReadWrite)165 TEST(FileTest, ReadWrite) {
166   base::ScopedTempDir temp_dir;
167   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
168   FilePath file_path = temp_dir.GetPath().AppendASCII("read_write_file");
169   File file(file_path,
170             base::File::FLAG_CREATE | base::File::FLAG_READ |
171                 base::File::FLAG_WRITE);
172   ASSERT_TRUE(file.IsValid());
173 
174   char data_to_write[] = "test";
175   const int kTestDataSize = 4;
176 
177   // Write 0 bytes to the file.
178   int bytes_written = file.Write(0, data_to_write, 0);
179   EXPECT_EQ(0, bytes_written);
180 
181   // Write 0 bytes, with buf=nullptr.
182   bytes_written = file.Write(0, nullptr, 0);
183   EXPECT_EQ(0, bytes_written);
184 
185   // Write "test" to the file.
186   bytes_written = file.Write(0, data_to_write, kTestDataSize);
187   EXPECT_EQ(kTestDataSize, bytes_written);
188 
189   // Read from EOF.
190   char data_read_1[32];
191   int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
192   EXPECT_EQ(0, bytes_read);
193 
194   // Read from somewhere in the middle of the file.
195   const int kPartialReadOffset = 1;
196   bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
197   EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
198   for (int i = 0; i < bytes_read; i++)
199     EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
200 
201   // Read 0 bytes.
202   bytes_read = file.Read(0, data_read_1, 0);
203   EXPECT_EQ(0, bytes_read);
204 
205   // Read the entire file.
206   bytes_read = file.Read(0, data_read_1, kTestDataSize);
207   EXPECT_EQ(kTestDataSize, bytes_read);
208   for (int i = 0; i < bytes_read; i++)
209     EXPECT_EQ(data_to_write[i], data_read_1[i]);
210 
211   // Read again, but using the trivial native wrapper.
212   bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
213   EXPECT_LE(bytes_read, kTestDataSize);
214   for (int i = 0; i < bytes_read; i++)
215     EXPECT_EQ(data_to_write[i], data_read_1[i]);
216 
217   // Write past the end of the file.
218   const int kOffsetBeyondEndOfFile = 10;
219   const int kPartialWriteLength = 2;
220   bytes_written = file.Write(kOffsetBeyondEndOfFile,
221                              data_to_write, kPartialWriteLength);
222   EXPECT_EQ(kPartialWriteLength, bytes_written);
223 
224   // Make sure the file was extended.
225   int64_t file_size = 0;
226   EXPECT_TRUE(GetFileSize(file_path, &file_size));
227   EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
228 
229   // Make sure the file was zero-padded.
230   char data_read_2[32];
231   bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
232   EXPECT_EQ(file_size, bytes_read);
233   for (int i = 0; i < kTestDataSize; i++)
234     EXPECT_EQ(data_to_write[i], data_read_2[i]);
235   for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
236     EXPECT_EQ(0, data_read_2[i]);
237   for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
238     EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
239 }
240 
TEST(FileTest,GetLastFileError)241 TEST(FileTest, GetLastFileError) {
242 #if defined(OS_WIN)
243   ::SetLastError(ERROR_ACCESS_DENIED);
244 #else
245   errno = EACCES;
246 #endif
247   EXPECT_EQ(File::FILE_ERROR_ACCESS_DENIED, File::GetLastFileError());
248 
249   base::ScopedTempDir temp_dir;
250   EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
251 
252   FilePath nonexistent_path(temp_dir.GetPath().AppendASCII("nonexistent"));
253   File file(nonexistent_path, File::FLAG_OPEN | File::FLAG_READ);
254   File::Error last_error = File::GetLastFileError();
255   EXPECT_FALSE(file.IsValid());
256   EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, file.error_details());
257   EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, last_error);
258 }
259 
TEST(FileTest,Append)260 TEST(FileTest, Append) {
261   base::ScopedTempDir temp_dir;
262   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
263   FilePath file_path = temp_dir.GetPath().AppendASCII("append_file");
264   File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
265   ASSERT_TRUE(file.IsValid());
266 
267   char data_to_write[] = "test";
268   const int kTestDataSize = 4;
269 
270   // Write 0 bytes to the file.
271   int bytes_written = file.Write(0, data_to_write, 0);
272   EXPECT_EQ(0, bytes_written);
273 
274   // Write 0 bytes, with buf=nullptr.
275   bytes_written = file.Write(0, nullptr, 0);
276   EXPECT_EQ(0, bytes_written);
277 
278   // Write "test" to the file.
279   bytes_written = file.Write(0, data_to_write, kTestDataSize);
280   EXPECT_EQ(kTestDataSize, bytes_written);
281 
282   file.Close();
283   File file2(file_path,
284              base::File::FLAG_OPEN | base::File::FLAG_READ |
285                  base::File::FLAG_APPEND);
286   ASSERT_TRUE(file2.IsValid());
287 
288   // Test passing the file around.
289   file = std::move(file2);
290   EXPECT_FALSE(file2.IsValid());
291   ASSERT_TRUE(file.IsValid());
292 
293   char append_data_to_write[] = "78";
294   const int kAppendDataSize = 2;
295 
296   // Append "78" to the file.
297   bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
298   EXPECT_EQ(kAppendDataSize, bytes_written);
299 
300   // Read the entire file.
301   char data_read_1[32];
302   int bytes_read = file.Read(0, data_read_1,
303                              kTestDataSize + kAppendDataSize);
304   EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
305   for (int i = 0; i < kTestDataSize; i++)
306     EXPECT_EQ(data_to_write[i], data_read_1[i]);
307   for (int i = 0; i < kAppendDataSize; i++)
308     EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
309 }
310 
311 
TEST(FileTest,Length)312 TEST(FileTest, Length) {
313   base::ScopedTempDir temp_dir;
314   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
315   FilePath file_path = temp_dir.GetPath().AppendASCII("truncate_file");
316   File file(file_path,
317             base::File::FLAG_CREATE | base::File::FLAG_READ |
318                 base::File::FLAG_WRITE);
319   ASSERT_TRUE(file.IsValid());
320   EXPECT_EQ(0, file.GetLength());
321 
322   // Write "test" to the file.
323   char data_to_write[] = "test";
324   int kTestDataSize = 4;
325   int bytes_written = file.Write(0, data_to_write, kTestDataSize);
326   EXPECT_EQ(kTestDataSize, bytes_written);
327 
328   // Extend the file.
329   const int kExtendedFileLength = 10;
330   int64_t file_size = 0;
331   EXPECT_TRUE(file.SetLength(kExtendedFileLength));
332   EXPECT_EQ(kExtendedFileLength, file.GetLength());
333   EXPECT_TRUE(GetFileSize(file_path, &file_size));
334   EXPECT_EQ(kExtendedFileLength, file_size);
335 
336   // Make sure the file was zero-padded.
337   char data_read[32];
338   int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
339   EXPECT_EQ(file_size, bytes_read);
340   for (int i = 0; i < kTestDataSize; i++)
341     EXPECT_EQ(data_to_write[i], data_read[i]);
342   for (int i = kTestDataSize; i < file_size; i++)
343     EXPECT_EQ(0, data_read[i]);
344 
345   // Truncate the file.
346   const int kTruncatedFileLength = 2;
347   EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
348   EXPECT_EQ(kTruncatedFileLength, file.GetLength());
349   EXPECT_TRUE(GetFileSize(file_path, &file_size));
350   EXPECT_EQ(kTruncatedFileLength, file_size);
351 
352   // Make sure the file was truncated.
353   bytes_read = file.Read(0, data_read, kTestDataSize);
354   EXPECT_EQ(file_size, bytes_read);
355   for (int i = 0; i < file_size; i++)
356     EXPECT_EQ(data_to_write[i], data_read[i]);
357 
358   // Close the file and reopen with base::File::FLAG_CREATE_ALWAYS, and make
359   // sure the file is empty (old file was overridden).
360   file.Close();
361   file.Initialize(file_path,
362                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
363   EXPECT_EQ(0, file.GetLength());
364 }
365 
366 // Flakily fails: http://crbug.com/86494
367 #if defined(OS_ANDROID)
TEST(FileTest,TouchGetInfo)368 TEST(FileTest, TouchGetInfo) {
369 #else
370 TEST(FileTest, DISABLED_TouchGetInfo) {
371 #endif
372   base::ScopedTempDir temp_dir;
373   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
374   File file(temp_dir.GetPath().AppendASCII("touch_get_info_file"),
375             base::File::FLAG_CREATE | base::File::FLAG_WRITE |
376                 base::File::FLAG_WRITE_ATTRIBUTES);
377   ASSERT_TRUE(file.IsValid());
378 
379   // Get info for a newly created file.
380   base::File::Info info;
381   EXPECT_TRUE(file.GetInfo(&info));
382 
383   // Add 2 seconds to account for possible rounding errors on
384   // filesystems that use a 1s or 2s timestamp granularity.
385   base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
386   EXPECT_EQ(0, info.size);
387   EXPECT_FALSE(info.is_directory);
388   EXPECT_FALSE(info.is_symbolic_link);
389   EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
390   EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
391   EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
392   base::Time creation_time = info.creation_time;
393 
394   // Write "test" to the file.
395   char data[] = "test";
396   const int kTestDataSize = 4;
397   int bytes_written = file.Write(0, data, kTestDataSize);
398   EXPECT_EQ(kTestDataSize, bytes_written);
399 
400   // Change the last_accessed and last_modified dates.
401   // It's best to add values that are multiples of 2 (in seconds)
402   // to the current last_accessed and last_modified times, because
403   // FATxx uses a 2s timestamp granularity.
404   base::Time new_last_accessed =
405       info.last_accessed + base::TimeDelta::FromSeconds(234);
406   base::Time new_last_modified =
407       info.last_modified + base::TimeDelta::FromMinutes(567);
408 
409   EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
410 
411   // Make sure the file info was updated accordingly.
412   EXPECT_TRUE(file.GetInfo(&info));
413   EXPECT_EQ(info.size, kTestDataSize);
414   EXPECT_FALSE(info.is_directory);
415   EXPECT_FALSE(info.is_symbolic_link);
416 
417   // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
418 #if defined(OS_POSIX)
419   EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
420             new_last_accessed.ToTimeVal().tv_sec);
421   EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
422             new_last_modified.ToTimeVal().tv_sec);
423 #else
424   EXPECT_EQ(info.last_accessed.ToInternalValue(),
425             new_last_accessed.ToInternalValue());
426   EXPECT_EQ(info.last_modified.ToInternalValue(),
427             new_last_modified.ToInternalValue());
428 #endif
429 
430   EXPECT_EQ(info.creation_time.ToInternalValue(),
431             creation_time.ToInternalValue());
432 }
433 
434 TEST(FileTest, ReadAtCurrentPosition) {
435   base::ScopedTempDir temp_dir;
436   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
437   FilePath file_path =
438       temp_dir.GetPath().AppendASCII("read_at_current_position");
439   File file(file_path,
440             base::File::FLAG_CREATE | base::File::FLAG_READ |
441                 base::File::FLAG_WRITE);
442   EXPECT_TRUE(file.IsValid());
443 
444   const char kData[] = "test";
445   const int kDataSize = sizeof(kData) - 1;
446   EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
447 
448   EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
449 
450   char buffer[kDataSize];
451   int first_chunk_size = kDataSize / 2;
452   EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
453   EXPECT_EQ(kDataSize - first_chunk_size,
454             file.ReadAtCurrentPos(buffer + first_chunk_size,
455                                   kDataSize - first_chunk_size));
456   EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
457 }
458 
459 TEST(FileTest, WriteAtCurrentPosition) {
460   base::ScopedTempDir temp_dir;
461   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
462   FilePath file_path =
463       temp_dir.GetPath().AppendASCII("write_at_current_position");
464   File file(file_path,
465             base::File::FLAG_CREATE | base::File::FLAG_READ |
466                 base::File::FLAG_WRITE);
467   EXPECT_TRUE(file.IsValid());
468 
469   const char kData[] = "test";
470   const int kDataSize = sizeof(kData) - 1;
471 
472   int first_chunk_size = kDataSize / 2;
473   EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
474   EXPECT_EQ(kDataSize - first_chunk_size,
475             file.WriteAtCurrentPos(kData + first_chunk_size,
476                                    kDataSize - first_chunk_size));
477 
478   char buffer[kDataSize];
479   EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
480   EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
481 }
482 
483 TEST(FileTest, Seek) {
484   base::ScopedTempDir temp_dir;
485   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
486   FilePath file_path = temp_dir.GetPath().AppendASCII("seek_file");
487   File file(file_path,
488             base::File::FLAG_CREATE | base::File::FLAG_READ |
489                 base::File::FLAG_WRITE);
490   ASSERT_TRUE(file.IsValid());
491 
492   const int64_t kOffset = 10;
493   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset));
494   EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset));
495   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset));
496   EXPECT_TRUE(file.SetLength(kOffset * 2));
497   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset));
498 }
499 
500 TEST(FileTest, Duplicate) {
501   base::ScopedTempDir temp_dir;
502   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
503   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
504   File file(file_path,(base::File::FLAG_CREATE |
505                        base::File::FLAG_READ |
506                        base::File::FLAG_WRITE));
507   ASSERT_TRUE(file.IsValid());
508 
509   File file2(file.Duplicate());
510   ASSERT_TRUE(file2.IsValid());
511 
512   // Write through one handle, close it, read through the other.
513   static const char kData[] = "now is a good time.";
514   static const int kDataLen = sizeof(kData) - 1;
515 
516   ASSERT_EQ(0, file.Seek(base::File::FROM_CURRENT, 0));
517   ASSERT_EQ(0, file2.Seek(base::File::FROM_CURRENT, 0));
518   ASSERT_EQ(kDataLen, file.WriteAtCurrentPos(kData, kDataLen));
519   ASSERT_EQ(kDataLen, file.Seek(base::File::FROM_CURRENT, 0));
520   ASSERT_EQ(kDataLen, file2.Seek(base::File::FROM_CURRENT, 0));
521   file.Close();
522   char buf[kDataLen];
523   ASSERT_EQ(kDataLen, file2.Read(0, &buf[0], kDataLen));
524   ASSERT_EQ(std::string(kData, kDataLen), std::string(&buf[0], kDataLen));
525 }
526 
527 TEST(FileTest, DuplicateDeleteOnClose) {
528   base::ScopedTempDir temp_dir;
529   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
530   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
531   File file(file_path,(base::File::FLAG_CREATE |
532                        base::File::FLAG_READ |
533                        base::File::FLAG_WRITE |
534                        base::File::FLAG_DELETE_ON_CLOSE));
535   ASSERT_TRUE(file.IsValid());
536   File file2(file.Duplicate());
537   ASSERT_TRUE(file2.IsValid());
538   file.Close();
539   file2.Close();
540   ASSERT_FALSE(base::PathExists(file_path));
541 }
542 
543 #if defined(OS_WIN)
544 // Flakily times out on Windows, see http://crbug.com/846276.
545 #define MAYBE_WriteDataToLargeOffset DISABLED_WriteDataToLargeOffset
546 #else
547 #define MAYBE_WriteDataToLargeOffset WriteDataToLargeOffset
548 #endif
549 TEST(FileTest, MAYBE_WriteDataToLargeOffset) {
550   base::ScopedTempDir temp_dir;
551   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
552   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
553   File file(file_path,
554             (base::File::FLAG_CREATE | base::File::FLAG_READ |
555              base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE));
556   ASSERT_TRUE(file.IsValid());
557 
558   const char kData[] = "this file is sparse.";
559   const int kDataLen = sizeof(kData) - 1;
560   const int64_t kLargeFileOffset = (1LL << 31);
561 
562   // If the file fails to write, it is probably we are running out of disk space
563   // and the file system doesn't support sparse file.
564   if (file.Write(kLargeFileOffset - kDataLen - 1, kData, kDataLen) < 0)
565     return;
566 
567   ASSERT_EQ(kDataLen, file.Write(kLargeFileOffset + 1, kData, kDataLen));
568 }
569 
570 #if defined(OS_WIN)
571 TEST(FileTest, GetInfoForDirectory) {
572   base::ScopedTempDir temp_dir;
573   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
574   FilePath empty_dir =
575       temp_dir.GetPath().Append(FILE_PATH_LITERAL("gpfi_test"));
576   ASSERT_TRUE(CreateDirectory(empty_dir));
577 
578   base::File dir(
579       ::CreateFile(empty_dir.value().c_str(),
580                    GENERIC_READ | GENERIC_WRITE,
581                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
582                    NULL,
583                    OPEN_EXISTING,
584                    FILE_FLAG_BACKUP_SEMANTICS,  // Needed to open a directory.
585                    NULL));
586   ASSERT_TRUE(dir.IsValid());
587 
588   base::File::Info info;
589   EXPECT_TRUE(dir.GetInfo(&info));
590   EXPECT_TRUE(info.is_directory);
591   EXPECT_FALSE(info.is_symbolic_link);
592   EXPECT_EQ(0, info.size);
593 }
594 
595 TEST(FileTest, DeleteNoop) {
596   base::ScopedTempDir temp_dir;
597   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
598   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
599 
600   // Creating and closing a file with DELETE perms should do nothing special.
601   File file(file_path,
602             (base::File::FLAG_CREATE | base::File::FLAG_READ |
603              base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
604   ASSERT_TRUE(file.IsValid());
605   file.Close();
606   ASSERT_TRUE(base::PathExists(file_path));
607 }
608 
609 TEST(FileTest, Delete) {
610   base::ScopedTempDir temp_dir;
611   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
612   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
613 
614   // Creating a file with DELETE and then marking for delete on close should
615   // delete it.
616   File file(file_path,
617             (base::File::FLAG_CREATE | base::File::FLAG_READ |
618              base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
619   ASSERT_TRUE(file.IsValid());
620   ASSERT_TRUE(file.DeleteOnClose(true));
621   file.Close();
622   ASSERT_FALSE(base::PathExists(file_path));
623 }
624 
625 TEST(FileTest, DeleteThenRevoke) {
626   base::ScopedTempDir temp_dir;
627   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
628   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
629 
630   // Creating a file with DELETE, marking it for delete, then clearing delete on
631   // close should not delete it.
632   File file(file_path,
633             (base::File::FLAG_CREATE | base::File::FLAG_READ |
634              base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
635   ASSERT_TRUE(file.IsValid());
636   ASSERT_TRUE(file.DeleteOnClose(true));
637   ASSERT_TRUE(file.DeleteOnClose(false));
638   file.Close();
639   ASSERT_TRUE(base::PathExists(file_path));
640 }
641 
642 TEST(FileTest, IrrevokableDeleteOnClose) {
643   base::ScopedTempDir temp_dir;
644   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
645   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
646 
647   // DELETE_ON_CLOSE cannot be revoked by this opener.
648   File file(
649       file_path,
650       (base::File::FLAG_CREATE | base::File::FLAG_READ |
651        base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
652        base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
653   ASSERT_TRUE(file.IsValid());
654   // https://msdn.microsoft.com/library/windows/desktop/aa364221.aspx says that
655   // setting the dispositon has no effect if the handle was opened with
656   // FLAG_DELETE_ON_CLOSE. Do not make the test's success dependent on whether
657   // or not SetFileInformationByHandle indicates success or failure. (It happens
658   // to indicate success on Windows 10.)
659   file.DeleteOnClose(false);
660   file.Close();
661   ASSERT_FALSE(base::PathExists(file_path));
662 }
663 
664 TEST(FileTest, IrrevokableDeleteOnCloseOther) {
665   base::ScopedTempDir temp_dir;
666   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
667   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
668 
669   // DELETE_ON_CLOSE cannot be revoked by another opener.
670   File file(
671       file_path,
672       (base::File::FLAG_CREATE | base::File::FLAG_READ |
673        base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
674        base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
675   ASSERT_TRUE(file.IsValid());
676 
677   File file2(
678       file_path,
679       (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
680        base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
681   ASSERT_TRUE(file2.IsValid());
682 
683   file2.DeleteOnClose(false);
684   file2.Close();
685   ASSERT_TRUE(base::PathExists(file_path));
686   file.Close();
687   ASSERT_FALSE(base::PathExists(file_path));
688 }
689 
690 TEST(FileTest, DeleteWithoutPermission) {
691   base::ScopedTempDir temp_dir;
692   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
693   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
694 
695   // It should not be possible to mark a file for deletion when it was not
696   // created/opened with DELETE.
697   File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
698                         base::File::FLAG_WRITE));
699   ASSERT_TRUE(file.IsValid());
700   ASSERT_FALSE(file.DeleteOnClose(true));
701   file.Close();
702   ASSERT_TRUE(base::PathExists(file_path));
703 }
704 
705 TEST(FileTest, UnsharedDeleteOnClose) {
706   base::ScopedTempDir temp_dir;
707   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
708   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
709 
710   // Opening with DELETE_ON_CLOSE when a previous opener hasn't enabled sharing
711   // will fail.
712   File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
713                         base::File::FLAG_WRITE));
714   ASSERT_TRUE(file.IsValid());
715   File file2(
716       file_path,
717       (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
718        base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_SHARE_DELETE));
719   ASSERT_FALSE(file2.IsValid());
720 
721   file.Close();
722   ASSERT_TRUE(base::PathExists(file_path));
723 }
724 
725 TEST(FileTest, NoDeleteOnCloseWithMappedFile) {
726   base::ScopedTempDir temp_dir;
727   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
728   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
729 
730   // Mapping a file into memory blocks DeleteOnClose.
731   File file(file_path,
732             (base::File::FLAG_CREATE | base::File::FLAG_READ |
733              base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
734   ASSERT_TRUE(file.IsValid());
735   ASSERT_EQ(5, file.WriteAtCurrentPos("12345", 5));
736 
737   {
738     base::MemoryMappedFile mapping;
739     ASSERT_TRUE(mapping.Initialize(file.Duplicate()));
740     ASSERT_EQ(5U, mapping.length());
741 
742     EXPECT_FALSE(file.DeleteOnClose(true));
743   }
744 
745   file.Close();
746   ASSERT_TRUE(base::PathExists(file_path));
747 }
748 
749 // Check that we handle the async bit being set incorrectly in a sane way.
750 TEST(FileTest, UseSyncApiWithAsyncFile) {
751   base::ScopedTempDir temp_dir;
752   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
753   FilePath file_path = temp_dir.GetPath().AppendASCII("file");
754 
755   File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE |
756                            base::File::FLAG_ASYNC);
757   File lying_file(file.TakePlatformFile(), false /* async */);
758   ASSERT_TRUE(lying_file.IsValid());
759 
760   ASSERT_EQ(lying_file.WriteAtCurrentPos("12345", 5), -1);
761 }
762 #endif  // defined(OS_WIN)
763