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