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 27 WebCacheManagerTest() 28 : ui_thread_(BrowserThread::UI, &message_loop_) { 29 } 30 31 // Thunks to access protected members of WebCacheManager 32 static std::map<int, WebCacheManager::RendererInfo>& stats( 33 WebCacheManager* h) { 34 return h->stats_; 35 } 36 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 43 static std::set<int>& active_renderers(WebCacheManager* h) { 44 return h->active_renderers_; 45 } 46 static std::set<int>& inactive_renderers(WebCacheManager* h) { 47 return h->inactive_renderers_; 48 } 49 static void GatherStats(WebCacheManager* h, 50 std::set<int> renderers, 51 WebCache::UsageStats* stats) { 52 h->GatherStats(renderers, stats); 53 } 54 static size_t GetSize(int tactic, 55 const WebCache::UsageStats& stats) { 56 return WebCacheManager::GetSize( 57 static_cast<WebCacheManager::AllocationTactic>(tactic), stats); 58 } 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 } 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 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 123 static bool operator==(const WebCache::UsageStats& lhs, 124 const WebCache::UsageStats& rhs) { 125 return !::memcmp(&lhs, &rhs, sizeof(WebCache::UsageStats)); 126 } 127 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 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 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 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 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 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 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 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