1 // Copyright 2014 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"
18 using storage::FileSystemUsageCache
;
19 using storage::ObfuscatedFileUtil
;
20 using storage::QuotaBackendImpl
;
21 using storage::SandboxFileSystemBackendDelegate
;
27 const char kOrigin
[] = "http://example.com";
29 bool DidReserveQuota(bool accepted
,
30 base::File::Error
* error_out
,
32 base::File::Error error
,
41 class MockQuotaManagerProxy
: public storage::QuotaManagerProxy
{
43 MockQuotaManagerProxy()
44 : QuotaManagerProxy(NULL
, NULL
),
45 storage_modified_count_(0),
46 usage_(0), quota_(0) {}
48 // We don't mock them.
49 virtual void NotifyOriginInUse(const GURL
& origin
) OVERRIDE
{}
50 virtual void NotifyOriginNoLongerInUse(const GURL
& origin
) OVERRIDE
{}
51 virtual void SetUsageCacheEnabled(storage::QuotaClient::ID client_id
,
53 storage::StorageType type
,
54 bool enabled
) OVERRIDE
{}
56 virtual void NotifyStorageModified(storage::QuotaClient::ID client_id
,
58 storage::StorageType type
,
59 int64 delta
) OVERRIDE
{
60 ++storage_modified_count_
;
62 ASSERT_LE(usage_
, quota_
);
65 virtual void GetUsageAndQuota(
66 base::SequencedTaskRunner
* original_task_runner
,
68 storage::StorageType type
,
69 const GetUsageAndQuotaCallback
& callback
) OVERRIDE
{
70 callback
.Run(storage::kQuotaStatusOk
, usage_
, quota_
);
73 int storage_modified_count() { return storage_modified_count_
; }
74 int64
usage() { return usage_
; }
75 void set_usage(int64 usage
) { usage_
= usage
; }
76 void set_quota(int64 quota
) { quota_
= quota
; }
79 virtual ~MockQuotaManagerProxy() {}
82 int storage_modified_count_
;
86 DISALLOW_COPY_AND_ASSIGN(MockQuotaManagerProxy
);
91 class QuotaBackendImplTest
: public testing::Test
{
93 QuotaBackendImplTest()
94 : file_system_usage_cache_(file_task_runner()),
95 quota_manager_proxy_(new MockQuotaManagerProxy
) {}
97 virtual void SetUp() OVERRIDE
{
98 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
99 in_memory_env_
.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
100 file_util_
.reset(ObfuscatedFileUtil::CreateForTesting(
101 NULL
, data_dir_
.path(), in_memory_env_
.get(), file_task_runner()));
102 backend_
.reset(new QuotaBackendImpl(file_task_runner(),
104 &file_system_usage_cache_
,
105 quota_manager_proxy_
.get()));
108 virtual void TearDown() OVERRIDE
{
110 quota_manager_proxy_
= NULL
;
112 message_loop_
.RunUntilIdle();
116 void InitializeForOriginAndType(const GURL
& origin
,
117 storage::FileSystemType type
) {
118 ASSERT_TRUE(file_util_
->InitOriginDatabase(origin
, true /* create */));
119 ASSERT_TRUE(file_util_
->origin_database_
!= NULL
);
121 std::string type_string
=
122 SandboxFileSystemBackendDelegate::GetTypeString(type
);
123 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
124 base::FilePath path
= file_util_
->GetDirectoryForOriginAndType(
125 origin
, type_string
, true /* create */, &error
);
126 ASSERT_EQ(base::File::FILE_OK
, error
);
128 ASSERT_TRUE(file_system_usage_cache_
.UpdateUsage(
129 GetUsageCachePath(origin
, type
), 0));
132 base::SequencedTaskRunner
* file_task_runner() {
133 return base::MessageLoopProxy::current().get();
136 base::FilePath
GetUsageCachePath(const GURL
& origin
,
137 storage::FileSystemType type
) {
139 base::File::Error error
=
140 backend_
->GetUsageCachePath(origin
, type
, &path
);
141 EXPECT_EQ(base::File::FILE_OK
, error
);
142 EXPECT_FALSE(path
.empty());
146 base::MessageLoop message_loop_
;
147 base::ScopedTempDir data_dir_
;
148 scoped_ptr
<leveldb::Env
> in_memory_env_
;
149 scoped_ptr
<ObfuscatedFileUtil
> file_util_
;
150 FileSystemUsageCache file_system_usage_cache_
;
151 scoped_refptr
<MockQuotaManagerProxy
> quota_manager_proxy_
;
152 scoped_ptr
<QuotaBackendImpl
> backend_
;
155 DISALLOW_COPY_AND_ASSIGN(QuotaBackendImplTest
);
158 TEST_F(QuotaBackendImplTest
, ReserveQuota_Basic
) {
159 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
160 InitializeForOriginAndType(GURL(kOrigin
), type
);
161 quota_manager_proxy_
->set_quota(10000);
165 const int64 kDelta1
= 1000;
166 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
167 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta1
,
168 base::Bind(&DidReserveQuota
, true, &error
, &delta
));
169 EXPECT_EQ(base::File::FILE_OK
, error
);
170 EXPECT_EQ(kDelta1
, delta
);
171 EXPECT_EQ(kDelta1
, quota_manager_proxy_
->usage());
173 const int64 kDelta2
= -300;
174 error
= base::File::FILE_ERROR_FAILED
;
175 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta2
,
176 base::Bind(&DidReserveQuota
, true, &error
, &delta
));
177 EXPECT_EQ(base::File::FILE_OK
, error
);
178 EXPECT_EQ(kDelta2
, delta
);
179 EXPECT_EQ(kDelta1
+ kDelta2
, quota_manager_proxy_
->usage());
181 EXPECT_EQ(2, quota_manager_proxy_
->storage_modified_count());
184 TEST_F(QuotaBackendImplTest
, ReserveQuota_NoSpace
) {
185 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
186 InitializeForOriginAndType(GURL(kOrigin
), type
);
187 quota_manager_proxy_
->set_quota(100);
191 const int64 kDelta
= 1000;
192 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
193 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta
,
194 base::Bind(&DidReserveQuota
, true, &error
, &delta
));
195 EXPECT_EQ(base::File::FILE_OK
, error
);
196 EXPECT_EQ(100, delta
);
197 EXPECT_EQ(100, quota_manager_proxy_
->usage());
199 EXPECT_EQ(1, quota_manager_proxy_
->storage_modified_count());
202 TEST_F(QuotaBackendImplTest
, ReserveQuota_Revert
) {
203 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
204 InitializeForOriginAndType(GURL(kOrigin
), type
);
205 quota_manager_proxy_
->set_quota(10000);
209 const int64 kDelta
= 1000;
210 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
211 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta
,
212 base::Bind(&DidReserveQuota
, false, &error
, &delta
));
213 EXPECT_EQ(base::File::FILE_OK
, error
);
214 EXPECT_EQ(kDelta
, delta
);
215 EXPECT_EQ(0, quota_manager_proxy_
->usage());
217 EXPECT_EQ(2, quota_manager_proxy_
->storage_modified_count());
220 TEST_F(QuotaBackendImplTest
, ReleaseReservedQuota
) {
221 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
222 InitializeForOriginAndType(GURL(kOrigin
), type
);
223 const int64 kInitialUsage
= 2000;
224 quota_manager_proxy_
->set_usage(kInitialUsage
);
225 quota_manager_proxy_
->set_quota(10000);
227 const int64 kSize
= 1000;
228 backend_
->ReleaseReservedQuota(GURL(kOrigin
), type
, kSize
);
229 EXPECT_EQ(kInitialUsage
- kSize
, quota_manager_proxy_
->usage());
231 EXPECT_EQ(1, quota_manager_proxy_
->storage_modified_count());
234 TEST_F(QuotaBackendImplTest
, CommitQuotaUsage
) {
235 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
236 InitializeForOriginAndType(GURL(kOrigin
), type
);
237 quota_manager_proxy_
->set_quota(10000);
238 base::FilePath path
= GetUsageCachePath(GURL(kOrigin
), type
);
240 const int64 kDelta1
= 1000;
241 backend_
->CommitQuotaUsage(GURL(kOrigin
), type
, kDelta1
);
242 EXPECT_EQ(kDelta1
, quota_manager_proxy_
->usage());
244 EXPECT_TRUE(file_system_usage_cache_
.GetUsage(path
, &usage
));
245 EXPECT_EQ(kDelta1
, usage
);
247 const int64 kDelta2
= -300;
248 backend_
->CommitQuotaUsage(GURL(kOrigin
), type
, kDelta2
);
249 EXPECT_EQ(kDelta1
+ kDelta2
, quota_manager_proxy_
->usage());
251 EXPECT_TRUE(file_system_usage_cache_
.GetUsage(path
, &usage
));
252 EXPECT_EQ(kDelta1
+ kDelta2
, usage
);
254 EXPECT_EQ(2, quota_manager_proxy_
->storage_modified_count());
257 TEST_F(QuotaBackendImplTest
, DirtyCount
) {
258 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
259 InitializeForOriginAndType(GURL(kOrigin
), type
);
260 base::FilePath path
= GetUsageCachePath(GURL(kOrigin
), type
);
262 backend_
->IncrementDirtyCount(GURL(kOrigin
), type
);
264 ASSERT_TRUE(file_system_usage_cache_
.GetDirty(path
, &dirty
));
265 EXPECT_EQ(1u, dirty
);
267 backend_
->DecrementDirtyCount(GURL(kOrigin
), type
);
268 ASSERT_TRUE(file_system_usage_cache_
.GetDirty(path
, &dirty
));
269 EXPECT_EQ(0u, dirty
);
272 } // namespace content