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.
5 #include "webkit/browser/fileapi/quota/quota_backend_impl.h"
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 "third_party/leveldatabase/src/helpers/memenv/memenv.h"
13 #include "third_party/leveldatabase/src/include/leveldb/env.h"
14 #include "webkit/browser/fileapi/file_system_usage_cache.h"
15 #include "webkit/browser/fileapi/obfuscated_file_util.h"
16 #include "webkit/browser/quota/quota_manager_proxy.h"
22 const char kOrigin[] = "http://example.com";
24 bool DidReserveQuota(bool accepted,
25 base::File::Error* error_out,
27 base::File::Error error,
36 class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
38 MockQuotaManagerProxy()
39 : QuotaManagerProxy(NULL, NULL),
40 storage_modified_count_(0),
41 usage_(0), quota_(0) {}
43 // We don't mock them.
44 virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
45 virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
46 virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
48 quota::StorageType type,
49 bool enabled) OVERRIDE {}
51 virtual void NotifyStorageModified(
52 quota::QuotaClient::ID client_id,
54 quota::StorageType type,
55 int64 delta) OVERRIDE {
56 ++storage_modified_count_;
58 ASSERT_LE(usage_, quota_);
61 virtual void GetUsageAndQuota(
62 base::SequencedTaskRunner* original_task_runner,
64 quota::StorageType type,
65 const GetUsageAndQuotaCallback& callback) OVERRIDE {
66 callback.Run(quota::kQuotaStatusOk, usage_, quota_);
69 int storage_modified_count() { return storage_modified_count_; }
70 int64 usage() { return usage_; }
71 void set_usage(int64 usage) { usage_ = usage; }
72 void set_quota(int64 quota) { quota_ = quota; }
75 virtual ~MockQuotaManagerProxy() {}
78 int storage_modified_count_;
82 DISALLOW_COPY_AND_ASSIGN(MockQuotaManagerProxy);
87 class QuotaBackendImplTest : public testing::Test {
89 QuotaBackendImplTest()
90 : file_system_usage_cache_(file_task_runner()),
91 quota_manager_proxy_(new MockQuotaManagerProxy) {}
93 virtual void SetUp() OVERRIDE {
94 ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
95 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
96 file_util_.reset(ObfuscatedFileUtil::CreateForTesting(
97 NULL, data_dir_.path(), in_memory_env_.get(), file_task_runner()));
98 backend_.reset(new QuotaBackendImpl(file_task_runner(),
100 &file_system_usage_cache_,
101 quota_manager_proxy_.get()));
104 virtual void TearDown() OVERRIDE {
106 quota_manager_proxy_ = NULL;
108 message_loop_.RunUntilIdle();
112 void InitializeForOriginAndType(const GURL& origin, FileSystemType type) {
113 ASSERT_TRUE(file_util_->InitOriginDatabase(origin, true /* create */));
114 ASSERT_TRUE(file_util_->origin_database_ != NULL);
116 std::string type_string =
117 SandboxFileSystemBackendDelegate::GetTypeString(type);
118 base::File::Error error = base::File::FILE_ERROR_FAILED;
119 base::FilePath path = file_util_->GetDirectoryForOriginAndType(
120 origin, type_string, true /* create */, &error);
121 ASSERT_EQ(base::File::FILE_OK, error);
123 ASSERT_TRUE(file_system_usage_cache_.UpdateUsage(
124 GetUsageCachePath(origin, type), 0));
127 base::SequencedTaskRunner* file_task_runner() {
128 return base::MessageLoopProxy::current().get();
131 base::FilePath GetUsageCachePath(const GURL& origin, FileSystemType type) {
133 base::File::Error error =
134 backend_->GetUsageCachePath(origin, type, &path);
135 EXPECT_EQ(base::File::FILE_OK, error);
136 EXPECT_FALSE(path.empty());
140 base::MessageLoop message_loop_;
141 base::ScopedTempDir data_dir_;
142 scoped_ptr<leveldb::Env> in_memory_env_;
143 scoped_ptr<ObfuscatedFileUtil> file_util_;
144 FileSystemUsageCache file_system_usage_cache_;
145 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
146 scoped_ptr<QuotaBackendImpl> backend_;
149 DISALLOW_COPY_AND_ASSIGN(QuotaBackendImplTest);
152 TEST_F(QuotaBackendImplTest, ReserveQuota_Basic) {
153 FileSystemType type = fileapi::kFileSystemTypeTemporary;
154 InitializeForOriginAndType(GURL(kOrigin), type);
155 quota_manager_proxy_->set_quota(10000);
159 const int64 kDelta1 = 1000;
160 base::File::Error error = base::File::FILE_ERROR_FAILED;
161 backend_->ReserveQuota(GURL(kOrigin), type, kDelta1,
162 base::Bind(&DidReserveQuota, true, &error, &delta));
163 EXPECT_EQ(base::File::FILE_OK, error);
164 EXPECT_EQ(kDelta1, delta);
165 EXPECT_EQ(kDelta1, quota_manager_proxy_->usage());
167 const int64 kDelta2 = -300;
168 error = base::File::FILE_ERROR_FAILED;
169 backend_->ReserveQuota(GURL(kOrigin), type, kDelta2,
170 base::Bind(&DidReserveQuota, true, &error, &delta));
171 EXPECT_EQ(base::File::FILE_OK, error);
172 EXPECT_EQ(kDelta2, delta);
173 EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage());
175 EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
178 TEST_F(QuotaBackendImplTest, ReserveQuota_NoSpace) {
179 FileSystemType type = fileapi::kFileSystemTypeTemporary;
180 InitializeForOriginAndType(GURL(kOrigin), type);
181 quota_manager_proxy_->set_quota(100);
185 const int64 kDelta = 1000;
186 base::File::Error error = base::File::FILE_ERROR_FAILED;
187 backend_->ReserveQuota(GURL(kOrigin), type, kDelta,
188 base::Bind(&DidReserveQuota, true, &error, &delta));
189 EXPECT_EQ(base::File::FILE_OK, error);
190 EXPECT_EQ(100, delta);
191 EXPECT_EQ(100, quota_manager_proxy_->usage());
193 EXPECT_EQ(1, quota_manager_proxy_->storage_modified_count());
196 TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) {
197 FileSystemType type = fileapi::kFileSystemTypeTemporary;
198 InitializeForOriginAndType(GURL(kOrigin), type);
199 quota_manager_proxy_->set_quota(10000);
203 const int64 kDelta = 1000;
204 base::File::Error error = base::File::FILE_ERROR_FAILED;
205 backend_->ReserveQuota(GURL(kOrigin), type, kDelta,
206 base::Bind(&DidReserveQuota, false, &error, &delta));
207 EXPECT_EQ(base::File::FILE_OK, error);
208 EXPECT_EQ(kDelta, delta);
209 EXPECT_EQ(0, quota_manager_proxy_->usage());
211 EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
214 TEST_F(QuotaBackendImplTest, ReleaseReservedQuota) {
215 FileSystemType type = fileapi::kFileSystemTypeTemporary;
216 InitializeForOriginAndType(GURL(kOrigin), type);
217 const int64 kInitialUsage = 2000;
218 quota_manager_proxy_->set_usage(kInitialUsage);
219 quota_manager_proxy_->set_quota(10000);
221 const int64 kSize = 1000;
222 backend_->ReleaseReservedQuota(GURL(kOrigin), type, kSize);
223 EXPECT_EQ(kInitialUsage - kSize, quota_manager_proxy_->usage());
225 EXPECT_EQ(1, quota_manager_proxy_->storage_modified_count());
228 TEST_F(QuotaBackendImplTest, CommitQuotaUsage) {
229 FileSystemType type = fileapi::kFileSystemTypeTemporary;
230 InitializeForOriginAndType(GURL(kOrigin), type);
231 quota_manager_proxy_->set_quota(10000);
232 base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
234 const int64 kDelta1 = 1000;
235 backend_->CommitQuotaUsage(GURL(kOrigin), type, kDelta1);
236 EXPECT_EQ(kDelta1, quota_manager_proxy_->usage());
238 EXPECT_TRUE(file_system_usage_cache_.GetUsage(path, &usage));
239 EXPECT_EQ(kDelta1, usage);
241 const int64 kDelta2 = -300;
242 backend_->CommitQuotaUsage(GURL(kOrigin), type, kDelta2);
243 EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage());
245 EXPECT_TRUE(file_system_usage_cache_.GetUsage(path, &usage));
246 EXPECT_EQ(kDelta1 + kDelta2, usage);
248 EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
251 TEST_F(QuotaBackendImplTest, DirtyCount) {
252 FileSystemType type = fileapi::kFileSystemTypeTemporary;
253 InitializeForOriginAndType(GURL(kOrigin), type);
254 base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
256 backend_->IncrementDirtyCount(GURL(kOrigin), type);
258 ASSERT_TRUE(file_system_usage_cache_.GetDirty(path, &dirty));
259 EXPECT_EQ(1u, dirty);
261 backend_->DecrementDirtyCount(GURL(kOrigin), type);
262 ASSERT_TRUE(file_system_usage_cache_.GetDirty(path, &dirty));
263 EXPECT_EQ(0u, dirty);
266 } // namespace fileapi