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 #include "base/files/file_util.h"
      7 #include "base/files/scoped_temp_dir.h"
      8 #include "base/time/time.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 using base::File;
     12 using base::FilePath;
     13 
     14 TEST(FileTest, Create) {
     15   base::ScopedTempDir temp_dir;
     16   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
     17   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
     18 
     19   {
     20     // Don't create a File at all.
     21     File file;
     22     EXPECT_FALSE(file.IsValid());
     23     EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
     24 
     25     File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
     26     EXPECT_FALSE(file2.IsValid());
     27     EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
     28   }
     29 
     30   {
     31     // Open a file that doesn't exist.
     32     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     33     EXPECT_FALSE(file.IsValid());
     34     EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
     35   }
     36 
     37   {
     38     // Open or create a file.
     39     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
     40     EXPECT_TRUE(file.IsValid());
     41     EXPECT_TRUE(file.created());
     42     EXPECT_EQ(base::File::FILE_OK, file.error_details());
     43   }
     44 
     45   {
     46     // Open an existing file.
     47     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     48     EXPECT_TRUE(file.IsValid());
     49     EXPECT_FALSE(file.created());
     50     EXPECT_EQ(base::File::FILE_OK, file.error_details());
     51 
     52     // This time verify closing the file.
     53     file.Close();
     54     EXPECT_FALSE(file.IsValid());
     55   }
     56 
     57   {
     58     // Open an existing file through Initialize
     59     File file;
     60     file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     61     EXPECT_TRUE(file.IsValid());
     62     EXPECT_FALSE(file.created());
     63     EXPECT_EQ(base::File::FILE_OK, file.error_details());
     64 
     65     // This time verify closing the file.
     66     file.Close();
     67     EXPECT_FALSE(file.IsValid());
     68   }
     69 
     70   {
     71     // Create a file that exists.
     72     File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
     73     EXPECT_FALSE(file.IsValid());
     74     EXPECT_FALSE(file.created());
     75     EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
     76   }
     77 
     78   {
     79     // Create or overwrite a file.
     80     File file(file_path,
     81               base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
     82     EXPECT_TRUE(file.IsValid());
     83     EXPECT_TRUE(file.created());
     84     EXPECT_EQ(base::File::FILE_OK, file.error_details());
     85   }
     86 
     87   {
     88     // Create a delete-on-close file.
     89     file_path = temp_dir.path().AppendASCII("create_file_2");
     90     File file(file_path,
     91               base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
     92                   base::File::FLAG_DELETE_ON_CLOSE);
     93     EXPECT_TRUE(file.IsValid());
     94     EXPECT_TRUE(file.created());
     95     EXPECT_EQ(base::File::FILE_OK, file.error_details());
     96   }
     97 
     98   EXPECT_FALSE(base::PathExists(file_path));
     99 }
    100 
    101 TEST(FileTest, Async) {
    102   base::ScopedTempDir temp_dir;
    103   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    104   FilePath file_path = temp_dir.path().AppendASCII("create_file");
    105 
    106   {
    107     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC);
    108     EXPECT_TRUE(file.IsValid());
    109     EXPECT_TRUE(file.async());
    110   }
    111 
    112   {
    113     File file(file_path, base::File::FLAG_OPEN_ALWAYS);
    114     EXPECT_TRUE(file.IsValid());
    115     EXPECT_FALSE(file.async());
    116   }
    117 }
    118 
    119 TEST(FileTest, DeleteOpenFile) {
    120   base::ScopedTempDir temp_dir;
    121   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    122   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
    123 
    124   // Create a file.
    125   File file(file_path,
    126             base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
    127                 base::File::FLAG_SHARE_DELETE);
    128   EXPECT_TRUE(file.IsValid());
    129   EXPECT_TRUE(file.created());
    130   EXPECT_EQ(base::File::FILE_OK, file.error_details());
    131 
    132   // Open an existing file and mark it as delete on close.
    133   File same_file(file_path,
    134                  base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
    135                      base::File::FLAG_READ);
    136   EXPECT_TRUE(file.IsValid());
    137   EXPECT_FALSE(same_file.created());
    138   EXPECT_EQ(base::File::FILE_OK, same_file.error_details());
    139 
    140   // Close both handles and check that the file is gone.
    141   file.Close();
    142   same_file.Close();
    143   EXPECT_FALSE(base::PathExists(file_path));
    144 }
    145 
    146 TEST(FileTest, ReadWrite) {
    147   base::ScopedTempDir temp_dir;
    148   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    149   FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
    150   File file(file_path,
    151             base::File::FLAG_CREATE | base::File::FLAG_READ |
    152                 base::File::FLAG_WRITE);
    153   ASSERT_TRUE(file.IsValid());
    154 
    155   char data_to_write[] = "test";
    156   const int kTestDataSize = 4;
    157 
    158   // Write 0 bytes to the file.
    159   int bytes_written = file.Write(0, data_to_write, 0);
    160   EXPECT_EQ(0, bytes_written);
    161 
    162   // Write "test" to the file.
    163   bytes_written = file.Write(0, data_to_write, kTestDataSize);
    164   EXPECT_EQ(kTestDataSize, bytes_written);
    165 
    166   // Read from EOF.
    167   char data_read_1[32];
    168   int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
    169   EXPECT_EQ(0, bytes_read);
    170 
    171   // Read from somewhere in the middle of the file.
    172   const int kPartialReadOffset = 1;
    173   bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
    174   EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
    175   for (int i = 0; i < bytes_read; i++)
    176     EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
    177 
    178   // Read 0 bytes.
    179   bytes_read = file.Read(0, data_read_1, 0);
    180   EXPECT_EQ(0, bytes_read);
    181 
    182   // Read the entire file.
    183   bytes_read = file.Read(0, data_read_1, kTestDataSize);
    184   EXPECT_EQ(kTestDataSize, bytes_read);
    185   for (int i = 0; i < bytes_read; i++)
    186     EXPECT_EQ(data_to_write[i], data_read_1[i]);
    187 
    188   // Read again, but using the trivial native wrapper.
    189   bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
    190   EXPECT_LE(bytes_read, kTestDataSize);
    191   for (int i = 0; i < bytes_read; i++)
    192     EXPECT_EQ(data_to_write[i], data_read_1[i]);
    193 
    194   // Write past the end of the file.
    195   const int kOffsetBeyondEndOfFile = 10;
    196   const int kPartialWriteLength = 2;
    197   bytes_written = file.Write(kOffsetBeyondEndOfFile,
    198                              data_to_write, kPartialWriteLength);
    199   EXPECT_EQ(kPartialWriteLength, bytes_written);
    200 
    201   // Make sure the file was extended.
    202   int64 file_size = 0;
    203   EXPECT_TRUE(GetFileSize(file_path, &file_size));
    204   EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
    205 
    206   // Make sure the file was zero-padded.
    207   char data_read_2[32];
    208   bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
    209   EXPECT_EQ(file_size, bytes_read);
    210   for (int i = 0; i < kTestDataSize; i++)
    211     EXPECT_EQ(data_to_write[i], data_read_2[i]);
    212   for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
    213     EXPECT_EQ(0, data_read_2[i]);
    214   for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
    215     EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
    216 }
    217 
    218 TEST(FileTest, Append) {
    219   base::ScopedTempDir temp_dir;
    220   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    221   FilePath file_path = temp_dir.path().AppendASCII("append_file");
    222   File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
    223   ASSERT_TRUE(file.IsValid());
    224 
    225   char data_to_write[] = "test";
    226   const int kTestDataSize = 4;
    227 
    228   // Write 0 bytes to the file.
    229   int bytes_written = file.Write(0, data_to_write, 0);
    230   EXPECT_EQ(0, bytes_written);
    231 
    232   // Write "test" to the file.
    233   bytes_written = file.Write(0, data_to_write, kTestDataSize);
    234   EXPECT_EQ(kTestDataSize, bytes_written);
    235 
    236   file.Close();
    237   File file2(file_path,
    238              base::File::FLAG_OPEN | base::File::FLAG_READ |
    239                  base::File::FLAG_APPEND);
    240   ASSERT_TRUE(file2.IsValid());
    241 
    242   // Test passing the file around.
    243   file = file2.Pass();
    244   EXPECT_FALSE(file2.IsValid());
    245   ASSERT_TRUE(file.IsValid());
    246 
    247   char append_data_to_write[] = "78";
    248   const int kAppendDataSize = 2;
    249 
    250   // Append "78" to the file.
    251   bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
    252   EXPECT_EQ(kAppendDataSize, bytes_written);
    253 
    254   // Read the entire file.
    255   char data_read_1[32];
    256   int bytes_read = file.Read(0, data_read_1,
    257                              kTestDataSize + kAppendDataSize);
    258   EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
    259   for (int i = 0; i < kTestDataSize; i++)
    260     EXPECT_EQ(data_to_write[i], data_read_1[i]);
    261   for (int i = 0; i < kAppendDataSize; i++)
    262     EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
    263 }
    264 
    265 
    266 TEST(FileTest, Length) {
    267   base::ScopedTempDir temp_dir;
    268   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    269   FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
    270   File file(file_path,
    271             base::File::FLAG_CREATE | base::File::FLAG_READ |
    272                 base::File::FLAG_WRITE);
    273   ASSERT_TRUE(file.IsValid());
    274   EXPECT_EQ(0, file.GetLength());
    275 
    276   // Write "test" to the file.
    277   char data_to_write[] = "test";
    278   int kTestDataSize = 4;
    279   int bytes_written = file.Write(0, data_to_write, kTestDataSize);
    280   EXPECT_EQ(kTestDataSize, bytes_written);
    281 
    282   // Extend the file.
    283   const int kExtendedFileLength = 10;
    284   int64 file_size = 0;
    285   EXPECT_TRUE(file.SetLength(kExtendedFileLength));
    286   EXPECT_EQ(kExtendedFileLength, file.GetLength());
    287   EXPECT_TRUE(GetFileSize(file_path, &file_size));
    288   EXPECT_EQ(kExtendedFileLength, file_size);
    289 
    290   // Make sure the file was zero-padded.
    291   char data_read[32];
    292   int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
    293   EXPECT_EQ(file_size, bytes_read);
    294   for (int i = 0; i < kTestDataSize; i++)
    295     EXPECT_EQ(data_to_write[i], data_read[i]);
    296   for (int i = kTestDataSize; i < file_size; i++)
    297     EXPECT_EQ(0, data_read[i]);
    298 
    299   // Truncate the file.
    300   const int kTruncatedFileLength = 2;
    301   EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
    302   EXPECT_EQ(kTruncatedFileLength, file.GetLength());
    303   EXPECT_TRUE(GetFileSize(file_path, &file_size));
    304   EXPECT_EQ(kTruncatedFileLength, file_size);
    305 
    306   // Make sure the file was truncated.
    307   bytes_read = file.Read(0, data_read, kTestDataSize);
    308   EXPECT_EQ(file_size, bytes_read);
    309   for (int i = 0; i < file_size; i++)
    310     EXPECT_EQ(data_to_write[i], data_read[i]);
    311 }
    312 
    313 // Flakily fails: http://crbug.com/86494
    314 #if defined(OS_ANDROID)
    315 TEST(FileTest, TouchGetInfo) {
    316 #else
    317 TEST(FileTest, DISABLED_TouchGetInfo) {
    318 #endif
    319   base::ScopedTempDir temp_dir;
    320   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    321   File file(temp_dir.path().AppendASCII("touch_get_info_file"),
    322             base::File::FLAG_CREATE | base::File::FLAG_WRITE |
    323                 base::File::FLAG_WRITE_ATTRIBUTES);
    324   ASSERT_TRUE(file.IsValid());
    325 
    326   // Get info for a newly created file.
    327   base::File::Info info;
    328   EXPECT_TRUE(file.GetInfo(&info));
    329 
    330   // Add 2 seconds to account for possible rounding errors on
    331   // filesystems that use a 1s or 2s timestamp granularity.
    332   base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
    333   EXPECT_EQ(0, info.size);
    334   EXPECT_FALSE(info.is_directory);
    335   EXPECT_FALSE(info.is_symbolic_link);
    336   EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
    337   EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
    338   EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
    339   base::Time creation_time = info.creation_time;
    340 
    341   // Write "test" to the file.
    342   char data[] = "test";
    343   const int kTestDataSize = 4;
    344   int bytes_written = file.Write(0, data, kTestDataSize);
    345   EXPECT_EQ(kTestDataSize, bytes_written);
    346 
    347   // Change the last_accessed and last_modified dates.
    348   // It's best to add values that are multiples of 2 (in seconds)
    349   // to the current last_accessed and last_modified times, because
    350   // FATxx uses a 2s timestamp granularity.
    351   base::Time new_last_accessed =
    352       info.last_accessed + base::TimeDelta::FromSeconds(234);
    353   base::Time new_last_modified =
    354       info.last_modified + base::TimeDelta::FromMinutes(567);
    355 
    356   EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
    357 
    358   // Make sure the file info was updated accordingly.
    359   EXPECT_TRUE(file.GetInfo(&info));
    360   EXPECT_EQ(info.size, kTestDataSize);
    361   EXPECT_FALSE(info.is_directory);
    362   EXPECT_FALSE(info.is_symbolic_link);
    363 
    364   // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
    365 #if defined(OS_POSIX)
    366   EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
    367             new_last_accessed.ToTimeVal().tv_sec);
    368   EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
    369             new_last_modified.ToTimeVal().tv_sec);
    370 #else
    371   EXPECT_EQ(info.last_accessed.ToInternalValue(),
    372             new_last_accessed.ToInternalValue());
    373   EXPECT_EQ(info.last_modified.ToInternalValue(),
    374             new_last_modified.ToInternalValue());
    375 #endif
    376 
    377   EXPECT_EQ(info.creation_time.ToInternalValue(),
    378             creation_time.ToInternalValue());
    379 }
    380 
    381 TEST(FileTest, ReadAtCurrentPosition) {
    382   base::ScopedTempDir temp_dir;
    383   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    384   FilePath file_path = temp_dir.path().AppendASCII("read_at_current_position");
    385   File file(file_path,
    386             base::File::FLAG_CREATE | base::File::FLAG_READ |
    387                 base::File::FLAG_WRITE);
    388   EXPECT_TRUE(file.IsValid());
    389 
    390   const char kData[] = "test";
    391   const int kDataSize = sizeof(kData) - 1;
    392   EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
    393 
    394   EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
    395 
    396   char buffer[kDataSize];
    397   int first_chunk_size = kDataSize / 2;
    398   EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
    399   EXPECT_EQ(kDataSize - first_chunk_size,
    400             file.ReadAtCurrentPos(buffer + first_chunk_size,
    401                                   kDataSize - first_chunk_size));
    402   EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
    403 }
    404 
    405 TEST(FileTest, WriteAtCurrentPosition) {
    406   base::ScopedTempDir temp_dir;
    407   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    408   FilePath file_path = temp_dir.path().AppendASCII("write_at_current_position");
    409   File file(file_path,
    410             base::File::FLAG_CREATE | base::File::FLAG_READ |
    411                 base::File::FLAG_WRITE);
    412   EXPECT_TRUE(file.IsValid());
    413 
    414   const char kData[] = "test";
    415   const int kDataSize = sizeof(kData) - 1;
    416 
    417   int first_chunk_size = kDataSize / 2;
    418   EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
    419   EXPECT_EQ(kDataSize - first_chunk_size,
    420             file.WriteAtCurrentPos(kData + first_chunk_size,
    421                                    kDataSize - first_chunk_size));
    422 
    423   char buffer[kDataSize];
    424   EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
    425   EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
    426 }
    427 
    428 TEST(FileTest, Seek) {
    429   base::ScopedTempDir temp_dir;
    430   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    431   FilePath file_path = temp_dir.path().AppendASCII("seek_file");
    432   File file(file_path,
    433             base::File::FLAG_CREATE | base::File::FLAG_READ |
    434                 base::File::FLAG_WRITE);
    435   ASSERT_TRUE(file.IsValid());
    436 
    437   const int64 kOffset = 10;
    438   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset));
    439   EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset));
    440   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset));
    441   EXPECT_TRUE(file.SetLength(kOffset * 2));
    442   EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset));
    443 }
    444 
    445 #if defined(OS_WIN)
    446 TEST(FileTest, GetInfoForDirectory) {
    447   base::ScopedTempDir temp_dir;
    448   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    449   FilePath empty_dir = temp_dir.path().Append(FILE_PATH_LITERAL("gpfi_test"));
    450   ASSERT_TRUE(CreateDirectory(empty_dir));
    451 
    452   base::File dir(
    453       ::CreateFile(empty_dir.value().c_str(),
    454                    FILE_ALL_ACCESS,
    455                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    456                    NULL,
    457                    OPEN_EXISTING,
    458                    FILE_FLAG_BACKUP_SEMANTICS,  // Needed to open a directory.
    459                    NULL));
    460   ASSERT_TRUE(dir.IsValid());
    461 
    462   base::File::Info info;
    463   EXPECT_TRUE(dir.GetInfo(&info));
    464   EXPECT_TRUE(info.is_directory);
    465   EXPECT_FALSE(info.is_symbolic_link);
    466   EXPECT_EQ(0, info.size);
    467 }
    468 #endif  // defined(OS_WIN)
    469