Home | History | Annotate | Download | only in files
      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 
     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 
    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 
    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 
    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 
    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 
    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)
    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