Home | History | Annotate | Download | only in local
      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 "base/stl_util.h"
      6 #include "base/thread_task_runner_handle.h"
      7 #include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
      8 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h"
      9 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
     10 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
     11 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
     12 #include "content/public/test/async_file_test_helper.h"
     13 #include "content/public/test/sandbox_file_system_test_helper.h"
     14 #include "content/public/test/test_browser_thread_bundle.h"
     15 #include "storage/browser/fileapi/file_system_context.h"
     16 #include "storage/browser/fileapi/file_system_operation_context.h"
     17 #include "storage/browser/fileapi/isolated_context.h"
     18 #include "storage/browser/quota/quota_manager.h"
     19 #include "storage/common/fileapi/file_system_types.h"
     20 #include "storage/common/quota/quota_types.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
     23 #include "third_party/leveldatabase/src/include/leveldb/env.h"
     24 
     25 using content::SandboxFileSystemTestHelper;
     26 using storage::FileSystemContext;
     27 using storage::FileSystemOperationContext;
     28 using storage::FileSystemURL;
     29 using storage::FileSystemURLSet;
     30 using storage::QuotaManager;
     31 using storage::QuotaStatusCode;
     32 
     33 namespace sync_file_system {
     34 
     35 class SyncableFileSystemTest : public testing::Test {
     36  public:
     37   SyncableFileSystemTest()
     38       : in_memory_env_(leveldb::NewMemEnv(leveldb::Env::Default())),
     39         file_system_(GURL("http://example.com/"),
     40                      in_memory_env_.get(),
     41                      base::ThreadTaskRunnerHandle::Get().get(),
     42                      base::ThreadTaskRunnerHandle::Get().get()),
     43         weak_factory_(this) {}
     44 
     45   virtual void SetUp() {
     46     ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
     47     file_system_.SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
     48 
     49     sync_context_ =
     50         new LocalFileSyncContext(data_dir_.path(),
     51                                  in_memory_env_.get(),
     52                                  base::ThreadTaskRunnerHandle::Get().get(),
     53                                  base::ThreadTaskRunnerHandle::Get().get());
     54     ASSERT_EQ(
     55         sync_file_system::SYNC_STATUS_OK,
     56         file_system_.MaybeInitializeFileSystemContext(sync_context_.get()));
     57   }
     58 
     59   virtual void TearDown() {
     60     if (sync_context_.get())
     61       sync_context_->ShutdownOnUIThread();
     62     sync_context_ = NULL;
     63 
     64     file_system_.TearDown();
     65 
     66     // Make sure we don't leave the external filesystem.
     67     // (CannedSyncableFileSystem::TearDown does not do this as there may be
     68     // multiple syncable file systems registered for the name)
     69     RevokeSyncableFileSystem();
     70   }
     71 
     72  protected:
     73   void VerifyAndClearChange(const FileSystemURL& url,
     74                             const FileChange& expected_change) {
     75     SCOPED_TRACE(testing::Message() << url.DebugString() <<
     76                  " expecting:" << expected_change.DebugString());
     77     // Get the changes for URL and verify.
     78     FileChangeList changes;
     79     change_tracker()->GetChangesForURL(url, &changes);
     80     ASSERT_EQ(1U, changes.size());
     81     SCOPED_TRACE(testing::Message() << url.DebugString() <<
     82                  " actual:" << changes.DebugString());
     83     EXPECT_EQ(expected_change, changes.front());
     84 
     85     // Clear the URL from the change tracker.
     86     change_tracker()->ClearChangesForURL(url);
     87   }
     88 
     89   FileSystemURL URL(const std::string& path) {
     90     return file_system_.URL(path);
     91   }
     92 
     93   FileSystemContext* file_system_context() {
     94     return file_system_.file_system_context();
     95   }
     96 
     97   LocalFileChangeTracker* change_tracker() {
     98     return file_system_.backend()->change_tracker();
     99   }
    100 
    101   base::ScopedTempDir data_dir_;
    102   content::TestBrowserThreadBundle thread_bundle_;
    103   scoped_ptr<leveldb::Env> in_memory_env_;
    104   CannedSyncableFileSystem file_system_;
    105 
    106  private:
    107   scoped_refptr<LocalFileSyncContext> sync_context_;
    108 
    109   base::WeakPtrFactory<SyncableFileSystemTest> weak_factory_;
    110 
    111   DISALLOW_COPY_AND_ASSIGN(SyncableFileSystemTest);
    112 };
    113 
    114 // Brief combined testing. Just see if all the sandbox feature works.
    115 TEST_F(SyncableFileSystemTest, SyncableLocalSandboxCombined) {
    116   // Opens a syncable file system.
    117   EXPECT_EQ(base::File::FILE_OK,
    118             file_system_.OpenFileSystem());
    119 
    120   // Do some operations.
    121   EXPECT_EQ(base::File::FILE_OK,
    122             file_system_.CreateDirectory(URL("dir")));
    123   EXPECT_EQ(base::File::FILE_OK,
    124             file_system_.CreateFile(URL("dir/foo")));
    125 
    126   const int64 kOriginalQuota = QuotaManager::kSyncableStorageDefaultHostQuota;
    127 
    128   const int64 kQuota = 12345 * 1024;
    129   QuotaManager::kSyncableStorageDefaultHostQuota = kQuota;
    130   int64 usage, quota;
    131   EXPECT_EQ(storage::kQuotaStatusOk,
    132             file_system_.GetUsageAndQuota(&usage, &quota));
    133 
    134   // Returned quota must be what we overrode. Usage must be greater than 0
    135   // as creating a file or directory consumes some space.
    136   EXPECT_EQ(kQuota, quota);
    137   EXPECT_GT(usage, 0);
    138 
    139   // Truncate to extend an existing file and see if the usage reflects it.
    140   const int64 kFileSizeToExtend = 333;
    141   EXPECT_EQ(base::File::FILE_OK,
    142             file_system_.CreateFile(URL("dir/foo")));
    143 
    144   EXPECT_EQ(base::File::FILE_OK,
    145             file_system_.TruncateFile(URL("dir/foo"), kFileSizeToExtend));
    146 
    147   int64 new_usage;
    148   EXPECT_EQ(storage::kQuotaStatusOk,
    149             file_system_.GetUsageAndQuota(&new_usage, &quota));
    150   EXPECT_EQ(kFileSizeToExtend, new_usage - usage);
    151 
    152   // Shrink the quota to the current usage, try to extend the file further
    153   // and see if it fails.
    154   QuotaManager::kSyncableStorageDefaultHostQuota = new_usage;
    155   EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
    156             file_system_.TruncateFile(URL("dir/foo"), kFileSizeToExtend + 1));
    157 
    158   usage = new_usage;
    159   EXPECT_EQ(storage::kQuotaStatusOk,
    160             file_system_.GetUsageAndQuota(&new_usage, &quota));
    161   EXPECT_EQ(usage, new_usage);
    162 
    163   // Deletes the file system.
    164   EXPECT_EQ(base::File::FILE_OK,
    165             file_system_.DeleteFileSystem());
    166 
    167   // Now the usage must be zero.
    168   EXPECT_EQ(storage::kQuotaStatusOk,
    169             file_system_.GetUsageAndQuota(&usage, &quota));
    170   EXPECT_EQ(0, usage);
    171 
    172   // Restore the system default quota.
    173   QuotaManager::kSyncableStorageDefaultHostQuota = kOriginalQuota;
    174 }
    175 
    176 // Combined testing with LocalFileChangeTracker.
    177 TEST_F(SyncableFileSystemTest, ChangeTrackerSimple) {
    178   EXPECT_EQ(base::File::FILE_OK,
    179             file_system_.OpenFileSystem());
    180 
    181   const char kPath0[] = "dir a";
    182   const char kPath1[] = "dir a/dir";   // child of kPath0
    183   const char kPath2[] = "dir a/file";  // child of kPath0
    184   const char kPath3[] = "dir b";
    185 
    186   // Do some operations.
    187   EXPECT_EQ(base::File::FILE_OK,
    188             file_system_.CreateDirectory(URL(kPath0)));  // Creates a dir.
    189   EXPECT_EQ(base::File::FILE_OK,
    190             file_system_.CreateDirectory(URL(kPath1)));  // Creates another.
    191   EXPECT_EQ(base::File::FILE_OK,
    192             file_system_.CreateFile(URL(kPath2)));       // Creates a file.
    193   EXPECT_EQ(base::File::FILE_OK,
    194             file_system_.TruncateFile(URL(kPath2), 1));  // Modifies the file.
    195   EXPECT_EQ(base::File::FILE_OK,
    196             file_system_.TruncateFile(URL(kPath2), 2));  // Modifies it again.
    197 
    198   FileSystemURLSet urls;
    199   file_system_.GetChangedURLsInTracker(&urls);
    200 
    201   EXPECT_EQ(3U, urls.size());
    202   EXPECT_TRUE(ContainsKey(urls, URL(kPath0)));
    203   EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
    204   EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
    205 
    206   VerifyAndClearChange(URL(kPath0),
    207                        FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
    208                                   sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
    209   VerifyAndClearChange(URL(kPath1),
    210                        FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
    211                                   sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
    212   VerifyAndClearChange(URL(kPath2),
    213                        FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
    214                                   sync_file_system::SYNC_FILE_TYPE_FILE));
    215 
    216   // Creates and removes a same directory.
    217   EXPECT_EQ(base::File::FILE_OK,
    218             file_system_.CreateDirectory(URL(kPath3)));
    219   EXPECT_EQ(base::File::FILE_OK,
    220             file_system_.Remove(URL(kPath3), false /* recursive */));
    221 
    222   // The changes will be offset.
    223   urls.clear();
    224   file_system_.GetChangedURLsInTracker(&urls);
    225   EXPECT_TRUE(urls.empty());
    226 
    227   // Recursively removes the kPath0 directory.
    228   EXPECT_EQ(base::File::FILE_OK,
    229             file_system_.Remove(URL(kPath0), true /* recursive */));
    230 
    231   urls.clear();
    232   file_system_.GetChangedURLsInTracker(&urls);
    233 
    234   // kPath0 and its all chidren (kPath1 and kPath2) must have been deleted.
    235   EXPECT_EQ(3U, urls.size());
    236   EXPECT_TRUE(ContainsKey(urls, URL(kPath0)));
    237   EXPECT_TRUE(ContainsKey(urls, URL(kPath1)));
    238   EXPECT_TRUE(ContainsKey(urls, URL(kPath2)));
    239 
    240   VerifyAndClearChange(URL(kPath0),
    241                        FileChange(FileChange::FILE_CHANGE_DELETE,
    242                                   sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
    243   VerifyAndClearChange(URL(kPath1),
    244                        FileChange(FileChange::FILE_CHANGE_DELETE,
    245                                   sync_file_system::SYNC_FILE_TYPE_DIRECTORY));
    246   VerifyAndClearChange(URL(kPath2),
    247                        FileChange(FileChange::FILE_CHANGE_DELETE,
    248                                   sync_file_system::SYNC_FILE_TYPE_FILE));
    249 }
    250 
    251 }  // namespace sync_file_system
    252