OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 |
| 6 #include "base/memory/ref_counted.h" |
| 7 #include "base/message_loop.h" |
| 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/time.h" |
| 10 #include "chrome/browser/history/history.h" |
| 11 #include "chrome/browser/history/history_types.h" |
| 12 #include "chrome/browser/history/in_memory_database.h" |
| 13 #include "chrome/browser/history/url_database.h" |
| 14 #include "chrome/browser/predictors/resource_prefetch_predictor.h" |
| 15 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" |
| 16 #include "chrome/test/base/testing_profile.h" |
| 17 #include "content/public/test/test_browser_thread.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 #include "testing/gmock/include/gmock/gmock.h" |
| 20 |
| 21 using testing::ContainerEq; |
| 22 using testing::Pointee; |
| 23 using testing::SetArgPointee; |
| 24 |
| 25 namespace predictors { |
| 26 |
| 27 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary; |
| 28 typedef ResourcePrefetchPredictorTables::UrlTableRow UrlTableRow; |
| 29 typedef ResourcePrefetchPredictorTables::UrlTableRows UrlTableRows; |
| 30 |
| 31 class MockResourcePrefetchPredictorTables |
| 32 : public ResourcePrefetchPredictorTables { |
| 33 public: |
| 34 MockResourcePrefetchPredictorTables() { } |
| 35 |
| 36 MOCK_METHOD1(GetAllRows, void(std::vector<UrlTableRow>* url_row_buffer)); |
| 37 MOCK_METHOD2(UpdateRowsForUrl, void(const GURL& main_page_url, |
| 38 const UrlTableRows& row_buffer)); |
| 39 MOCK_METHOD1(DeleteRowsForUrls, void(const std::vector<GURL>& urls)); |
| 40 MOCK_METHOD0(DeleteAllRows, void()); |
| 41 |
| 42 private: |
| 43 ~MockResourcePrefetchPredictorTables() { } |
| 44 }; |
| 45 |
| 46 class ResourcePrefetchPredictorTest : public testing::Test { |
| 47 public: |
| 48 ResourcePrefetchPredictorTest(); |
| 49 ~ResourcePrefetchPredictorTest(); |
| 50 void SetUp() OVERRIDE; |
| 51 void TearDown() OVERRIDE; |
| 52 |
| 53 protected: |
| 54 void AddUrlToHistory(const std::string& url, |
| 55 int visit_count, |
| 56 time_t last_visit) { |
| 57 history::URLRow row = history::URLRow(GURL(url)); |
| 58 row.set_visit_count(visit_count); |
| 59 row.set_last_visit(base::Time::FromTimeT(last_visit)); |
| 60 url_db_->AddURL(row); |
| 61 } |
| 62 |
| 63 NavigationID CreateNavigationID(int process_id, |
| 64 int render_view_id, |
| 65 const std::string& main_frame_url) { |
| 66 NavigationID navigation_id; |
| 67 navigation_id.render_process_id = process_id; |
| 68 navigation_id.render_view_id = render_view_id; |
| 69 navigation_id.main_frame_url = GURL(main_frame_url); |
| 70 navigation_id.creation_time = base::TimeTicks::Now(); |
| 71 return navigation_id; |
| 72 } |
| 73 |
| 74 ResourcePrefetchPredictor::URLRequestSummary CreateURLRequestSummary( |
| 75 int process_id, |
| 76 int render_view_id, |
| 77 const std::string& main_frame_url, |
| 78 const std::string& resource_url, |
| 79 ResourceType::Type resource_type, |
| 80 const std::string& mime_type, |
| 81 bool was_cached) { |
| 82 ResourcePrefetchPredictor::URLRequestSummary summary; |
| 83 summary.navigation_id = CreateNavigationID(process_id, render_view_id, |
| 84 main_frame_url); |
| 85 summary.resource_url = GURL(resource_url); |
| 86 summary.resource_type = resource_type; |
| 87 summary.mime_type = mime_type; |
| 88 summary.was_cached = was_cached; |
| 89 return summary; |
| 90 } |
| 91 |
| 92 bool URLRequestSummaryAreEqual(const URLRequestSummary& lhs, |
| 93 const URLRequestSummary& rhs) { |
| 94 return lhs.navigation_id == rhs.navigation_id && |
| 95 lhs.resource_url == rhs.resource_url && |
| 96 lhs.resource_type == rhs.resource_type && |
| 97 lhs.mime_type == rhs.mime_type && |
| 98 lhs.was_cached == rhs.was_cached; |
| 99 } |
| 100 |
| 101 void ResetPredictor() { |
| 102 ResourcePrefetchPredictor::Config config; |
| 103 config.max_urls_to_track = 3; |
| 104 config.min_url_visit_count = 2; |
| 105 config.max_resources_per_entry = 4; |
| 106 config.max_consecutive_misses = 2; |
| 107 predictor_.reset(new ResourcePrefetchPredictor(config, &profile_)); |
| 108 predictor_->SetTablesForTesting(mock_tables_); |
| 109 } |
| 110 |
| 111 MessageLoop loop_; |
| 112 content::TestBrowserThread ui_thread_; |
| 113 content::TestBrowserThread db_thread_; |
| 114 TestingProfile profile_; |
| 115 |
| 116 scoped_ptr<ResourcePrefetchPredictor> predictor_; |
| 117 scoped_refptr<MockResourcePrefetchPredictorTables> mock_tables_; |
| 118 UrlTableRows test_url_rows_; |
| 119 history::URLDatabase* url_db_; |
| 120 }; |
| 121 |
| 122 ResourcePrefetchPredictorTest::ResourcePrefetchPredictorTest() |
| 123 : loop_(MessageLoop::TYPE_DEFAULT), |
| 124 ui_thread_(content::BrowserThread::UI, &loop_), |
| 125 db_thread_(content::BrowserThread::DB, &loop_), |
| 126 predictor_(NULL), |
| 127 mock_tables_(new MockResourcePrefetchPredictorTables()) { |
| 128 test_url_rows_.push_back(UrlTableRow( |
| 129 "http://www.google.com", |
| 130 "http://google.com/style1.css", |
| 131 ResourceType::STYLESHEET, |
| 132 3, 2, 1, 1.0)); |
| 133 test_url_rows_.push_back(UrlTableRow( |
| 134 "http://www.google.com", |
| 135 "http://google.com/script3.js", |
| 136 ResourceType::SCRIPT, |
| 137 4, 0, 1, 2.1)); |
| 138 test_url_rows_.push_back(UrlTableRow( |
| 139 "http://www.google.com", |
| 140 "http://google.com/script4.js", |
| 141 ResourceType::SCRIPT, |
| 142 11, 0, 0, 2.1)); |
| 143 test_url_rows_.push_back(UrlTableRow( |
| 144 "http://www.google.com", |
| 145 "http://google.com/image1.png", |
| 146 ResourceType::IMAGE, |
| 147 6, 3, 0, 2.2)); |
| 148 test_url_rows_.push_back(UrlTableRow( |
| 149 "http://www.google.com", |
| 150 "http://google.com/a.font", |
| 151 ResourceType::LAST_TYPE, |
| 152 2, 0, 0, 5.1)); |
| 153 |
| 154 test_url_rows_.push_back(UrlTableRow( |
| 155 "http://www.reddit.com", |
| 156 "http://reddit-resource.com/script1.js", |
| 157 ResourceType::SCRIPT, |
| 158 4, 0, 1, 1.0)); |
| 159 test_url_rows_.push_back(UrlTableRow( |
| 160 "http://www.reddit.com", |
| 161 "http://reddit-resource.com/script2.js", |
| 162 ResourceType::SCRIPT, |
| 163 2, 0, 0, 2.1)); |
| 164 |
| 165 test_url_rows_.push_back(UrlTableRow( |
| 166 "http://www.yahoo.com", |
| 167 "http://google.com/image.png", |
| 168 ResourceType::IMAGE, |
| 169 20, 1, 0, 10.0)); |
| 170 } |
| 171 |
| 172 ResourcePrefetchPredictorTest::~ResourcePrefetchPredictorTest() { |
| 173 } |
| 174 |
| 175 void ResourcePrefetchPredictorTest::SetUp() { |
| 176 profile_.CreateHistoryService(true, false); |
| 177 profile_.BlockUntilHistoryProcessesPendingRequests(); |
| 178 EXPECT_TRUE(profile_.GetHistoryService(Profile::EXPLICIT_ACCESS)); |
| 179 url_db_ = profile_.GetHistoryService( |
| 180 Profile::EXPLICIT_ACCESS)->InMemoryDatabase(); |
| 181 |
| 182 // Initialize the predictor with empty data. |
| 183 ResetPredictor(); |
| 184 EXPECT_EQ(predictor_->initialization_state_, |
| 185 ResourcePrefetchPredictor::NOT_INITIALIZED); |
| 186 EXPECT_CALL(*mock_tables_, GetAllRows(Pointee(ContainerEq(UrlTableRows())))); |
| 187 predictor_->LazilyInitialize(); |
| 188 profile_.BlockUntilHistoryProcessesPendingRequests(); |
| 189 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); |
| 190 EXPECT_EQ(predictor_->initialization_state_, |
| 191 ResourcePrefetchPredictor::INITIALIZED); |
| 192 } |
| 193 |
| 194 void ResourcePrefetchPredictorTest::TearDown() { |
| 195 predictor_.reset(NULL); |
| 196 profile_.DestroyHistoryService(); |
| 197 } |
| 198 |
| 199 TEST_F(ResourcePrefetchPredictorTest, LazilyInitializeEmpty) { |
| 200 // Tests that the predictor initializes correctly without any data. |
| 201 EXPECT_TRUE(predictor_->url_table_cache_.empty()); |
| 202 } |
| 203 |
| 204 TEST_F(ResourcePrefetchPredictorTest, LazilyInitializeWithData) { |
| 205 // Tests that the history and the db tables data are loaded correctly. |
| 206 AddUrlToHistory("http://www.google.com", 4, 12345); |
| 207 AddUrlToHistory("http://www.yahoo.com", 2, 12346); |
| 208 |
| 209 EXPECT_CALL(*mock_tables_, GetAllRows(Pointee(ContainerEq(UrlTableRows())))) |
| 210 .WillOnce(SetArgPointee<0>(test_url_rows_)); |
| 211 |
| 212 std::vector<GURL> urls_to_delete; |
| 213 urls_to_delete.push_back(GURL("http://www.reddit.com")); |
| 214 EXPECT_CALL(*mock_tables_, DeleteRowsForUrls(ContainerEq(urls_to_delete))); |
| 215 |
| 216 ResetPredictor(); |
| 217 predictor_->LazilyInitialize(); |
| 218 loop_.RunAllPending(); |
| 219 |
| 220 // Test that the internal variables correctly initialized. |
| 221 EXPECT_EQ(predictor_->initialization_state_, |
| 222 ResourcePrefetchPredictor::INITIALIZED); |
| 223 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); |
| 224 EXPECT_EQ(2, static_cast<int>(predictor_->url_table_cache_.size())); |
| 225 |
| 226 UrlTableRows google_rows(test_url_rows_.begin(), |
| 227 test_url_rows_.begin() + 5); |
| 228 std::sort(google_rows.begin(), google_rows.end(), |
| 229 ResourcePrefetchPredictorTables::UrlTableRowSorter()); |
| 230 EXPECT_EQ(predictor_->url_table_cache_[GURL("http://www.google.com")].rows, |
| 231 google_rows); |
| 232 EXPECT_EQ( |
| 233 predictor_->url_table_cache_[GURL("http://www.google.com")].last_visit, |
| 234 base::Time::FromTimeT(12345)); |
| 235 |
| 236 UrlTableRows yahoo_rows(test_url_rows_.begin() + 7, |
| 237 test_url_rows_.begin() + 8); |
| 238 EXPECT_EQ(predictor_->url_table_cache_[GURL("http://www.yahoo.com")].rows, |
| 239 yahoo_rows); |
| 240 EXPECT_EQ( |
| 241 predictor_->url_table_cache_[GURL("http://www.yahoo.com")].last_visit, |
| 242 base::Time::FromTimeT(12346)); |
| 243 } |
| 244 |
| 245 TEST_F(ResourcePrefetchPredictorTest, NavigationNotRecorded) { |
| 246 // Single navigation but history count is low, so should not record. |
| 247 AddUrlToHistory("http://www.google.com", 1, 12345); |
| 248 |
| 249 URLRequestSummary main_frame = CreateURLRequestSummary( |
| 250 1, 1, "http://www.google.com", "http://www.google.com", |
| 251 ResourceType::MAIN_FRAME, "", false); |
| 252 predictor_->RecordURLRequest(main_frame); |
| 253 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 254 |
| 255 // Now add a few subresources. |
| 256 URLRequestSummary resource1 = CreateURLRequestSummary( |
| 257 1, 1, "http://www.google.com", "http://google.com/style1.css", |
| 258 ResourceType::STYLESHEET, "text/css", false); |
| 259 predictor_->RecordUrlResponse(resource1); |
| 260 URLRequestSummary resource2 = CreateURLRequestSummary( |
| 261 1, 1, "http://www.google.com", "http://google.com/script1.js", |
| 262 ResourceType::SCRIPT, "text/javascript", false); |
| 263 predictor_->RecordUrlResponse(resource2); |
| 264 URLRequestSummary resource3 = CreateURLRequestSummary( |
| 265 1, 1, "http://www.google.com", "http://google.com/script2.js", |
| 266 ResourceType::SCRIPT, "text/javascript", false); |
| 267 predictor_->RecordUrlResponse(resource3); |
| 268 predictor_->OnNavigationComplete(main_frame.navigation_id); |
| 269 } |
| 270 |
| 271 TEST_F(ResourcePrefetchPredictorTest, NavigationUrlNotInDB) { |
| 272 // Single navigation that will be recorded. Will check for duplicate |
| 273 // resources and also for number of resources saved. |
| 274 AddUrlToHistory("http://www.google.com", 4, 12345); |
| 275 |
| 276 URLRequestSummary main_frame = CreateURLRequestSummary( |
| 277 1, 1, "http://www.google.com", "http://www.google.com", |
| 278 ResourceType::MAIN_FRAME, "", false); |
| 279 predictor_->RecordURLRequest(main_frame); |
| 280 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 281 |
| 282 URLRequestSummary resource1 = CreateURLRequestSummary( |
| 283 1, 1, "http://www.google.com", "http://google.com/style1.css", |
| 284 ResourceType::STYLESHEET, "text/css", false); |
| 285 predictor_->RecordUrlResponse(resource1); |
| 286 URLRequestSummary resource2 = CreateURLRequestSummary( |
| 287 1, 1, "http://www.google.com", "http://google.com/script1.js", |
| 288 ResourceType::SCRIPT, "text/javascript", false); |
| 289 predictor_->RecordUrlResponse(resource2); |
| 290 URLRequestSummary resource3 = CreateURLRequestSummary( |
| 291 1, 1, "http://www.google.com", "http://google.com/script2.js", |
| 292 ResourceType::SCRIPT, "text/javascript", false); |
| 293 predictor_->RecordUrlResponse(resource3); |
| 294 URLRequestSummary resource4 = CreateURLRequestSummary( |
| 295 1, 1, "http://www.google.com", "http://google.com/script1.js", |
| 296 ResourceType::SCRIPT, "text/javascript", true); |
| 297 predictor_->RecordUrlResponse(resource4); |
| 298 URLRequestSummary resource5 = CreateURLRequestSummary( |
| 299 1, 1, "http://www.google.com", "http://google.com/image1.png", |
| 300 ResourceType::IMAGE, "image/png", false); |
| 301 predictor_->RecordUrlResponse(resource5); |
| 302 URLRequestSummary resource6 = CreateURLRequestSummary( |
| 303 1, 1, "http://www.google.com", "http://google.com/image2.png", |
| 304 ResourceType::IMAGE, "image/png", false); |
| 305 predictor_->RecordUrlResponse(resource6); |
| 306 URLRequestSummary resource7 = CreateURLRequestSummary( |
| 307 1, 1, "http://www.google.com", "http://google.com/style2.css", |
| 308 ResourceType::STYLESHEET, "text/css", false); |
| 309 predictor_->OnSubresourceLoadedFromMemory( |
| 310 resource7.navigation_id, |
| 311 resource7.resource_url, |
| 312 resource7.mime_type, |
| 313 resource7.resource_type); |
| 314 |
| 315 UrlTableRows db_rows; |
| 316 db_rows.push_back(UrlTableRow( |
| 317 "http://www.google.com", "http://google.com/style1.css", |
| 318 ResourceType::STYLESHEET, 1, 0, 0, 1.0)); |
| 319 db_rows.push_back(UrlTableRow( |
| 320 "http://www.google.com", "http://google.com/script1.js", |
| 321 ResourceType::SCRIPT, 1, 0, 0, 2.0)); |
| 322 db_rows.push_back(UrlTableRow( |
| 323 "http://www.google.com", "http://google.com/script2.js", |
| 324 ResourceType::SCRIPT, 1, 0, 0, 3.0)); |
| 325 db_rows.push_back(UrlTableRow( |
| 326 "http://www.google.com", "http://google.com/style2.css", |
| 327 ResourceType::STYLESHEET, 1, 0, 0, 7.0)); |
| 328 EXPECT_CALL(*mock_tables_, |
| 329 UpdateRowsForUrl(GURL("http://www.google.com"), |
| 330 ContainerEq(db_rows))); |
| 331 |
| 332 predictor_->OnNavigationComplete(main_frame.navigation_id); |
| 333 } |
| 334 |
| 335 TEST_F(ResourcePrefetchPredictorTest, NavigationUrlInDB) { |
| 336 // Tests that navigation is recoreded correctly for URL already present in |
| 337 // the database cache. |
| 338 AddUrlToHistory("http://www.google.com", 4, 12345); |
| 339 |
| 340 EXPECT_CALL(*mock_tables_, GetAllRows(Pointee(ContainerEq(UrlTableRows())))) |
| 341 .WillOnce(SetArgPointee<0>(test_url_rows_)); |
| 342 |
| 343 std::vector<GURL> urls_to_delete; |
| 344 urls_to_delete.push_back(GURL("http://www.reddit.com")); |
| 345 urls_to_delete.push_back(GURL("http://www.yahoo.com")); |
| 346 EXPECT_CALL(*mock_tables_, DeleteRowsForUrls(ContainerEq(urls_to_delete))); |
| 347 |
| 348 ResetPredictor(); |
| 349 predictor_->LazilyInitialize(); |
| 350 loop_.RunAllPending(); |
| 351 |
| 352 URLRequestSummary main_frame = CreateURLRequestSummary( |
| 353 1, 1, "http://www.google.com", "http://www.google.com", |
| 354 ResourceType::MAIN_FRAME, "", false); |
| 355 predictor_->RecordURLRequest(main_frame); |
| 356 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 357 |
| 358 URLRequestSummary resource1 = CreateURLRequestSummary( |
| 359 1, 1, "http://www.google.com", "http://google.com/style1.css", |
| 360 ResourceType::STYLESHEET, "text/css", false); |
| 361 predictor_->RecordUrlResponse(resource1); |
| 362 URLRequestSummary resource2 = CreateURLRequestSummary( |
| 363 1, 1, "http://www.google.com", "http://google.com/script1.js", |
| 364 ResourceType::SCRIPT, "text/javascript", false); |
| 365 predictor_->RecordUrlResponse(resource2); |
| 366 URLRequestSummary resource3 = CreateURLRequestSummary( |
| 367 1, 1, "http://www.google.com", "http://google.com/script2.js", |
| 368 ResourceType::SCRIPT, "text/javascript", false); |
| 369 predictor_->RecordUrlResponse(resource3); |
| 370 URLRequestSummary resource4 = CreateURLRequestSummary( |
| 371 1, 1, "http://www.google.com", "http://google.com/script1.js", |
| 372 ResourceType::SCRIPT, "text/javascript", true); |
| 373 predictor_->RecordUrlResponse(resource4); |
| 374 URLRequestSummary resource5 = CreateURLRequestSummary( |
| 375 1, 1, "http://www.google.com", "http://google.com/image1.png", |
| 376 ResourceType::IMAGE, "image/png", false); |
| 377 predictor_->RecordUrlResponse(resource5); |
| 378 URLRequestSummary resource6 = CreateURLRequestSummary( |
| 379 1, 1, "http://www.google.com", "http://google.com/image2.png", |
| 380 ResourceType::IMAGE, "image/png", false); |
| 381 predictor_->RecordUrlResponse(resource6); |
| 382 URLRequestSummary resource7 = CreateURLRequestSummary( |
| 383 1, 1, "http://www.google.com", "http://google.com/style2.css", |
| 384 ResourceType::STYLESHEET, "text/css", false); |
| 385 predictor_->OnSubresourceLoadedFromMemory( |
| 386 resource7.navigation_id, |
| 387 resource7.resource_url, |
| 388 resource7.mime_type, |
| 389 resource7.resource_type); |
| 390 |
| 391 UrlTableRows db_rows; |
| 392 db_rows.push_back(UrlTableRow( |
| 393 "http://www.google.com", "http://google.com/style1.css", |
| 394 ResourceType::STYLESHEET, 4, 2, 0, 1.0)); |
| 395 db_rows.push_back(UrlTableRow( |
| 396 "http://www.google.com", "http://google.com/script1.js", |
| 397 ResourceType::SCRIPT, 1, 0, 0, 2.0)); |
| 398 db_rows.push_back(UrlTableRow( |
| 399 "http://www.google.com", "http://google.com/script4.js", |
| 400 ResourceType::SCRIPT, 11, 1, 1, 2.1)); |
| 401 db_rows.push_back(UrlTableRow( |
| 402 "http://www.google.com", "http://google.com/script2.js", |
| 403 ResourceType::SCRIPT, 1, 0, 0, 3.0)); |
| 404 EXPECT_CALL(*mock_tables_, |
| 405 UpdateRowsForUrl(GURL("http://www.google.com"), |
| 406 ContainerEq(db_rows))); |
| 407 |
| 408 predictor_->OnNavigationComplete(main_frame.navigation_id); |
| 409 } |
| 410 |
| 411 TEST_F(ResourcePrefetchPredictorTest, NavigationUrlNotInDBAndDBFull) { |
| 412 // Tests that a URL is deleted before another is added if the cache is full. |
| 413 AddUrlToHistory("http://www.google.com", 4, 12345); |
| 414 AddUrlToHistory("http://www.reddit.com", 4, 12340); // Should be deleted. |
| 415 AddUrlToHistory("http://www.yahoo.com", 4, 12350); |
| 416 AddUrlToHistory("http://www.nike.com", 4, 10000); |
| 417 |
| 418 EXPECT_CALL(*mock_tables_, GetAllRows(Pointee(ContainerEq(UrlTableRows())))) |
| 419 .WillOnce(SetArgPointee<0>(test_url_rows_)); |
| 420 |
| 421 ResetPredictor(); |
| 422 predictor_->LazilyInitialize(); |
| 423 loop_.RunAllPending(); |
| 424 EXPECT_EQ(3, static_cast<int>(predictor_->url_table_cache_.size())); |
| 425 |
| 426 URLRequestSummary main_frame = CreateURLRequestSummary( |
| 427 1, 1, "http://www.nike.com", "http://www.nike.com", |
| 428 ResourceType::MAIN_FRAME, "", false); |
| 429 predictor_->RecordURLRequest(main_frame); |
| 430 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 431 |
| 432 URLRequestSummary resource1 = CreateURLRequestSummary( |
| 433 1, 1, "http://www.nike.com", "http://nike.com/style1.css", |
| 434 ResourceType::STYLESHEET, "text/css", false); |
| 435 predictor_->RecordUrlResponse(resource1); |
| 436 URLRequestSummary resource2 = CreateURLRequestSummary( |
| 437 1, 1, "http://www.nike.com", "http://nike.com/image2.png", |
| 438 ResourceType::IMAGE, "image/png", false); |
| 439 predictor_->RecordUrlResponse(resource2); |
| 440 |
| 441 std::vector<GURL> urls_to_delete; |
| 442 urls_to_delete.push_back(GURL("http://www.reddit.com")); |
| 443 EXPECT_CALL(*mock_tables_, DeleteRowsForUrls(ContainerEq(urls_to_delete))); |
| 444 |
| 445 UrlTableRows db_rows; |
| 446 db_rows.push_back(UrlTableRow( |
| 447 "http://www.nike.com", "http://nike.com/style1.css", |
| 448 ResourceType::STYLESHEET, 1, 0, 0, 1.0)); |
| 449 db_rows.push_back(UrlTableRow( |
| 450 "http://www.nike.com", "http://nike.com/image2.png", |
| 451 ResourceType::IMAGE, 1, 0, 0, 2.0)); |
| 452 EXPECT_CALL(*mock_tables_, |
| 453 UpdateRowsForUrl(GURL("http://www.nike.com"), |
| 454 ContainerEq(db_rows))); |
| 455 |
| 456 predictor_->OnNavigationComplete(main_frame.navigation_id); |
| 457 } |
| 458 |
| 459 TEST_F(ResourcePrefetchPredictorTest, DeleteUrls) { |
| 460 // Add some dummy entries to cache. |
| 461 predictor_->url_table_cache_[GURL("http://www.google.com")]; |
| 462 predictor_->url_table_cache_[GURL("http://www.yahoo.com")]; |
| 463 predictor_->url_table_cache_[GURL("http://www.apple.com")]; |
| 464 predictor_->url_table_cache_[GURL("http://www.nike.com")]; |
| 465 predictor_->url_table_cache_[GURL("http://www.reddit.com")]; |
| 466 |
| 467 history::URLRows rows; |
| 468 rows.push_back(history::URLRow(GURL("http://www.apple.com"))); |
| 469 rows.push_back(history::URLRow(GURL("http://www.yahoo.com"))); |
| 470 |
| 471 std::vector<GURL> urls_to_delete; |
| 472 urls_to_delete.push_back(GURL("http://www.apple.com")); |
| 473 urls_to_delete.push_back(GURL("http://www.yahoo.com")); |
| 474 EXPECT_CALL(*mock_tables_, DeleteRowsForUrls(ContainerEq(urls_to_delete))); |
| 475 predictor_->DeleteUrls(rows); |
| 476 EXPECT_EQ(3, static_cast<int>(predictor_->url_table_cache_.size())); |
| 477 |
| 478 EXPECT_CALL(*mock_tables_, DeleteAllRows()); |
| 479 |
| 480 predictor_->DeleteAllUrls(); |
| 481 EXPECT_TRUE(predictor_->url_table_cache_.empty()); |
| 482 } |
| 483 |
| 484 TEST_F(ResourcePrefetchPredictorTest, OnMainFrameRequest) { |
| 485 URLRequestSummary summary1 = CreateURLRequestSummary( |
| 486 1, 1, "http://www.google.com", "http://www.google.com", |
| 487 ResourceType::MAIN_FRAME, "", false); |
| 488 URLRequestSummary summary2 = CreateURLRequestSummary( |
| 489 1, 2, "http://www.google.com", "http://www.google.com", |
| 490 ResourceType::MAIN_FRAME, "", false); |
| 491 URLRequestSummary summary3 = CreateURLRequestSummary( |
| 492 2, 1, "http://www.yahoo.com", "http://www.yahoo.com", |
| 493 ResourceType::MAIN_FRAME, "", false); |
| 494 |
| 495 predictor_->OnMainFrameRequest(summary1); |
| 496 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 497 predictor_->OnMainFrameRequest(summary2); |
| 498 EXPECT_EQ(2, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 499 predictor_->OnMainFrameRequest(summary3); |
| 500 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 501 |
| 502 // Insert anther with same navigation id. It should replace. |
| 503 URLRequestSummary summary4 = CreateURLRequestSummary( |
| 504 1, 1, "http://www.nike.com", "http://www.nike.com", |
| 505 ResourceType::MAIN_FRAME, "", false); |
| 506 URLRequestSummary summary5 = CreateURLRequestSummary( |
| 507 1, 2, "http://www.google.com", "http://www.google.com", |
| 508 ResourceType::MAIN_FRAME, "", false); |
| 509 |
| 510 predictor_->OnMainFrameRequest(summary4); |
| 511 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 512 |
| 513 // Change this creation time so that it will go away on the next insert. |
| 514 summary5.navigation_id.creation_time = base::TimeTicks::Now() - |
| 515 base::TimeDelta::FromDays(1); |
| 516 predictor_->OnMainFrameRequest(summary5); |
| 517 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 518 |
| 519 URLRequestSummary summary6 = CreateURLRequestSummary( |
| 520 3, 1, "http://www.shoes.com", "http://www.shoes.com", |
| 521 ResourceType::MAIN_FRAME, "", false); |
| 522 predictor_->OnMainFrameRequest(summary6); |
| 523 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 524 |
| 525 EXPECT_TRUE(predictor_->inflight_navigations_.find(summary3.navigation_id) != |
| 526 predictor_->inflight_navigations_.end()); |
| 527 EXPECT_TRUE(predictor_->inflight_navigations_.find(summary4.navigation_id) != |
| 528 predictor_->inflight_navigations_.end()); |
| 529 EXPECT_TRUE(predictor_->inflight_navigations_.find(summary6.navigation_id) != |
| 530 predictor_->inflight_navigations_.end()); |
| 531 } |
| 532 |
| 533 TEST_F(ResourcePrefetchPredictorTest, OnMainFrameRedirect) { |
| 534 URLRequestSummary summary1 = CreateURLRequestSummary( |
| 535 1, 1, "http://www.google.com", "http://www.google.com", |
| 536 ResourceType::MAIN_FRAME, "", false); |
| 537 URLRequestSummary summary2 = CreateURLRequestSummary( |
| 538 1, 2, "http://www.google.com", "http://www.google.com", |
| 539 ResourceType::MAIN_FRAME, "", false); |
| 540 URLRequestSummary summary3 = CreateURLRequestSummary( |
| 541 2, 1, "http://www.yahoo.com", "http://www.yahoo.com", |
| 542 ResourceType::MAIN_FRAME, "", false); |
| 543 |
| 544 predictor_->OnMainFrameRedirect(summary1); |
| 545 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); |
| 546 |
| 547 predictor_->OnMainFrameRequest(summary1); |
| 548 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 549 predictor_->OnMainFrameRequest(summary2); |
| 550 EXPECT_EQ(2, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 551 |
| 552 predictor_->OnMainFrameRedirect(summary3); |
| 553 EXPECT_EQ(2, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 554 predictor_->OnMainFrameRedirect(summary1); |
| 555 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 556 predictor_->OnMainFrameRedirect(summary2); |
| 557 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); |
| 558 } |
| 559 |
| 560 TEST_F(ResourcePrefetchPredictorTest, OnSubresourceResponse) { |
| 561 // If there is no inflight navigation, nothing happens. |
| 562 URLRequestSummary resource1 = CreateURLRequestSummary( |
| 563 1, 1, "http://www.google.com", "http://google.com/style1.css", |
| 564 ResourceType::STYLESHEET, "text/css", false); |
| 565 predictor_->OnSubresourceResponse(resource1); |
| 566 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); |
| 567 |
| 568 // Add an inflight navigation. |
| 569 URLRequestSummary main_frame1 = CreateURLRequestSummary( |
| 570 1, 1, "http://www.google.com", "http://www.google.com", |
| 571 ResourceType::MAIN_FRAME, "", false); |
| 572 predictor_->OnMainFrameRequest(main_frame1); |
| 573 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 574 |
| 575 // Now add a few subresources. |
| 576 URLRequestSummary resource2 = CreateURLRequestSummary( |
| 577 1, 1, "http://www.google.com", "http://google.com/script1.js", |
| 578 ResourceType::SCRIPT, "text/javascript", false); |
| 579 URLRequestSummary resource3 = CreateURLRequestSummary( |
| 580 1, 1, "http://www.google.com", "http://google.com/script2.js", |
| 581 ResourceType::SCRIPT, "text/javascript", false); |
| 582 predictor_->OnSubresourceResponse(resource1); |
| 583 predictor_->OnSubresourceResponse(resource2); |
| 584 predictor_->OnSubresourceResponse(resource3); |
| 585 |
| 586 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); |
| 587 EXPECT_EQ(3, static_cast<int>( |
| 588 predictor_->inflight_navigations_[main_frame1.navigation_id].size())); |
| 589 EXPECT_TRUE(URLRequestSummaryAreEqual( |
| 590 resource1, |
| 591 predictor_->inflight_navigations_[main_frame1.navigation_id][0])); |
| 592 EXPECT_TRUE(URLRequestSummaryAreEqual( |
| 593 resource2, |
| 594 predictor_->inflight_navigations_[main_frame1.navigation_id][1])); |
| 595 EXPECT_TRUE(URLRequestSummaryAreEqual( |
| 596 resource3, |
| 597 predictor_->inflight_navigations_[main_frame1.navigation_id][2])); |
| 598 } |
| 599 |
| 600 } // namespace predictors |
OLD | NEW |