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