Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / web_cache / browser / web_cache_manager_unittest.cc
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.
4
5 #include <string>
6
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"
11
12 using base::Time;
13 using base::TimeDelta;
14 using content::BrowserThread;
15 using blink::WebCache;
16
17 namespace web_cache {
18
19 class WebCacheManagerTest : public testing::Test {
20  protected:
21   typedef WebCacheManager::StatsMap StatsMap;
22   typedef WebCacheManager::Allocation Allocation;
23   typedef WebCacheManager::AllocationStrategy AllocationStrategy;
24
25   static const int kRendererID;
26   static const int kRendererID2;
27   static const WebCache::UsageStats kStats;
28   static const WebCache::UsageStats kStats2;
29
30   WebCacheManagerTest()
31       : ui_thread_(BrowserThread::UI, &message_loop_) {
32   }
33
34   // Thunks to access protected members of WebCacheManager
35   static std::map<int, WebCacheManager::RendererInfo>& stats(
36         WebCacheManager* h) {
37     return h->stats_;
38   }
39
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();
44   }
45
46   static std::set<int>& active_renderers(WebCacheManager* h) {
47     return h->active_renderers_;
48   }
49   static std::set<int>& inactive_renderers(WebCacheManager* h) {
50     return h->inactive_renderers_;
51   }
52   static void GatherStats(WebCacheManager* h,
53                           std::set<int> renderers,
54                           WebCache::UsageStats* stats) {
55     h->GatherStats(renderers, stats);
56   }
57   static size_t GetSize(int tactic,
58                         const WebCache::UsageStats& stats) {
59     return WebCacheManager::GetSize(
60         static_cast<WebCacheManager::AllocationTactic>(tactic), stats);
61   }
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);
74   }
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);
84   }
85
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,
92   };
93
94   WebCacheManager* manager() { return &manager_; }
95
96  private:
97   WebCacheManager manager_;
98   base::MessageLoop message_loop_;
99   content::TestBrowserThread ui_thread_;
100 };
101
102 // static
103 const int WebCacheManagerTest::kRendererID = 146;
104
105 // static
106 const int WebCacheManagerTest::kRendererID2 = 245;
107
108 // static
109 const WebCache::UsageStats WebCacheManagerTest::kStats = {
110     0,
111     1024 * 1024,
112     1024 * 1024,
113     256 * 1024,
114     512,
115   };
116
117 // static
118 const WebCache::UsageStats WebCacheManagerTest::kStats2 = {
119     0,
120     2 * 1024 * 1024,
121     2 * 1024 * 1024,
122     2 * 256 * 1024,
123     2 * 512,
124   };
125
126 static bool operator==(const WebCache::UsageStats& lhs,
127                        const WebCache::UsageStats& rhs) {
128   return !::memcmp(&lhs, &rhs, sizeof(WebCache::UsageStats));
129 }
130
131 TEST_F(WebCacheManagerTest, AddRemoveRendererTest) {
132   EXPECT_EQ(0U, active_renderers(manager()).size());
133   EXPECT_EQ(0U, inactive_renderers(manager()).size());
134
135   manager()->Add(kRendererID);
136   EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
137   EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
138
139   manager()->Remove(kRendererID);
140   EXPECT_EQ(0U, active_renderers(manager()).size());
141   EXPECT_EQ(0U, inactive_renderers(manager()).size());
142 }
143
144 TEST_F(WebCacheManagerTest, ActiveInactiveTest) {
145   manager()->Add(kRendererID);
146
147   manager()->ObserveActivity(kRendererID);
148   EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
149   EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
150
151   SimulateInactivity(manager(), kRendererID);
152   EXPECT_EQ(0U, active_renderers(manager()).count(kRendererID));
153   EXPECT_EQ(1U, inactive_renderers(manager()).count(kRendererID));
154
155   manager()->ObserveActivity(kRendererID);
156   EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
157   EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
158
159   manager()->Remove(kRendererID);
160 }
161
162 TEST_F(WebCacheManagerTest, ObserveStatsTest) {
163   manager()->Add(kRendererID);
164
165   EXPECT_EQ(1U, stats(manager()).size());
166
167   manager()->ObserveStats(kRendererID, kStats);
168
169   EXPECT_EQ(1U, stats(manager()).size());
170   EXPECT_TRUE(kStats == stats(manager())[kRendererID]);
171
172   manager()->Remove(kRendererID);
173 }
174
175 TEST_F(WebCacheManagerTest, SetGlobalSizeLimitTest) {
176   size_t limit = manager()->GetDefaultGlobalSizeLimit();
177   manager()->SetGlobalSizeLimit(limit);
178   EXPECT_EQ(limit, manager()->global_size_limit());
179
180   manager()->SetGlobalSizeLimit(0);
181   EXPECT_EQ(0U, manager()->global_size_limit());
182 }
183
184 TEST_F(WebCacheManagerTest, GatherStatsTest) {
185   manager()->Add(kRendererID);
186   manager()->Add(kRendererID2);
187
188   manager()->ObserveStats(kRendererID, kStats);
189   manager()->ObserveStats(kRendererID2, kStats2);
190
191   std::set<int> renderer_set;
192   renderer_set.insert(kRendererID);
193
194   WebCache::UsageStats stats;
195   GatherStats(manager(), renderer_set, &stats);
196
197   EXPECT_TRUE(kStats == stats);
198
199   renderer_set.insert(kRendererID2);
200   GatherStats(manager(), renderer_set, &stats);
201
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;
208
209   EXPECT_TRUE(expected_stats == stats);
210
211   manager()->Remove(kRendererID);
212   manager()->Remove(kRendererID2);
213 }
214
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));
221 }
222
223 TEST_F(WebCacheManagerTest, AttemptTacticTest) {
224   manager()->Add(kRendererID);
225   manager()->Add(kRendererID2);
226
227   manager()->ObserveActivity(kRendererID);
228   SimulateInactivity(manager(), kRendererID2);
229
230   manager()->ObserveStats(kRendererID, kStats);
231   manager()->ObserveStats(kRendererID2, kStats2);
232
233   manager()->SetGlobalSizeLimit(kStats.liveSize + kStats.deadSize +
234                         kStats2.liveSize + kStats2.deadSize/2);
235
236   AllocationStrategy strategy;
237
238   EXPECT_FALSE(AttemptTactic(manager(),
239                              KEEP_CURRENT,
240                              kStats,
241                              KEEP_CURRENT,
242                              kStats2,
243                              &strategy));
244   EXPECT_TRUE(strategy.empty());
245
246   EXPECT_TRUE(AttemptTactic(manager(),
247                             KEEP_CURRENT,
248                             kStats,
249                             KEEP_LIVE,
250                             kStats2,
251                             &strategy));
252   EXPECT_EQ(2U, strategy.size());
253
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;
263   }
264
265   manager()->Remove(kRendererID);
266   manager()->Remove(kRendererID2);
267 }
268
269 TEST_F(WebCacheManagerTest, AddToStrategyTest) {
270   manager()->Add(kRendererID);
271   manager()->Add(kRendererID2);
272
273   std::set<int> renderer_set;
274   renderer_set.insert(kRendererID);
275   renderer_set.insert(kRendererID2);
276
277   manager()->ObserveStats(kRendererID, kStats);
278   manager()->ObserveStats(kRendererID2, kStats2);
279
280   const size_t kExtraBytesToAllocate = 10 * 1024;
281
282   AllocationStrategy strategy;
283   AddToStrategy(manager(),
284                 renderer_set,
285                 KEEP_CURRENT,
286                 kExtraBytesToAllocate,
287                 &strategy);
288
289   EXPECT_EQ(2U, strategy.size());
290
291   size_t total_bytes = 0;
292   AllocationStrategy::iterator iter = strategy.begin();
293   while (iter != strategy.end()) {
294     total_bytes += iter->second;
295
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;
303   }
304
305   size_t expected_total_bytes = kExtraBytesToAllocate +
306                                 kStats.liveSize + kStats.deadSize +
307                                 kStats2.liveSize + kStats2.deadSize;
308
309   EXPECT_GE(expected_total_bytes, total_bytes);
310
311   manager()->Remove(kRendererID);
312   manager()->Remove(kRendererID2);
313 }
314
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());
324
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();
333
334   // The following order will cause a crash in http://crbug.com/12362.
335   manager()->Remove(kRendererID);
336   manager()->ReviseAllocationStrategy();
337
338   manager()->ObserveActivity(kRendererID);
339   manager()->ReviseAllocationStrategy();
340
341   manager()->Remove(kRendererID2);
342   manager()->ReviseAllocationStrategy();
343 }
344
345 TEST_F(WebCacheManagerTest,
346        CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2) {
347   EXPECT_EQ(0U, active_renderers(manager()).size());
348   EXPECT_EQ(0U, inactive_renderers(manager()).size());
349
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();
358
359   manager()->Remove(kRendererID);
360   manager()->ReviseAllocationStrategy();
361
362   manager()->Remove(kRendererID2);
363   manager()->ReviseAllocationStrategy();
364
365   manager()->ObserveActivity(kRendererID);
366   manager()->ReviseAllocationStrategy();
367
368 }
369
370 TEST_F(WebCacheManagerTest,
371        CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3) {
372   EXPECT_EQ(0U, active_renderers(manager()).size());
373   EXPECT_EQ(0U, inactive_renderers(manager()).size());
374
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();
383
384   manager()->ObserveActivity(kRendererID);
385   EXPECT_EQ(0U, inactive_renderers(manager()).size());
386
387   manager()->Remove(kRendererID);
388   manager()->ReviseAllocationStrategy();
389
390   manager()->Remove(kRendererID2);
391   manager()->ReviseAllocationStrategy();
392 }
393
394 TEST_F(WebCacheManagerTest,
395        CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4) {
396   EXPECT_EQ(0U, active_renderers(manager()).size());
397   EXPECT_EQ(0U, inactive_renderers(manager()).size());
398
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();
407
408   manager()->ObserveActivity(kRendererID);
409   EXPECT_EQ(0U, inactive_renderers(manager()).size());
410
411   manager()->Remove(kRendererID2);
412   manager()->ReviseAllocationStrategy();
413
414   manager()->Remove(kRendererID);
415   manager()->ReviseAllocationStrategy();
416 }
417
418 TEST_F(WebCacheManagerTest,
419        CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5) {
420   EXPECT_EQ(0U, active_renderers(manager()).size());
421   EXPECT_EQ(0U, inactive_renderers(manager()).size());
422
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();
431
432   manager()->Remove(kRendererID2);
433   manager()->ReviseAllocationStrategy();
434
435   manager()->ObserveActivity(kRendererID);
436   manager()->ReviseAllocationStrategy();
437
438   manager()->Remove(kRendererID);
439   manager()->ReviseAllocationStrategy();
440 }
441
442 TEST_F(WebCacheManagerTest,
443        CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6) {
444   EXPECT_EQ(0U, active_renderers(manager()).size());
445   EXPECT_EQ(0U, inactive_renderers(manager()).size());
446
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();
455
456   manager()->Remove(kRendererID2);
457   manager()->ReviseAllocationStrategy();
458
459   manager()->Remove(kRendererID);
460   manager()->ReviseAllocationStrategy();
461
462   manager()->ObserveActivity(kRendererID);
463   manager()->ReviseAllocationStrategy();
464 }
465
466 }  // namespace web_cache