Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / quota / quota_temporary_storage_evictor_unittest.cc
blob6c00c0f877f9d62843998364341918f1e045a4e1
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/message_loop/message_loop_proxy.h"
14 #include "base/run_loop.h"
15 #include "content/public/test/mock_storage_client.h"
16 #include "storage/browser/quota/quota_manager.h"
17 #include "storage/browser/quota/quota_temporary_storage_evictor.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using storage::QuotaTemporaryStorageEvictor;
21 using storage::StorageType;
22 using storage::UsageAndQuota;
24 namespace content {
26 class QuotaTemporaryStorageEvictorTest;
28 namespace {
30 class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler {
31 public:
32 explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest *test)
33 : quota_(0),
34 available_space_(0),
35 error_on_evict_origin_data_(false),
36 error_on_get_usage_and_quota_(false) {}
38 void EvictOriginData(const GURL& origin,
39 StorageType type,
40 const EvictOriginDataCallback& callback) override {
41 if (error_on_evict_origin_data_) {
42 callback.Run(storage::kQuotaErrorInvalidModification);
43 return;
45 int64 origin_usage = EnsureOriginRemoved(origin);
46 if (origin_usage >= 0)
47 available_space_ += origin_usage;
48 callback.Run(storage::kQuotaStatusOk);
51 void GetUsageAndQuotaForEviction(
52 const UsageAndQuotaCallback& callback) override {
53 if (error_on_get_usage_and_quota_) {
54 callback.Run(storage::kQuotaErrorInvalidAccess, UsageAndQuota());
55 return;
57 if (!task_for_get_usage_and_quota_.is_null())
58 task_for_get_usage_and_quota_.Run();
59 UsageAndQuota quota_and_usage(-1, GetUsage(), quota_, available_space_);
60 callback.Run(storage::kQuotaStatusOk, quota_and_usage);
63 void GetLRUOrigin(StorageType type,
64 const GetLRUOriginCallback& callback) override {
65 if (origin_order_.empty())
66 callback.Run(GURL());
67 else
68 callback.Run(GURL(origin_order_.front()));
71 int64 GetUsage() const {
72 int64 total_usage = 0;
73 for (std::map<GURL, int64>::const_iterator p = origins_.begin();
74 p != origins_.end();
75 ++p)
76 total_usage += p->second;
77 return total_usage;
80 void set_quota(int64 quota) {
81 quota_ = quota;
83 void set_available_space(int64 available_space) {
84 available_space_ = available_space;
86 void set_task_for_get_usage_and_quota(const base::Closure& task) {
87 task_for_get_usage_and_quota_= task;
89 void set_error_on_evict_origin_data(bool error_on_evict_origin_data) {
90 error_on_evict_origin_data_ = error_on_evict_origin_data;
92 void set_error_on_get_usage_and_quota(bool error_on_get_usage_and_quota) {
93 error_on_get_usage_and_quota_ = error_on_get_usage_and_quota;
96 // Simulates an access to |origin|. It reorders the internal LRU list.
97 // It internally uses AddOrigin().
98 void AccessOrigin(const GURL& origin) {
99 std::map<GURL, int64>::iterator found = origins_.find(origin);
100 EXPECT_TRUE(origins_.end() != found);
101 AddOrigin(origin, found->second);
104 // Simulates adding or overwriting the |origin| to the internal origin set
105 // with the |usage|. It also adds or moves the |origin| to the end of the
106 // LRU list.
107 void AddOrigin(const GURL& origin, int64 usage) {
108 EnsureOriginRemoved(origin);
109 origin_order_.push_back(origin);
110 origins_[origin] = usage;
113 private:
114 int64 EnsureOriginRemoved(const GURL& origin) {
115 int64 origin_usage;
116 if (origins_.find(origin) == origins_.end())
117 return -1;
118 else
119 origin_usage = origins_[origin];
121 origins_.erase(origin);
122 origin_order_.remove(origin);
123 return origin_usage;
126 int64 quota_;
127 int64 available_space_;
128 std::list<GURL> origin_order_;
129 std::map<GURL, int64> origins_;
130 bool error_on_evict_origin_data_;
131 bool error_on_get_usage_and_quota_;
133 base::Closure task_for_get_usage_and_quota_;
136 } // namespace
138 class QuotaTemporaryStorageEvictorTest : public testing::Test {
139 public:
140 QuotaTemporaryStorageEvictorTest()
141 : num_get_usage_and_quota_for_eviction_(0),
142 weak_factory_(this) {}
144 void SetUp() override {
145 quota_eviction_handler_.reset(new MockQuotaEvictionHandler(this));
147 // Run multiple evictions in a single RunUntilIdle() when interval_ms == 0
148 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
149 quota_eviction_handler_.get(), 0));
152 void TearDown() override {
153 temporary_storage_evictor_.reset();
154 quota_eviction_handler_.reset();
155 base::RunLoop().RunUntilIdle();
158 void TaskForRepeatedEvictionTest(
159 const std::pair<GURL, int64>& origin_to_be_added,
160 const GURL& origin_to_be_accessed,
161 int expected_usage_after_first,
162 int expected_usage_after_second) {
163 EXPECT_GE(4, num_get_usage_and_quota_for_eviction_);
164 switch (num_get_usage_and_quota_for_eviction_) {
165 case 2:
166 EXPECT_EQ(expected_usage_after_first,
167 quota_eviction_handler()->GetUsage());
168 if (!origin_to_be_added.first.is_empty())
169 quota_eviction_handler()->AddOrigin(origin_to_be_added.first,
170 origin_to_be_added.second);
171 if (!origin_to_be_accessed.is_empty())
172 quota_eviction_handler()->AccessOrigin(origin_to_be_accessed);
173 break;
174 case 3:
175 EXPECT_EQ(expected_usage_after_second,
176 quota_eviction_handler()->GetUsage());
177 temporary_storage_evictor()->set_repeated_eviction(false);
178 break;
180 ++num_get_usage_and_quota_for_eviction_;
183 protected:
184 MockQuotaEvictionHandler* quota_eviction_handler() const {
185 return static_cast<MockQuotaEvictionHandler*>(
186 quota_eviction_handler_.get());
189 QuotaTemporaryStorageEvictor* temporary_storage_evictor() const {
190 return temporary_storage_evictor_.get();
193 const QuotaTemporaryStorageEvictor::Statistics& statistics() const {
194 return temporary_storage_evictor()->statistics_;
197 void set_repeated_eviction(bool repeated_eviction) const {
198 return temporary_storage_evictor_->set_repeated_eviction(repeated_eviction);
201 int num_get_usage_and_quota_for_eviction() const {
202 return num_get_usage_and_quota_for_eviction_;
205 int64 default_min_available_disk_space_to_start_eviction() const {
206 return 1000 * 1000 * 500;
209 void set_min_available_disk_space_to_start_eviction(int64 value) const {
210 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
211 value);
214 void reset_min_available_disk_space_to_start_eviction() const {
215 temporary_storage_evictor_->
216 reset_min_available_disk_space_to_start_eviction();
219 base::MessageLoop message_loop_;
220 scoped_ptr<MockQuotaEvictionHandler> quota_eviction_handler_;
221 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
223 int num_get_usage_and_quota_for_eviction_;
225 base::WeakPtrFactory<QuotaTemporaryStorageEvictorTest> weak_factory_;
227 DISALLOW_COPY_AND_ASSIGN(QuotaTemporaryStorageEvictorTest);
230 TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) {
231 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 3000);
232 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 200);
233 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 500);
234 quota_eviction_handler()->set_quota(4000);
235 quota_eviction_handler()->set_available_space(1000000000);
236 EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage());
237 set_repeated_eviction(false);
238 temporary_storage_evictor()->Start();
239 base::RunLoop().RunUntilIdle();
240 EXPECT_EQ(200 + 500, quota_eviction_handler()->GetUsage());
242 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
243 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
244 EXPECT_EQ(1, statistics().num_evicted_origins);
245 EXPECT_EQ(1, statistics().num_eviction_rounds);
246 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
249 TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) {
250 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 20);
251 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 2900);
252 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450);
253 quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 400);
254 quota_eviction_handler()->set_quota(4000);
255 quota_eviction_handler()->set_available_space(1000000000);
256 EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage());
257 set_repeated_eviction(false);
258 temporary_storage_evictor()->Start();
259 base::RunLoop().RunUntilIdle();
260 EXPECT_EQ(450 + 400, quota_eviction_handler()->GetUsage());
262 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
263 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
264 EXPECT_EQ(2, statistics().num_evicted_origins);
265 EXPECT_EQ(1, statistics().num_eviction_rounds);
266 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
269 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionTest) {
270 const int64 a_size = 400;
271 const int64 b_size = 150;
272 const int64 c_size = 120;
273 const int64 d_size = 292;
274 const int64 initial_total_size = a_size + b_size + c_size + d_size;
275 const int64 e_size = 275;
277 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
278 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
279 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
280 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
281 quota_eviction_handler()->set_quota(1000);
282 quota_eviction_handler()->set_available_space(1000000000);
283 quota_eviction_handler()->set_task_for_get_usage_and_quota(
284 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
285 weak_factory_.GetWeakPtr(),
286 std::make_pair(GURL("http://www.e.com"), e_size), GURL(),
287 initial_total_size - d_size,
288 initial_total_size - d_size + e_size - c_size));
289 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
290 temporary_storage_evictor()->Start();
291 base::RunLoop().RunUntilIdle();
292 EXPECT_EQ(initial_total_size - d_size + e_size - c_size - b_size,
293 quota_eviction_handler()->GetUsage());
294 EXPECT_EQ(5, num_get_usage_and_quota_for_eviction());
296 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
297 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
298 EXPECT_EQ(3, statistics().num_evicted_origins);
299 EXPECT_EQ(2, statistics().num_eviction_rounds);
300 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
303 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionSkippedTest) {
304 const int64 a_size = 400;
305 const int64 b_size = 150;
306 const int64 c_size = 120;
307 const int64 d_size = 292;
308 const int64 initial_total_size = a_size + b_size + c_size + d_size;
310 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
311 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
312 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
313 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
314 quota_eviction_handler()->set_quota(1000);
315 quota_eviction_handler()->set_available_space(1000000000);
316 quota_eviction_handler()->set_task_for_get_usage_and_quota(
317 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
318 weak_factory_.GetWeakPtr(), std::make_pair(GURL(), 0), GURL(),
319 initial_total_size - d_size, initial_total_size - d_size));
320 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
321 set_repeated_eviction(true);
322 temporary_storage_evictor()->Start();
323 base::RunLoop().RunUntilIdle();
324 EXPECT_EQ(initial_total_size - d_size, quota_eviction_handler()->GetUsage());
325 EXPECT_EQ(4, num_get_usage_and_quota_for_eviction());
327 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
328 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
329 EXPECT_EQ(1, statistics().num_evicted_origins);
330 EXPECT_EQ(3, statistics().num_eviction_rounds);
331 EXPECT_EQ(2, statistics().num_skipped_eviction_rounds);
334 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) {
335 const int64 a_size = 400;
336 const int64 b_size = 150;
337 const int64 c_size = 120;
338 const int64 d_size = 292;
339 const int64 initial_total_size = a_size + b_size + c_size + d_size;
340 const int64 e_size = 275;
342 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
343 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
344 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
345 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
346 quota_eviction_handler()->set_quota(1000);
347 quota_eviction_handler()->set_available_space(1000000000);
348 quota_eviction_handler()->set_task_for_get_usage_and_quota(
349 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
350 weak_factory_.GetWeakPtr(),
351 std::make_pair(GURL("http://www.e.com"), e_size),
352 GURL("http://www.c.com"),
353 initial_total_size - d_size,
354 initial_total_size - d_size + e_size - b_size));
355 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
356 temporary_storage_evictor()->Start();
357 base::RunLoop().RunUntilIdle();
358 EXPECT_EQ(initial_total_size - d_size + e_size - b_size - a_size,
359 quota_eviction_handler()->GetUsage());
360 EXPECT_EQ(5, num_get_usage_and_quota_for_eviction());
362 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
363 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
364 EXPECT_EQ(3, statistics().num_evicted_origins);
365 EXPECT_EQ(2, statistics().num_eviction_rounds);
366 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
369 TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) {
370 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 414);
371 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450);
372 quota_eviction_handler()->set_quota(10000);
373 quota_eviction_handler()->set_available_space(
374 default_min_available_disk_space_to_start_eviction() - 350);
375 EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage());
376 reset_min_available_disk_space_to_start_eviction();
377 set_repeated_eviction(false);
378 temporary_storage_evictor()->Start();
379 base::RunLoop().RunUntilIdle();
380 EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage());
382 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
383 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
384 EXPECT_EQ(0, statistics().num_evicted_origins);
385 EXPECT_EQ(1, statistics().num_eviction_rounds);
386 EXPECT_EQ(1, statistics().num_skipped_eviction_rounds);
389 TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) {
390 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 294);
391 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 120);
392 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 150);
393 quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 300);
394 quota_eviction_handler()->set_quota(10000);
395 quota_eviction_handler()->set_available_space(
396 default_min_available_disk_space_to_start_eviction() - 350);
397 EXPECT_EQ(294 + 120 + 150 + 300, quota_eviction_handler()->GetUsage());
398 set_min_available_disk_space_to_start_eviction(
399 default_min_available_disk_space_to_start_eviction());
400 set_repeated_eviction(false);
401 temporary_storage_evictor()->Start();
402 base::RunLoop().RunUntilIdle();
403 EXPECT_EQ(150 + 300, quota_eviction_handler()->GetUsage());
405 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
406 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
407 EXPECT_EQ(2, statistics().num_evicted_origins);
408 EXPECT_EQ(1, statistics().num_eviction_rounds);
409 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
412 } // namespace content