Home | History | Annotate | Download | only in quota
      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/quota/quota_backend_impl.h"
      6 
      7 #include <string>
      8 
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "webkit/browser/fileapi/file_system_usage_cache.h"
     13 #include "webkit/browser/fileapi/obfuscated_file_util.h"
     14 #include "webkit/browser/quota/quota_manager.h"
     15 
     16 namespace fileapi {
     17 
     18 namespace {
     19 
     20 const char kOrigin[] = "http://example.com";
     21 
     22 bool DidReserveQuota(bool accepted,
     23                      base::PlatformFileError* error_out,
     24                      base::PlatformFileError error) {
     25   DCHECK(error_out);
     26   *error_out = error;
     27   return accepted;
     28 }
     29 
     30 class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
     31  public:
     32   MockQuotaManagerProxy()
     33       : QuotaManagerProxy(NULL, NULL),
     34         storage_modified_count_(0),
     35         usage_(0), quota_(0) {}
     36 
     37   // We don't mock them.
     38   virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
     39   virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
     40   virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
     41                                     const GURL& origin,
     42                                     quota::StorageType type,
     43                                     bool enabled) OVERRIDE {}
     44 
     45   virtual void NotifyStorageModified(
     46       quota::QuotaClient::ID client_id,
     47       const GURL& origin,
     48       quota::StorageType type,
     49       int64 delta) OVERRIDE {
     50     ++storage_modified_count_;
     51     usage_ += delta;
     52     ASSERT_LT(usage_, quota_);
     53   }
     54 
     55   virtual void GetUsageAndQuota(
     56       base::SequencedTaskRunner* original_task_runner,
     57       const GURL& origin,
     58       quota::StorageType type,
     59       const GetUsageAndQuotaCallback& callback) OVERRIDE {
     60     callback.Run(quota::kQuotaStatusOk, usage_, quota_);
     61   }
     62 
     63   int storage_modified_count() { return storage_modified_count_; }
     64   int64 usage() { return usage_; }
     65   void set_usage(int64 usage) { usage_ = usage; }
     66   void set_quota(int64 quota) { quota_ = quota; }
     67 
     68  protected:
     69   virtual ~MockQuotaManagerProxy() {}
     70 
     71  private:
     72   int storage_modified_count_;
     73   int64 usage_;
     74   int64 quota_;
     75 
     76   DISALLOW_COPY_AND_ASSIGN(MockQuotaManagerProxy);
     77 };
     78 
     79 }  // namespace
     80 
     81 class QuotaBackendImplTest : public testing::Test {
     82  public:
     83   QuotaBackendImplTest()
     84       : file_system_usage_cache_(file_task_runner()),
     85         quota_manager_proxy_(new MockQuotaManagerProxy) {}
     86 
     87   virtual void SetUp() OVERRIDE {
     88     ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
     89     file_util_.reset(ObfuscatedFileUtil::CreateForTesting(
     90         NULL, data_dir_.path(), file_task_runner()));
     91     backend_.reset(new QuotaBackendImpl(file_task_runner(),
     92                                         file_util_.get(),
     93                                         &file_system_usage_cache_,
     94                                         quota_manager_proxy_.get()));
     95   }
     96 
     97   virtual void TearDown() OVERRIDE {
     98     backend_.reset();
     99     quota_manager_proxy_ = NULL;
    100     file_util_.reset();
    101     message_loop_.RunUntilIdle();
    102   }
    103 
    104  protected:
    105   void InitializeForOriginAndType(const GURL& origin, FileSystemType type) {
    106     ASSERT_TRUE(file_util_->InitOriginDatabase(origin, true /* create */));
    107     ASSERT_TRUE(file_util_->origin_database_ != NULL);
    108 
    109     std::string type_string =
    110         SandboxFileSystemBackendDelegate::GetTypeString(type);
    111     base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
    112     base::FilePath path = file_util_->GetDirectoryForOriginAndType(
    113         origin, type_string, true /* create */, &error);
    114     ASSERT_EQ(base::PLATFORM_FILE_OK, error);
    115 
    116     ASSERT_TRUE(file_system_usage_cache_.UpdateUsage(
    117         GetUsageCachePath(origin, type), 0));
    118   }
    119 
    120   base::SequencedTaskRunner* file_task_runner() {
    121     return base::MessageLoopProxy::current().get();
    122   }
    123 
    124   base::FilePath GetUsageCachePath(const GURL& origin, FileSystemType type) {
    125     base::FilePath path;
    126     base::PlatformFileError error =
    127         backend_->GetUsageCachePath(origin, type, &path);
    128     EXPECT_EQ(base::PLATFORM_FILE_OK, error);
    129     EXPECT_FALSE(path.empty());
    130     return path;
    131   }
    132 
    133   base::MessageLoop message_loop_;
    134   base::ScopedTempDir data_dir_;
    135   scoped_ptr<ObfuscatedFileUtil> file_util_;
    136   FileSystemUsageCache file_system_usage_cache_;
    137   scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
    138   scoped_ptr<QuotaBackendImpl> backend_;
    139 
    140  private:
    141   DISALLOW_COPY_AND_ASSIGN(QuotaBackendImplTest);
    142 };
    143 
    144 TEST_F(QuotaBackendImplTest, ReserveQuota_Basic) {
    145   FileSystemType type = fileapi::kFileSystemTypeTemporary;
    146   InitializeForOriginAndType(GURL(kOrigin), type);
    147   quota_manager_proxy_->set_quota(10000);
    148 
    149   const int64 kDelta1 = 1000;
    150   base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
    151   backend_->ReserveQuota(GURL(kOrigin), type, kDelta1,
    152                          base::Bind(&DidReserveQuota, true, &error));
    153   EXPECT_EQ(base::PLATFORM_FILE_OK, error);
    154   EXPECT_EQ(kDelta1, quota_manager_proxy_->usage());
    155 
    156   const int64 kDelta2 = -300;
    157   error = base::PLATFORM_FILE_ERROR_FAILED;
    158   backend_->ReserveQuota(GURL(kOrigin), type, kDelta2,
    159                          base::Bind(&DidReserveQuota, true, &error));
    160   EXPECT_EQ(base::PLATFORM_FILE_OK, error);
    161   EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage());
    162 
    163   EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
    164 }
    165 
    166 TEST_F(QuotaBackendImplTest, ReserveQuota_NoSpace) {
    167   FileSystemType type = fileapi::kFileSystemTypeTemporary;
    168   InitializeForOriginAndType(GURL(kOrigin), type);
    169   quota_manager_proxy_->set_quota(100);
    170 
    171   const int64 kDelta = 1000;
    172   base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
    173   backend_->ReserveQuota(GURL(kOrigin), type, kDelta,
    174                          base::Bind(&DidReserveQuota, true, &error));
    175   EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, error);
    176   EXPECT_EQ(0, quota_manager_proxy_->usage());
    177 
    178   EXPECT_EQ(0, quota_manager_proxy_->storage_modified_count());
    179 }
    180 
    181 TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) {
    182   FileSystemType type = fileapi::kFileSystemTypeTemporary;
    183   InitializeForOriginAndType(GURL(kOrigin), type);
    184   quota_manager_proxy_->set_quota(10000);
    185 
    186   const int64 kDelta = 1000;
    187   base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
    188   backend_->ReserveQuota(GURL(kOrigin), type, kDelta,
    189                          base::Bind(&DidReserveQuota, false, &error));
    190   EXPECT_EQ(base::PLATFORM_FILE_OK, error);
    191   EXPECT_EQ(0, quota_manager_proxy_->usage());
    192 
    193   EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
    194 }
    195 
    196 TEST_F(QuotaBackendImplTest, ReleaseReservedQuota) {
    197   FileSystemType type = fileapi::kFileSystemTypeTemporary;
    198   InitializeForOriginAndType(GURL(kOrigin), type);
    199   const int64 kInitialUsage = 2000;
    200   quota_manager_proxy_->set_usage(kInitialUsage);
    201   quota_manager_proxy_->set_quota(10000);
    202 
    203   const int64 kSize = 1000;
    204   backend_->ReleaseReservedQuota(GURL(kOrigin), type, kSize);
    205   EXPECT_EQ(kInitialUsage - kSize, quota_manager_proxy_->usage());
    206 
    207   EXPECT_EQ(1, quota_manager_proxy_->storage_modified_count());
    208 }
    209 
    210 TEST_F(QuotaBackendImplTest, CommitQuotaUsage) {
    211   FileSystemType type = fileapi::kFileSystemTypeTemporary;
    212   InitializeForOriginAndType(GURL(kOrigin), type);
    213   quota_manager_proxy_->set_quota(10000);
    214   base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
    215 
    216   const int64 kDelta1 = 1000;
    217   backend_->CommitQuotaUsage(GURL(kOrigin), type, kDelta1);
    218   EXPECT_EQ(kDelta1, quota_manager_proxy_->usage());
    219   int64 usage = 0;
    220   EXPECT_TRUE(file_system_usage_cache_.GetUsage(path, &usage));
    221   EXPECT_EQ(kDelta1, usage);
    222 
    223   const int64 kDelta2 = -300;
    224   backend_->CommitQuotaUsage(GURL(kOrigin), type, kDelta2);
    225   EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage());
    226   usage = 0;
    227   EXPECT_TRUE(file_system_usage_cache_.GetUsage(path, &usage));
    228   EXPECT_EQ(kDelta1 + kDelta2, usage);
    229 
    230   EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
    231 }
    232 
    233 TEST_F(QuotaBackendImplTest, DirtyCount) {
    234   FileSystemType type = fileapi::kFileSystemTypeTemporary;
    235   InitializeForOriginAndType(GURL(kOrigin), type);
    236   base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
    237 
    238   backend_->IncrementDirtyCount(GURL(kOrigin), type);
    239   uint32 dirty = 0;
    240   ASSERT_TRUE(file_system_usage_cache_.GetDirty(path, &dirty));
    241   EXPECT_EQ(1u, dirty);
    242 
    243   backend_->DecrementDirtyCount(GURL(kOrigin), type);
    244   ASSERT_TRUE(file_system_usage_cache_.GetDirty(path, &dirty));
    245   EXPECT_EQ(0u, dirty);
    246 }
    247 
    248 }  // namespace fileapi
    249