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