Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / web_cache / browser / web_cache_manager_unittest.cc
blobbc8bcbd5076add3928f586991648bb482eb4d5d1
1 // Copyright (c) 2011 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 <string>
7 #include "base/message_loop/message_loop.h"
8 #include "components/web_cache/browser/web_cache_manager.h"
9 #include "content/public/test/test_browser_thread.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 using base::Time;
13 using base::TimeDelta;
14 using content::BrowserThread;
15 using blink::WebCache;
17 namespace web_cache {
19 class WebCacheManagerTest : public testing::Test {
20 protected:
21 typedef WebCacheManager::StatsMap StatsMap;
22 typedef WebCacheManager::Allocation Allocation;
23 typedef WebCacheManager::AllocationStrategy AllocationStrategy;
25 static const int kRendererID;
26 static const int kRendererID2;
27 static const WebCache::UsageStats kStats;
28 static const WebCache::UsageStats kStats2;
30 WebCacheManagerTest()
31 : ui_thread_(BrowserThread::UI, &message_loop_) {
34 // Thunks to access protected members of WebCacheManager
35 static std::map<int, WebCacheManager::RendererInfo>& stats(
36 WebCacheManager* h) {
37 return h->stats_;
40 static void SimulateInactivity(WebCacheManager* h, int renderer_id) {
41 stats(h)[renderer_id].access = Time::Now() - TimeDelta::FromMinutes(
42 WebCacheManager::kRendererInactiveThresholdMinutes);
43 h->FindInactiveRenderers();
46 static std::set<int>& active_renderers(WebCacheManager* h) {
47 return h->active_renderers_;
49 static std::set<int>& inactive_renderers(WebCacheManager* h) {
50 return h->inactive_renderers_;
52 static void GatherStats(WebCacheManager* h,
53 std::set<int> renderers,
54 WebCache::UsageStats* stats) {
55 h->GatherStats(renderers, stats);
57 static size_t GetSize(int tactic,
58 const WebCache::UsageStats& stats) {
59 return WebCacheManager::GetSize(
60 static_cast<WebCacheManager::AllocationTactic>(tactic), stats);
62 static bool AttemptTactic(WebCacheManager* h,
63 int active_tactic,
64 const WebCache::UsageStats& active_stats,
65 int inactive_tactic,
66 const WebCache::UsageStats& inactive_stats,
67 std::list< std::pair<int,size_t> >* strategy) {
68 return h->AttemptTactic(
69 static_cast<WebCacheManager::AllocationTactic>(active_tactic),
70 active_stats,
71 static_cast<WebCacheManager::AllocationTactic>(inactive_tactic),
72 inactive_stats,
73 strategy);
75 static void AddToStrategy(WebCacheManager* h,
76 std::set<int> renderers,
77 int tactic,
78 size_t extra_bytes_to_allocate,
79 std::list< std::pair<int,size_t> >* strategy) {
80 h->AddToStrategy(renderers,
81 static_cast<WebCacheManager::AllocationTactic>(tactic),
82 extra_bytes_to_allocate,
83 strategy);
86 enum {
87 DIVIDE_EVENLY = WebCacheManager::DIVIDE_EVENLY,
88 KEEP_CURRENT_WITH_HEADROOM = WebCacheManager::KEEP_CURRENT_WITH_HEADROOM,
89 KEEP_CURRENT = WebCacheManager::KEEP_CURRENT,
90 KEEP_LIVE_WITH_HEADROOM = WebCacheManager::KEEP_LIVE_WITH_HEADROOM,
91 KEEP_LIVE = WebCacheManager::KEEP_LIVE,
94 WebCacheManager* manager() { return &manager_; }
96 private:
97 WebCacheManager manager_;
98 base::MessageLoop message_loop_;
99 content::TestBrowserThread ui_thread_;
102 // static
103 const int WebCacheManagerTest::kRendererID = 146;
105 // static
106 const int WebCacheManagerTest::kRendererID2 = 245;
108 // static
109 const WebCache::UsageStats WebCacheManagerTest::kStats = {
111 1024 * 1024,
112 1024 * 1024,
113 256 * 1024,
114 512,
117 // static
118 const WebCache::UsageStats WebCacheManagerTest::kStats2 = {
120 2 * 1024 * 1024,
121 2 * 1024 * 1024,
122 2 * 256 * 1024,
123 2 * 512,
126 static bool operator==(const WebCache::UsageStats& lhs,
127 const WebCache::UsageStats& rhs) {
128 return !::memcmp(&lhs, &rhs, sizeof(WebCache::UsageStats));
131 TEST_F(WebCacheManagerTest, AddRemoveRendererTest) {
132 EXPECT_EQ(0U, active_renderers(manager()).size());
133 EXPECT_EQ(0U, inactive_renderers(manager()).size());
135 manager()->Add(kRendererID);
136 EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
137 EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
139 manager()->Remove(kRendererID);
140 EXPECT_EQ(0U, active_renderers(manager()).size());
141 EXPECT_EQ(0U, inactive_renderers(manager()).size());
144 TEST_F(WebCacheManagerTest, ActiveInactiveTest) {
145 manager()->Add(kRendererID);
147 manager()->ObserveActivity(kRendererID);
148 EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
149 EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
151 SimulateInactivity(manager(), kRendererID);
152 EXPECT_EQ(0U, active_renderers(manager()).count(kRendererID));
153 EXPECT_EQ(1U, inactive_renderers(manager()).count(kRendererID));
155 manager()->ObserveActivity(kRendererID);
156 EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
157 EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
159 manager()->Remove(kRendererID);
162 TEST_F(WebCacheManagerTest, ObserveStatsTest) {
163 manager()->Add(kRendererID);
165 EXPECT_EQ(1U, stats(manager()).size());
167 manager()->ObserveStats(kRendererID, kStats);
169 EXPECT_EQ(1U, stats(manager()).size());
170 EXPECT_TRUE(kStats == stats(manager())[kRendererID]);
172 manager()->Remove(kRendererID);
175 TEST_F(WebCacheManagerTest, SetGlobalSizeLimitTest) {
176 size_t limit = manager()->GetDefaultGlobalSizeLimit();
177 manager()->SetGlobalSizeLimit(limit);
178 EXPECT_EQ(limit, manager()->global_size_limit());
180 manager()->SetGlobalSizeLimit(0);
181 EXPECT_EQ(0U, manager()->global_size_limit());
184 TEST_F(WebCacheManagerTest, GatherStatsTest) {
185 manager()->Add(kRendererID);
186 manager()->Add(kRendererID2);
188 manager()->ObserveStats(kRendererID, kStats);
189 manager()->ObserveStats(kRendererID2, kStats2);
191 std::set<int> renderer_set;
192 renderer_set.insert(kRendererID);
194 WebCache::UsageStats stats;
195 GatherStats(manager(), renderer_set, &stats);
197 EXPECT_TRUE(kStats == stats);
199 renderer_set.insert(kRendererID2);
200 GatherStats(manager(), renderer_set, &stats);
202 WebCache::UsageStats expected_stats = kStats;
203 expected_stats.minDeadCapacity += kStats2.minDeadCapacity;
204 expected_stats.maxDeadCapacity += kStats2.maxDeadCapacity;
205 expected_stats.capacity += kStats2.capacity;
206 expected_stats.liveSize += kStats2.liveSize;
207 expected_stats.deadSize += kStats2.deadSize;
209 EXPECT_TRUE(expected_stats == stats);
211 manager()->Remove(kRendererID);
212 manager()->Remove(kRendererID2);
215 TEST_F(WebCacheManagerTest, GetSizeTest) {
216 EXPECT_EQ(0U, GetSize(DIVIDE_EVENLY, kStats));
217 EXPECT_LT(256 * 1024u + 512, GetSize(KEEP_CURRENT_WITH_HEADROOM, kStats));
218 EXPECT_EQ(256 * 1024u + 512, GetSize(KEEP_CURRENT, kStats));
219 EXPECT_LT(256 * 1024u, GetSize(KEEP_LIVE_WITH_HEADROOM, kStats));
220 EXPECT_EQ(256 * 1024u, GetSize(KEEP_LIVE, kStats));
223 TEST_F(WebCacheManagerTest, AttemptTacticTest) {
224 manager()->Add(kRendererID);
225 manager()->Add(kRendererID2);
227 manager()->ObserveActivity(kRendererID);
228 SimulateInactivity(manager(), kRendererID2);
230 manager()->ObserveStats(kRendererID, kStats);
231 manager()->ObserveStats(kRendererID2, kStats2);
233 manager()->SetGlobalSizeLimit(kStats.liveSize + kStats.deadSize +
234 kStats2.liveSize + kStats2.deadSize/2);
236 AllocationStrategy strategy;
238 EXPECT_FALSE(AttemptTactic(manager(),
239 KEEP_CURRENT,
240 kStats,
241 KEEP_CURRENT,
242 kStats2,
243 &strategy));
244 EXPECT_TRUE(strategy.empty());
246 EXPECT_TRUE(AttemptTactic(manager(),
247 KEEP_CURRENT,
248 kStats,
249 KEEP_LIVE,
250 kStats2,
251 &strategy));
252 EXPECT_EQ(2U, strategy.size());
254 AllocationStrategy::iterator iter = strategy.begin();
255 while (iter != strategy.end()) {
256 if (iter->first == kRendererID)
257 EXPECT_LE(kStats.liveSize + kStats.deadSize, iter->second);
258 else if (iter->first == kRendererID2)
259 EXPECT_LE(kStats2.liveSize, iter->second);
260 else
261 ADD_FAILURE(); // Unexpected entry in strategy.
262 ++iter;
265 manager()->Remove(kRendererID);
266 manager()->Remove(kRendererID2);
269 TEST_F(WebCacheManagerTest, AddToStrategyTest) {
270 manager()->Add(kRendererID);
271 manager()->Add(kRendererID2);
273 std::set<int> renderer_set;
274 renderer_set.insert(kRendererID);
275 renderer_set.insert(kRendererID2);
277 manager()->ObserveStats(kRendererID, kStats);
278 manager()->ObserveStats(kRendererID2, kStats2);
280 const size_t kExtraBytesToAllocate = 10 * 1024;
282 AllocationStrategy strategy;
283 AddToStrategy(manager(),
284 renderer_set,
285 KEEP_CURRENT,
286 kExtraBytesToAllocate,
287 &strategy);
289 EXPECT_EQ(2U, strategy.size());
291 size_t total_bytes = 0;
292 AllocationStrategy::iterator iter = strategy.begin();
293 while (iter != strategy.end()) {
294 total_bytes += iter->second;
296 if (iter->first == kRendererID)
297 EXPECT_LE(kStats.liveSize + kStats.deadSize, iter->second);
298 else if (iter->first == kRendererID2)
299 EXPECT_LE(kStats2.liveSize + kStats2.deadSize, iter->second);
300 else
301 ADD_FAILURE(); // Unexpected entry in strategy.
302 ++iter;
305 size_t expected_total_bytes = kExtraBytesToAllocate +
306 kStats.liveSize + kStats.deadSize +
307 kStats2.liveSize + kStats2.deadSize;
309 EXPECT_GE(expected_total_bytes, total_bytes);
311 manager()->Remove(kRendererID);
312 manager()->Remove(kRendererID2);
315 // Regression test for http://crbug.com/12362.
316 // There are three operations in the following order will cause the crash:
317 // Remove(kRendererID) -> ObserveActivity(kRendererID) -> Remove(kRendererID2)
318 // To prevent similar failures in the future, 6 tests are added in total to
319 // cover all the possible orderings of these three operations.
320 TEST_F(WebCacheManagerTest,
321 CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_1) {
322 EXPECT_EQ(0U, active_renderers(manager()).size());
323 EXPECT_EQ(0U, inactive_renderers(manager()).size());
325 // Add, Remove, and ObserveActivity trigger deferred
326 // calls to ReviseAllocationStrategy and that we call it directly after each
327 // operation to sidestep the need to wait for an unobservable background
328 // operation.
329 manager()->Add(kRendererID);
330 manager()->ReviseAllocationStrategy();
331 manager()->Add(kRendererID2);
332 manager()->ReviseAllocationStrategy();
334 // The following order will cause a crash in http://crbug.com/12362.
335 manager()->Remove(kRendererID);
336 manager()->ReviseAllocationStrategy();
338 manager()->ObserveActivity(kRendererID);
339 manager()->ReviseAllocationStrategy();
341 manager()->Remove(kRendererID2);
342 manager()->ReviseAllocationStrategy();
345 TEST_F(WebCacheManagerTest,
346 CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2) {
347 EXPECT_EQ(0U, active_renderers(manager()).size());
348 EXPECT_EQ(0U, inactive_renderers(manager()).size());
350 // Add, Remove, and ObserveActivity trigger deferred
351 // calls to ReviseAllocationStrategy and that we call it directly after each
352 // operation to sidestep the need to wait for an unobservable background
353 // operation.
354 manager()->Add(kRendererID);
355 manager()->ReviseAllocationStrategy();
356 manager()->Add(kRendererID2);
357 manager()->ReviseAllocationStrategy();
359 manager()->Remove(kRendererID);
360 manager()->ReviseAllocationStrategy();
362 manager()->Remove(kRendererID2);
363 manager()->ReviseAllocationStrategy();
365 manager()->ObserveActivity(kRendererID);
366 manager()->ReviseAllocationStrategy();
370 TEST_F(WebCacheManagerTest,
371 CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3) {
372 EXPECT_EQ(0U, active_renderers(manager()).size());
373 EXPECT_EQ(0U, inactive_renderers(manager()).size());
375 // Add, Remove, and ObserveActivity trigger deferred
376 // calls to ReviseAllocationStrategy and that we call it directly after each
377 // operation to sidestep the need to wait for an unobservable background
378 // operation.
379 manager()->Add(kRendererID);
380 manager()->ReviseAllocationStrategy();
381 manager()->Add(kRendererID2);
382 manager()->ReviseAllocationStrategy();
384 manager()->ObserveActivity(kRendererID);
385 EXPECT_EQ(0U, inactive_renderers(manager()).size());
387 manager()->Remove(kRendererID);
388 manager()->ReviseAllocationStrategy();
390 manager()->Remove(kRendererID2);
391 manager()->ReviseAllocationStrategy();
394 TEST_F(WebCacheManagerTest,
395 CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4) {
396 EXPECT_EQ(0U, active_renderers(manager()).size());
397 EXPECT_EQ(0U, inactive_renderers(manager()).size());
399 // Add, Remove, and ObserveActivity trigger deferred
400 // calls to ReviseAllocationStrategy and that we call it directly after each
401 // operation to sidestep the need to wait for an unobservable background
402 // operation.
403 manager()->Add(kRendererID);
404 manager()->ReviseAllocationStrategy();
405 manager()->Add(kRendererID2);
406 manager()->ReviseAllocationStrategy();
408 manager()->ObserveActivity(kRendererID);
409 EXPECT_EQ(0U, inactive_renderers(manager()).size());
411 manager()->Remove(kRendererID2);
412 manager()->ReviseAllocationStrategy();
414 manager()->Remove(kRendererID);
415 manager()->ReviseAllocationStrategy();
418 TEST_F(WebCacheManagerTest,
419 CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5) {
420 EXPECT_EQ(0U, active_renderers(manager()).size());
421 EXPECT_EQ(0U, inactive_renderers(manager()).size());
423 // Add, Remove, and ObserveActivity trigger deferred
424 // calls to ReviseAllocationStrategy and that we call it directly after each
425 // operation to sidestep the need to wait for an unobservable background
426 // operation.
427 manager()->Add(kRendererID);
428 manager()->ReviseAllocationStrategy();
429 manager()->Add(kRendererID2);
430 manager()->ReviseAllocationStrategy();
432 manager()->Remove(kRendererID2);
433 manager()->ReviseAllocationStrategy();
435 manager()->ObserveActivity(kRendererID);
436 manager()->ReviseAllocationStrategy();
438 manager()->Remove(kRendererID);
439 manager()->ReviseAllocationStrategy();
442 TEST_F(WebCacheManagerTest,
443 CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6) {
444 EXPECT_EQ(0U, active_renderers(manager()).size());
445 EXPECT_EQ(0U, inactive_renderers(manager()).size());
447 // Add, Remove, and ObserveActivity trigger deferred
448 // calls to ReviseAllocationStrategy and that we call it directly after each
449 // operation to sidestep the need to wait for an unobservable background
450 // operation.
451 manager()->Add(kRendererID);
452 manager()->ReviseAllocationStrategy();
453 manager()->Add(kRendererID2);
454 manager()->ReviseAllocationStrategy();
456 manager()->Remove(kRendererID2);
457 manager()->ReviseAllocationStrategy();
459 manager()->Remove(kRendererID);
460 manager()->ReviseAllocationStrategy();
462 manager()->ObserveActivity(kRendererID);
463 manager()->ReviseAllocationStrategy();
466 } // namespace web_cache