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.
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/predictors/predictor_database.h"
12 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
13 #include "chrome/test/base/testing_profile.h"
14 #include "content/public/test/test_browser_thread.h"
15 #include "sql/statement.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace predictors
{
20 class ResourcePrefetchPredictorTablesTest
: public testing::Test
{
22 ResourcePrefetchPredictorTablesTest();
23 ~ResourcePrefetchPredictorTablesTest() override
;
24 void SetUp() override
;
25 void TearDown() override
;
28 void TestGetAllData();
29 void TestUpdateData();
30 void TestDeleteData();
31 void TestDeleteSingleDataPoint();
32 void TestDeleteAllData();
34 base::MessageLoop loop_
;
35 content::TestBrowserThread db_thread_
;
36 TestingProfile profile_
;
37 scoped_ptr
<PredictorDatabase
> db_
;
38 scoped_refptr
<ResourcePrefetchPredictorTables
> tables_
;
41 typedef ResourcePrefetchPredictorTables::ResourceRow ResourceRow
;
42 typedef std::vector
<ResourceRow
> ResourceRows
;
43 typedef ResourcePrefetchPredictorTables::PrefetchData PrefetchData
;
44 typedef ResourcePrefetchPredictorTables::PrefetchDataMap PrefetchDataMap
;
46 // Initializes the tables, |test_url_data_| and |test_host_data_|.
47 void InitializeSampleData();
49 // Checks that the input PrefetchData are the same, although the resources
50 // can be in different order.
51 void TestPrefetchDataAreEqual(const PrefetchDataMap
& lhs
,
52 const PrefetchDataMap
& rhs
) const;
53 void TestResourceRowsAreEqual(const ResourceRows
& lhs
,
54 const ResourceRows
& rhs
) const;
56 void AddKey(PrefetchDataMap
* m
, const std::string
& key
) const;
58 // Useful for debugging test.
59 void PrintPrefetchData(const PrefetchData
& data
) const {
60 LOG(ERROR
) << "[" << data
.key_type
<< "," << data
.primary_key
61 << "," << data
.last_visit
.ToInternalValue() << "]";
62 for (ResourceRows::const_iterator it
= data
.resources
.begin();
63 it
!= data
.resources
.end(); ++it
) {
64 LOG(ERROR
) << "\t\t" << it
->resource_url
<< "\t" << it
->resource_type
65 << "\t" << it
->number_of_hits
<< "\t" << it
->number_of_misses
66 << "\t" << it
->consecutive_misses
67 << "\t" << it
->average_position
72 PrefetchDataMap test_url_data_
;
73 PrefetchDataMap test_host_data_
;
76 class ResourcePrefetchPredictorTablesReopenTest
77 : public ResourcePrefetchPredictorTablesTest
{
79 void SetUp() override
{
80 // Write data to the table, and then reopen the db.
81 ResourcePrefetchPredictorTablesTest::SetUp();
82 ResourcePrefetchPredictorTablesTest::TearDown();
84 db_
.reset(new PredictorDatabase(&profile_
));
86 tables_
= db_
->resource_prefetch_tables();
90 ResourcePrefetchPredictorTablesTest::ResourcePrefetchPredictorTablesTest()
91 : loop_(base::MessageLoop::TYPE_DEFAULT
),
92 db_thread_(content::BrowserThread::DB
, &loop_
),
93 db_(new PredictorDatabase(&profile_
)),
94 tables_(db_
->resource_prefetch_tables()) {
98 ResourcePrefetchPredictorTablesTest::~ResourcePrefetchPredictorTablesTest() {
101 void ResourcePrefetchPredictorTablesTest::SetUp() {
102 tables_
->DeleteAllData();
103 InitializeSampleData();
106 void ResourcePrefetchPredictorTablesTest::TearDown() {
109 loop_
.RunUntilIdle();
112 void ResourcePrefetchPredictorTablesTest::TestGetAllData() {
113 PrefetchDataMap actual_url_data
, actual_host_data
;
114 tables_
->GetAllData(&actual_url_data
, &actual_host_data
);
116 TestPrefetchDataAreEqual(test_url_data_
, actual_url_data
);
117 TestPrefetchDataAreEqual(test_host_data_
, actual_host_data
);
120 void ResourcePrefetchPredictorTablesTest::TestDeleteData() {
121 std::vector
<std::string
> urls_to_delete
, hosts_to_delete
;
122 urls_to_delete
.push_back("http://www.google.com");
123 urls_to_delete
.push_back("http://www.yahoo.com");
124 hosts_to_delete
.push_back("www.yahoo.com");
126 tables_
->DeleteData(urls_to_delete
, hosts_to_delete
);
128 PrefetchDataMap actual_url_data
, actual_host_data
;
129 tables_
->GetAllData(&actual_url_data
, &actual_host_data
);
131 PrefetchDataMap expected_url_data
, expected_host_data
;
132 AddKey(&expected_url_data
, "http://www.reddit.com");
133 AddKey(&expected_host_data
, "www.facebook.com");
135 TestPrefetchDataAreEqual(expected_url_data
, actual_url_data
);
136 TestPrefetchDataAreEqual(expected_host_data
, actual_host_data
);
139 void ResourcePrefetchPredictorTablesTest::TestDeleteSingleDataPoint() {
141 tables_
->DeleteSingleDataPoint("http://www.reddit.com",
142 PREFETCH_KEY_TYPE_URL
);
144 PrefetchDataMap actual_url_data
, actual_host_data
;
145 tables_
->GetAllData(&actual_url_data
, &actual_host_data
);
147 PrefetchDataMap expected_url_data
;
148 AddKey(&expected_url_data
, "http://www.google.com");
149 AddKey(&expected_url_data
, "http://www.yahoo.com");
151 TestPrefetchDataAreEqual(expected_url_data
, actual_url_data
);
152 TestPrefetchDataAreEqual(test_host_data_
, actual_host_data
);
155 tables_
->DeleteSingleDataPoint("www.facebook.com", PREFETCH_KEY_TYPE_HOST
);
156 actual_url_data
.clear();
157 actual_host_data
.clear();
158 tables_
->GetAllData(&actual_url_data
, &actual_host_data
);
160 PrefetchDataMap expected_host_data
;
161 AddKey(&expected_host_data
, "www.yahoo.com");
163 TestPrefetchDataAreEqual(expected_url_data
, actual_url_data
);
164 TestPrefetchDataAreEqual(expected_host_data
, actual_host_data
);
167 void ResourcePrefetchPredictorTablesTest::TestUpdateData() {
168 PrefetchData
google(PREFETCH_KEY_TYPE_URL
, "http://www.google.com");
169 google
.last_visit
= base::Time::FromInternalValue(10);
170 google
.resources
.push_back(ResourceRow(std::string(),
171 "http://www.google.com/style.css",
172 content::RESOURCE_TYPE_STYLESHEET
,
177 google
.resources
.push_back(ResourceRow(std::string(),
178 "http://www.google.com/image.png",
179 content::RESOURCE_TYPE_IMAGE
,
184 google
.resources
.push_back(ResourceRow(std::string(),
185 "http://www.google.com/a.xml",
186 content::RESOURCE_TYPE_LAST_TYPE
,
192 .push_back(ResourceRow(std::string(),
193 "http://www.resources.google.com/script.js",
194 content::RESOURCE_TYPE_SCRIPT
,
200 PrefetchData
yahoo(PREFETCH_KEY_TYPE_HOST
, "www.yahoo.com");
201 yahoo
.last_visit
= base::Time::FromInternalValue(7);
202 yahoo
.resources
.push_back(ResourceRow(std::string(),
203 "http://www.yahoo.com/image.png",
204 content::RESOURCE_TYPE_IMAGE
,
210 tables_
->UpdateData(google
, yahoo
);
212 PrefetchDataMap actual_url_data
, actual_host_data
;
213 tables_
->GetAllData(&actual_url_data
, &actual_host_data
);
215 PrefetchDataMap expected_url_data
, expected_host_data
;
216 AddKey(&expected_url_data
, "http://www.reddit.com");
217 AddKey(&expected_url_data
, "http://www.yahoo.com");
218 expected_url_data
.insert(std::make_pair("http://www.google.com", google
));
220 AddKey(&expected_host_data
, "www.facebook.com");
221 expected_host_data
.insert(std::make_pair("www.yahoo.com", yahoo
));
223 TestPrefetchDataAreEqual(expected_url_data
, actual_url_data
);
224 TestPrefetchDataAreEqual(expected_host_data
, actual_host_data
);
227 void ResourcePrefetchPredictorTablesTest::TestDeleteAllData() {
228 tables_
->DeleteAllData();
230 PrefetchDataMap actual_url_data
, actual_host_data
;
231 tables_
->GetAllData(&actual_url_data
, &actual_host_data
);
232 EXPECT_TRUE(actual_url_data
.empty());
233 EXPECT_TRUE(actual_host_data
.empty());
236 void ResourcePrefetchPredictorTablesTest::TestPrefetchDataAreEqual(
237 const PrefetchDataMap
& lhs
,
238 const PrefetchDataMap
& rhs
) const {
239 EXPECT_EQ(lhs
.size(), rhs
.size());
241 for (PrefetchDataMap::const_iterator rhs_it
= rhs
.begin();
242 rhs_it
!= rhs
.end(); ++rhs_it
) {
243 PrefetchDataMap::const_iterator lhs_it
= lhs
.find(rhs_it
->first
);
244 ASSERT_TRUE(lhs_it
!= lhs
.end()) << rhs_it
->first
;
246 TestResourceRowsAreEqual(lhs_it
->second
.resources
,
247 rhs_it
->second
.resources
);
251 void ResourcePrefetchPredictorTablesTest::TestResourceRowsAreEqual(
252 const ResourceRows
& lhs
,
253 const ResourceRows
& rhs
) const {
254 EXPECT_EQ(lhs
.size(), rhs
.size());
256 std::set
<GURL
> resources_seen
;
257 for (ResourceRows::const_iterator rhs_it
= rhs
.begin();
258 rhs_it
!= rhs
.end(); ++rhs_it
) {
259 const GURL
& resource
= rhs_it
->resource_url
;
260 EXPECT_FALSE(ContainsKey(resources_seen
, resource
));
262 for (ResourceRows::const_iterator lhs_it
= lhs
.begin();
263 lhs_it
!= lhs
.end(); ++lhs_it
) {
264 if (*rhs_it
== *lhs_it
) {
265 resources_seen
.insert(resource
);
269 EXPECT_TRUE(ContainsKey(resources_seen
, resource
));
271 EXPECT_EQ(lhs
.size(), resources_seen
.size());
274 void ResourcePrefetchPredictorTablesTest::AddKey(PrefetchDataMap
* m
,
275 const std::string
& key
) const {
276 PrefetchDataMap::const_iterator it
= test_url_data_
.find(key
);
277 if (it
!= test_url_data_
.end()) {
278 m
->insert(std::make_pair(it
->first
, it
->second
));
281 it
= test_host_data_
.find(key
);
282 ASSERT_TRUE(it
!= test_host_data_
.end());
283 m
->insert(std::make_pair(it
->first
, it
->second
));
286 void ResourcePrefetchPredictorTablesTest::InitializeSampleData() {
288 PrefetchData
google(PREFETCH_KEY_TYPE_URL
, "http://www.google.com");
289 google
.last_visit
= base::Time::FromInternalValue(1);
290 google
.resources
.push_back(ResourceRow(std::string(),
291 "http://www.google.com/style.css",
292 content::RESOURCE_TYPE_STYLESHEET
,
297 google
.resources
.push_back(ResourceRow(std::string(),
298 "http://www.google.com/script.js",
299 content::RESOURCE_TYPE_SCRIPT
,
304 google
.resources
.push_back(ResourceRow(std::string(),
305 "http://www.google.com/image.png",
306 content::RESOURCE_TYPE_IMAGE
,
311 google
.resources
.push_back(ResourceRow(std::string(),
312 "http://www.google.com/a.font",
313 content::RESOURCE_TYPE_LAST_TYPE
,
319 .push_back(ResourceRow(std::string(),
320 "http://www.resources.google.com/script.js",
321 content::RESOURCE_TYPE_SCRIPT
,
327 PrefetchData
reddit(PREFETCH_KEY_TYPE_URL
, "http://www.reddit.com");
328 reddit
.last_visit
= base::Time::FromInternalValue(2);
330 .push_back(ResourceRow(std::string(),
331 "http://reddit-resource.com/script1.js",
332 content::RESOURCE_TYPE_SCRIPT
,
338 .push_back(ResourceRow(std::string(),
339 "http://reddit-resource.com/script2.js",
340 content::RESOURCE_TYPE_SCRIPT
,
346 PrefetchData
yahoo(PREFETCH_KEY_TYPE_URL
, "http://www.yahoo.com");
347 yahoo
.last_visit
= base::Time::FromInternalValue(3);
348 yahoo
.resources
.push_back(ResourceRow(std::string(),
349 "http://www.google.com/image.png",
350 content::RESOURCE_TYPE_IMAGE
,
356 test_url_data_
.clear();
357 test_url_data_
.insert(std::make_pair("http://www.google.com", google
));
358 test_url_data_
.insert(std::make_pair("http://www.reddit.com", reddit
));
359 test_url_data_
.insert(std::make_pair("http://www.yahoo.com", yahoo
));
361 PrefetchData
empty_host_data(PREFETCH_KEY_TYPE_HOST
, std::string());
362 tables_
->UpdateData(google
, empty_host_data
);
363 tables_
->UpdateData(reddit
, empty_host_data
);
364 tables_
->UpdateData(yahoo
, empty_host_data
);
368 PrefetchData
facebook(PREFETCH_KEY_TYPE_HOST
, "www.facebook.com");
369 facebook
.last_visit
= base::Time::FromInternalValue(4);
371 .push_back(ResourceRow(std::string(),
372 "http://www.facebook.com/style.css",
373 content::RESOURCE_TYPE_STYLESHEET
,
379 .push_back(ResourceRow(std::string(),
380 "http://www.facebook.com/script.js",
381 content::RESOURCE_TYPE_SCRIPT
,
387 .push_back(ResourceRow(std::string(),
388 "http://www.facebook.com/image.png",
389 content::RESOURCE_TYPE_IMAGE
,
394 facebook
.resources
.push_back(ResourceRow(std::string(),
395 "http://www.facebook.com/a.font",
396 content::RESOURCE_TYPE_LAST_TYPE
,
402 .push_back(ResourceRow(std::string(),
403 "http://www.resources.facebook.com/script.js",
404 content::RESOURCE_TYPE_SCRIPT
,
410 PrefetchData
yahoo(PREFETCH_KEY_TYPE_HOST
, "www.yahoo.com");
411 yahoo
.last_visit
= base::Time::FromInternalValue(5);
412 yahoo
.resources
.push_back(ResourceRow(std::string(),
413 "http://www.google.com/image.png",
414 content::RESOURCE_TYPE_IMAGE
,
420 test_host_data_
.clear();
421 test_host_data_
.insert(std::make_pair("www.facebook.com", facebook
));
422 test_host_data_
.insert(std::make_pair("www.yahoo.com", yahoo
));
424 PrefetchData
empty_url_data(PREFETCH_KEY_TYPE_URL
, std::string());
425 tables_
->UpdateData(empty_url_data
, facebook
);
426 tables_
->UpdateData(empty_url_data
, yahoo
);
432 TEST_F(ResourcePrefetchPredictorTablesTest
, GetAllData
) {
436 TEST_F(ResourcePrefetchPredictorTablesTest
, UpdateData
) {
440 TEST_F(ResourcePrefetchPredictorTablesTest
, DeleteData
) {
444 TEST_F(ResourcePrefetchPredictorTablesTest
, DeleteSingleDataPoint
) {
445 TestDeleteSingleDataPoint();
448 TEST_F(ResourcePrefetchPredictorTablesTest
, DeleteAllData
) {
452 TEST_F(ResourcePrefetchPredictorTablesReopenTest
, GetAllData
) {
456 TEST_F(ResourcePrefetchPredictorTablesReopenTest
, UpdateData
) {
460 TEST_F(ResourcePrefetchPredictorTablesReopenTest
, DeleteData
) {
464 TEST_F(ResourcePrefetchPredictorTablesReopenTest
, DeleteSingleDataPoint
) {
465 TestDeleteSingleDataPoint();
468 TEST_F(ResourcePrefetchPredictorTablesReopenTest
, DeleteAllData
) {
472 } // namespace predictors