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     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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)
    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