Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / quota / quota_temporary_storage_evictor_unittest.cc
blob0a67300263a6aff1b64303e2290ed346b969edff
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 "testing/gtest/include/gtest/gtest.h"
17 #include "webkit/browser/quota/quota_manager.h"
18 #include "webkit/browser/quota/quota_temporary_storage_evictor.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 virtual void EvictOriginData(
39 const GURL& origin,
40 StorageType type,
41 const EvictOriginDataCallback& callback) OVERRIDE {
42 if (error_on_evict_origin_data_) {
43 callback.Run(storage::kQuotaErrorInvalidModification);
44 return;
46 int64 origin_usage = EnsureOriginRemoved(origin);
47 if (origin_usage >= 0)
48 available_space_ += origin_usage;
49 callback.Run(storage::kQuotaStatusOk);
52 virtual void GetUsageAndQuotaForEviction(
53 const UsageAndQuotaCallback& callback) OVERRIDE {
54 if (error_on_get_usage_and_quota_) {
55 callback.Run(storage::kQuotaErrorInvalidAccess, UsageAndQuota());
56 return;
58 if (!task_for_get_usage_and_quota_.is_null())
59 task_for_get_usage_and_quota_.Run();
60 UsageAndQuota quota_and_usage(-1, GetUsage(), quota_, available_space_);
61 callback.Run(storage::kQuotaStatusOk, quota_and_usage);
64 virtual void GetLRUOrigin(
65 StorageType type,
66 const GetLRUOriginCallback& callback) OVERRIDE {
67 if (origin_order_.empty())
68 callback.Run(GURL());
69 else
70 callback.Run(GURL(origin_order_.front()));
73 int64 GetUsage() const {
74 int64 total_usage = 0;
75 for (std::map<GURL, int64>::const_iterator p = origins_.begin();
76 p != origins_.end();
77 ++p)
78 total_usage += p->second;
79 return total_usage;
82 void set_quota(int64 quota) {
83 quota_ = quota;
85 void set_available_space(int64 available_space) {
86 available_space_ = available_space;
88 void set_task_for_get_usage_and_quota(const base::Closure& task) {
89 task_for_get_usage_and_quota_= task;
91 void set_error_on_evict_origin_data(bool error_on_evict_origin_data) {
92 error_on_evict_origin_data_ = error_on_evict_origin_data;
94 void set_error_on_get_usage_and_quota(bool error_on_get_usage_and_quota) {
95 error_on_get_usage_and_quota_ = error_on_get_usage_and_quota;
98 // Simulates an access to |origin|. It reorders the internal LRU list.
99 // It internally uses AddOrigin().
100 void AccessOrigin(const GURL& origin) {
101 std::map<GURL, int64>::iterator found = origins_.find(origin);
102 EXPECT_TRUE(origins_.end() != found);
103 AddOrigin(origin, found->second);
106 // Simulates adding or overwriting the |origin| to the internal origin set
107 // with the |usage|. It also adds or moves the |origin| to the end of the
108 // LRU list.
109 void AddOrigin(const GURL& origin, int64 usage) {
110 EnsureOriginRemoved(origin);
111 origin_order_.push_back(origin);
112 origins_[origin] = usage;
115 private:
116 int64 EnsureOriginRemoved(const GURL& origin) {
117 int64 origin_usage;
118 if (origins_.find(origin) == origins_.end())
119 return -1;
120 else
121 origin_usage = origins_[origin];
123 origins_.erase(origin);
124 origin_order_.remove(origin);
125 return origin_usage;
128 int64 quota_;
129 int64 available_space_;
130 std::list<GURL> origin_order_;
131 std::map<GURL, int64> origins_;
132 bool error_on_evict_origin_data_;
133 bool error_on_get_usage_and_quota_;
135 base::Closure task_for_get_usage_and_quota_;
138 } // namespace
140 class QuotaTemporaryStorageEvictorTest : public testing::Test {
141 public:
142 QuotaTemporaryStorageEvictorTest()
143 : num_get_usage_and_quota_for_eviction_(0),
144 weak_factory_(this) {}
146 virtual void SetUp() {
147 quota_eviction_handler_.reset(new MockQuotaEvictionHandler(this));
149 // Run multiple evictions in a single RunUntilIdle() when interval_ms == 0
150 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
151 quota_eviction_handler_.get(), 0));
154 virtual void TearDown() {
155 temporary_storage_evictor_.reset();
156 quota_eviction_handler_.reset();
157 base::RunLoop().RunUntilIdle();
160 void TaskForRepeatedEvictionTest(
161 const std::pair<GURL, int64>& origin_to_be_added,
162 const GURL& origin_to_be_accessed,
163 int expected_usage_after_first,
164 int expected_usage_after_second) {
165 EXPECT_GE(4, num_get_usage_and_quota_for_eviction_);
166 switch (num_get_usage_and_quota_for_eviction_) {
167 case 2:
168 EXPECT_EQ(expected_usage_after_first,
169 quota_eviction_handler()->GetUsage());
170 if (!origin_to_be_added.first.is_empty())
171 quota_eviction_handler()->AddOrigin(origin_to_be_added.first,
172 origin_to_be_added.second);
173 if (!origin_to_be_accessed.is_empty())
174 quota_eviction_handler()->AccessOrigin(origin_to_be_accessed);
175 break;
176 case 3:
177 EXPECT_EQ(expected_usage_after_second,
178 quota_eviction_handler()->GetUsage());
179 temporary_storage_evictor()->set_repeated_eviction(false);
180 break;
182 ++num_get_usage_and_quota_for_eviction_;
185 protected:
186 MockQuotaEvictionHandler* quota_eviction_handler() const {
187 return static_cast<MockQuotaEvictionHandler*>(
188 quota_eviction_handler_.get());
191 QuotaTemporaryStorageEvictor* temporary_storage_evictor() const {
192 return temporary_storage_evictor_.get();
195 const QuotaTemporaryStorageEvictor::Statistics& statistics() const {
196 return temporary_storage_evictor()->statistics_;
199 void set_repeated_eviction(bool repeated_eviction) const {
200 return temporary_storage_evictor_->set_repeated_eviction(repeated_eviction);
203 int num_get_usage_and_quota_for_eviction() const {
204 return num_get_usage_and_quota_for_eviction_;
207 int64 default_min_available_disk_space_to_start_eviction() const {
208 return 1000 * 1000 * 500;
211 void set_min_available_disk_space_to_start_eviction(int64 value) const {
212 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
213 value);
216 void reset_min_available_disk_space_to_start_eviction() const {
217 temporary_storage_evictor_->
218 reset_min_available_disk_space_to_start_eviction();
221 base::MessageLoop message_loop_;
222 scoped_ptr<MockQuotaEvictionHandler> quota_eviction_handler_;
223 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
225 int num_get_usage_and_quota_for_eviction_;
227 base::WeakPtrFactory<QuotaTemporaryStorageEvictorTest> weak_factory_;
229 DISALLOW_COPY_AND_ASSIGN(QuotaTemporaryStorageEvictorTest);
232 TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) {
233 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 3000);
234 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 200);
235 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 500);
236 quota_eviction_handler()->set_quota(4000);
237 quota_eviction_handler()->set_available_space(1000000000);
238 EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage());
239 set_repeated_eviction(false);
240 temporary_storage_evictor()->Start();
241 base::RunLoop().RunUntilIdle();
242 EXPECT_EQ(200 + 500, quota_eviction_handler()->GetUsage());
244 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
245 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
246 EXPECT_EQ(1, statistics().num_evicted_origins);
247 EXPECT_EQ(1, statistics().num_eviction_rounds);
248 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
251 TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) {
252 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 20);
253 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 2900);
254 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450);
255 quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 400);
256 quota_eviction_handler()->set_quota(4000);
257 quota_eviction_handler()->set_available_space(1000000000);
258 EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage());
259 set_repeated_eviction(false);
260 temporary_storage_evictor()->Start();
261 base::RunLoop().RunUntilIdle();
262 EXPECT_EQ(450 + 400, quota_eviction_handler()->GetUsage());
264 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
265 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
266 EXPECT_EQ(2, statistics().num_evicted_origins);
267 EXPECT_EQ(1, statistics().num_eviction_rounds);
268 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
271 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionTest) {
272 const int64 a_size = 400;
273 const int64 b_size = 150;
274 const int64 c_size = 120;
275 const int64 d_size = 292;
276 const int64 initial_total_size = a_size + b_size + c_size + d_size;
277 const int64 e_size = 275;
279 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
280 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
281 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
282 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
283 quota_eviction_handler()->set_quota(1000);
284 quota_eviction_handler()->set_available_space(1000000000);
285 quota_eviction_handler()->set_task_for_get_usage_and_quota(
286 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
287 weak_factory_.GetWeakPtr(),
288 std::make_pair(GURL("http://www.e.com"), e_size), GURL(),
289 initial_total_size - d_size,
290 initial_total_size - d_size + e_size - c_size));
291 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
292 temporary_storage_evictor()->Start();
293 base::RunLoop().RunUntilIdle();
294 EXPECT_EQ(initial_total_size - d_size + e_size - c_size - b_size,
295 quota_eviction_handler()->GetUsage());
296 EXPECT_EQ(5, num_get_usage_and_quota_for_eviction());
298 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
299 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
300 EXPECT_EQ(3, statistics().num_evicted_origins);
301 EXPECT_EQ(2, statistics().num_eviction_rounds);
302 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
305 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionSkippedTest) {
306 const int64 a_size = 400;
307 const int64 b_size = 150;
308 const int64 c_size = 120;
309 const int64 d_size = 292;
310 const int64 initial_total_size = a_size + b_size + c_size + d_size;
312 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
313 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
314 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
315 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
316 quota_eviction_handler()->set_quota(1000);
317 quota_eviction_handler()->set_available_space(1000000000);
318 quota_eviction_handler()->set_task_for_get_usage_and_quota(
319 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
320 weak_factory_.GetWeakPtr(), std::make_pair(GURL(), 0), GURL(),
321 initial_total_size - d_size, initial_total_size - d_size));
322 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
323 set_repeated_eviction(true);
324 temporary_storage_evictor()->Start();
325 base::RunLoop().RunUntilIdle();
326 EXPECT_EQ(initial_total_size - d_size, quota_eviction_handler()->GetUsage());
327 EXPECT_EQ(4, num_get_usage_and_quota_for_eviction());
329 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
330 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
331 EXPECT_EQ(1, statistics().num_evicted_origins);
332 EXPECT_EQ(3, statistics().num_eviction_rounds);
333 EXPECT_EQ(2, statistics().num_skipped_eviction_rounds);
336 TEST_F(QuotaTemporaryStorageEvictorTest, RepeatedEvictionWithAccessOriginTest) {
337 const int64 a_size = 400;
338 const int64 b_size = 150;
339 const int64 c_size = 120;
340 const int64 d_size = 292;
341 const int64 initial_total_size = a_size + b_size + c_size + d_size;
342 const int64 e_size = 275;
344 quota_eviction_handler()->AddOrigin(GURL("http://www.d.com"), d_size);
345 quota_eviction_handler()->AddOrigin(GURL("http://www.c.com"), c_size);
346 quota_eviction_handler()->AddOrigin(GURL("http://www.b.com"), b_size);
347 quota_eviction_handler()->AddOrigin(GURL("http://www.a.com"), a_size);
348 quota_eviction_handler()->set_quota(1000);
349 quota_eviction_handler()->set_available_space(1000000000);
350 quota_eviction_handler()->set_task_for_get_usage_and_quota(
351 base::Bind(&QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest,
352 weak_factory_.GetWeakPtr(),
353 std::make_pair(GURL("http://www.e.com"), e_size),
354 GURL("http://www.c.com"),
355 initial_total_size - d_size,
356 initial_total_size - d_size + e_size - b_size));
357 EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage());
358 temporary_storage_evictor()->Start();
359 base::RunLoop().RunUntilIdle();
360 EXPECT_EQ(initial_total_size - d_size + e_size - b_size - a_size,
361 quota_eviction_handler()->GetUsage());
362 EXPECT_EQ(5, num_get_usage_and_quota_for_eviction());
364 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
365 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
366 EXPECT_EQ(3, statistics().num_evicted_origins);
367 EXPECT_EQ(2, statistics().num_eviction_rounds);
368 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
371 TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceNonEvictionTest) {
372 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 414);
373 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 450);
374 quota_eviction_handler()->set_quota(10000);
375 quota_eviction_handler()->set_available_space(
376 default_min_available_disk_space_to_start_eviction() - 350);
377 EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage());
378 reset_min_available_disk_space_to_start_eviction();
379 set_repeated_eviction(false);
380 temporary_storage_evictor()->Start();
381 base::RunLoop().RunUntilIdle();
382 EXPECT_EQ(414 + 450, quota_eviction_handler()->GetUsage());
384 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
385 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
386 EXPECT_EQ(0, statistics().num_evicted_origins);
387 EXPECT_EQ(1, statistics().num_eviction_rounds);
388 EXPECT_EQ(1, statistics().num_skipped_eviction_rounds);
391 TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) {
392 quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 294);
393 quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 120);
394 quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 150);
395 quota_eviction_handler()->AddOrigin(GURL("http://www.w.com"), 300);
396 quota_eviction_handler()->set_quota(10000);
397 quota_eviction_handler()->set_available_space(
398 default_min_available_disk_space_to_start_eviction() - 350);
399 EXPECT_EQ(294 + 120 + 150 + 300, quota_eviction_handler()->GetUsage());
400 set_min_available_disk_space_to_start_eviction(
401 default_min_available_disk_space_to_start_eviction());
402 set_repeated_eviction(false);
403 temporary_storage_evictor()->Start();
404 base::RunLoop().RunUntilIdle();
405 EXPECT_EQ(150 + 300, quota_eviction_handler()->GetUsage());
407 EXPECT_EQ(0, statistics().num_errors_on_evicting_origin);
408 EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota);
409 EXPECT_EQ(2, statistics().num_evicted_origins);
410 EXPECT_EQ(1, statistics().num_eviction_rounds);
411 EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
414 } // namespace content