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/file_util.h"
      6 #include "base/files/file.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(File, 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     // Open a file that doesn't exist.
     21     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     22     EXPECT_FALSE(file.IsValid());
     23     EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error());
     24   }
     25 
     26   {
     27     // Open or create a file.
     28     File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
     29     EXPECT_TRUE(file.IsValid());
     30     EXPECT_TRUE(file.created());
     31     EXPECT_EQ(base::File::FILE_OK, file.error());
     32   }
     33 
     34   {
     35     // Open an existing file.
     36     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     37     EXPECT_TRUE(file.IsValid());
     38     EXPECT_FALSE(file.created());
     39     EXPECT_EQ(base::File::FILE_OK, file.error());
     40 
     41     // This time verify closing the file.
     42     file.Close();
     43     EXPECT_FALSE(file.IsValid());
     44   }
     45 
     46   {
     47     // Create a file that exists.
     48     File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
     49     EXPECT_FALSE(file.IsValid());
     50     EXPECT_FALSE(file.created());
     51     EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error());
     52   }
     53 
     54   {
     55     // Create or overwrite a file.
     56     File file(file_path,
     57               base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ);
     58     EXPECT_TRUE(file.IsValid());
     59     EXPECT_TRUE(file.created());
     60     EXPECT_EQ(base::File::FILE_OK, file.error());
     61   }
     62 
     63   {
     64     // Create a delete-on-close file.
     65     file_path = temp_dir.path().AppendASCII("create_file_2");
     66     File file(file_path,
     67               base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
     68                   base::File::FLAG_DELETE_ON_CLOSE);
     69     EXPECT_TRUE(file.IsValid());
     70     EXPECT_TRUE(file.created());
     71     EXPECT_EQ(base::File::FILE_OK, file.error());
     72   }
     73 
     74   EXPECT_FALSE(base::PathExists(file_path));
     75 }
     76 
     77 TEST(File, DeleteOpenFile) {
     78   base::ScopedTempDir temp_dir;
     79   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
     80   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
     81 
     82   // Create a file.
     83   File file(file_path,
     84             base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
     85                 base::File::FLAG_SHARE_DELETE);
     86   EXPECT_TRUE(file.IsValid());
     87   EXPECT_TRUE(file.created());
     88   EXPECT_EQ(base::File::FILE_OK, file.error());
     89 
     90   // Open an existing file and mark it as delete on close.
     91   File same_file(file_path,
     92                  base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
     93                      base::File::FLAG_READ);
     94   EXPECT_TRUE(file.IsValid());
     95   EXPECT_FALSE(same_file.created());
     96   EXPECT_EQ(base::File::FILE_OK, same_file.error());
     97 
     98   // Close both handles and check that the file is gone.
     99   file.Close();
    100   same_file.Close();
    101   EXPECT_FALSE(base::PathExists(file_path));
    102 }
    103 
    104 TEST(File, ReadWrite) {
    105   base::ScopedTempDir temp_dir;
    106   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    107   FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
    108   File file(file_path,
    109             base::File::FLAG_CREATE | base::File::FLAG_READ |
    110                 base::File::FLAG_WRITE);
    111   ASSERT_TRUE(file.IsValid());
    112 
    113   char data_to_write[] = "test";
    114   const int kTestDataSize = 4;
    115 
    116   // Write 0 bytes to the file.
    117   int bytes_written = file.Write(0, data_to_write, 0);
    118   EXPECT_EQ(0, bytes_written);
    119 
    120   // Write "test" to the file.
    121   bytes_written = file.Write(0, data_to_write, kTestDataSize);
    122   EXPECT_EQ(kTestDataSize, bytes_written);
    123 
    124   // Read from EOF.
    125   char data_read_1[32];
    126   int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
    127   EXPECT_EQ(0, bytes_read);
    128 
    129   // Read from somewhere in the middle of the file.
    130   const int kPartialReadOffset = 1;
    131   bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
    132   EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
    133   for (int i = 0; i < bytes_read; i++)
    134     EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
    135 
    136   // Read 0 bytes.
    137   bytes_read = file.Read(0, data_read_1, 0);
    138   EXPECT_EQ(0, bytes_read);
    139 
    140   // Read the entire file.
    141   bytes_read = file.Read(0, data_read_1, kTestDataSize);
    142   EXPECT_EQ(kTestDataSize, bytes_read);
    143   for (int i = 0; i < bytes_read; i++)
    144     EXPECT_EQ(data_to_write[i], data_read_1[i]);
    145 
    146   // Read again, but using the trivial native wrapper.
    147   bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
    148   EXPECT_LE(bytes_read, kTestDataSize);
    149   for (int i = 0; i < bytes_read; i++)
    150     EXPECT_EQ(data_to_write[i], data_read_1[i]);
    151 
    152   // Write past the end of the file.
    153   const int kOffsetBeyondEndOfFile = 10;
    154   const int kPartialWriteLength = 2;
    155   bytes_written = file.Write(kOffsetBeyondEndOfFile,
    156                              data_to_write, kPartialWriteLength);
    157   EXPECT_EQ(kPartialWriteLength, bytes_written);
    158 
    159   // Make sure the file was extended.
    160   int64 file_size = 0;
    161   EXPECT_TRUE(GetFileSize(file_path, &file_size));
    162   EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
    163 
    164   // Make sure the file was zero-padded.
    165   char data_read_2[32];
    166   bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
    167   EXPECT_EQ(file_size, bytes_read);
    168   for (int i = 0; i < kTestDataSize; i++)
    169     EXPECT_EQ(data_to_write[i], data_read_2[i]);
    170   for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
    171     EXPECT_EQ(0, data_read_2[i]);
    172   for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
    173     EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
    174 }
    175 
    176 TEST(File, Append) {
    177   base::ScopedTempDir temp_dir;
    178   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    179   FilePath file_path = temp_dir.path().AppendASCII("append_file");
    180   File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
    181   ASSERT_TRUE(file.IsValid());
    182 
    183   char data_to_write[] = "test";
    184   const int kTestDataSize = 4;
    185 
    186   // Write 0 bytes to the file.
    187   int bytes_written = file.Write(0, data_to_write, 0);
    188   EXPECT_EQ(0, bytes_written);
    189 
    190   // Write "test" to the file.
    191   bytes_written = file.Write(0, data_to_write, kTestDataSize);
    192   EXPECT_EQ(kTestDataSize, bytes_written);
    193 
    194   file.Close();
    195   File file2(file_path,
    196              base::File::FLAG_OPEN | base::File::FLAG_READ |
    197                  base::File::FLAG_APPEND);
    198   ASSERT_TRUE(file2.IsValid());
    199 
    200   // Test passing the file around.
    201   file = file2.Pass();
    202   EXPECT_FALSE(file2.IsValid());
    203   ASSERT_TRUE(file.IsValid());
    204 
    205   char append_data_to_write[] = "78";
    206   const int kAppendDataSize = 2;
    207 
    208   // Append "78" to the file.
    209   bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
    210   EXPECT_EQ(kAppendDataSize, bytes_written);
    211 
    212   // Read the entire file.
    213   char data_read_1[32];
    214   int bytes_read = file.Read(0, data_read_1,
    215                              kTestDataSize + kAppendDataSize);
    216   EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
    217   for (int i = 0; i < kTestDataSize; i++)
    218     EXPECT_EQ(data_to_write[i], data_read_1[i]);
    219   for (int i = 0; i < kAppendDataSize; i++)
    220     EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
    221 }
    222 
    223 
    224 TEST(File, Truncate) {
    225   base::ScopedTempDir temp_dir;
    226   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    227   FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
    228   File file(file_path,
    229             base::File::FLAG_CREATE | base::File::FLAG_READ |
    230                 base::File::FLAG_WRITE);
    231   ASSERT_TRUE(file.IsValid());
    232 
    233   // Write "test" to the file.
    234   char data_to_write[] = "test";
    235   int kTestDataSize = 4;
    236   int bytes_written = file.Write(0, data_to_write, kTestDataSize);
    237   EXPECT_EQ(kTestDataSize, bytes_written);
    238 
    239   // Extend the file.
    240   const int kExtendedFileLength = 10;
    241   int64 file_size = 0;
    242   EXPECT_TRUE(file.Truncate(kExtendedFileLength));
    243   EXPECT_TRUE(GetFileSize(file_path, &file_size));
    244   EXPECT_EQ(kExtendedFileLength, file_size);
    245 
    246   // Make sure the file was zero-padded.
    247   char data_read[32];
    248   int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
    249   EXPECT_EQ(file_size, bytes_read);
    250   for (int i = 0; i < kTestDataSize; i++)
    251     EXPECT_EQ(data_to_write[i], data_read[i]);
    252   for (int i = kTestDataSize; i < file_size; i++)
    253     EXPECT_EQ(0, data_read[i]);
    254 
    255   // Truncate the file.
    256   const int kTruncatedFileLength = 2;
    257   EXPECT_TRUE(file.Truncate(kTruncatedFileLength));
    258   EXPECT_TRUE(GetFileSize(file_path, &file_size));
    259   EXPECT_EQ(kTruncatedFileLength, file_size);
    260 
    261   // Make sure the file was truncated.
    262   bytes_read = file.Read(0, data_read, kTestDataSize);
    263   EXPECT_EQ(file_size, bytes_read);
    264   for (int i = 0; i < file_size; i++)
    265     EXPECT_EQ(data_to_write[i], data_read[i]);
    266 }
    267 
    268 // Flakily fails: http://crbug.com/86494
    269 #if defined(OS_ANDROID)
    270 TEST(File, TouchGetInfo) {
    271 #else
    272 TEST(File, DISABLED_TouchGetInfo) {
    273 #endif
    274   base::ScopedTempDir temp_dir;
    275   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    276   File file(temp_dir.path().AppendASCII("touch_get_info_file"),
    277             base::File::FLAG_CREATE | base::File::FLAG_WRITE |
    278                 base::File::FLAG_WRITE_ATTRIBUTES);
    279   ASSERT_TRUE(file.IsValid());
    280 
    281   // Get info for a newly created file.
    282   base::File::Info info;
    283   EXPECT_TRUE(file.GetInfo(&info));
    284 
    285   // Add 2 seconds to account for possible rounding errors on
    286   // filesystems that use a 1s or 2s timestamp granularity.
    287   base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
    288   EXPECT_EQ(0, info.size);
    289   EXPECT_FALSE(info.is_directory);
    290   EXPECT_FALSE(info.is_symbolic_link);
    291   EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
    292   EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
    293   EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
    294   base::Time creation_time = info.creation_time;
    295 
    296   // Write "test" to the file.
    297   char data[] = "test";
    298   const int kTestDataSize = 4;
    299   int bytes_written = file.Write(0, data, kTestDataSize);
    300   EXPECT_EQ(kTestDataSize, bytes_written);
    301 
    302   // Change the last_accessed and last_modified dates.
    303   // It's best to add values that are multiples of 2 (in seconds)
    304   // to the current last_accessed and last_modified times, because
    305   // FATxx uses a 2s timestamp granularity.
    306   base::Time new_last_accessed =
    307       info.last_accessed + base::TimeDelta::FromSeconds(234);
    308   base::Time new_last_modified =
    309       info.last_modified + base::TimeDelta::FromMinutes(567);
    310 
    311   EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
    312 
    313   // Make sure the file info was updated accordingly.
    314   EXPECT_TRUE(file.GetInfo(&info));
    315   EXPECT_EQ(info.size, kTestDataSize);
    316   EXPECT_FALSE(info.is_directory);
    317   EXPECT_FALSE(info.is_symbolic_link);
    318 
    319   // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
    320 #if defined(OS_POSIX)
    321   EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
    322             new_last_accessed.ToTimeVal().tv_sec);
    323   EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
    324             new_last_modified.ToTimeVal().tv_sec);
    325 #else
    326   EXPECT_EQ(info.last_accessed.ToInternalValue(),
    327             new_last_accessed.ToInternalValue());
    328   EXPECT_EQ(info.last_modified.ToInternalValue(),
    329             new_last_modified.ToInternalValue());
    330 #endif
    331 
    332   EXPECT_EQ(info.creation_time.ToInternalValue(),
    333             creation_time.ToInternalValue());
    334 }
    335 
    336 TEST(File, ReadFileAtCurrentPosition) {
    337   base::ScopedTempDir temp_dir;
    338   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    339   FilePath file_path =
    340       temp_dir.path().AppendASCII("read_file_at_current_position");
    341   File file(file_path,
    342             base::File::FLAG_CREATE | base::File::FLAG_READ |
    343                 base::File::FLAG_WRITE);
    344   EXPECT_TRUE(file.IsValid());
    345 
    346   const char kData[] = "test";
    347   const int kDataSize = arraysize(kData) - 1;
    348   EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
    349 
    350   EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
    351 
    352   char buffer[kDataSize];
    353   int first_chunk_size = kDataSize / 2;
    354   EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
    355   EXPECT_EQ(kDataSize - first_chunk_size,
    356             file.ReadAtCurrentPos(buffer + first_chunk_size,
    357                                   kDataSize - first_chunk_size));
    358   EXPECT_EQ(std::string(buffer, buffer + kDataSize),
    359             std::string(kData));
    360 }
    361