Home | History | Annotate | Download | only in fileapi
      1 // Copyright 2014 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 <set>
      6 
      7 #include "base/files/file.h"
      8 #include "base/files/file_path.h"
      9 #include "base/files/file_util.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "storage/browser/fileapi/native_file_util.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 using storage::FileSystemFileUtil;
     15 using storage::FileSystemOperation;
     16 using storage::NativeFileUtil;
     17 
     18 namespace content {
     19 
     20 class NativeFileUtilTest : public testing::Test {
     21  public:
     22   NativeFileUtilTest() {}
     23 
     24   virtual void SetUp() {
     25     ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
     26   }
     27 
     28  protected:
     29   base::FilePath Path() {
     30     return data_dir_.path();
     31   }
     32 
     33   base::FilePath Path(const char* file_name) {
     34     return data_dir_.path().AppendASCII(file_name);
     35   }
     36 
     37   bool FileExists(const base::FilePath& path) {
     38     return base::PathExists(path) &&
     39            !base::DirectoryExists(path);
     40   }
     41 
     42   int64 GetSize(const base::FilePath& path) {
     43     base::File::Info info;
     44     base::GetFileInfo(path, &info);
     45     return info.size;
     46   }
     47 
     48  private:
     49   base::ScopedTempDir data_dir_;
     50 
     51   DISALLOW_COPY_AND_ASSIGN(NativeFileUtilTest);
     52 };
     53 
     54 TEST_F(NativeFileUtilTest, CreateCloseAndDeleteFile) {
     55   base::FilePath file_name = Path("test_file");
     56   int flags = base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
     57   base::File file =
     58       NativeFileUtil::CreateOrOpen(file_name, base::File::FLAG_CREATE | flags);
     59   ASSERT_TRUE(file.IsValid());
     60   ASSERT_TRUE(file.created());
     61 
     62   EXPECT_TRUE(base::PathExists(file_name));
     63   EXPECT_TRUE(NativeFileUtil::PathExists(file_name));
     64   EXPECT_EQ(0, GetSize(file_name));
     65   file.Close();
     66 
     67   file = NativeFileUtil::CreateOrOpen(file_name, base::File::FLAG_OPEN | flags);
     68   ASSERT_TRUE(file.IsValid());
     69   ASSERT_FALSE(file.created());
     70   file.Close();
     71 
     72   ASSERT_EQ(base::File::FILE_OK,
     73             NativeFileUtil::DeleteFile(file_name));
     74   EXPECT_FALSE(base::PathExists(file_name));
     75   EXPECT_FALSE(NativeFileUtil::PathExists(file_name));
     76 }
     77 
     78 TEST_F(NativeFileUtilTest, EnsureFileExists) {
     79   base::FilePath file_name = Path("foobar");
     80   bool created = false;
     81   ASSERT_EQ(base::File::FILE_OK,
     82             NativeFileUtil::EnsureFileExists(file_name, &created));
     83   ASSERT_TRUE(created);
     84 
     85   EXPECT_TRUE(FileExists(file_name));
     86   EXPECT_EQ(0, GetSize(file_name));
     87 
     88   ASSERT_EQ(base::File::FILE_OK,
     89             NativeFileUtil::EnsureFileExists(file_name, &created));
     90   EXPECT_FALSE(created);
     91 }
     92 
     93 TEST_F(NativeFileUtilTest, CreateAndDeleteDirectory) {
     94   base::FilePath dir_name = Path("test_dir");
     95   ASSERT_EQ(base::File::FILE_OK,
     96             NativeFileUtil::CreateDirectory(dir_name,
     97                                             false /* exclusive */,
     98                                             false /* recursive */));
     99 
    100   EXPECT_TRUE(NativeFileUtil::DirectoryExists(dir_name));
    101   EXPECT_TRUE(base::DirectoryExists(dir_name));
    102 
    103   ASSERT_EQ(base::File::FILE_ERROR_EXISTS,
    104             NativeFileUtil::CreateDirectory(dir_name,
    105                                             true /* exclusive */,
    106                                             false /* recursive */));
    107 
    108   ASSERT_EQ(base::File::FILE_OK,
    109             NativeFileUtil::DeleteDirectory(dir_name));
    110   EXPECT_FALSE(base::DirectoryExists(dir_name));
    111   EXPECT_FALSE(NativeFileUtil::DirectoryExists(dir_name));
    112 }
    113 
    114 TEST_F(NativeFileUtilTest, TouchFileAndGetFileInfo) {
    115   base::FilePath file_name = Path("test_file");
    116   base::File::Info native_info;
    117   ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    118             NativeFileUtil::GetFileInfo(file_name, &native_info));
    119 
    120   bool created = false;
    121   ASSERT_EQ(base::File::FILE_OK,
    122             NativeFileUtil::EnsureFileExists(file_name, &created));
    123   ASSERT_TRUE(created);
    124 
    125   base::File::Info info;
    126   ASSERT_TRUE(base::GetFileInfo(file_name, &info));
    127   ASSERT_EQ(base::File::FILE_OK,
    128             NativeFileUtil::GetFileInfo(file_name, &native_info));
    129   ASSERT_EQ(info.size, native_info.size);
    130   ASSERT_EQ(info.is_directory, native_info.is_directory);
    131   ASSERT_EQ(info.is_symbolic_link, native_info.is_symbolic_link);
    132   ASSERT_EQ(info.last_modified, native_info.last_modified);
    133   ASSERT_EQ(info.last_accessed, native_info.last_accessed);
    134   ASSERT_EQ(info.creation_time, native_info.creation_time);
    135 
    136   const base::Time new_accessed =
    137       info.last_accessed + base::TimeDelta::FromHours(10);
    138   const base::Time new_modified =
    139       info.last_modified + base::TimeDelta::FromHours(5);
    140 
    141   EXPECT_EQ(base::File::FILE_OK,
    142             NativeFileUtil::Touch(file_name,
    143                                   new_accessed, new_modified));
    144 
    145   ASSERT_TRUE(base::GetFileInfo(file_name, &info));
    146   EXPECT_EQ(new_accessed, info.last_accessed);
    147   EXPECT_EQ(new_modified, info.last_modified);
    148 }
    149 
    150 TEST_F(NativeFileUtilTest, CreateFileEnumerator) {
    151   base::FilePath path_1 = Path("dir1");
    152   base::FilePath path_2 = Path("file1");
    153   base::FilePath path_11 = Path("dir1").AppendASCII("file11");
    154   base::FilePath path_12 = Path("dir1").AppendASCII("dir12");
    155   base::FilePath path_121 =
    156       Path("dir1").AppendASCII("dir12").AppendASCII("file121");
    157   ASSERT_EQ(base::File::FILE_OK,
    158             NativeFileUtil::CreateDirectory(path_1, false, false));
    159   bool created = false;
    160   ASSERT_EQ(base::File::FILE_OK,
    161             NativeFileUtil::EnsureFileExists(path_2, &created));
    162   ASSERT_EQ(base::File::FILE_OK,
    163             NativeFileUtil::EnsureFileExists(path_11, &created));
    164   ASSERT_EQ(base::File::FILE_OK,
    165             NativeFileUtil::CreateDirectory(path_12, false, false));
    166   ASSERT_EQ(base::File::FILE_OK,
    167             NativeFileUtil::EnsureFileExists(path_121, &created));
    168 
    169   {
    170     scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator =
    171         NativeFileUtil::CreateFileEnumerator(Path(), false);
    172     std::set<base::FilePath> set;
    173     set.insert(path_1);
    174     set.insert(path_2);
    175     for (base::FilePath path = enumerator->Next(); !path.empty();
    176          path = enumerator->Next())
    177       EXPECT_EQ(1U, set.erase(path));
    178     EXPECT_TRUE(set.empty());
    179   }
    180 
    181   {
    182     scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator =
    183         NativeFileUtil::CreateFileEnumerator(Path(), true);
    184         std::set<base::FilePath> set;
    185     set.insert(path_1);
    186     set.insert(path_2);
    187     set.insert(path_11);
    188     set.insert(path_12);
    189     set.insert(path_121);
    190     for (base::FilePath path = enumerator->Next(); !path.empty();
    191          path = enumerator->Next())
    192       EXPECT_EQ(1U, set.erase(path));
    193     EXPECT_TRUE(set.empty());
    194   }
    195 }
    196 
    197 TEST_F(NativeFileUtilTest, Truncate) {
    198   base::FilePath file_name = Path("truncated");
    199   bool created = false;
    200   ASSERT_EQ(base::File::FILE_OK,
    201             NativeFileUtil::EnsureFileExists(file_name, &created));
    202   ASSERT_TRUE(created);
    203 
    204   ASSERT_EQ(base::File::FILE_OK,
    205             NativeFileUtil::Truncate(file_name, 1020));
    206 
    207   EXPECT_TRUE(FileExists(file_name));
    208   EXPECT_EQ(1020, GetSize(file_name));
    209 }
    210 
    211 TEST_F(NativeFileUtilTest, CopyFile) {
    212   base::FilePath from_file = Path("fromfile");
    213   base::FilePath to_file1 = Path("tofile1");
    214   base::FilePath to_file2 = Path("tofile2");
    215   const NativeFileUtil::CopyOrMoveMode nosync = NativeFileUtil::COPY_NOSYNC;
    216   const NativeFileUtil::CopyOrMoveMode sync = NativeFileUtil::COPY_SYNC;
    217   bool created = false;
    218   ASSERT_EQ(base::File::FILE_OK,
    219             NativeFileUtil::EnsureFileExists(from_file, &created));
    220   ASSERT_TRUE(created);
    221 
    222   ASSERT_EQ(base::File::FILE_OK,
    223             NativeFileUtil::Truncate(from_file, 1020));
    224 
    225   EXPECT_TRUE(FileExists(from_file));
    226   EXPECT_EQ(1020, GetSize(from_file));
    227 
    228   ASSERT_EQ(base::File::FILE_OK,
    229             NativeFileUtil::CopyOrMoveFile(
    230                 from_file, to_file1, FileSystemOperation::OPTION_NONE, nosync));
    231 
    232   ASSERT_EQ(base::File::FILE_OK,
    233             NativeFileUtil::CopyOrMoveFile(
    234                 from_file, to_file2, FileSystemOperation::OPTION_NONE, sync));
    235 
    236   EXPECT_TRUE(FileExists(from_file));
    237   EXPECT_EQ(1020, GetSize(from_file));
    238   EXPECT_TRUE(FileExists(to_file1));
    239   EXPECT_EQ(1020, GetSize(to_file1));
    240   EXPECT_TRUE(FileExists(to_file2));
    241   EXPECT_EQ(1020, GetSize(to_file2));
    242 
    243   base::FilePath dir = Path("dir");
    244   ASSERT_EQ(base::File::FILE_OK,
    245             NativeFileUtil::CreateDirectory(dir, false, false));
    246   ASSERT_TRUE(base::DirectoryExists(dir));
    247   base::FilePath to_dir_file = dir.AppendASCII("file");
    248   ASSERT_EQ(base::File::FILE_OK,
    249             NativeFileUtil::CopyOrMoveFile(
    250                 from_file, to_dir_file,
    251                 FileSystemOperation::OPTION_NONE, nosync));
    252   EXPECT_TRUE(FileExists(to_dir_file));
    253   EXPECT_EQ(1020, GetSize(to_dir_file));
    254 
    255   // Following tests are error checking.
    256   // Source doesn't exist.
    257   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    258             NativeFileUtil::CopyOrMoveFile(
    259                 Path("nonexists"), Path("file"),
    260                 FileSystemOperation::OPTION_NONE, nosync));
    261 
    262   // Source is not a file.
    263   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
    264             NativeFileUtil::CopyOrMoveFile(
    265                 dir, Path("file"), FileSystemOperation::OPTION_NONE, nosync));
    266   // Destination is not a file.
    267   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
    268             NativeFileUtil::CopyOrMoveFile(
    269                 from_file, dir, FileSystemOperation::OPTION_NONE, nosync));
    270   // Destination's parent doesn't exist.
    271   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    272             NativeFileUtil::CopyOrMoveFile(
    273                 from_file, Path("nodir").AppendASCII("file"),
    274                 FileSystemOperation::OPTION_NONE, nosync));
    275   // Destination's parent is a file.
    276   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    277             NativeFileUtil::CopyOrMoveFile(
    278                 from_file, Path("tofile1").AppendASCII("file"),
    279                 FileSystemOperation::OPTION_NONE, nosync));
    280 }
    281 
    282 TEST_F(NativeFileUtilTest, MoveFile) {
    283   base::FilePath from_file = Path("fromfile");
    284   base::FilePath to_file = Path("tofile");
    285   const NativeFileUtil::CopyOrMoveMode move = NativeFileUtil::MOVE;
    286   bool created = false;
    287   ASSERT_EQ(base::File::FILE_OK,
    288             NativeFileUtil::EnsureFileExists(from_file, &created));
    289   ASSERT_TRUE(created);
    290 
    291   ASSERT_EQ(base::File::FILE_OK, NativeFileUtil::Truncate(from_file, 1020));
    292 
    293   EXPECT_TRUE(FileExists(from_file));
    294   EXPECT_EQ(1020, GetSize(from_file));
    295 
    296   ASSERT_EQ(base::File::FILE_OK,
    297             NativeFileUtil::CopyOrMoveFile(
    298                 from_file, to_file, FileSystemOperation::OPTION_NONE, move));
    299 
    300   EXPECT_FALSE(FileExists(from_file));
    301   EXPECT_TRUE(FileExists(to_file));
    302   EXPECT_EQ(1020, GetSize(to_file));
    303 
    304   ASSERT_EQ(base::File::FILE_OK,
    305             NativeFileUtil::EnsureFileExists(from_file, &created));
    306   ASSERT_TRUE(FileExists(from_file));
    307   ASSERT_EQ(base::File::FILE_OK, NativeFileUtil::Truncate(from_file, 1020));
    308 
    309   base::FilePath dir = Path("dir");
    310   ASSERT_EQ(base::File::FILE_OK,
    311             NativeFileUtil::CreateDirectory(dir, false, false));
    312   ASSERT_TRUE(base::DirectoryExists(dir));
    313   base::FilePath to_dir_file = dir.AppendASCII("file");
    314   ASSERT_EQ(base::File::FILE_OK,
    315             NativeFileUtil::CopyOrMoveFile(
    316                 from_file, to_dir_file,
    317                 FileSystemOperation::OPTION_NONE, move));
    318   EXPECT_FALSE(FileExists(from_file));
    319   EXPECT_TRUE(FileExists(to_dir_file));
    320   EXPECT_EQ(1020, GetSize(to_dir_file));
    321 
    322   // Following is error checking.
    323   // Source doesn't exist.
    324   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    325             NativeFileUtil::CopyOrMoveFile(
    326                 Path("nonexists"), Path("file"),
    327                 FileSystemOperation::OPTION_NONE, move));
    328 
    329   // Source is not a file.
    330   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
    331             NativeFileUtil::CopyOrMoveFile(
    332                 dir, Path("file"), FileSystemOperation::OPTION_NONE, move));
    333   ASSERT_EQ(base::File::FILE_OK,
    334             NativeFileUtil::EnsureFileExists(from_file, &created));
    335   ASSERT_TRUE(FileExists(from_file));
    336   // Destination is not a file.
    337   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
    338             NativeFileUtil::CopyOrMoveFile(
    339                 from_file, dir, FileSystemOperation::OPTION_NONE, move));
    340 
    341   ASSERT_EQ(base::File::FILE_OK,
    342             NativeFileUtil::EnsureFileExists(from_file, &created));
    343   ASSERT_TRUE(FileExists(from_file));
    344   // Destination's parent doesn't exist.
    345   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    346             NativeFileUtil::CopyOrMoveFile(
    347                 from_file, Path("nodir").AppendASCII("file"),
    348                 FileSystemOperation::OPTION_NONE, move));
    349   // Destination's parent is a file.
    350   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
    351             NativeFileUtil::CopyOrMoveFile(
    352                 from_file, Path("tofile1").AppendASCII("file"),
    353                 FileSystemOperation::OPTION_NONE, move));
    354 }
    355 
    356 TEST_F(NativeFileUtilTest, PreserveLastModified) {
    357   base::FilePath from_file = Path("fromfile");
    358   base::FilePath to_file1 = Path("tofile1");
    359   base::FilePath to_file2 = Path("tofile2");
    360   base::FilePath to_file3 = Path("tofile3");
    361   bool created = false;
    362   ASSERT_EQ(base::File::FILE_OK,
    363             NativeFileUtil::EnsureFileExists(from_file, &created));
    364   ASSERT_TRUE(created);
    365   EXPECT_TRUE(FileExists(from_file));
    366 
    367   base::File::Info file_info1;
    368   ASSERT_EQ(base::File::FILE_OK,
    369             NativeFileUtil::GetFileInfo(from_file, &file_info1));
    370 
    371   // Test for copy (nosync).
    372   ASSERT_EQ(base::File::FILE_OK,
    373             NativeFileUtil::CopyOrMoveFile(
    374                 from_file, to_file1,
    375                 FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
    376                 NativeFileUtil::COPY_NOSYNC));
    377 
    378   base::File::Info file_info2;
    379   ASSERT_TRUE(FileExists(to_file1));
    380   ASSERT_EQ(base::File::FILE_OK,
    381             NativeFileUtil::GetFileInfo(to_file1, &file_info2));
    382   EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
    383 
    384   // Test for copy (sync).
    385   ASSERT_EQ(base::File::FILE_OK,
    386             NativeFileUtil::CopyOrMoveFile(
    387                 from_file, to_file2,
    388                 FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
    389                 NativeFileUtil::COPY_SYNC));
    390 
    391   ASSERT_TRUE(FileExists(to_file2));
    392   ASSERT_EQ(base::File::FILE_OK,
    393             NativeFileUtil::GetFileInfo(to_file1, &file_info2));
    394   EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
    395 
    396   // Test for move.
    397   ASSERT_EQ(base::File::FILE_OK,
    398             NativeFileUtil::CopyOrMoveFile(
    399                 from_file, to_file3,
    400                 FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
    401                 NativeFileUtil::MOVE));
    402 
    403   ASSERT_TRUE(FileExists(to_file3));
    404   ASSERT_EQ(base::File::FILE_OK,
    405             NativeFileUtil::GetFileInfo(to_file2, &file_info2));
    406   EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
    407 }
    408 
    409 }  // namespace content
    410