1 // Copyright (c) 2006-2008 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.h"
8 #include "chrome/browser/renderer_host/web_cache_manager.h"
9 #include "content/browser/browser_thread.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 using base::Time;
13 using base::TimeDelta;
14 using WebKit::WebCache;
15
16 class WebCacheManagerTest : public testing::Test {
17 protected:
18 typedef WebCacheManager::StatsMap StatsMap;
19 typedef WebCacheManager::Allocation Allocation;
20 typedef WebCacheManager::AllocationStrategy AllocationStrategy;
21
22 static const int kRendererID;
23 static const int kRendererID2;
24 static const WebCache::UsageStats kStats;
25 static const WebCache::UsageStats kStats2;
26
WebCacheManagerTest()27 WebCacheManagerTest()
28 : ui_thread_(BrowserThread::UI, &message_loop_) {
29 }
30
31 // Thunks to access protected members of WebCacheManager
stats(WebCacheManager * h)32 static std::map<int, WebCacheManager::RendererInfo>& stats(
33 WebCacheManager* h) {
34 return h->stats_;
35 }
36
SimulateInactivity(WebCacheManager * h,int renderer_id)37 static void SimulateInactivity(WebCacheManager* h, int renderer_id) {
38 stats(h)[renderer_id].access = Time::Now() - TimeDelta::FromMinutes(
39 WebCacheManager::kRendererInactiveThresholdMinutes);
40 h->FindInactiveRenderers();
41 }
42
active_renderers(WebCacheManager * h)43 static std::set<int>& active_renderers(WebCacheManager* h) {
44 return h->active_renderers_;
45 }
inactive_renderers(WebCacheManager * h)46 static std::set<int>& inactive_renderers(WebCacheManager* h) {
47 return h->inactive_renderers_;
48 }
GatherStats(WebCacheManager * h,std::set<int> renderers,WebCache::UsageStats * stats)49 static void GatherStats(WebCacheManager* h,
50 std::set<int> renderers,
51 WebCache::UsageStats* stats) {
52 h->GatherStats(renderers, stats);
53 }
GetSize(int tactic,const WebCache::UsageStats & stats)54 static size_t GetSize(int tactic,
55 const WebCache::UsageStats& stats) {
56 return WebCacheManager::GetSize(
57 static_cast<WebCacheManager::AllocationTactic>(tactic), stats);
58 }
AttemptTactic(WebCacheManager * h,int active_tactic,const WebCache::UsageStats & active_stats,int inactive_tactic,const WebCache::UsageStats & inactive_stats,std::list<std::pair<int,size_t>> * strategy)59 static bool AttemptTactic(WebCacheManager* h,
60 int active_tactic,
61 const WebCache::UsageStats& active_stats,
62 int inactive_tactic,
63 const WebCache::UsageStats& inactive_stats,
64 std::list< std::pair<int,size_t> >* strategy) {
65 return h->AttemptTactic(
66 static_cast<WebCacheManager::AllocationTactic>(active_tactic),
67 active_stats,
68 static_cast<WebCacheManager::AllocationTactic>(inactive_tactic),
69 inactive_stats,
70 strategy);
71 }
AddToStrategy(WebCacheManager * h,std::set<int> renderers,int tactic,size_t extra_bytes_to_allocate,std::list<std::pair<int,size_t>> * strategy)72 static void AddToStrategy(WebCacheManager* h,
73 std::set<int> renderers,
74 int tactic,
75 size_t extra_bytes_to_allocate,
76 std::list< std::pair<int,size_t> >* strategy) {
77 h->AddToStrategy(renderers,
78 static_cast<WebCacheManager::AllocationTactic>(tactic),
79 extra_bytes_to_allocate,
80 strategy);
81 }
82
83 enum {
84 DIVIDE_EVENLY = WebCacheManager::DIVIDE_EVENLY,
85 KEEP_CURRENT_WITH_HEADROOM = WebCacheManager::KEEP_CURRENT_WITH_HEADROOM,
86 KEEP_CURRENT = WebCacheManager::KEEP_CURRENT,
87 KEEP_LIVE_WITH_HEADROOM = WebCacheManager::KEEP_LIVE_WITH_HEADROOM,
88 KEEP_LIVE = WebCacheManager::KEEP_LIVE,
89 };
90
manager()91 WebCacheManager* manager() { return &manager_; }
92
93 private:
94 WebCacheManager manager_;
95 MessageLoop message_loop_;
96 BrowserThread ui_thread_;
97 };
98
99 // static
100 const int WebCacheManagerTest::kRendererID = 146;
101
102 // static
103 const int WebCacheManagerTest::kRendererID2 = 245;
104
105 // static
106 const WebCache::UsageStats WebCacheManagerTest::kStats = {
107 0,
108 1024 * 1024,
109 1024 * 1024,
110 256 * 1024,
111 512,
112 };
113
114 // static
115 const WebCache::UsageStats WebCacheManagerTest::kStats2 = {
116 0,
117 2 * 1024 * 1024,
118 2 * 1024 * 1024,
119 2 * 256 * 1024,
120 2 * 512,
121 };
122
operator ==(const WebCache::UsageStats & lhs,const WebCache::UsageStats & rhs)123 static bool operator==(const WebCache::UsageStats& lhs,
124 const WebCache::UsageStats& rhs) {
125 return !::memcmp(&lhs, &rhs, sizeof(WebCache::UsageStats));
126 }
127
TEST_F(WebCacheManagerTest,AddRemoveRendererTest)128 TEST_F(WebCacheManagerTest, AddRemoveRendererTest) {
129 EXPECT_EQ(0U, active_renderers(manager()).size());
130 EXPECT_EQ(0U, inactive_renderers(manager()).size());
131
132 manager()->Add(kRendererID);
133 EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
134 EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
135
136 manager()->Remove(kRendererID);
137 EXPECT_EQ(0U, active_renderers(manager()).size());
138 EXPECT_EQ(0U, inactive_renderers(manager()).size());
139 }
140
TEST_F(WebCacheManagerTest,ActiveInactiveTest)141 TEST_F(WebCacheManagerTest, ActiveInactiveTest) {
142 manager()->Add(kRendererID);
143
144 manager()->ObserveActivity(kRendererID);
145 EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
146 EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
147
148 SimulateInactivity(manager(), kRendererID);
149 EXPECT_EQ(0U, active_renderers(manager()).count(kRendererID));
150 EXPECT_EQ(1U, inactive_renderers(manager()).count(kRendererID));
151
152 manager()->ObserveActivity(kRendererID);
153 EXPECT_EQ(1U, active_renderers(manager()).count(kRendererID));
154 EXPECT_EQ(0U, inactive_renderers(manager()).count(kRendererID));
155
156 manager()->Remove(kRendererID);
157 }
158
TEST_F(WebCacheManagerTest,ObserveStatsTest)159 TEST_F(WebCacheManagerTest, ObserveStatsTest) {
160 manager()->Add(kRendererID);
161
162 EXPECT_EQ(1U, stats(manager()).size());
163
164 manager()->ObserveStats(kRendererID, kStats);
165
166 EXPECT_EQ(1U, stats(manager()).size());
167 EXPECT_TRUE(kStats == stats(manager())[kRendererID]);
168
169 manager()->Remove(kRendererID);
170 }
171
TEST_F(WebCacheManagerTest,SetGlobalSizeLimitTest)172 TEST_F(WebCacheManagerTest, SetGlobalSizeLimitTest) {
173 size_t limit = manager()->GetDefaultGlobalSizeLimit();
174 manager()->SetGlobalSizeLimit(limit);
175 EXPECT_EQ(limit, manager()->global_size_limit());
176
177 manager()->SetGlobalSizeLimit(0);
178 EXPECT_EQ(0U, manager()->global_size_limit());
179 }
180
TEST_F(WebCacheManagerTest,GatherStatsTest)181 TEST_F(WebCacheManagerTest, GatherStatsTest) {
182 manager()->Add(kRendererID);
183 manager()->Add(kRendererID2);
184
185 manager()->ObserveStats(kRendererID, kStats);
186 manager()->ObserveStats(kRendererID2, kStats2);
187
188 std::set<int> renderer_set;
189 renderer_set.insert(kRendererID);
190
191 WebCache::UsageStats stats;
192 GatherStats(manager(), renderer_set, &stats);
193
194 EXPECT_TRUE(kStats == stats);
195
196 renderer_set.insert(kRendererID2);
197 GatherStats(manager(), renderer_set, &stats);
198
199 WebCache::UsageStats expected_stats = kStats;
200 expected_stats.minDeadCapacity += kStats2.minDeadCapacity;
201 expected_stats.maxDeadCapacity += kStats2.maxDeadCapacity;
202 expected_stats.capacity += kStats2.capacity;
203 expected_stats.liveSize += kStats2.liveSize;
204 expected_stats.deadSize += kStats2.deadSize;
205
206 EXPECT_TRUE(expected_stats == stats);
207
208 manager()->Remove(kRendererID);
209 manager()->Remove(kRendererID2);
210 }
211
TEST_F(WebCacheManagerTest,GetSizeTest)212 TEST_F(WebCacheManagerTest, GetSizeTest) {
213 EXPECT_EQ(0U, GetSize(DIVIDE_EVENLY, kStats));
214 EXPECT_LT(256 * 1024u + 512, GetSize(KEEP_CURRENT_WITH_HEADROOM, kStats));
215 EXPECT_EQ(256 * 1024u + 512, GetSize(KEEP_CURRENT, kStats));
216 EXPECT_LT(256 * 1024u, GetSize(KEEP_LIVE_WITH_HEADROOM, kStats));
217 EXPECT_EQ(256 * 1024u, GetSize(KEEP_LIVE, kStats));
218 }
219
TEST_F(WebCacheManagerTest,AttemptTacticTest)220 TEST_F(WebCacheManagerTest, AttemptTacticTest) {
221 manager()->Add(kRendererID);
222 manager()->Add(kRendererID2);
223
224 manager()->ObserveActivity(kRendererID);
225 SimulateInactivity(manager(), kRendererID2);
226
227 manager()->ObserveStats(kRendererID, kStats);
228 manager()->ObserveStats(kRendererID2, kStats2);
229
230 manager()->SetGlobalSizeLimit(kStats.liveSize + kStats.deadSize +
231 kStats2.liveSize + kStats2.deadSize/2);
232
233 AllocationStrategy strategy;
234
235 EXPECT_FALSE(AttemptTactic(manager(),
236 KEEP_CURRENT,
237 kStats,
238 KEEP_CURRENT,
239 kStats2,
240 &strategy));
241 EXPECT_TRUE(strategy.empty());
242
243 EXPECT_TRUE(AttemptTactic(manager(),
244 KEEP_CURRENT,
245 kStats,
246 KEEP_LIVE,
247 kStats2,
248 &strategy));
249 EXPECT_EQ(2U, strategy.size());
250
251 AllocationStrategy::iterator iter = strategy.begin();
252 while (iter != strategy.end()) {
253 if (iter->first == kRendererID)
254 EXPECT_LE(kStats.liveSize + kStats.deadSize, iter->second);
255 else if (iter->first == kRendererID2)
256 EXPECT_LE(kStats2.liveSize, iter->second);
257 else
258 EXPECT_FALSE("Unexpected entry in strategy");
259 ++iter;
260 }
261
262 manager()->Remove(kRendererID);
263 manager()->Remove(kRendererID2);
264 }
265
TEST_F(WebCacheManagerTest,AddToStrategyTest)266 TEST_F(WebCacheManagerTest, AddToStrategyTest) {
267 manager()->Add(kRendererID);
268 manager()->Add(kRendererID2);
269
270 std::set<int> renderer_set;
271 renderer_set.insert(kRendererID);
272 renderer_set.insert(kRendererID2);
273
274 manager()->ObserveStats(kRendererID, kStats);
275 manager()->ObserveStats(kRendererID2, kStats2);
276
277 const size_t kExtraBytesToAllocate = 10 * 1024;
278
279 AllocationStrategy strategy;
280 AddToStrategy(manager(),
281 renderer_set,
282 KEEP_CURRENT,
283 kExtraBytesToAllocate,
284 &strategy);
285
286 EXPECT_EQ(2U, strategy.size());
287
288 size_t total_bytes = 0;
289 AllocationStrategy::iterator iter = strategy.begin();
290 while (iter != strategy.end()) {
291 total_bytes += iter->second;
292
293 if (iter->first == kRendererID)
294 EXPECT_LE(kStats.liveSize + kStats.deadSize, iter->second);
295 else if (iter->first == kRendererID2)
296 EXPECT_LE(kStats2.liveSize + kStats2.deadSize, iter->second);
297 else
298 EXPECT_FALSE("Unexpected entry in strategy");
299 ++iter;
300 }
301
302 size_t expected_total_bytes = kExtraBytesToAllocate +
303 kStats.liveSize + kStats.deadSize +
304 kStats2.liveSize + kStats2.deadSize;
305
306 EXPECT_GE(expected_total_bytes, total_bytes);
307
308 manager()->Remove(kRendererID);
309 manager()->Remove(kRendererID2);
310 }
311