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