Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / quota / quota_temporary_storage_evictor_unittest.cc
blob2d63362ceffd180954667e7a860b77d71205f8c5
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 <list>
6 #include <map>
7 #include <utility>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/run_loop.h"
14 #include "content/public/test/mock_storage_client.h"
15 #include "storage/browser/quota/quota_manager.h"
16 #include "storage/browser/quota/quota_temporary_storage_evictor.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using storage::QuotaTemporaryStorageEvictor;
20 using storage::StorageType;
21 using storage::UsageAndQuota;
23 namespace content {
25 class QuotaTemporaryStorageEvictorTest;
27 namespace {
29 class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler {
30 public:
31 explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest *test)
32 : quota_(0),
33 available_space_(0),
34 error_on_evict_origin_data_(false),
35 error_on_get_usage_and_quota_(false) {}
37 void EvictOriginData(const GURL& origin,
38 StorageType type,
39 const EvictOriginDataCallback& callback) override {
40 if (error_on_evict_origin_data_) {
41 callback.Run(storage::kQuotaErrorInvalidModification);
42 return;
44 int64 origin_usage = EnsureOriginRemoved(origin);
45 if (origin_usage >= 0)
46 available_space_ += origin_usage;
47 callback.Run(storage::kQuotaStatusOk);
50 void GetUsageAndQuotaForEviction(
51 const UsageAndQuotaCallback& callback) override {
52 if (error_on_get_usage_and_quota_) {
53 callback.Run(storage::kQuotaErrorInvalidAccess, UsageAndQuota());
54 return;
56 if (!task_for_get_usage_and_quota_.is_null())
57 task_for_get_usage_and_quota_.Run();
58 UsageAndQuota quota_and_usage(-1, GetUsage(), quota_, available_space_);
59 callback.Run(storage::kQuotaStatusOk, quota_and_usage);
62 void GetEvictionOrigin(StorageType type,
63 const storage::GetOriginCallback& callback) override {
64 if (origin_order_.empty())
65 callback.Run(GURL());
66 else
67 callback.Run(GURL(origin_order_.front()));
70 int64 GetUsage() const {
71 int64 total_usage = 0;
72 for (std::map<GURL, int64>::const_iterator p = origins_.begin();
73 p != origins_.end();
74 ++p)
75 total_usage += p->second;
76 return total_usage;
79 void set_quota(int64 quota) {
80 quota_ = quota;
82 void set_available_space(int64 available_space) {
83 available_space_ = available_space;
85 void set_task_for_get_usage_and_quota(const base::Closure& task) {
86 task_for_get_usage_and_quota_= task;
88 void set_error_on_evict_origin_data(bool error_on_evict_origin_data) {
89 error_on_evict_origin_data_ = error_on_evict_origin_data;
91 void set_error_on_get_usage_and_quota(bool error_on_get_usage_and_quota) {
92 error_on_get_usage_and_quota_ = error_on_get_usage_and_quota;
95 // Simulates an access to |origin|. It reorders the internal LRU list.
96 // It internally uses AddOrigin().
97 void AccessOrigin(const GURL& origin) {
98 std::map<GURL, int64>::iterator found = origins_.find(origin);
99 EXPECT_TRUE(origins_.end() != found);
100 AddOrigin(origin, found->second);
103 // Simulates adding or overwriting the |origin| to the internal origin set
104 // with the |usage|. It also adds or moves the |origin| to the end of the
105 // LRU list.
106 void AddOrigin(const GURL& origin, int64 usage) {
107 EnsureOriginRemoved(origin);
108 origin_order_.push_back(origin);
109 origins_[origin] = usage;
112 private:
113 int64 EnsureOriginRemoved(const GURL& origin) {
114 int64 origin_usage;
115 if (origins_.find(origin) == origins_.end())
116 return -1;
117 else
118 origin_usage = origins_[origin];
120 origins_.erase(origin);
121 origin_order_.remove(origin);
122 return origin_usage;
125 int64 quota_;
126 int64 available_space_;
127 std::list<GURL> origin_order_;
128 std::map<GURL, int64> origins_;
129 bool error_on_evict_origin_data_;
130 bool error_on_get_usage_and_quota_;
132 base::Closure task_for_get_usage_and_quota_;
135 } // namespace
137 class QuotaTemporaryStorageEvictorTest : public testing::Test {
138 public:
139 QuotaTemporaryStorageEvictorTest()
140 : num_get_usage_and_quota_for_eviction_(0),
141 weak_factory_(this) {}
143 void SetUp() override {
144 quota_eviction_handler_.reset(new MockQuotaEvictionHandler(this));
146 // Run multiple evictions in a single RunUntilIdle() when interval_ms == 0
147 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
148 quota_eviction_handler_.get(), 0));
151 void TearDown() override {
152 temporary_storage_evictor_.reset();
153 quota_eviction_handler_.reset();
154 base::RunLoop().RunUntilIdle();
157 void TaskForRepeatedEvictionTest(
158 const std::pair<GURL, int64>& origin_to_be_added,
159 const GURL& origin_to_be_accessed,
160 int expected_usage_after_first,
161 int expected_usage_after_second) {
162 EXPECT_GE(4, num_get_usage_and_quota_for_eviction_);
163 switch (num_get_usage_and_quota_for_eviction_) {
164 case 2:
165 EXPECT_EQ(expected_usage_after_first,
166 quota_eviction_handler()->GetUsage());
167 if (!origin_to_be_added.first.is_empty())
168 quota_eviction_handler()->AddOrigin(origin_to_be_added.first,
169 origin_to_be_added.second);
170 if (!origin_to_be_accessed.is_empty())
171 quota_eviction_handler()->AccessOrigin(origin_to_be_accessed);
172 break;
173 case 3:
174 EXPECT_EQ(expected_usage_after_second,
175 quota_eviction_handler()->GetUsage());
176 temporary_storage_evictor()->set_repeated_eviction(false);
177 break;
179 ++num_get_usage_and_quota_for_eviction_;
182 protected:
183 MockQuotaEvictionHandler* quota_eviction_handler() const {
184 return static_cast<MockQuotaEvictionHandler*>(
185 quota_eviction_handler_.get());
188 QuotaTemporaryStorageEvictor* temporary_storage_evictor() const {
189 return temporary_storage_evictor_.get();
192 const QuotaTemporaryStorageEvictor::Statistics& statistics() const {
193 return temporary_storage_evictor()->statistics_;
196 void set_repeated_eviction(bool repeated_eviction) const {
197 return temporary_storage_evictor_->set_repeated_eviction(repeated_eviction);
200 int num_get_usage_and_quota_for_eviction() const {
201 return num_get_usage_and_quota_for_eviction_;
204 int64 default_min_available_disk_space_to_start_eviction() const {
205 return 1000 * 1000 * 500;
208 void set_min_available_disk_space_to_start_eviction(int64 value) const {
209 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
210 value);
213 void reset_min_available_disk_space_to_start_eviction() const {
214 temporary_storage_evictor_->
215 reset_min_available_disk_space_to_start_eviction();
218 base::MessageLoop message_loop_;
219 scoped_ptr<MockQuotaEvictionHandler> quota_eviction_handler_;
220 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
222 int num_get_usage_and_quota_for_eviction_;
224 base::WeakPtrFactory<QuotaTemporaryStorageEvictorTest> weak_factory_;
226 DISALLOW_COPY_AND_ASSIGN(QuotaTemporaryStorageEvictorTest);
229 TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) {
230 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 3000);
231 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 200);
232 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 500);
233 quota_eviction_handler()->set_quota(4000);
234 quota_eviction_handler()->set_available_space(1000000000);
235 EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage());
236 set_repeated_eviction(false);
237 temporary_storage_evictor()->Start();
238 base::RunLoop().RunUntilIdle();
239 EXPECT_EQ(200 + 500, quota_eviction_handler()->GetUsage());
241 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
242 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
243 EXPECT_EQ(1, statistics().num_evicted_origins);
244 EXPECT_EQ(1, statistics().num_eviction_rounds);
245 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
248 TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) {
249 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 20);
250 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 2900);
251 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450);
252 quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 400);
253 quota_eviction_handler()->set_quota(4000);
254 quota_eviction_handler()->set_available_space(1000000000);
255 EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage());
256 set_repeated_eviction(false);
257 temporary_storage_evictor()->Start();
258 base::RunLoop().RunUntilIdle();
259 EXPECT_EQ(450 + 400, quota_eviction_handler()->GetUsage());
261 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
262 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
263 EXPECT_EQ(2, statistics().num_evicted_origins);
264 EXPECT_EQ(1, statistics().num_eviction_rounds);
265 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
268 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionTest) {
269 const int64 a_size = 400;
270 const int64 b_size = 150;
271 const int64 c_size = 120;
272 const int64 d_size = 292;
273 const int64 initial_total_size = a_size + b_size + c_size + d_size;
274 const int64 e_size = 275;
276 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
277 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
278 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
279 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
280 quota_eviction_handler()->set_quota(1000);
281 quota_eviction_handler()->set_available_space(1000000000);
282 quota_eviction_handler()->set_task_for_get_usage_and_quota(
283 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
284 weak_factory_.GetWeakPtr(),
285 std::make_pair(GURL("http://www.e.com"), e_size), GURL(),
286 initial_total_size - d_size,
287 initial_total_size - d_size + e_size - c_size));
288 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
289 temporary_storage_evictor()->Start();
290 base::RunLoop().RunUntilIdle();
291 EXPECT_EQ(initial_total_size - d_size + e_size - c_size - b_size,
292 quota_eviction_handler()->GetUsage());
293 EXPECT_EQ(5, num_get_usage_and_quota_for_eviction());
295 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
296 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
297 EXPECT_EQ(3, statistics().num_evicted_origins);
298 EXPECT_EQ(2, statistics().num_eviction_rounds);
299 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
302 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionSkippedTest) {
303 const int64 a_size = 400;
304 const int64 b_size = 150;
305 const int64 c_size = 120;
306 const int64 d_size = 292;
307 const int64 initial_total_size = a_size + b_size + c_size + d_size;
309 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
310 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
311 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
312 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
313 quota_eviction_handler()->set_quota(1000);
314 quota_eviction_handler()->set_available_space(1000000000);
315 quota_eviction_handler()->set_task_for_get_usage_and_quota(
316 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
317 weak_factory_.GetWeakPtr(), std::make_pair(GURL(), 0), GURL(),
318 initial_total_size - d_size, initial_total_size - d_size));
319 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
320 set_repeated_eviction(true);
321 temporary_storage_evictor()->Start();
322 base::RunLoop().RunUntilIdle();
323 EXPECT_EQ(initial_total_size - d_size, quota_eviction_handler()->GetUsage());
324 EXPECT_EQ(4, num_get_usage_and_quota_for_eviction());
326 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
327 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
328 EXPECT_EQ(1, statistics().num_evicted_origins);
329 EXPECT_EQ(3, statistics().num_eviction_rounds);
330 EXPECT_EQ(2, statistics().num_skipped_eviction_rounds);
333 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) {
334 const int64 a_size = 400;
335 const int64 b_size = 150;
336 const int64 c_size = 120;
337 const int64 d_size = 292;
338 const int64 initial_total_size = a_size + b_size + c_size + d_size;
339 const int64 e_size = 275;
341 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
342 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
343 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
344 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
345 quota_eviction_handler()->set_quota(1000);
346 quota_eviction_handler()->set_available_space(1000000000);
347 quota_eviction_handler()->set_task_for_get_usage_and_quota(
348 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
349 weak_factory_.GetWeakPtr(),
350 std::make_pair(GURL("http://www.e.com"), e_size),
351 GURL("http://www.c.com"),
352 initial_total_size - d_size,
353 initial_total_size - d_size + e_size - b_size));
354 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
355 temporary_storage_evictor()->Start();
356 base::RunLoop().RunUntilIdle();
357 EXPECT_EQ(initial_total_size - d_size + e_size - b_size - a_size,
358 quota_eviction_handler()->GetUsage());
359 EXPECT_EQ(5, num_get_usage_and_quota_for_eviction());
361 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
362 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
363 EXPECT_EQ(3, statistics().num_evicted_origins);
364 EXPECT_EQ(2, statistics().num_eviction_rounds);
365 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
368 TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) {
369 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 414);
370 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450);
371 quota_eviction_handler()->set_quota(10000);
372 quota_eviction_handler()->set_available_space(
373 default_min_available_disk_space_to_start_eviction() - 350);
374 EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage());
375 reset_min_available_disk_space_to_start_eviction();
376 set_repeated_eviction(false);
377 temporary_storage_evictor()->Start();
378 base::RunLoop().RunUntilIdle();
379 EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage());
381 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
382 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
383 EXPECT_EQ(0, statistics().num_evicted_origins);
384 EXPECT_EQ(1, statistics().num_eviction_rounds);
385 EXPECT_EQ(1, statistics().num_skipped_eviction_rounds);
388 TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) {
389 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 294);
390 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 120);
391 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 150);
392 quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 300);
393 quota_eviction_handler()->set_quota(10000);
394 quota_eviction_handler()->set_available_space(
395 default_min_available_disk_space_to_start_eviction() - 350);
396 EXPECT_EQ(294 + 120 + 150 + 300, quota_eviction_handler()->GetUsage());
397 set_min_available_disk_space_to_start_eviction(
398 default_min_available_disk_space_to_start_eviction());
399 set_repeated_eviction(false);
400 temporary_storage_evictor()->Start();
401 base::RunLoop().RunUntilIdle();
402 EXPECT_EQ(150 + 300, quota_eviction_handler()->GetUsage());
404 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
405 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
406 EXPECT_EQ(2, statistics().num_evicted_origins);
407 EXPECT_EQ(1, statistics().num_eviction_rounds);
408 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
411 } // namespace content