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 "storage/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 "storage/browser/fileapi/file_system_usage_cache.h"
12 #include "storage/browser/fileapi/obfuscated_file_util.h"
13 #include "storage/browser/quota/quota_manager_proxy.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
16 #include "third_party/leveldatabase/src/include/leveldb/env.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 void NotifyOriginInUse(const GURL
& origin
) override
{}
50 void NotifyOriginNoLongerInUse(const GURL
& origin
) override
{}
51 void SetUsageCacheEnabled(storage::QuotaClient::ID client_id
,
53 storage::StorageType type
,
54 bool enabled
) override
{}
56 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 void GetUsageAndQuota(base::SequencedTaskRunner
* original_task_runner
,
67 storage::StorageType type
,
68 const GetUsageAndQuotaCallback
& callback
) override
{
69 callback
.Run(storage::kQuotaStatusOk
, usage_
, quota_
);
72 int storage_modified_count() { return storage_modified_count_
; }
73 int64
usage() { return usage_
; }
74 void set_usage(int64 usage
) { usage_
= usage
; }
75 void set_quota(int64 quota
) { quota_
= quota
; }
78 ~MockQuotaManagerProxy() override
{}
81 int storage_modified_count_
;
85 DISALLOW_COPY_AND_ASSIGN(MockQuotaManagerProxy
);
90 class QuotaBackendImplTest
: public testing::Test
{
92 QuotaBackendImplTest()
93 : file_system_usage_cache_(file_task_runner()),
94 quota_manager_proxy_(new MockQuotaManagerProxy
) {}
96 void SetUp() override
{
97 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
98 in_memory_env_
.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
99 file_util_
.reset(ObfuscatedFileUtil::CreateForTesting(
100 NULL
, data_dir_
.path(), in_memory_env_
.get(), file_task_runner()));
101 backend_
.reset(new QuotaBackendImpl(file_task_runner(),
103 &file_system_usage_cache_
,
104 quota_manager_proxy_
.get()));
107 void TearDown() override
{
109 quota_manager_proxy_
= NULL
;
111 message_loop_
.RunUntilIdle();
115 void InitializeForOriginAndType(const GURL
& origin
,
116 storage::FileSystemType type
) {
117 ASSERT_TRUE(file_util_
->InitOriginDatabase(origin
, true /* create */));
118 ASSERT_TRUE(file_util_
->origin_database_
!= NULL
);
120 std::string type_string
=
121 SandboxFileSystemBackendDelegate::GetTypeString(type
);
122 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
123 base::FilePath path
= file_util_
->GetDirectoryForOriginAndType(
124 origin
, type_string
, true /* create */, &error
);
125 ASSERT_EQ(base::File::FILE_OK
, error
);
127 ASSERT_TRUE(file_system_usage_cache_
.UpdateUsage(
128 GetUsageCachePath(origin
, type
), 0));
131 base::SequencedTaskRunner
* file_task_runner() {
132 return base::MessageLoopProxy::current().get();
135 base::FilePath
GetUsageCachePath(const GURL
& origin
,
136 storage::FileSystemType type
) {
138 base::File::Error error
=
139 backend_
->GetUsageCachePath(origin
, type
, &path
);
140 EXPECT_EQ(base::File::FILE_OK
, error
);
141 EXPECT_FALSE(path
.empty());
145 base::MessageLoop message_loop_
;
146 base::ScopedTempDir data_dir_
;
147 scoped_ptr
<leveldb::Env
> in_memory_env_
;
148 scoped_ptr
<ObfuscatedFileUtil
> file_util_
;
149 FileSystemUsageCache file_system_usage_cache_
;
150 scoped_refptr
<MockQuotaManagerProxy
> quota_manager_proxy_
;
151 scoped_ptr
<QuotaBackendImpl
> backend_
;
154 DISALLOW_COPY_AND_ASSIGN(QuotaBackendImplTest
);
157 TEST_F(QuotaBackendImplTest
, ReserveQuota_Basic
) {
158 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
159 InitializeForOriginAndType(GURL(kOrigin
), type
);
160 quota_manager_proxy_
->set_quota(10000);
164 const int64 kDelta1
= 1000;
165 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
166 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta1
,
167 base::Bind(&DidReserveQuota
, true, &error
, &delta
));
168 EXPECT_EQ(base::File::FILE_OK
, error
);
169 EXPECT_EQ(kDelta1
, delta
);
170 EXPECT_EQ(kDelta1
, quota_manager_proxy_
->usage());
172 const int64 kDelta2
= -300;
173 error
= base::File::FILE_ERROR_FAILED
;
174 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta2
,
175 base::Bind(&DidReserveQuota
, true, &error
, &delta
));
176 EXPECT_EQ(base::File::FILE_OK
, error
);
177 EXPECT_EQ(kDelta2
, delta
);
178 EXPECT_EQ(kDelta1
+ kDelta2
, quota_manager_proxy_
->usage());
180 EXPECT_EQ(2, quota_manager_proxy_
->storage_modified_count());
183 TEST_F(QuotaBackendImplTest
, ReserveQuota_NoSpace
) {
184 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
185 InitializeForOriginAndType(GURL(kOrigin
), type
);
186 quota_manager_proxy_
->set_quota(100);
190 const int64 kDelta
= 1000;
191 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
192 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta
,
193 base::Bind(&DidReserveQuota
, true, &error
, &delta
));
194 EXPECT_EQ(base::File::FILE_OK
, error
);
195 EXPECT_EQ(100, delta
);
196 EXPECT_EQ(100, quota_manager_proxy_
->usage());
198 EXPECT_EQ(1, quota_manager_proxy_
->storage_modified_count());
201 TEST_F(QuotaBackendImplTest
, ReserveQuota_Revert
) {
202 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
203 InitializeForOriginAndType(GURL(kOrigin
), type
);
204 quota_manager_proxy_
->set_quota(10000);
208 const int64 kDelta
= 1000;
209 base::File::Error error
= base::File::FILE_ERROR_FAILED
;
210 backend_
->ReserveQuota(GURL(kOrigin
), type
, kDelta
,
211 base::Bind(&DidReserveQuota
, false, &error
, &delta
));
212 EXPECT_EQ(base::File::FILE_OK
, error
);
213 EXPECT_EQ(kDelta
, delta
);
214 EXPECT_EQ(0, quota_manager_proxy_
->usage());
216 EXPECT_EQ(2, quota_manager_proxy_
->storage_modified_count());
219 TEST_F(QuotaBackendImplTest
, ReleaseReservedQuota
) {
220 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
221 InitializeForOriginAndType(GURL(kOrigin
), type
);
222 const int64 kInitialUsage
= 2000;
223 quota_manager_proxy_
->set_usage(kInitialUsage
);
224 quota_manager_proxy_
->set_quota(10000);
226 const int64 kSize
= 1000;
227 backend_
->ReleaseReservedQuota(GURL(kOrigin
), type
, kSize
);
228 EXPECT_EQ(kInitialUsage
- kSize
, quota_manager_proxy_
->usage());
230 EXPECT_EQ(1, quota_manager_proxy_
->storage_modified_count());
233 TEST_F(QuotaBackendImplTest
, CommitQuotaUsage
) {
234 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
235 InitializeForOriginAndType(GURL(kOrigin
), type
);
236 quota_manager_proxy_
->set_quota(10000);
237 base::FilePath path
= GetUsageCachePath(GURL(kOrigin
), type
);
239 const int64 kDelta1
= 1000;
240 backend_
->CommitQuotaUsage(GURL(kOrigin
), type
, kDelta1
);
241 EXPECT_EQ(kDelta1
, quota_manager_proxy_
->usage());
243 EXPECT_TRUE(file_system_usage_cache_
.GetUsage(path
, &usage
));
244 EXPECT_EQ(kDelta1
, usage
);
246 const int64 kDelta2
= -300;
247 backend_
->CommitQuotaUsage(GURL(kOrigin
), type
, kDelta2
);
248 EXPECT_EQ(kDelta1
+ kDelta2
, quota_manager_proxy_
->usage());
250 EXPECT_TRUE(file_system_usage_cache_
.GetUsage(path
, &usage
));
251 EXPECT_EQ(kDelta1
+ kDelta2
, usage
);
253 EXPECT_EQ(2, quota_manager_proxy_
->storage_modified_count());
256 TEST_F(QuotaBackendImplTest
, DirtyCount
) {
257 storage::FileSystemType type
= storage::kFileSystemTypeTemporary
;
258 InitializeForOriginAndType(GURL(kOrigin
), type
);
259 base::FilePath path
= GetUsageCachePath(GURL(kOrigin
), type
);
261 backend_
->IncrementDirtyCount(GURL(kOrigin
), type
);
263 ASSERT_TRUE(file_system_usage_cache_
.GetDirty(path
, &dirty
));
264 EXPECT_EQ(1u, dirty
);
266 backend_
->DecrementDirtyCount(GURL(kOrigin
), type
);
267 ASSERT_TRUE(file_system_usage_cache_
.GetDirty(path
, &dirty
));
268 EXPECT_EQ(0u, dirty
);
271 } // namespace content