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 #include <iostream> | |
6 #include "base/memory/ref_counted.h" | |
7 #include "base/memory/scoped_ptr.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "base/run_loop.h" | |
10 #include "base/time/time.h" | |
11 #include "chrome/browser/history/history_service.h" | |
12 #include "chrome/browser/history/history_service_factory.h" | |
13 #include "chrome/browser/history/history_types.h" | |
14 #include "chrome/browser/history/in_memory_database.h" | |
15 #include "chrome/browser/history/url_database.h" | |
16 #include "chrome/browser/predictors/resource_prefetch_predictor.h" | |
17 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" | |
18 #include "chrome/test/base/testing_profile.h" | |
19 #include "content/public/test/test_browser_thread.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using testing::ContainerEq; | |
24 using testing::Pointee; | |
25 using testing::SetArgPointee; | |
26 using testing::StrictMock; | |
27 | |
28 namespace predictors { | |
29 | |
30 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary; | |
31 typedef ResourcePrefetchPredictorTables::ResourceRow ResourceRow; | |
32 typedef std::vector<ResourceRow> ResourceRows; | |
33 typedef ResourcePrefetchPredictorTables::PrefetchData PrefetchData; | |
34 typedef ResourcePrefetchPredictorTables::PrefetchDataMap PrefetchDataMap; | |
35 | |
36 // For printing failures nicely. | |
37 void PrintTo(const ResourceRow& row, ::std::ostream* os) { | |
38 *os << "[" << row.primary_key << "," << row.resource_url | |
39 << "," << row.resource_type << "," << row.number_of_hits | |
40 << "," << row.number_of_misses << "," << row.consecutive_misses | |
41 << "," << row.average_position << "," << row.score << "]"; | |
42 } | |
43 | |
44 void PrintTo(const PrefetchData& data, ::std::ostream* os) { | |
45 *os << "[" << data.key_type << "," << data.primary_key | |
46 << "," << data.last_visit.ToInternalValue() << "]\n"; | |
47 for (ResourceRows::const_iterator it = data.resources.begin(); | |
48 it != data.resources.end(); ++it) { | |
49 *os << "\t\t"; | |
50 PrintTo(*it, os); | |
51 *os << "\n"; | |
52 } | |
53 } | |
54 | |
55 class MockResourcePrefetchPredictorTables | |
56 : public ResourcePrefetchPredictorTables { | |
57 public: | |
58 MockResourcePrefetchPredictorTables() { } | |
59 | |
60 MOCK_METHOD2(GetAllData, void(PrefetchDataMap* url_data_map, | |
61 PrefetchDataMap* host_data_map)); | |
62 MOCK_METHOD2(UpdateData, void(const PrefetchData& url_data, | |
63 const PrefetchData& host_data)); | |
64 MOCK_METHOD2(DeleteData, void(const std::vector<std::string>& urls, | |
65 const std::vector<std::string>& hosts)); | |
66 MOCK_METHOD2(DeleteSingleDataPoint, void(const std::string& key, | |
67 PrefetchKeyType key_type)); | |
68 MOCK_METHOD0(DeleteAllData, void()); | |
69 | |
70 protected: | |
71 ~MockResourcePrefetchPredictorTables() { } | |
72 }; | |
73 | |
74 class ResourcePrefetchPredictorTest : public testing::Test { | |
75 public: | |
76 ResourcePrefetchPredictorTest(); | |
77 virtual ~ResourcePrefetchPredictorTest(); | |
78 virtual void SetUp() OVERRIDE; | |
79 virtual void TearDown() OVERRIDE; | |
80 | |
81 protected: | |
82 void AddUrlToHistory(const std::string& url, int visit_count) { | |
83 HistoryServiceFactory::GetForProfile(profile_.get(), | |
84 Profile::EXPLICIT_ACCESS)-> | |
85 AddPageWithDetails( | |
86 GURL(url), | |
87 base::string16(), | |
88 visit_count, | |
89 0, | |
90 base::Time::Now(), | |
91 false, | |
92 history::SOURCE_BROWSED); | |
93 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
94 } | |
95 | |
96 NavigationID CreateNavigationID(int process_id, | |
97 int render_view_id, | |
98 const std::string& main_frame_url) { | |
99 NavigationID navigation_id; | |
100 navigation_id.render_process_id = process_id; | |
101 navigation_id.render_view_id = render_view_id; | |
102 navigation_id.main_frame_url = GURL(main_frame_url); | |
103 navigation_id.creation_time = base::TimeTicks::Now(); | |
104 return navigation_id; | |
105 } | |
106 | |
107 ResourcePrefetchPredictor::URLRequestSummary CreateURLRequestSummary( | |
108 int process_id, | |
109 int render_view_id, | |
110 const std::string& main_frame_url, | |
111 const std::string& resource_url, | |
112 ResourceType::Type resource_type, | |
113 const std::string& mime_type, | |
114 bool was_cached) { | |
115 ResourcePrefetchPredictor::URLRequestSummary summary; | |
116 summary.navigation_id = CreateNavigationID(process_id, render_view_id, | |
117 main_frame_url); | |
118 summary.resource_url = GURL(resource_url); | |
119 summary.resource_type = resource_type; | |
120 summary.mime_type = mime_type; | |
121 summary.was_cached = was_cached; | |
122 return summary; | |
123 } | |
124 | |
125 void InitializePredictor() { | |
126 predictor_->StartInitialization(); | |
127 base::RunLoop loop; | |
128 loop.RunUntilIdle(); // Runs the DB lookup. | |
129 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
130 } | |
131 | |
132 bool URLRequestSummaryAreEqual(const URLRequestSummary& lhs, | |
133 const URLRequestSummary& rhs) { | |
134 return lhs.navigation_id == rhs.navigation_id && | |
135 lhs.resource_url == rhs.resource_url && | |
136 lhs.resource_type == rhs.resource_type && | |
137 lhs.mime_type == rhs.mime_type && | |
138 lhs.was_cached == rhs.was_cached; | |
139 } | |
140 | |
141 void ResetPredictor() { | |
142 ResourcePrefetchPredictorConfig config; | |
143 config.max_urls_to_track = 3; | |
144 config.max_hosts_to_track = 2; | |
145 config.min_url_visit_count = 2; | |
146 config.max_resources_per_entry = 4; | |
147 config.max_consecutive_misses = 2; | |
148 | |
149 // TODO(shishir): Enable the prefetching mode in the tests. | |
150 config.mode |= ResourcePrefetchPredictorConfig::URL_LEARNING; | |
151 config.mode |= ResourcePrefetchPredictorConfig::HOST_LEARNING; | |
152 predictor_.reset(new ResourcePrefetchPredictor(config, profile_.get())); | |
153 predictor_->set_mock_tables(mock_tables_); | |
154 } | |
155 | |
156 void InitializeSampleData(); | |
157 | |
158 base::MessageLoop loop_; | |
159 content::TestBrowserThread ui_thread_; | |
160 content::TestBrowserThread db_thread_; | |
161 scoped_ptr<TestingProfile> profile_; | |
162 | |
163 scoped_ptr<ResourcePrefetchPredictor> predictor_; | |
164 scoped_refptr<StrictMock<MockResourcePrefetchPredictorTables> > mock_tables_; | |
165 | |
166 PrefetchDataMap test_url_data_; | |
167 PrefetchDataMap test_host_data_; | |
168 PrefetchData empty_url_data_; | |
169 PrefetchData empty_host_data_; | |
170 }; | |
171 | |
172 ResourcePrefetchPredictorTest::ResourcePrefetchPredictorTest() | |
173 : loop_(base::MessageLoop::TYPE_DEFAULT), | |
174 ui_thread_(content::BrowserThread::UI, &loop_), | |
175 db_thread_(content::BrowserThread::DB, &loop_), | |
176 profile_(new TestingProfile()), | |
177 mock_tables_(new StrictMock<MockResourcePrefetchPredictorTables>()), | |
178 empty_url_data_(PREFETCH_KEY_TYPE_URL, std::string()), | |
179 empty_host_data_(PREFETCH_KEY_TYPE_HOST, std::string()) {} | |
180 | |
181 ResourcePrefetchPredictorTest::~ResourcePrefetchPredictorTest() { | |
182 profile_.reset(NULL); | |
183 loop_.RunUntilIdle(); | |
184 } | |
185 | |
186 void ResourcePrefetchPredictorTest::SetUp() { | |
187 InitializeSampleData(); | |
188 | |
189 ASSERT_TRUE(profile_->CreateHistoryService(true, false)); | |
190 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
191 EXPECT_TRUE(HistoryServiceFactory::GetForProfile(profile_.get(), | |
192 Profile::EXPLICIT_ACCESS)); | |
193 // Initialize the predictor with empty data. | |
194 ResetPredictor(); | |
195 EXPECT_EQ(predictor_->initialization_state_, | |
196 ResourcePrefetchPredictor::NOT_INITIALIZED); | |
197 EXPECT_CALL(*mock_tables_.get(), | |
198 GetAllData(Pointee(ContainerEq(PrefetchDataMap())), | |
199 Pointee(ContainerEq(PrefetchDataMap())))); | |
200 InitializePredictor(); | |
201 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); | |
202 EXPECT_EQ(predictor_->initialization_state_, | |
203 ResourcePrefetchPredictor::INITIALIZED); | |
204 } | |
205 | |
206 void ResourcePrefetchPredictorTest::TearDown() { | |
207 predictor_.reset(NULL); | |
208 profile_->DestroyHistoryService(); | |
209 } | |
210 | |
211 void ResourcePrefetchPredictorTest::InitializeSampleData() { | |
212 { // Url data. | |
213 PrefetchData google(PREFETCH_KEY_TYPE_URL, "http://www.google.com/"); | |
214 google.last_visit = base::Time::FromInternalValue(1); | |
215 google.resources.push_back(ResourceRow(std::string(), | |
216 "http://google.com/style1.css", | |
217 ResourceType::STYLESHEET, | |
218 3, | |
219 2, | |
220 1, | |
221 1.0)); | |
222 google.resources.push_back(ResourceRow(std::string(), | |
223 "http://google.com/script3.js", | |
224 ResourceType::SCRIPT, | |
225 4, | |
226 0, | |
227 1, | |
228 2.1)); | |
229 google.resources.push_back(ResourceRow(std::string(), | |
230 "http://google.com/script4.js", | |
231 ResourceType::SCRIPT, | |
232 11, | |
233 0, | |
234 0, | |
235 2.1)); | |
236 google.resources.push_back(ResourceRow(std::string(), | |
237 "http://google.com/image1.png", | |
238 ResourceType::IMAGE, | |
239 6, | |
240 3, | |
241 0, | |
242 2.2)); | |
243 google.resources.push_back(ResourceRow(std::string(), | |
244 "http://google.com/a.font", | |
245 ResourceType::LAST_TYPE, | |
246 2, | |
247 0, | |
248 0, | |
249 5.1)); | |
250 | |
251 PrefetchData reddit(PREFETCH_KEY_TYPE_URL, "http://www.reddit.com/"); | |
252 reddit.last_visit = base::Time::FromInternalValue(2); | |
253 reddit.resources | |
254 .push_back(ResourceRow(std::string(), | |
255 "http://reddit-resource.com/script1.js", | |
256 ResourceType::SCRIPT, | |
257 4, | |
258 0, | |
259 1, | |
260 1.0)); | |
261 reddit.resources | |
262 .push_back(ResourceRow(std::string(), | |
263 "http://reddit-resource.com/script2.js", | |
264 ResourceType::SCRIPT, | |
265 2, | |
266 0, | |
267 0, | |
268 2.1)); | |
269 | |
270 PrefetchData yahoo(PREFETCH_KEY_TYPE_URL, "http://www.yahoo.com/"); | |
271 yahoo.last_visit = base::Time::FromInternalValue(3); | |
272 yahoo.resources.push_back(ResourceRow(std::string(), | |
273 "http://google.com/image.png", | |
274 ResourceType::IMAGE, | |
275 20, | |
276 1, | |
277 0, | |
278 10.0)); | |
279 | |
280 test_url_data_.clear(); | |
281 test_url_data_.insert(std::make_pair("http://www.google.com/", google)); | |
282 test_url_data_.insert(std::make_pair("http://www.reddit.com/", reddit)); | |
283 test_url_data_.insert(std::make_pair("http://www.yahoo.com/", yahoo)); | |
284 } | |
285 | |
286 { // Host data. | |
287 PrefetchData facebook(PREFETCH_KEY_TYPE_HOST, "www.facebook.com"); | |
288 facebook.last_visit = base::Time::FromInternalValue(4); | |
289 facebook.resources | |
290 .push_back(ResourceRow(std::string(), | |
291 "http://www.facebook.com/style.css", | |
292 ResourceType::STYLESHEET, | |
293 5, | |
294 2, | |
295 1, | |
296 1.1)); | |
297 facebook.resources | |
298 .push_back(ResourceRow(std::string(), | |
299 "http://www.facebook.com/script.js", | |
300 ResourceType::SCRIPT, | |
301 4, | |
302 0, | |
303 1, | |
304 2.1)); | |
305 facebook.resources | |
306 .push_back(ResourceRow(std::string(), | |
307 "http://www.facebook.com/image.png", | |
308 ResourceType::IMAGE, | |
309 6, | |
310 3, | |
311 0, | |
312 2.2)); | |
313 facebook.resources.push_back(ResourceRow(std::string(), | |
314 "http://www.facebook.com/a.font", | |
315 ResourceType::LAST_TYPE, | |
316 2, | |
317 0, | |
318 0, | |
319 5.1)); | |
320 facebook.resources | |
321 .push_back(ResourceRow(std::string(), | |
322 "http://www.resources.facebook.com/script.js", | |
323 ResourceType::SCRIPT, | |
324 11, | |
325 0, | |
326 0, | |
327 8.5)); | |
328 | |
329 PrefetchData yahoo(PREFETCH_KEY_TYPE_HOST, "www.yahoo.com"); | |
330 yahoo.last_visit = base::Time::FromInternalValue(5); | |
331 yahoo.resources.push_back(ResourceRow(std::string(), | |
332 "http://google.com/image.png", | |
333 ResourceType::IMAGE, | |
334 20, | |
335 1, | |
336 0, | |
337 10.0)); | |
338 | |
339 test_host_data_.clear(); | |
340 test_host_data_.insert(std::make_pair("www.facebook.com", facebook)); | |
341 test_host_data_.insert(std::make_pair("www.yahoo.com", yahoo)); | |
342 } | |
343 } | |
344 | |
345 TEST_F(ResourcePrefetchPredictorTest, LazilyInitializeEmpty) { | |
346 // Tests that the predictor initializes correctly without any data. | |
347 EXPECT_TRUE(predictor_->url_table_cache_->empty()); | |
348 EXPECT_TRUE(predictor_->host_table_cache_->empty()); | |
349 } | |
350 | |
351 TEST_F(ResourcePrefetchPredictorTest, LazilyInitializeWithData) { | |
352 // Tests that the history and the db tables data are loaded correctly. | |
353 AddUrlToHistory("http://www.google.com/", 4); | |
354 AddUrlToHistory("http://www.yahoo.com/", 2); | |
355 | |
356 EXPECT_CALL(*mock_tables_.get(), | |
357 GetAllData(Pointee(ContainerEq(PrefetchDataMap())), | |
358 Pointee(ContainerEq(PrefetchDataMap())))) | |
359 .WillOnce(DoAll(SetArgPointee<0>(test_url_data_), | |
360 SetArgPointee<1>(test_host_data_))); | |
361 | |
362 ResetPredictor(); | |
363 InitializePredictor(); | |
364 | |
365 // Test that the internal variables correctly initialized. | |
366 EXPECT_EQ(predictor_->initialization_state_, | |
367 ResourcePrefetchPredictor::INITIALIZED); | |
368 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); | |
369 | |
370 EXPECT_EQ(test_url_data_, *predictor_->url_table_cache_); | |
371 EXPECT_EQ(test_host_data_, *predictor_->host_table_cache_); | |
372 } | |
373 | |
374 TEST_F(ResourcePrefetchPredictorTest, NavigationNotRecorded) { | |
375 // Single navigation but history count is low, so should not record. | |
376 AddUrlToHistory("http://www.google.com", 1); | |
377 | |
378 URLRequestSummary main_frame = | |
379 CreateURLRequestSummary(1, | |
380 1, | |
381 "http://www.google.com", | |
382 "http://www.google.com", | |
383 ResourceType::MAIN_FRAME, | |
384 std::string(), | |
385 false); | |
386 predictor_->RecordURLRequest(main_frame); | |
387 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
388 | |
389 // Now add a few subresources. | |
390 URLRequestSummary resource1 = CreateURLRequestSummary( | |
391 1, 1, "http://www.google.com", "http://google.com/style1.css", | |
392 ResourceType::STYLESHEET, "text/css", false); | |
393 predictor_->RecordURLResponse(resource1); | |
394 URLRequestSummary resource2 = CreateURLRequestSummary( | |
395 1, 1, "http://www.google.com", "http://google.com/script1.js", | |
396 ResourceType::SCRIPT, "text/javascript", false); | |
397 predictor_->RecordURLResponse(resource2); | |
398 URLRequestSummary resource3 = CreateURLRequestSummary( | |
399 1, 1, "http://www.google.com", "http://google.com/script2.js", | |
400 ResourceType::SCRIPT, "text/javascript", false); | |
401 predictor_->RecordURLResponse(resource3); | |
402 | |
403 PrefetchData host_data(PREFETCH_KEY_TYPE_HOST, "www.google.com"); | |
404 host_data.resources.push_back(ResourceRow(std::string(), | |
405 "http://google.com/style1.css", | |
406 ResourceType::STYLESHEET, | |
407 1, | |
408 0, | |
409 0, | |
410 1.0)); | |
411 host_data.resources.push_back(ResourceRow(std::string(), | |
412 "http://google.com/script1.js", | |
413 ResourceType::SCRIPT, | |
414 1, | |
415 0, | |
416 0, | |
417 2.0)); | |
418 host_data.resources.push_back(ResourceRow(std::string(), | |
419 "http://google.com/script2.js", | |
420 ResourceType::SCRIPT, | |
421 1, | |
422 0, | |
423 0, | |
424 3.0)); | |
425 EXPECT_CALL(*mock_tables_.get(), UpdateData(empty_url_data_, host_data)); | |
426 | |
427 predictor_->OnNavigationComplete(main_frame.navigation_id); | |
428 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
429 } | |
430 | |
431 TEST_F(ResourcePrefetchPredictorTest, NavigationUrlNotInDB) { | |
432 // Single navigation that will be recorded. Will check for duplicate | |
433 // resources and also for number of resources saved. | |
434 AddUrlToHistory("http://www.google.com", 4); | |
435 | |
436 URLRequestSummary main_frame = | |
437 CreateURLRequestSummary(1, | |
438 1, | |
439 "http://www.google.com", | |
440 "http://www.google.com", | |
441 ResourceType::MAIN_FRAME, | |
442 std::string(), | |
443 false); | |
444 predictor_->RecordURLRequest(main_frame); | |
445 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
446 | |
447 URLRequestSummary resource1 = CreateURLRequestSummary( | |
448 1, 1, "http://www.google.com", "http://google.com/style1.css", | |
449 ResourceType::STYLESHEET, "text/css", false); | |
450 predictor_->RecordURLResponse(resource1); | |
451 URLRequestSummary resource2 = CreateURLRequestSummary( | |
452 1, 1, "http://www.google.com", "http://google.com/script1.js", | |
453 ResourceType::SCRIPT, "text/javascript", false); | |
454 predictor_->RecordURLResponse(resource2); | |
455 URLRequestSummary resource3 = CreateURLRequestSummary( | |
456 1, 1, "http://www.google.com", "http://google.com/script2.js", | |
457 ResourceType::SCRIPT, "text/javascript", false); | |
458 predictor_->RecordURLResponse(resource3); | |
459 URLRequestSummary resource4 = CreateURLRequestSummary( | |
460 1, 1, "http://www.google.com", "http://google.com/script1.js", | |
461 ResourceType::SCRIPT, "text/javascript", true); | |
462 predictor_->RecordURLResponse(resource4); | |
463 URLRequestSummary resource5 = CreateURLRequestSummary( | |
464 1, 1, "http://www.google.com", "http://google.com/image1.png", | |
465 ResourceType::IMAGE, "image/png", false); | |
466 predictor_->RecordURLResponse(resource5); | |
467 URLRequestSummary resource6 = CreateURLRequestSummary( | |
468 1, 1, "http://www.google.com", "http://google.com/image2.png", | |
469 ResourceType::IMAGE, "image/png", false); | |
470 predictor_->RecordURLResponse(resource6); | |
471 URLRequestSummary resource7 = CreateURLRequestSummary( | |
472 1, 1, "http://www.google.com", "http://google.com/style2.css", | |
473 ResourceType::STYLESHEET, "text/css", true); | |
474 predictor_->RecordURLResponse(resource7); | |
475 | |
476 PrefetchData url_data(PREFETCH_KEY_TYPE_URL, "http://www.google.com/"); | |
477 url_data.resources.push_back(ResourceRow(std::string(), | |
478 "http://google.com/style1.css", | |
479 ResourceType::STYLESHEET, | |
480 1, | |
481 0, | |
482 0, | |
483 1.0)); | |
484 url_data.resources.push_back(ResourceRow(std::string(), | |
485 "http://google.com/script1.js", | |
486 ResourceType::SCRIPT, | |
487 1, | |
488 0, | |
489 0, | |
490 2.0)); | |
491 url_data.resources.push_back(ResourceRow(std::string(), | |
492 "http://google.com/script2.js", | |
493 ResourceType::SCRIPT, | |
494 1, | |
495 0, | |
496 0, | |
497 3.0)); | |
498 url_data.resources.push_back(ResourceRow(std::string(), | |
499 "http://google.com/style2.css", | |
500 ResourceType::STYLESHEET, | |
501 1, | |
502 0, | |
503 0, | |
504 7.0)); | |
505 EXPECT_CALL(*mock_tables_.get(), UpdateData(url_data, empty_host_data_)); | |
506 | |
507 PrefetchData host_data(PREFETCH_KEY_TYPE_HOST, "www.google.com"); | |
508 host_data.resources = url_data.resources; | |
509 EXPECT_CALL(*mock_tables_.get(), UpdateData(empty_url_data_, host_data)); | |
510 | |
511 predictor_->OnNavigationComplete(main_frame.navigation_id); | |
512 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
513 } | |
514 | |
515 TEST_F(ResourcePrefetchPredictorTest, NavigationUrlInDB) { | |
516 // Tests that navigation is recorded correctly for URL already present in | |
517 // the database cache. | |
518 AddUrlToHistory("http://www.google.com", 4); | |
519 | |
520 EXPECT_CALL(*mock_tables_.get(), | |
521 GetAllData(Pointee(ContainerEq(PrefetchDataMap())), | |
522 Pointee(ContainerEq(PrefetchDataMap())))) | |
523 .WillOnce(DoAll(SetArgPointee<0>(test_url_data_), | |
524 SetArgPointee<1>(test_host_data_))); | |
525 ResetPredictor(); | |
526 InitializePredictor(); | |
527 EXPECT_EQ(3, static_cast<int>(predictor_->url_table_cache_->size())); | |
528 EXPECT_EQ(2, static_cast<int>(predictor_->host_table_cache_->size())); | |
529 | |
530 URLRequestSummary main_frame = | |
531 CreateURLRequestSummary(1, | |
532 1, | |
533 "http://www.google.com", | |
534 "http://www.google.com", | |
535 ResourceType::MAIN_FRAME, | |
536 std::string(), | |
537 false); | |
538 predictor_->RecordURLRequest(main_frame); | |
539 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
540 | |
541 URLRequestSummary resource1 = CreateURLRequestSummary( | |
542 1, 1, "http://www.google.com", "http://google.com/style1.css", | |
543 ResourceType::STYLESHEET, "text/css", false); | |
544 predictor_->RecordURLResponse(resource1); | |
545 URLRequestSummary resource2 = CreateURLRequestSummary( | |
546 1, 1, "http://www.google.com", "http://google.com/script1.js", | |
547 ResourceType::SCRIPT, "text/javascript", false); | |
548 predictor_->RecordURLResponse(resource2); | |
549 URLRequestSummary resource3 = CreateURLRequestSummary( | |
550 1, 1, "http://www.google.com", "http://google.com/script2.js", | |
551 ResourceType::SCRIPT, "text/javascript", false); | |
552 predictor_->RecordURLResponse(resource3); | |
553 URLRequestSummary resource4 = CreateURLRequestSummary( | |
554 1, 1, "http://www.google.com", "http://google.com/script1.js", | |
555 ResourceType::SCRIPT, "text/javascript", true); | |
556 predictor_->RecordURLResponse(resource4); | |
557 URLRequestSummary resource5 = CreateURLRequestSummary( | |
558 1, 1, "http://www.google.com", "http://google.com/image1.png", | |
559 ResourceType::IMAGE, "image/png", false); | |
560 predictor_->RecordURLResponse(resource5); | |
561 URLRequestSummary resource6 = CreateURLRequestSummary( | |
562 1, 1, "http://www.google.com", "http://google.com/image2.png", | |
563 ResourceType::IMAGE, "image/png", false); | |
564 predictor_->RecordURLResponse(resource6); | |
565 URLRequestSummary resource7 = CreateURLRequestSummary( | |
566 1, 1, "http://www.google.com", "http://google.com/style2.css", | |
567 ResourceType::STYLESHEET, "text/css", true); | |
568 predictor_->RecordURLResponse(resource7); | |
569 | |
570 PrefetchData url_data(PREFETCH_KEY_TYPE_URL, "http://www.google.com/"); | |
571 url_data.resources.push_back(ResourceRow(std::string(), | |
572 "http://google.com/style1.css", | |
573 ResourceType::STYLESHEET, | |
574 4, | |
575 2, | |
576 0, | |
577 1.0)); | |
578 url_data.resources.push_back(ResourceRow(std::string(), | |
579 "http://google.com/script1.js", | |
580 ResourceType::SCRIPT, | |
581 1, | |
582 0, | |
583 0, | |
584 2.0)); | |
585 url_data.resources.push_back(ResourceRow(std::string(), | |
586 "http://google.com/script4.js", | |
587 ResourceType::SCRIPT, | |
588 11, | |
589 1, | |
590 1, | |
591 2.1)); | |
592 url_data.resources.push_back(ResourceRow(std::string(), | |
593 "http://google.com/script2.js", | |
594 ResourceType::SCRIPT, | |
595 1, | |
596 0, | |
597 0, | |
598 3.0)); | |
599 EXPECT_CALL(*mock_tables_.get(), UpdateData(url_data, empty_host_data_)); | |
600 | |
601 EXPECT_CALL( | |
602 *mock_tables_.get(), | |
603 DeleteSingleDataPoint("www.facebook.com", PREFETCH_KEY_TYPE_HOST)); | |
604 | |
605 PrefetchData host_data(PREFETCH_KEY_TYPE_HOST, "www.google.com"); | |
606 host_data.resources.push_back(ResourceRow(std::string(), | |
607 "http://google.com/style1.css", | |
608 ResourceType::STYLESHEET, | |
609 1, | |
610 0, | |
611 0, | |
612 1.0)); | |
613 host_data.resources.push_back(ResourceRow(std::string(), | |
614 "http://google.com/script1.js", | |
615 ResourceType::SCRIPT, | |
616 1, | |
617 0, | |
618 0, | |
619 2.0)); | |
620 host_data.resources.push_back(ResourceRow(std::string(), | |
621 "http://google.com/script2.js", | |
622 ResourceType::SCRIPT, | |
623 1, | |
624 0, | |
625 0, | |
626 3.0)); | |
627 host_data.resources.push_back(ResourceRow(std::string(), | |
628 "http://google.com/style2.css", | |
629 ResourceType::STYLESHEET, | |
630 1, | |
631 0, | |
632 0, | |
633 7.0)); | |
634 EXPECT_CALL(*mock_tables_.get(), UpdateData(empty_url_data_, host_data)); | |
635 | |
636 predictor_->OnNavigationComplete(main_frame.navigation_id); | |
637 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
638 } | |
639 | |
640 TEST_F(ResourcePrefetchPredictorTest, NavigationUrlNotInDBAndDBFull) { | |
641 // Tests that a URL is deleted before another is added if the cache is full. | |
642 AddUrlToHistory("http://www.nike.com/", 4); | |
643 | |
644 EXPECT_CALL(*mock_tables_.get(), | |
645 GetAllData(Pointee(ContainerEq(PrefetchDataMap())), | |
646 Pointee(ContainerEq(PrefetchDataMap())))) | |
647 .WillOnce(DoAll(SetArgPointee<0>(test_url_data_), | |
648 SetArgPointee<1>(test_host_data_))); | |
649 ResetPredictor(); | |
650 InitializePredictor(); | |
651 EXPECT_EQ(3, static_cast<int>(predictor_->url_table_cache_->size())); | |
652 EXPECT_EQ(2, static_cast<int>(predictor_->host_table_cache_->size())); | |
653 | |
654 URLRequestSummary main_frame = | |
655 CreateURLRequestSummary(1, | |
656 1, | |
657 "http://www.nike.com", | |
658 "http://www.nike.com", | |
659 ResourceType::MAIN_FRAME, | |
660 std::string(), | |
661 false); | |
662 predictor_->RecordURLRequest(main_frame); | |
663 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
664 | |
665 URLRequestSummary resource1 = CreateURLRequestSummary( | |
666 1, 1, "http://www.nike.com", "http://nike.com/style1.css", | |
667 ResourceType::STYLESHEET, "text/css", false); | |
668 predictor_->RecordURLResponse(resource1); | |
669 URLRequestSummary resource2 = CreateURLRequestSummary( | |
670 1, 1, "http://www.nike.com", "http://nike.com/image2.png", | |
671 ResourceType::IMAGE, "image/png", false); | |
672 predictor_->RecordURLResponse(resource2); | |
673 | |
674 EXPECT_CALL( | |
675 *mock_tables_.get(), | |
676 DeleteSingleDataPoint("http://www.google.com/", PREFETCH_KEY_TYPE_URL)); | |
677 EXPECT_CALL( | |
678 *mock_tables_.get(), | |
679 DeleteSingleDataPoint("www.facebook.com", PREFETCH_KEY_TYPE_HOST)); | |
680 | |
681 PrefetchData url_data(PREFETCH_KEY_TYPE_URL, "http://www.nike.com/"); | |
682 url_data.resources.push_back(ResourceRow(std::string(), | |
683 "http://nike.com/style1.css", | |
684 ResourceType::STYLESHEET, | |
685 1, | |
686 0, | |
687 0, | |
688 1.0)); | |
689 url_data.resources.push_back(ResourceRow(std::string(), | |
690 "http://nike.com/image2.png", | |
691 ResourceType::IMAGE, | |
692 1, | |
693 0, | |
694 0, | |
695 2.0)); | |
696 EXPECT_CALL(*mock_tables_.get(), UpdateData(url_data, empty_host_data_)); | |
697 | |
698 PrefetchData host_data(PREFETCH_KEY_TYPE_HOST, "www.nike.com"); | |
699 host_data.resources = url_data.resources; | |
700 EXPECT_CALL(*mock_tables_.get(), UpdateData(empty_url_data_, host_data)); | |
701 | |
702 predictor_->OnNavigationComplete(main_frame.navigation_id); | |
703 profile_->BlockUntilHistoryProcessesPendingRequests(); | |
704 } | |
705 | |
706 TEST_F(ResourcePrefetchPredictorTest, DeleteUrls) { | |
707 // Add some dummy entries to cache. | |
708 predictor_->url_table_cache_->insert(std::make_pair( | |
709 "http://www.google.com/page1.html", | |
710 PrefetchData(PREFETCH_KEY_TYPE_URL, "http://www.google.com/page1.html"))); | |
711 predictor_->url_table_cache_->insert(std::make_pair( | |
712 "http://www.google.com/page2.html", | |
713 PrefetchData(PREFETCH_KEY_TYPE_URL, "http://www.google.com/page2.html"))); | |
714 predictor_->url_table_cache_->insert(std::make_pair( | |
715 "http://www.yahoo.com/", | |
716 PrefetchData(PREFETCH_KEY_TYPE_URL, "http://www.yahoo.com/"))); | |
717 predictor_->url_table_cache_->insert(std::make_pair( | |
718 "http://www.apple.com/", | |
719 PrefetchData(PREFETCH_KEY_TYPE_URL, "http://www.apple.com/"))); | |
720 predictor_->url_table_cache_->insert(std::make_pair( | |
721 "http://www.nike.com/", | |
722 PrefetchData(PREFETCH_KEY_TYPE_URL, "http://www.nike.com/"))); | |
723 | |
724 predictor_->host_table_cache_->insert(std::make_pair( | |
725 "www.google.com", | |
726 PrefetchData(PREFETCH_KEY_TYPE_HOST, "www.google.com"))); | |
727 predictor_->host_table_cache_->insert(std::make_pair( | |
728 "www.yahoo.com", | |
729 PrefetchData(PREFETCH_KEY_TYPE_HOST, "www.yahoo.com"))); | |
730 predictor_->host_table_cache_->insert(std::make_pair( | |
731 "www.apple.com", | |
732 PrefetchData(PREFETCH_KEY_TYPE_HOST, "www.apple.com"))); | |
733 | |
734 history::URLRows rows; | |
735 rows.push_back(history::URLRow(GURL("http://www.google.com/page2.html"))); | |
736 rows.push_back(history::URLRow(GURL("http://www.apple.com"))); | |
737 rows.push_back(history::URLRow(GURL("http://www.nike.com"))); | |
738 | |
739 std::vector<std::string> urls_to_delete, hosts_to_delete; | |
740 urls_to_delete.push_back("http://www.google.com/page2.html"); | |
741 urls_to_delete.push_back("http://www.apple.com/"); | |
742 urls_to_delete.push_back("http://www.nike.com/"); | |
743 hosts_to_delete.push_back("www.google.com"); | |
744 hosts_to_delete.push_back("www.apple.com"); | |
745 | |
746 EXPECT_CALL( | |
747 *mock_tables_.get(), | |
748 DeleteData(ContainerEq(urls_to_delete), ContainerEq(hosts_to_delete))); | |
749 | |
750 predictor_->DeleteUrls(rows); | |
751 EXPECT_EQ(2, static_cast<int>(predictor_->url_table_cache_->size())); | |
752 EXPECT_EQ(1, static_cast<int>(predictor_->host_table_cache_->size())); | |
753 | |
754 EXPECT_CALL(*mock_tables_.get(), DeleteAllData()); | |
755 | |
756 predictor_->DeleteAllUrls(); | |
757 EXPECT_TRUE(predictor_->url_table_cache_->empty()); | |
758 EXPECT_TRUE(predictor_->host_table_cache_->empty()); | |
759 } | |
760 | |
761 TEST_F(ResourcePrefetchPredictorTest, OnMainFrameRequest) { | |
762 URLRequestSummary summary1 = CreateURLRequestSummary(1, | |
763 1, | |
764 "http://www.google.com", | |
765 "http://www.google.com", | |
766 ResourceType::MAIN_FRAME, | |
767 std::string(), | |
768 false); | |
769 URLRequestSummary summary2 = CreateURLRequestSummary(1, | |
770 2, | |
771 "http://www.google.com", | |
772 "http://www.google.com", | |
773 ResourceType::MAIN_FRAME, | |
774 std::string(), | |
775 false); | |
776 URLRequestSummary summary3 = CreateURLRequestSummary(2, | |
777 1, | |
778 "http://www.yahoo.com", | |
779 "http://www.yahoo.com", | |
780 ResourceType::MAIN_FRAME, | |
781 std::string(), | |
782 false); | |
783 | |
784 predictor_->OnMainFrameRequest(summary1); | |
785 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
786 predictor_->OnMainFrameRequest(summary2); | |
787 EXPECT_EQ(2, static_cast<int>(predictor_->inflight_navigations_.size())); | |
788 predictor_->OnMainFrameRequest(summary3); | |
789 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); | |
790 | |
791 // Insert anther with same navigation id. It should replace. | |
792 URLRequestSummary summary4 = CreateURLRequestSummary(1, | |
793 1, | |
794 "http://www.nike.com", | |
795 "http://www.nike.com", | |
796 ResourceType::MAIN_FRAME, | |
797 std::string(), | |
798 false); | |
799 URLRequestSummary summary5 = CreateURLRequestSummary(1, | |
800 2, | |
801 "http://www.google.com", | |
802 "http://www.google.com", | |
803 ResourceType::MAIN_FRAME, | |
804 std::string(), | |
805 false); | |
806 | |
807 predictor_->OnMainFrameRequest(summary4); | |
808 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); | |
809 | |
810 // Change this creation time so that it will go away on the next insert. | |
811 summary5.navigation_id.creation_time = base::TimeTicks::Now() - | |
812 base::TimeDelta::FromDays(1); | |
813 predictor_->OnMainFrameRequest(summary5); | |
814 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); | |
815 | |
816 URLRequestSummary summary6 = CreateURLRequestSummary(3, | |
817 1, | |
818 "http://www.shoes.com", | |
819 "http://www.shoes.com", | |
820 ResourceType::MAIN_FRAME, | |
821 std::string(), | |
822 false); | |
823 predictor_->OnMainFrameRequest(summary6); | |
824 EXPECT_EQ(3, static_cast<int>(predictor_->inflight_navigations_.size())); | |
825 | |
826 EXPECT_TRUE(predictor_->inflight_navigations_.find(summary3.navigation_id) != | |
827 predictor_->inflight_navigations_.end()); | |
828 EXPECT_TRUE(predictor_->inflight_navigations_.find(summary4.navigation_id) != | |
829 predictor_->inflight_navigations_.end()); | |
830 EXPECT_TRUE(predictor_->inflight_navigations_.find(summary6.navigation_id) != | |
831 predictor_->inflight_navigations_.end()); | |
832 } | |
833 | |
834 TEST_F(ResourcePrefetchPredictorTest, OnMainFrameRedirect) { | |
835 URLRequestSummary summary1 = CreateURLRequestSummary(1, | |
836 1, | |
837 "http://www.google.com", | |
838 "http://www.google.com", | |
839 ResourceType::MAIN_FRAME, | |
840 std::string(), | |
841 false); | |
842 URLRequestSummary summary2 = CreateURLRequestSummary(1, | |
843 2, | |
844 "http://www.google.com", | |
845 "http://www.google.com", | |
846 ResourceType::MAIN_FRAME, | |
847 std::string(), | |
848 false); | |
849 URLRequestSummary summary3 = CreateURLRequestSummary(2, | |
850 1, | |
851 "http://www.yahoo.com", | |
852 "http://www.yahoo.com", | |
853 ResourceType::MAIN_FRAME, | |
854 std::string(), | |
855 false); | |
856 | |
857 predictor_->OnMainFrameRedirect(summary1); | |
858 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); | |
859 | |
860 predictor_->OnMainFrameRequest(summary1); | |
861 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
862 predictor_->OnMainFrameRequest(summary2); | |
863 EXPECT_EQ(2, static_cast<int>(predictor_->inflight_navigations_.size())); | |
864 | |
865 predictor_->OnMainFrameRedirect(summary3); | |
866 EXPECT_EQ(2, static_cast<int>(predictor_->inflight_navigations_.size())); | |
867 predictor_->OnMainFrameRedirect(summary1); | |
868 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
869 predictor_->OnMainFrameRedirect(summary2); | |
870 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); | |
871 } | |
872 | |
873 TEST_F(ResourcePrefetchPredictorTest, OnSubresourceResponse) { | |
874 // If there is no inflight navigation, nothing happens. | |
875 URLRequestSummary resource1 = CreateURLRequestSummary( | |
876 1, 1, "http://www.google.com", "http://google.com/style1.css", | |
877 ResourceType::STYLESHEET, "text/css", false); | |
878 predictor_->OnSubresourceResponse(resource1); | |
879 EXPECT_TRUE(predictor_->inflight_navigations_.empty()); | |
880 | |
881 // Add an inflight navigation. | |
882 URLRequestSummary main_frame1 = | |
883 CreateURLRequestSummary(1, | |
884 1, | |
885 "http://www.google.com", | |
886 "http://www.google.com", | |
887 ResourceType::MAIN_FRAME, | |
888 std::string(), | |
889 false); | |
890 predictor_->OnMainFrameRequest(main_frame1); | |
891 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
892 | |
893 // Now add a few subresources. | |
894 URLRequestSummary resource2 = CreateURLRequestSummary( | |
895 1, 1, "http://www.google.com", "http://google.com/script1.js", | |
896 ResourceType::SCRIPT, "text/javascript", false); | |
897 URLRequestSummary resource3 = CreateURLRequestSummary( | |
898 1, 1, "http://www.google.com", "http://google.com/script2.js", | |
899 ResourceType::SCRIPT, "text/javascript", false); | |
900 predictor_->OnSubresourceResponse(resource1); | |
901 predictor_->OnSubresourceResponse(resource2); | |
902 predictor_->OnSubresourceResponse(resource3); | |
903 | |
904 EXPECT_EQ(1, static_cast<int>(predictor_->inflight_navigations_.size())); | |
905 EXPECT_EQ(3, static_cast<int>( | |
906 predictor_->inflight_navigations_[main_frame1.navigation_id]->size())); | |
907 EXPECT_TRUE(URLRequestSummaryAreEqual( | |
908 resource1, | |
909 predictor_->inflight_navigations_[main_frame1.navigation_id]->at(0))); | |
910 EXPECT_TRUE(URLRequestSummaryAreEqual( | |
911 resource2, | |
912 predictor_->inflight_navigations_[main_frame1.navigation_id]->at(1))); | |
913 EXPECT_TRUE(URLRequestSummaryAreEqual( | |
914 resource3, | |
915 predictor_->inflight_navigations_[main_frame1.navigation_id]->at(2))); | |
916 } | |
917 | |
918 } // namespace predictors | |
OLD | NEW |