Home | History | Annotate | Download | only in fileapi
      1 // Copyright 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 "webkit/browser/fileapi/file_system_operation_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/file_util.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/logging.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/weak_ptr.h"
     13 #include "base/run_loop.h"
     14 #include "base/strings/stringprintf.h"
     15 #include "content/browser/fileapi/mock_file_change_observer.h"
     16 #include "content/browser/quota/mock_quota_manager.h"
     17 #include "content/browser/quota/mock_quota_manager_proxy.h"
     18 #include "content/public/test/async_file_test_helper.h"
     19 #include "content/public/test/sandbox_file_system_test_helper.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 #include "url/gurl.h"
     22 #include "webkit/browser/fileapi/file_system_context.h"
     23 #include "webkit/browser/fileapi/file_system_file_util.h"
     24 #include "webkit/browser/fileapi/file_system_operation_context.h"
     25 #include "webkit/browser/fileapi/file_system_operation_runner.h"
     26 #include "webkit/browser/fileapi/sandbox_file_system_backend.h"
     27 #include "webkit/browser/quota/quota_manager.h"
     28 #include "webkit/browser/quota/quota_manager_proxy.h"
     29 #include "webkit/common/blob/shareable_file_reference.h"
     30 #include "webkit/common/fileapi/file_system_util.h"
     31 
     32 using content::AsyncFileTestHelper;
     33 using fileapi::FileSystemOperation;
     34 using fileapi::FileSystemOperationContext;
     35 using fileapi::FileSystemOperationRunner;
     36 using fileapi::FileSystemURL;
     37 using quota::QuotaManager;
     38 using quota::QuotaManagerProxy;
     39 using webkit_blob::ShareableFileReference;
     40 
     41 namespace content {
     42 
     43 namespace {
     44 
     45 const int kFileOperationStatusNotSet = 1;
     46 
     47 void AssertFileErrorEq(const tracked_objects::Location& from_here,
     48                        base::File::Error expected,
     49                        base::File::Error actual) {
     50   ASSERT_EQ(expected, actual) << from_here.ToString();
     51 }
     52 
     53 }  // namespace
     54 
     55 // Test class for FileSystemOperationImpl.
     56 class FileSystemOperationImplTest
     57     : public testing::Test {
     58  public:
     59   FileSystemOperationImplTest()
     60       : status_(kFileOperationStatusNotSet),
     61         weak_factory_(this) {}
     62 
     63  protected:
     64   virtual void SetUp() OVERRIDE {
     65     EXPECT_TRUE(base_.CreateUniqueTempDir());
     66     change_observers_ = fileapi::MockFileChangeObserver::CreateList(
     67         &change_observer_);
     68 
     69     base::FilePath base_dir = base_.path().AppendASCII("filesystem");
     70     quota_manager_ =
     71         new MockQuotaManager(false /* is_incognito */,
     72                                     base_dir,
     73                                     base::MessageLoopProxy::current().get(),
     74                                     base::MessageLoopProxy::current().get(),
     75                                     NULL /* special storage policy */);
     76     quota_manager_proxy_ = new MockQuotaManagerProxy(
     77         quota_manager(), base::MessageLoopProxy::current().get());
     78     sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get());
     79     sandbox_file_system_.AddFileChangeObserver(&change_observer_);
     80   }
     81 
     82   virtual void TearDown() OVERRIDE {
     83     // Let the client go away before dropping a ref of the quota manager proxy.
     84     quota_manager_proxy()->SimulateQuotaManagerDestroyed();
     85     quota_manager_ = NULL;
     86     quota_manager_proxy_ = NULL;
     87     sandbox_file_system_.TearDown();
     88   }
     89 
     90   FileSystemOperationRunner* operation_runner() {
     91     return sandbox_file_system_.operation_runner();
     92   }
     93 
     94   int status() const { return status_; }
     95   const base::File::Info& info() const { return info_; }
     96   const base::FilePath& path() const { return path_; }
     97   const std::vector<fileapi::DirectoryEntry>& entries() const {
     98     return entries_;
     99   }
    100 
    101   const ShareableFileReference* shareable_file_ref() const {
    102     return shareable_file_ref_.get();
    103   }
    104 
    105   MockQuotaManager* quota_manager() {
    106     return static_cast<MockQuotaManager*>(quota_manager_.get());
    107   }
    108 
    109   MockQuotaManagerProxy* quota_manager_proxy() {
    110     return static_cast<MockQuotaManagerProxy*>(
    111         quota_manager_proxy_.get());
    112   }
    113 
    114   fileapi::FileSystemFileUtil* file_util() {
    115     return sandbox_file_system_.file_util();
    116   }
    117 
    118   fileapi::MockFileChangeObserver* change_observer() {
    119     return &change_observer_;
    120   }
    121 
    122   scoped_ptr<FileSystemOperationContext> NewContext() {
    123     FileSystemOperationContext* context =
    124         sandbox_file_system_.NewOperationContext();
    125     // Grant enough quota for all test cases.
    126     context->set_allowed_bytes_growth(1000000);
    127     return make_scoped_ptr(context);
    128   }
    129 
    130   FileSystemURL URLForPath(const std::string& path) const {
    131     return sandbox_file_system_.CreateURLFromUTF8(path);
    132   }
    133 
    134   base::FilePath PlatformPath(const std::string& path) {
    135     return sandbox_file_system_.GetLocalPath(
    136         base::FilePath::FromUTF8Unsafe(path));
    137   }
    138 
    139   bool FileExists(const std::string& path) {
    140     return AsyncFileTestHelper::FileExists(
    141         sandbox_file_system_.file_system_context(), URLForPath(path),
    142         AsyncFileTestHelper::kDontCheckSize);
    143   }
    144 
    145   bool DirectoryExists(const std::string& path) {
    146     return AsyncFileTestHelper::DirectoryExists(
    147         sandbox_file_system_.file_system_context(), URLForPath(path));
    148   }
    149 
    150   FileSystemURL CreateFile(const std::string& path) {
    151     FileSystemURL url = URLForPath(path);
    152     bool created = false;
    153     EXPECT_EQ(base::File::FILE_OK,
    154               file_util()->EnsureFileExists(NewContext().get(),
    155                                             url, &created));
    156     EXPECT_TRUE(created);
    157     return url;
    158   }
    159 
    160   FileSystemURL CreateDirectory(const std::string& path) {
    161     FileSystemURL url = URLForPath(path);
    162     EXPECT_EQ(base::File::FILE_OK,
    163               file_util()->CreateDirectory(NewContext().get(), url,
    164                                            false /* exclusive */, true));
    165     return url;
    166   }
    167 
    168   int64 GetFileSize(const std::string& path) {
    169     base::File::Info info;
    170     EXPECT_TRUE(base::GetFileInfo(PlatformPath(path), &info));
    171     return info.size;
    172   }
    173 
    174   // Callbacks for recording test results.
    175   FileSystemOperation::StatusCallback RecordStatusCallback() {
    176     return base::Bind(&FileSystemOperationImplTest::DidFinish,
    177                       weak_factory_.GetWeakPtr());
    178   }
    179 
    180   FileSystemOperation::ReadDirectoryCallback
    181   RecordReadDirectoryCallback() {
    182     return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
    183                       weak_factory_.GetWeakPtr());
    184   }
    185 
    186   FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
    187     return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
    188                       weak_factory_.GetWeakPtr());
    189   }
    190 
    191   FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
    192     return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
    193                       weak_factory_.GetWeakPtr());
    194   }
    195 
    196   void DidFinish(base::File::Error status) {
    197     status_ = status;
    198   }
    199 
    200   void DidReadDirectory(
    201       base::File::Error status,
    202       const std::vector<fileapi::DirectoryEntry>& entries,
    203       bool /* has_more */) {
    204     entries_ = entries;
    205     status_ = status;
    206   }
    207 
    208   void DidGetMetadata(base::File::Error status,
    209                       const base::File::Info& info) {
    210     info_ = info;
    211     status_ = status;
    212   }
    213 
    214   void DidCreateSnapshotFile(
    215       base::File::Error status,
    216       const base::File::Info& info,
    217       const base::FilePath& platform_path,
    218       const scoped_refptr<ShareableFileReference>& shareable_file_ref) {
    219     info_ = info;
    220     path_ = platform_path;
    221     status_ = status;
    222     shareable_file_ref_ = shareable_file_ref;
    223   }
    224 
    225   int64 GetDataSizeOnDisk() {
    226     return sandbox_file_system_.ComputeCurrentOriginUsage() -
    227         sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
    228   }
    229 
    230   void GetUsageAndQuota(int64* usage, int64* quota) {
    231     quota::QuotaStatusCode status =
    232         AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
    233                                               sandbox_file_system_.origin(),
    234                                               sandbox_file_system_.type(),
    235                                               usage,
    236                                               quota);
    237     base::RunLoop().RunUntilIdle();
    238     ASSERT_EQ(quota::kQuotaStatusOk, status);
    239   }
    240 
    241   int64 ComputePathCost(const FileSystemURL& url) {
    242     int64 base_usage;
    243     GetUsageAndQuota(&base_usage, NULL);
    244 
    245     AsyncFileTestHelper::CreateFile(
    246         sandbox_file_system_.file_system_context(), url);
    247     operation_runner()->Remove(url, false /* recursive */,
    248                                base::Bind(&AssertFileErrorEq, FROM_HERE,
    249                                           base::File::FILE_OK));
    250     base::RunLoop().RunUntilIdle();
    251     change_observer()->ResetCount();
    252 
    253     int64 total_usage;
    254     GetUsageAndQuota(&total_usage, NULL);
    255     return total_usage - base_usage;
    256   }
    257 
    258   void GrantQuotaForCurrentUsage() {
    259     int64 usage;
    260     GetUsageAndQuota(&usage, NULL);
    261     quota_manager()->SetQuota(sandbox_file_system_.origin(),
    262                               sandbox_file_system_.storage_type(),
    263                               usage);
    264   }
    265 
    266   int64 GetUsage() {
    267     int64 usage = 0;
    268     GetUsageAndQuota(&usage, NULL);
    269     return usage;
    270   }
    271 
    272   void AddQuota(int64 quota_delta) {
    273     int64 quota;
    274     GetUsageAndQuota(NULL, &quota);
    275     quota_manager()->SetQuota(sandbox_file_system_.origin(),
    276                               sandbox_file_system_.storage_type(),
    277                               quota + quota_delta);
    278   }
    279 
    280  private:
    281   base::MessageLoop message_loop_;
    282   scoped_refptr<QuotaManager> quota_manager_;
    283   scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
    284 
    285   // Common temp base for nondestructive uses.
    286   base::ScopedTempDir base_;
    287 
    288   SandboxFileSystemTestHelper sandbox_file_system_;
    289 
    290   // For post-operation status.
    291   int status_;
    292   base::File::Info info_;
    293   base::FilePath path_;
    294   std::vector<fileapi::DirectoryEntry> entries_;
    295   scoped_refptr<ShareableFileReference> shareable_file_ref_;
    296 
    297   fileapi::MockFileChangeObserver change_observer_;
    298   fileapi::ChangeObserverList change_observers_;
    299 
    300   base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
    301 
    302   DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest);
    303 };
    304 
    305 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) {
    306   change_observer()->ResetCount();
    307   operation_runner()->Move(URLForPath("a"), URLForPath("b"),
    308                            FileSystemOperation::OPTION_NONE,
    309                            RecordStatusCallback());
    310   base::RunLoop().RunUntilIdle();
    311   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    312   EXPECT_TRUE(change_observer()->HasNoChange());
    313 }
    314 
    315 TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) {
    316   FileSystemURL src_dir(CreateDirectory("src"));
    317   FileSystemURL dest_dir(CreateDirectory("src/dest"));
    318 
    319   operation_runner()->Move(src_dir, dest_dir,
    320                            FileSystemOperation::OPTION_NONE,
    321                            RecordStatusCallback());
    322   base::RunLoop().RunUntilIdle();
    323   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
    324   EXPECT_TRUE(change_observer()->HasNoChange());
    325 }
    326 
    327 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) {
    328   // Src exists and is dir. Dest is a file.
    329   FileSystemURL src_dir(CreateDirectory("src"));
    330   FileSystemURL dest_dir(CreateDirectory("dest"));
    331   FileSystemURL dest_file(CreateFile("dest/file"));
    332 
    333   operation_runner()->Move(src_dir, dest_file,
    334                            FileSystemOperation::OPTION_NONE,
    335                            RecordStatusCallback());
    336   base::RunLoop().RunUntilIdle();
    337   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
    338   EXPECT_TRUE(change_observer()->HasNoChange());
    339 }
    340 
    341 TEST_F(FileSystemOperationImplTest,
    342        TestMoveFailureSrcFileExistsDestNonEmptyDir) {
    343   // Src exists and is a directory. Dest is a non-empty directory.
    344   FileSystemURL src_dir(CreateDirectory("src"));
    345   FileSystemURL dest_dir(CreateDirectory("dest"));
    346   FileSystemURL dest_file(CreateFile("dest/file"));
    347 
    348   operation_runner()->Move(src_dir, dest_dir,
    349                            FileSystemOperation::OPTION_NONE,
    350                            RecordStatusCallback());
    351   base::RunLoop().RunUntilIdle();
    352   EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status());
    353   EXPECT_TRUE(change_observer()->HasNoChange());
    354 }
    355 
    356 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) {
    357   // Src exists and is a file. Dest is a directory.
    358   FileSystemURL src_dir(CreateDirectory("src"));
    359   FileSystemURL src_file(CreateFile("src/file"));
    360   FileSystemURL dest_dir(CreateDirectory("dest"));
    361 
    362   operation_runner()->Move(src_file, dest_dir,
    363                            FileSystemOperation::OPTION_NONE,
    364                            RecordStatusCallback());
    365   base::RunLoop().RunUntilIdle();
    366   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
    367   EXPECT_TRUE(change_observer()->HasNoChange());
    368 }
    369 
    370 TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) {
    371   // Dest. parent path does not exist.
    372   FileSystemURL src_dir(CreateDirectory("src"));
    373   operation_runner()->Move(src_dir, URLForPath("nonexistent/deset"),
    374                            FileSystemOperation::OPTION_NONE,
    375                            RecordStatusCallback());
    376   base::RunLoop().RunUntilIdle();
    377   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    378   EXPECT_TRUE(change_observer()->HasNoChange());
    379 }
    380 
    381 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) {
    382   FileSystemURL src_file(CreateFile("src"));
    383   FileSystemURL dest_file(CreateFile("dest"));
    384 
    385   operation_runner()->Move(src_file, dest_file,
    386                            FileSystemOperation::OPTION_NONE,
    387                            RecordStatusCallback());
    388   base::RunLoop().RunUntilIdle();
    389   EXPECT_EQ(base::File::FILE_OK, status());
    390   EXPECT_TRUE(FileExists("dest"));
    391 
    392   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
    393   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
    394   EXPECT_TRUE(change_observer()->HasNoChange());
    395 
    396   EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
    397 }
    398 
    399 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) {
    400   FileSystemURL src_file(CreateFile("src"));
    401 
    402   operation_runner()->Move(src_file, URLForPath("new"),
    403                            FileSystemOperation::OPTION_NONE,
    404                            RecordStatusCallback());
    405   base::RunLoop().RunUntilIdle();
    406   EXPECT_EQ(base::File::FILE_OK, status());
    407   EXPECT_TRUE(FileExists("new"));
    408 
    409   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
    410   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
    411   EXPECT_TRUE(change_observer()->HasNoChange());
    412 }
    413 
    414 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) {
    415   FileSystemURL src_dir(CreateDirectory("src"));
    416   FileSystemURL dest_dir(CreateDirectory("dest"));
    417 
    418   operation_runner()->Move(src_dir, dest_dir,
    419                            FileSystemOperation::OPTION_NONE,
    420                            RecordStatusCallback());
    421   base::RunLoop().RunUntilIdle();
    422   EXPECT_EQ(base::File::FILE_OK, status());
    423   EXPECT_FALSE(DirectoryExists("src"));
    424 
    425   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
    426   EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
    427   EXPECT_TRUE(change_observer()->HasNoChange());
    428 
    429   // Make sure we've overwritten but not moved the source under the |dest_dir|.
    430   EXPECT_TRUE(DirectoryExists("dest"));
    431   EXPECT_FALSE(DirectoryExists("dest/src"));
    432 }
    433 
    434 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) {
    435   FileSystemURL src_dir(CreateDirectory("src"));
    436   FileSystemURL dest_dir(CreateDirectory("dest"));
    437 
    438   operation_runner()->Move(src_dir, URLForPath("dest/new"),
    439                            FileSystemOperation::OPTION_NONE,
    440                            RecordStatusCallback());
    441   base::RunLoop().RunUntilIdle();
    442   EXPECT_EQ(base::File::FILE_OK, status());
    443   EXPECT_FALSE(DirectoryExists("src"));
    444   EXPECT_TRUE(DirectoryExists("dest/new"));
    445 
    446   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
    447   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
    448   EXPECT_TRUE(change_observer()->HasNoChange());
    449 }
    450 
    451 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) {
    452   FileSystemURL src_dir(CreateDirectory("src"));
    453   CreateDirectory("src/dir");
    454   CreateFile("src/dir/sub");
    455 
    456   FileSystemURL dest_dir(CreateDirectory("dest"));
    457 
    458   operation_runner()->Move(src_dir, dest_dir,
    459                            FileSystemOperation::OPTION_NONE,
    460                            RecordStatusCallback());
    461   base::RunLoop().RunUntilIdle();
    462   EXPECT_EQ(base::File::FILE_OK, status());
    463   EXPECT_TRUE(DirectoryExists("dest/dir"));
    464   EXPECT_TRUE(FileExists("dest/dir/sub"));
    465 
    466   EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count());
    467   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
    468   EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
    469   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
    470   EXPECT_TRUE(change_observer()->HasNoChange());
    471 }
    472 
    473 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSamePath) {
    474   FileSystemURL src_dir(CreateDirectory("src"));
    475   CreateDirectory("src/dir");
    476   CreateFile("src/dir/sub");
    477 
    478   operation_runner()->Move(src_dir, src_dir,
    479                            FileSystemOperation::OPTION_NONE,
    480                            RecordStatusCallback());
    481   base::RunLoop().RunUntilIdle();
    482   EXPECT_EQ(base::File::FILE_OK, status());
    483   EXPECT_TRUE(DirectoryExists("src/dir"));
    484   EXPECT_TRUE(FileExists("src/dir/sub"));
    485 
    486   EXPECT_EQ(0, change_observer()->get_and_reset_remove_directory_count());
    487   EXPECT_EQ(0, change_observer()->get_and_reset_create_directory_count());
    488   EXPECT_EQ(0, change_observer()->get_and_reset_remove_file_count());
    489   EXPECT_EQ(0, change_observer()->get_and_reset_create_file_from_count());
    490   EXPECT_TRUE(change_observer()->HasNoChange());
    491 }
    492 
    493 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) {
    494   operation_runner()->Copy(URLForPath("a"), URLForPath("b"),
    495                            FileSystemOperation::OPTION_NONE,
    496                            FileSystemOperationRunner::CopyProgressCallback(),
    497                            RecordStatusCallback());
    498   base::RunLoop().RunUntilIdle();
    499   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    500   EXPECT_TRUE(change_observer()->HasNoChange());
    501 }
    502 
    503 TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) {
    504   FileSystemURL src_dir(CreateDirectory("src"));
    505   FileSystemURL dest_dir(CreateDirectory("src/dir"));
    506 
    507   operation_runner()->Copy(src_dir, dest_dir,
    508                            FileSystemOperation::OPTION_NONE,
    509                            FileSystemOperationRunner::CopyProgressCallback(),
    510                            RecordStatusCallback());
    511   base::RunLoop().RunUntilIdle();
    512   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
    513   EXPECT_TRUE(change_observer()->HasNoChange());
    514 }
    515 
    516 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) {
    517   // Src exists and is dir. Dest is a file.
    518   FileSystemURL src_dir(CreateDirectory("src"));
    519   FileSystemURL dest_dir(CreateDirectory("dest"));
    520   FileSystemURL dest_file(CreateFile("dest/file"));
    521 
    522   operation_runner()->Copy(src_dir, dest_file,
    523                            FileSystemOperation::OPTION_NONE,
    524                            FileSystemOperationRunner::CopyProgressCallback(),
    525                            RecordStatusCallback());
    526   base::RunLoop().RunUntilIdle();
    527   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
    528   EXPECT_TRUE(change_observer()->HasNoChange());
    529 }
    530 
    531 TEST_F(FileSystemOperationImplTest,
    532        TestCopyFailureSrcFileExistsDestNonEmptyDir) {
    533   // Src exists and is a directory. Dest is a non-empty directory.
    534   FileSystemURL src_dir(CreateDirectory("src"));
    535   FileSystemURL dest_dir(CreateDirectory("dest"));
    536   FileSystemURL dest_file(CreateFile("dest/file"));
    537 
    538   operation_runner()->Copy(src_dir, dest_dir,
    539                            FileSystemOperation::OPTION_NONE,
    540                            FileSystemOperationRunner::CopyProgressCallback(),
    541                            RecordStatusCallback());
    542   base::RunLoop().RunUntilIdle();
    543   EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status());
    544   EXPECT_TRUE(change_observer()->HasNoChange());
    545 }
    546 
    547 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) {
    548   // Src exists and is a file. Dest is a directory.
    549   FileSystemURL src_file(CreateFile("src"));
    550   FileSystemURL dest_dir(CreateDirectory("dest"));
    551 
    552   operation_runner()->Copy(src_file, dest_dir,
    553                            FileSystemOperation::OPTION_NONE,
    554                            FileSystemOperationRunner::CopyProgressCallback(),
    555                            RecordStatusCallback());
    556   base::RunLoop().RunUntilIdle();
    557   EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
    558   EXPECT_TRUE(change_observer()->HasNoChange());
    559 }
    560 
    561 TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) {
    562   // Dest. parent path does not exist.
    563   FileSystemURL src_dir(CreateDirectory("src"));
    564 
    565   operation_runner()->Copy(src_dir, URLForPath("nonexistent/dest"),
    566                            FileSystemOperation::OPTION_NONE,
    567                            FileSystemOperationRunner::CopyProgressCallback(),
    568                            RecordStatusCallback());
    569   base::RunLoop().RunUntilIdle();
    570   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    571   EXPECT_TRUE(change_observer()->HasNoChange());
    572 }
    573 
    574 TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) {
    575   FileSystemURL src_dir(CreateDirectory("src"));
    576   FileSystemURL src_file(CreateFile("src/file"));
    577   FileSystemURL dest_dir(CreateDirectory("dest"));
    578   operation_runner()->Truncate(src_file, 6, RecordStatusCallback());
    579   base::RunLoop().RunUntilIdle();
    580   EXPECT_EQ(base::File::FILE_OK, status());
    581   EXPECT_EQ(6, GetFileSize("src/file"));
    582 
    583   FileSystemURL dest_file(URLForPath("dest/file"));
    584   int64 dest_path_cost = ComputePathCost(dest_file);
    585   GrantQuotaForCurrentUsage();
    586   AddQuota(6 + dest_path_cost - 1);
    587 
    588   operation_runner()->Copy(src_file, dest_file,
    589                            FileSystemOperation::OPTION_NONE,
    590                            FileSystemOperationRunner::CopyProgressCallback(),
    591                            RecordStatusCallback());
    592   base::RunLoop().RunUntilIdle();
    593   EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
    594   EXPECT_FALSE(FileExists("dest/file"));
    595 }
    596 
    597 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) {
    598   FileSystemURL src_file(CreateFile("src"));
    599   FileSystemURL dest_file(CreateFile("dest"));
    600 
    601   operation_runner()->Copy(src_file, dest_file,
    602                            FileSystemOperation::OPTION_NONE,
    603                            FileSystemOperationRunner::CopyProgressCallback(),
    604                            RecordStatusCallback());
    605   base::RunLoop().RunUntilIdle();
    606   EXPECT_EQ(base::File::FILE_OK, status());
    607   EXPECT_TRUE(FileExists("dest"));
    608   EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
    609 
    610   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
    611   EXPECT_TRUE(change_observer()->HasNoChange());
    612 }
    613 
    614 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) {
    615   FileSystemURL src_file(CreateFile("src"));
    616 
    617   operation_runner()->Copy(src_file, URLForPath("new"),
    618                            FileSystemOperation::OPTION_NONE,
    619                            FileSystemOperationRunner::CopyProgressCallback(),
    620                            RecordStatusCallback());
    621   base::RunLoop().RunUntilIdle();
    622   EXPECT_EQ(base::File::FILE_OK, status());
    623   EXPECT_TRUE(FileExists("new"));
    624   EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
    625 
    626   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
    627   EXPECT_TRUE(change_observer()->HasNoChange());
    628 }
    629 
    630 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) {
    631   FileSystemURL src_dir(CreateDirectory("src"));
    632   FileSystemURL dest_dir(CreateDirectory("dest"));
    633 
    634   operation_runner()->Copy(src_dir, dest_dir,
    635                            FileSystemOperation::OPTION_NONE,
    636                            FileSystemOperationRunner::CopyProgressCallback(),
    637                            RecordStatusCallback());
    638   base::RunLoop().RunUntilIdle();
    639   EXPECT_EQ(base::File::FILE_OK, status());
    640 
    641   // Make sure we've overwritten but not copied the source under the |dest_dir|.
    642   EXPECT_TRUE(DirectoryExists("dest"));
    643   EXPECT_FALSE(DirectoryExists("dest/src"));
    644   EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 3);
    645 
    646   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
    647   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
    648   EXPECT_TRUE(change_observer()->HasNoChange());
    649 }
    650 
    651 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) {
    652   FileSystemURL src_dir(CreateDirectory("src"));
    653   FileSystemURL dest_dir_new(URLForPath("dest"));
    654 
    655   operation_runner()->Copy(src_dir, dest_dir_new,
    656                            FileSystemOperation::OPTION_NONE,
    657                            FileSystemOperationRunner::CopyProgressCallback(),
    658                            RecordStatusCallback());
    659   base::RunLoop().RunUntilIdle();
    660   EXPECT_EQ(base::File::FILE_OK, status());
    661   EXPECT_TRUE(DirectoryExists("dest"));
    662   EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2);
    663 
    664   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
    665   EXPECT_TRUE(change_observer()->HasNoChange());
    666 }
    667 
    668 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) {
    669   FileSystemURL src_dir(CreateDirectory("src"));
    670   CreateDirectory("src/dir");
    671   CreateFile("src/dir/sub");
    672 
    673   FileSystemURL dest_dir(CreateDirectory("dest"));
    674 
    675   operation_runner()->Copy(src_dir, dest_dir,
    676                            FileSystemOperation::OPTION_NONE,
    677                            FileSystemOperationRunner::CopyProgressCallback(),
    678                            RecordStatusCallback());
    679   base::RunLoop().RunUntilIdle();
    680 
    681   EXPECT_EQ(base::File::FILE_OK, status());
    682   EXPECT_TRUE(DirectoryExists("dest/dir"));
    683   EXPECT_TRUE(FileExists("dest/dir/sub"));
    684 
    685   // For recursive copy we may record multiple read access.
    686   EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 1);
    687 
    688   EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
    689   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
    690   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
    691   EXPECT_TRUE(change_observer()->HasNoChange());
    692 }
    693 
    694 TEST_F(FileSystemOperationImplTest, TestCopySuccessSamePath) {
    695   FileSystemURL src_dir(CreateDirectory("src"));
    696   CreateDirectory("src/dir");
    697   CreateFile("src/dir/sub");
    698 
    699   operation_runner()->Copy(src_dir, src_dir,
    700                            FileSystemOperation::OPTION_NONE,
    701                            FileSystemOperationRunner::CopyProgressCallback(),
    702                            RecordStatusCallback());
    703   base::RunLoop().RunUntilIdle();
    704 
    705   EXPECT_EQ(base::File::FILE_OK, status());
    706   EXPECT_TRUE(DirectoryExists("src/dir"));
    707   EXPECT_TRUE(FileExists("src/dir/sub"));
    708 
    709   EXPECT_EQ(0, change_observer()->get_and_reset_create_directory_count());
    710   EXPECT_EQ(0, change_observer()->get_and_reset_remove_file_count());
    711   EXPECT_EQ(0, change_observer()->get_and_reset_create_file_from_count());
    712   EXPECT_TRUE(change_observer()->HasNoChange());
    713 }
    714 
    715 TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) {
    716   base::FilePath src_local_disk_file_path;
    717   base::CreateTemporaryFile(&src_local_disk_file_path);
    718   const char test_data[] = "foo";
    719   int data_size = ARRAYSIZE_UNSAFE(test_data);
    720   base::WriteFile(src_local_disk_file_path, test_data, data_size);
    721 
    722   FileSystemURL dest_dir(CreateDirectory("dest"));
    723 
    724   int64 before_usage;
    725   GetUsageAndQuota(&before_usage, NULL);
    726 
    727   // Check that the file copied and corresponding usage increased.
    728   operation_runner()->CopyInForeignFile(src_local_disk_file_path,
    729                                         URLForPath("dest/file"),
    730                                         RecordStatusCallback());
    731   base::RunLoop().RunUntilIdle();
    732 
    733   EXPECT_EQ(1, change_observer()->create_file_count());
    734   EXPECT_EQ(base::File::FILE_OK, status());
    735   EXPECT_TRUE(FileExists("dest/file"));
    736   int64 after_usage;
    737   GetUsageAndQuota(&after_usage, NULL);
    738   EXPECT_GT(after_usage, before_usage);
    739 
    740   // Compare contents of src and copied file.
    741   char buffer[100];
    742   EXPECT_EQ(data_size, base::ReadFile(PlatformPath("dest/file"),
    743                                       buffer, data_size));
    744   for (int i = 0; i < data_size; ++i)
    745     EXPECT_EQ(test_data[i], buffer[i]);
    746 }
    747 
    748 TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) {
    749   base::FilePath src_local_disk_file_path;
    750   base::CreateTemporaryFile(&src_local_disk_file_path);
    751   const char test_data[] = "foo";
    752   base::WriteFile(src_local_disk_file_path, test_data,
    753                        ARRAYSIZE_UNSAFE(test_data));
    754 
    755   FileSystemURL dest_dir(CreateDirectory("dest"));
    756 
    757   GrantQuotaForCurrentUsage();
    758   operation_runner()->CopyInForeignFile(src_local_disk_file_path,
    759                                         URLForPath("dest/file"),
    760                                         RecordStatusCallback());
    761   base::RunLoop().RunUntilIdle();
    762 
    763   EXPECT_FALSE(FileExists("dest/file"));
    764   EXPECT_EQ(0, change_observer()->create_file_count());
    765   EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
    766 }
    767 
    768 TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) {
    769   // Already existing file and exclusive true.
    770   FileSystemURL file(CreateFile("file"));
    771   operation_runner()->CreateFile(file, true, RecordStatusCallback());
    772   base::RunLoop().RunUntilIdle();
    773   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status());
    774   EXPECT_TRUE(change_observer()->HasNoChange());
    775 }
    776 
    777 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) {
    778   // Already existing file and exclusive false.
    779   FileSystemURL file(CreateFile("file"));
    780   operation_runner()->CreateFile(file, false, RecordStatusCallback());
    781   base::RunLoop().RunUntilIdle();
    782   EXPECT_EQ(base::File::FILE_OK, status());
    783   EXPECT_TRUE(FileExists("file"));
    784 
    785   // The file was already there; did nothing.
    786   EXPECT_TRUE(change_observer()->HasNoChange());
    787 }
    788 
    789 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) {
    790   // File doesn't exist but exclusive is true.
    791   operation_runner()->CreateFile(URLForPath("new"), true,
    792                                  RecordStatusCallback());
    793   base::RunLoop().RunUntilIdle();
    794   EXPECT_EQ(base::File::FILE_OK, status());
    795   EXPECT_TRUE(FileExists("new"));
    796   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    797 }
    798 
    799 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) {
    800   // Non existing file.
    801   operation_runner()->CreateFile(URLForPath("nonexistent"), false,
    802                                  RecordStatusCallback());
    803   base::RunLoop().RunUntilIdle();
    804   EXPECT_EQ(base::File::FILE_OK, status());
    805   EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
    806 }
    807 
    808 TEST_F(FileSystemOperationImplTest,
    809        TestCreateDirFailureDestParentDoesntExist) {
    810   // Dest. parent path does not exist.
    811   operation_runner()->CreateDirectory(
    812       URLForPath("nonexistent/dir"), false, false,
    813       RecordStatusCallback());
    814   base::RunLoop().RunUntilIdle();
    815   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    816   EXPECT_TRUE(change_observer()->HasNoChange());
    817 }
    818 
    819 TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) {
    820   // Exclusive and dir existing at path.
    821   FileSystemURL dir(CreateDirectory("dir"));
    822   operation_runner()->CreateDirectory(dir, true, false,
    823                                       RecordStatusCallback());
    824   base::RunLoop().RunUntilIdle();
    825   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status());
    826   EXPECT_TRUE(change_observer()->HasNoChange());
    827 }
    828 
    829 TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) {
    830   // Exclusive true and file existing at path.
    831   FileSystemURL file(CreateFile("file"));
    832   operation_runner()->CreateDirectory(file, true, false,
    833                                       RecordStatusCallback());
    834   base::RunLoop().RunUntilIdle();
    835   EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status());
    836   EXPECT_TRUE(change_observer()->HasNoChange());
    837 }
    838 
    839 TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) {
    840   // Dir exists and exclusive is false.
    841   FileSystemURL dir(CreateDirectory("dir"));
    842   operation_runner()->CreateDirectory(dir, false, false,
    843                                       RecordStatusCallback());
    844   base::RunLoop().RunUntilIdle();
    845   EXPECT_EQ(base::File::FILE_OK, status());
    846   EXPECT_TRUE(change_observer()->HasNoChange());
    847 
    848   // Dir doesn't exist.
    849   operation_runner()->CreateDirectory(URLForPath("new"), false, false,
    850                                       RecordStatusCallback());
    851   base::RunLoop().RunUntilIdle();
    852   EXPECT_EQ(base::File::FILE_OK, status());
    853   EXPECT_TRUE(DirectoryExists("new"));
    854   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
    855 }
    856 
    857 TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) {
    858   // Dir doesn't exist.
    859   operation_runner()->CreateDirectory(URLForPath("new"), true, false,
    860                                       RecordStatusCallback());
    861   base::RunLoop().RunUntilIdle();
    862   EXPECT_EQ(base::File::FILE_OK, status());
    863   EXPECT_TRUE(DirectoryExists("new"));
    864   EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
    865   EXPECT_TRUE(change_observer()->HasNoChange());
    866 }
    867 
    868 TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) {
    869   operation_runner()->GetMetadata(URLForPath("nonexistent"),
    870                                   RecordMetadataCallback());
    871   base::RunLoop().RunUntilIdle();
    872   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    873 
    874   operation_runner()->FileExists(URLForPath("nonexistent"),
    875                                  RecordStatusCallback());
    876   base::RunLoop().RunUntilIdle();
    877   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    878 
    879   operation_runner()->DirectoryExists(URLForPath("nonexistent"),
    880                                       RecordStatusCallback());
    881   base::RunLoop().RunUntilIdle();
    882   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    883   EXPECT_TRUE(change_observer()->HasNoChange());
    884 }
    885 
    886 TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) {
    887   FileSystemURL dir(CreateDirectory("dir"));
    888   FileSystemURL file(CreateFile("dir/file"));
    889   int read_access = 0;
    890 
    891   operation_runner()->DirectoryExists(dir, RecordStatusCallback());
    892   base::RunLoop().RunUntilIdle();
    893   EXPECT_EQ(base::File::FILE_OK, status());
    894   ++read_access;
    895 
    896   operation_runner()->GetMetadata(dir, RecordMetadataCallback());
    897   base::RunLoop().RunUntilIdle();
    898   EXPECT_EQ(base::File::FILE_OK, status());
    899   EXPECT_TRUE(info().is_directory);
    900   ++read_access;
    901 
    902   operation_runner()->FileExists(file, RecordStatusCallback());
    903   base::RunLoop().RunUntilIdle();
    904   EXPECT_EQ(base::File::FILE_OK, status());
    905   ++read_access;
    906 
    907   operation_runner()->GetMetadata(file, RecordMetadataCallback());
    908   base::RunLoop().RunUntilIdle();
    909   EXPECT_EQ(base::File::FILE_OK, status());
    910   EXPECT_FALSE(info().is_directory);
    911   ++read_access;
    912 
    913   EXPECT_EQ(read_access,
    914             quota_manager_proxy()->notify_storage_accessed_count());
    915   EXPECT_TRUE(change_observer()->HasNoChange());
    916 }
    917 
    918 TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) {
    919   FileSystemURL dir(CreateDirectory("dir"));
    920   operation_runner()->FileExists(dir, RecordStatusCallback());
    921   base::RunLoop().RunUntilIdle();
    922   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, status());
    923 
    924   FileSystemURL file(CreateFile("file"));
    925   operation_runner()->DirectoryExists(file, RecordStatusCallback());
    926   base::RunLoop().RunUntilIdle();
    927   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, status());
    928 }
    929 
    930 TEST_F(FileSystemOperationImplTest, TestReadDirFailure) {
    931   // Path doesn't exist
    932   operation_runner()->ReadDirectory(URLForPath("nonexistent"),
    933                                     RecordReadDirectoryCallback());
    934   base::RunLoop().RunUntilIdle();
    935   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    936 
    937   // File exists.
    938   FileSystemURL file(CreateFile("file"));
    939   operation_runner()->ReadDirectory(file, RecordReadDirectoryCallback());
    940   base::RunLoop().RunUntilIdle();
    941   EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, status());
    942   EXPECT_TRUE(change_observer()->HasNoChange());
    943 }
    944 
    945 TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) {
    946   //      parent_dir
    947   //       |       |
    948   //  child_dir  child_file
    949   // Verify reading parent_dir.
    950   FileSystemURL parent_dir(CreateDirectory("dir"));
    951   FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
    952   FileSystemURL child_file(CreateFile("dir/child_file"));
    953 
    954   operation_runner()->ReadDirectory(parent_dir, RecordReadDirectoryCallback());
    955   base::RunLoop().RunUntilIdle();
    956   EXPECT_EQ(base::File::FILE_OK, status());
    957   EXPECT_EQ(2u, entries().size());
    958 
    959   for (size_t i = 0; i < entries().size(); ++i) {
    960     if (entries()[i].is_directory)
    961       EXPECT_EQ(FILE_PATH_LITERAL("child_dir"), entries()[i].name);
    962     else
    963       EXPECT_EQ(FILE_PATH_LITERAL("child_file"), entries()[i].name);
    964   }
    965   EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
    966   EXPECT_TRUE(change_observer()->HasNoChange());
    967 }
    968 
    969 TEST_F(FileSystemOperationImplTest, TestRemoveFailure) {
    970   // Path doesn't exist.
    971   operation_runner()->Remove(URLForPath("nonexistent"), false /* recursive */,
    972                              RecordStatusCallback());
    973   base::RunLoop().RunUntilIdle();
    974   EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
    975 
    976   // It's an error to try to remove a non-empty directory if recursive flag
    977   // is false.
    978   //      parent_dir
    979   //       |       |
    980   //  child_dir  child_file
    981   // Verify deleting parent_dir.
    982   FileSystemURL parent_dir(CreateDirectory("dir"));
    983   FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
    984   FileSystemURL child_file(CreateFile("dir/child_file"));
    985 
    986   operation_runner()->Remove(parent_dir, false /* recursive */,
    987                              RecordStatusCallback());
    988   base::RunLoop().RunUntilIdle();
    989   EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status());
    990   EXPECT_TRUE(change_observer()->HasNoChange());
    991 }
    992 
    993 TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) {
    994   FileSystemURL empty_dir(CreateDirectory("empty_dir"));
    995   EXPECT_TRUE(DirectoryExists("empty_dir"));
    996   operation_runner()->Remove(empty_dir, false /* recursive */,
    997                              RecordStatusCallback());
    998   base::RunLoop().RunUntilIdle();
    999   EXPECT_EQ(base::File::FILE_OK, status());
   1000   EXPECT_FALSE(DirectoryExists("empty_dir"));
   1001 
   1002   EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
   1003   EXPECT_TRUE(change_observer()->HasNoChange());
   1004 }
   1005 
   1006 TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) {
   1007   // Removing a non-empty directory with recursive flag == true should be ok.
   1008   //      parent_dir
   1009   //       |       |
   1010   //  child_dir  child_files
   1011   //       |
   1012   //  child_files
   1013   //
   1014   // Verify deleting parent_dir.
   1015   FileSystemURL parent_dir(CreateDirectory("dir"));
   1016   for (int i = 0; i < 8; ++i)
   1017     CreateFile(base::StringPrintf("dir/file-%d", i));
   1018   FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
   1019   for (int i = 0; i < 8; ++i)
   1020     CreateFile(base::StringPrintf("dir/child_dir/file-%d", i));
   1021 
   1022   operation_runner()->Remove(parent_dir, true /* recursive */,
   1023                              RecordStatusCallback());
   1024   base::RunLoop().RunUntilIdle();
   1025   EXPECT_EQ(base::File::FILE_OK, status());
   1026   EXPECT_FALSE(DirectoryExists("parent_dir"));
   1027 
   1028   EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
   1029   EXPECT_EQ(16, change_observer()->get_and_reset_remove_file_count());
   1030   EXPECT_TRUE(change_observer()->HasNoChange());
   1031 }
   1032 
   1033 TEST_F(FileSystemOperationImplTest, TestTruncate) {
   1034   FileSystemURL file(CreateFile("file"));
   1035   base::FilePath platform_path = PlatformPath("file");
   1036 
   1037   char test_data[] = "test data";
   1038   int data_size = static_cast<int>(sizeof(test_data));
   1039   EXPECT_EQ(data_size,
   1040             base::WriteFile(platform_path, test_data, data_size));
   1041 
   1042   // Check that its length is the size of the data written.
   1043   operation_runner()->GetMetadata(file, RecordMetadataCallback());
   1044   base::RunLoop().RunUntilIdle();
   1045   EXPECT_EQ(base::File::FILE_OK, status());
   1046   EXPECT_FALSE(info().is_directory);
   1047   EXPECT_EQ(data_size, info().size);
   1048 
   1049   // Extend the file by truncating it.
   1050   int length = 17;
   1051   operation_runner()->Truncate(file, length, RecordStatusCallback());
   1052   base::RunLoop().RunUntilIdle();
   1053   EXPECT_EQ(base::File::FILE_OK, status());
   1054 
   1055   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
   1056   EXPECT_TRUE(change_observer()->HasNoChange());
   1057 
   1058   // Check that its length is now 17 and that it's all zeroes after the test
   1059   // data.
   1060   EXPECT_EQ(length, GetFileSize("file"));
   1061   char data[100];
   1062   EXPECT_EQ(length, base::ReadFile(platform_path, data, length));
   1063   for (int i = 0; i < length; ++i) {
   1064     if (i < static_cast<int>(sizeof(test_data)))
   1065       EXPECT_EQ(test_data[i], data[i]);
   1066     else
   1067       EXPECT_EQ(0, data[i]);
   1068   }
   1069 
   1070   // Shorten the file by truncating it.
   1071   length = 3;
   1072   operation_runner()->Truncate(file, length, RecordStatusCallback());
   1073   base::RunLoop().RunUntilIdle();
   1074   EXPECT_EQ(base::File::FILE_OK, status());
   1075 
   1076   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
   1077   EXPECT_TRUE(change_observer()->HasNoChange());
   1078 
   1079   // Check that its length is now 3 and that it contains only bits of test data.
   1080   EXPECT_EQ(length, GetFileSize("file"));
   1081   EXPECT_EQ(length, base::ReadFile(platform_path, data, length));
   1082   for (int i = 0; i < length; ++i)
   1083     EXPECT_EQ(test_data[i], data[i]);
   1084 
   1085   // Truncate is not a 'read' access.  (Here expected access count is 1
   1086   // since we made 1 read access for GetMetadata.)
   1087   EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
   1088 }
   1089 
   1090 TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) {
   1091   FileSystemURL dir(CreateDirectory("dir"));
   1092   FileSystemURL file(CreateFile("dir/file"));
   1093 
   1094   GrantQuotaForCurrentUsage();
   1095   AddQuota(10);
   1096 
   1097   operation_runner()->Truncate(file, 10, RecordStatusCallback());
   1098   base::RunLoop().RunUntilIdle();
   1099   EXPECT_EQ(base::File::FILE_OK, status());
   1100   EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
   1101   EXPECT_TRUE(change_observer()->HasNoChange());
   1102 
   1103   EXPECT_EQ(10, GetFileSize("dir/file"));
   1104 
   1105   operation_runner()->Truncate(file, 11, RecordStatusCallback());
   1106   base::RunLoop().RunUntilIdle();
   1107   EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
   1108   EXPECT_TRUE(change_observer()->HasNoChange());
   1109 
   1110   EXPECT_EQ(10, GetFileSize("dir/file"));
   1111 }
   1112 
   1113 TEST_F(FileSystemOperationImplTest, TestTouchFile) {
   1114   FileSystemURL file(CreateFile("file"));
   1115   base::FilePath platform_path = PlatformPath("file");
   1116 
   1117   base::File::Info info;
   1118   EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
   1119   EXPECT_FALSE(info.is_directory);
   1120   EXPECT_EQ(0, info.size);
   1121   const base::Time last_modified = info.last_modified;
   1122   const base::Time last_accessed = info.last_accessed;
   1123 
   1124   const base::Time new_modified_time = base::Time::UnixEpoch();
   1125   const base::Time new_accessed_time = new_modified_time +
   1126       base::TimeDelta::FromHours(77);
   1127   ASSERT_NE(last_modified, new_modified_time);
   1128   ASSERT_NE(last_accessed, new_accessed_time);
   1129 
   1130   operation_runner()->TouchFile(file, new_accessed_time, new_modified_time,
   1131                                 RecordStatusCallback());
   1132   base::RunLoop().RunUntilIdle();
   1133   EXPECT_EQ(base::File::FILE_OK, status());
   1134   EXPECT_TRUE(change_observer()->HasNoChange());
   1135 
   1136   EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
   1137   // We compare as time_t here to lower our resolution, to avoid false
   1138   // negatives caused by conversion to the local filesystem's native
   1139   // representation and back.
   1140   EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT());
   1141   EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT());
   1142 }
   1143 
   1144 TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) {
   1145   FileSystemURL dir(CreateDirectory("dir"));
   1146 
   1147   // Create a file for the testing.
   1148   operation_runner()->DirectoryExists(dir, RecordStatusCallback());
   1149   FileSystemURL file(CreateFile("dir/file"));
   1150   operation_runner()->FileExists(file, RecordStatusCallback());
   1151   base::RunLoop().RunUntilIdle();
   1152   EXPECT_EQ(base::File::FILE_OK, status());
   1153 
   1154   // See if we can get a 'snapshot' file info for the file.
   1155   // Since FileSystemOperationImpl assumes the file exists in the local
   1156   // directory it should just returns the same metadata and platform_path
   1157   // as the file itself.
   1158   operation_runner()->CreateSnapshotFile(file, RecordSnapshotFileCallback());
   1159   base::RunLoop().RunUntilIdle();
   1160   EXPECT_EQ(base::File::FILE_OK, status());
   1161   EXPECT_FALSE(info().is_directory);
   1162   EXPECT_EQ(PlatformPath("dir/file"), path());
   1163   EXPECT_TRUE(change_observer()->HasNoChange());
   1164 
   1165   // The FileSystemOpration implementation does not create a
   1166   // shareable file reference.
   1167   EXPECT_EQ(NULL, shareable_file_ref());
   1168 }
   1169 
   1170 TEST_F(FileSystemOperationImplTest,
   1171        TestMoveSuccessSrcDirRecursiveWithQuota) {
   1172   FileSystemURL src(CreateDirectory("src"));
   1173   int src_path_cost = GetUsage();
   1174 
   1175   FileSystemURL dest(CreateDirectory("dest"));
   1176   FileSystemURL child_file1(CreateFile("src/file1"));
   1177   FileSystemURL child_file2(CreateFile("src/file2"));
   1178   FileSystemURL child_dir(CreateDirectory("src/dir"));
   1179   FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
   1180   FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
   1181 
   1182   int total_path_cost = GetUsage();
   1183   EXPECT_EQ(0, GetDataSizeOnDisk());
   1184 
   1185   operation_runner()->Truncate(
   1186       child_file1, 5000,
   1187       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1188   operation_runner()->Truncate(
   1189       child_file2, 400,
   1190       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1191   operation_runner()->Truncate(
   1192       grandchild_file1, 30,
   1193       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1194   operation_runner()->Truncate(
   1195       grandchild_file2, 2,
   1196       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1197   base::RunLoop().RunUntilIdle();
   1198 
   1199   const int64 all_file_size = 5000 + 400 + 30 + 2;
   1200   EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
   1201   EXPECT_EQ(all_file_size + total_path_cost, GetUsage());
   1202 
   1203   operation_runner()->Move(
   1204       src, dest, FileSystemOperation::OPTION_NONE,
   1205       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1206   base::RunLoop().RunUntilIdle();
   1207 
   1208   EXPECT_FALSE(DirectoryExists("src/dir"));
   1209   EXPECT_FALSE(FileExists("src/dir/file2"));
   1210   EXPECT_TRUE(DirectoryExists("dest/dir"));
   1211   EXPECT_TRUE(FileExists("dest/dir/file2"));
   1212 
   1213   EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
   1214   EXPECT_EQ(all_file_size + total_path_cost - src_path_cost,
   1215             GetUsage());
   1216 }
   1217 
   1218 TEST_F(FileSystemOperationImplTest,
   1219        TestCopySuccessSrcDirRecursiveWithQuota) {
   1220   FileSystemURL src(CreateDirectory("src"));
   1221   FileSystemURL dest1(CreateDirectory("dest1"));
   1222   FileSystemURL dest2(CreateDirectory("dest2"));
   1223 
   1224   int64 usage = GetUsage();
   1225   FileSystemURL child_file1(CreateFile("src/file1"));
   1226   FileSystemURL child_file2(CreateFile("src/file2"));
   1227   FileSystemURL child_dir(CreateDirectory("src/dir"));
   1228   int64 child_path_cost = GetUsage() - usage;
   1229   usage += child_path_cost;
   1230 
   1231   FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
   1232   FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
   1233   int64 total_path_cost = GetUsage();
   1234   int64 grandchild_path_cost = total_path_cost - usage;
   1235 
   1236   EXPECT_EQ(0, GetDataSizeOnDisk());
   1237 
   1238   operation_runner()->Truncate(
   1239       child_file1, 8000,
   1240       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1241   operation_runner()->Truncate(
   1242       child_file2, 700,
   1243       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1244   operation_runner()->Truncate(
   1245       grandchild_file1, 60,
   1246       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1247   operation_runner()->Truncate(
   1248       grandchild_file2, 5,
   1249       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1250   base::RunLoop().RunUntilIdle();
   1251 
   1252   const int64 child_file_size = 8000 + 700;
   1253   const int64 grandchild_file_size = 60 + 5;
   1254   const int64 all_file_size = child_file_size + grandchild_file_size;
   1255   int64 expected_usage = all_file_size + total_path_cost;
   1256 
   1257   usage = GetUsage();
   1258   EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
   1259   EXPECT_EQ(expected_usage, usage);
   1260 
   1261   // Copy src to dest1.
   1262   operation_runner()->Copy(
   1263       src, dest1, FileSystemOperation::OPTION_NONE,
   1264       FileSystemOperationRunner::CopyProgressCallback(),
   1265       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1266   base::RunLoop().RunUntilIdle();
   1267 
   1268   expected_usage += all_file_size + child_path_cost + grandchild_path_cost;
   1269   EXPECT_TRUE(DirectoryExists("src/dir"));
   1270   EXPECT_TRUE(FileExists("src/dir/file2"));
   1271   EXPECT_TRUE(DirectoryExists("dest1/dir"));
   1272   EXPECT_TRUE(FileExists("dest1/dir/file2"));
   1273 
   1274   EXPECT_EQ(2 * all_file_size, GetDataSizeOnDisk());
   1275   EXPECT_EQ(expected_usage, GetUsage());
   1276 
   1277   // Copy src/dir to dest2.
   1278   operation_runner()->Copy(
   1279       child_dir, dest2, FileSystemOperation::OPTION_NONE,
   1280       FileSystemOperationRunner::CopyProgressCallback(),
   1281       base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
   1282   base::RunLoop().RunUntilIdle();
   1283 
   1284   expected_usage += grandchild_file_size + grandchild_path_cost;
   1285   usage = GetUsage();
   1286   EXPECT_EQ(2 * child_file_size + 3 * grandchild_file_size,
   1287             GetDataSizeOnDisk());
   1288   EXPECT_EQ(expected_usage, usage);
   1289 }
   1290 
   1291 }  // namespace content
   1292