blob: f5b1f8ad070abf5bc8177081aa17798ac3ea8aad [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <set>
#include <utility>
#include <vector>
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/predictors/predictor_database.h"
#include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace predictors {
class ResourcePrefetchPredictorTablesTest : public testing::Test {
public:
ResourcePrefetchPredictorTablesTest();
virtual ~ResourcePrefetchPredictorTablesTest();
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
protected:
void TestGetAllData();
void TestUpdateData();
void TestDeleteData();
void TestDeleteSingleDataPoint();
void TestDeleteAllData();
base::MessageLoop loop_;
content::TestBrowserThread db_thread_;
TestingProfile profile_;
scoped_ptr<PredictorDatabase> db_;
scoped_refptr<ResourcePrefetchPredictorTables> tables_;
private:
typedef ResourcePrefetchPredictorTables::ResourceRow ResourceRow;
typedef std::vector<ResourceRow> ResourceRows;
typedef ResourcePrefetchPredictorTables::PrefetchData PrefetchData;
typedef ResourcePrefetchPredictorTables::PrefetchDataMap PrefetchDataMap;
// Initializes the tables, |test_url_data_| and |test_host_data_|.
void InitializeSampleData();
// Checks that the input PrefetchData are the same, although the resources
// can be in different order.
void TestPrefetchDataAreEqual(const PrefetchDataMap& lhs,
const PrefetchDataMap& rhs) const;
void TestResourceRowsAreEqual(const ResourceRows& lhs,
const ResourceRows& rhs) const;
void AddKey(PrefetchDataMap* m, const std::string& key) const;
// Useful for debugging test.
void PrintPrefetchData(const PrefetchData& data) const {
LOG(ERROR) << "[" << data.key_type << "," << data.primary_key
<< "," << data.last_visit.ToInternalValue() << "]";
for (ResourceRows::const_iterator it = data.resources.begin();
it != data.resources.end(); ++it) {
LOG(ERROR) << "\t\t" << it->resource_url << "\t" << it->resource_type
<< "\t" << it->number_of_hits << "\t" << it->number_of_misses
<< "\t" << it->consecutive_misses
<< "\t" << it->average_position
<< "\t" << it->score;
}
}
PrefetchDataMap test_url_data_;
PrefetchDataMap test_host_data_;
};
class ResourcePrefetchPredictorTablesReopenTest
: public ResourcePrefetchPredictorTablesTest {
public:
virtual void SetUp() OVERRIDE {
// Write data to the table, and then reopen the db.
ResourcePrefetchPredictorTablesTest::SetUp();
ResourcePrefetchPredictorTablesTest::TearDown();
db_.reset(new PredictorDatabase(&profile_));
loop_.RunUntilIdle();
tables_ = db_->resource_prefetch_tables();
}
};
ResourcePrefetchPredictorTablesTest::ResourcePrefetchPredictorTablesTest()
: loop_(base::MessageLoop::TYPE_DEFAULT),
db_thread_(content::BrowserThread::DB, &loop_),
db_(new PredictorDatabase(&profile_)),
tables_(db_->resource_prefetch_tables()) {
loop_.RunUntilIdle();
}
ResourcePrefetchPredictorTablesTest::~ResourcePrefetchPredictorTablesTest() {
}
void ResourcePrefetchPredictorTablesTest::SetUp() {
tables_->DeleteAllData();
InitializeSampleData();
}
void ResourcePrefetchPredictorTablesTest::TearDown() {
tables_ = NULL;
db_.reset();
loop_.RunUntilIdle();
}
void ResourcePrefetchPredictorTablesTest::TestGetAllData() {
PrefetchDataMap actual_url_data, actual_host_data;
tables_->GetAllData(&actual_url_data, &actual_host_data);
TestPrefetchDataAreEqual(test_url_data_, actual_url_data);
TestPrefetchDataAreEqual(test_host_data_, actual_host_data);
}
void ResourcePrefetchPredictorTablesTest::TestDeleteData() {
std::vector<std::string> urls_to_delete, hosts_to_delete;
urls_to_delete.push_back("http://www.google.com");
urls_to_delete.push_back("http://www.yahoo.com");
hosts_to_delete.push_back("www.yahoo.com");
tables_->DeleteData(urls_to_delete, hosts_to_delete);
PrefetchDataMap actual_url_data, actual_host_data;
tables_->GetAllData(&actual_url_data, &actual_host_data);
PrefetchDataMap expected_url_data, expected_host_data;
AddKey(&expected_url_data, "http://www.reddit.com");
AddKey(&expected_host_data, "www.facebook.com");
TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
TestPrefetchDataAreEqual(expected_host_data, actual_host_data);
}
void ResourcePrefetchPredictorTablesTest::TestDeleteSingleDataPoint() {
// Delete a URL.
tables_->DeleteSingleDataPoint("http://www.reddit.com",
PREFETCH_KEY_TYPE_URL);
PrefetchDataMap actual_url_data, actual_host_data;
tables_->GetAllData(&actual_url_data, &actual_host_data);
PrefetchDataMap expected_url_data;
AddKey(&expected_url_data, "http://www.google.com");
AddKey(&expected_url_data, "http://www.yahoo.com");
TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
TestPrefetchDataAreEqual(test_host_data_, actual_host_data);
// Delete a host.
tables_->DeleteSingleDataPoint("www.facebook.com", PREFETCH_KEY_TYPE_HOST);
actual_url_data.clear();
actual_host_data.clear();
tables_->GetAllData(&actual_url_data, &actual_host_data);
PrefetchDataMap expected_host_data;
AddKey(&expected_host_data, "www.yahoo.com");
TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
TestPrefetchDataAreEqual(expected_host_data, actual_host_data);
}
void ResourcePrefetchPredictorTablesTest::TestUpdateData() {
PrefetchData google(PREFETCH_KEY_TYPE_URL, "http://www.google.com");
google.last_visit = base::Time::FromInternalValue(10);
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/style.css",
ResourceType::STYLESHEET,
6,
2,
0,
1.0));
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/image.png",
ResourceType::IMAGE,
6,
4,
1,
4.2));
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/a.xml",
ResourceType::LAST_TYPE,
1,
0,
0,
6.1));
google.resources
.push_back(ResourceRow(std::string(),
"http://www.resources.google.com/script.js",
ResourceType::SCRIPT,
12,
0,
0,
8.5));
PrefetchData yahoo(PREFETCH_KEY_TYPE_HOST, "www.yahoo.com");
yahoo.last_visit = base::Time::FromInternalValue(7);
yahoo.resources.push_back(ResourceRow(std::string(),
"http://www.yahoo.com/image.png",
ResourceType::IMAGE,
120,
1,
1,
10.0));
tables_->UpdateData(google, yahoo);
PrefetchDataMap actual_url_data, actual_host_data;
tables_->GetAllData(&actual_url_data, &actual_host_data);
PrefetchDataMap expected_url_data, expected_host_data;
AddKey(&expected_url_data, "http://www.reddit.com");
AddKey(&expected_url_data, "http://www.yahoo.com");
expected_url_data.insert(std::make_pair("http://www.google.com", google));
AddKey(&expected_host_data, "www.facebook.com");
expected_host_data.insert(std::make_pair("www.yahoo.com", yahoo));
TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
TestPrefetchDataAreEqual(expected_host_data, actual_host_data);
}
void ResourcePrefetchPredictorTablesTest::TestDeleteAllData() {
tables_->DeleteAllData();
PrefetchDataMap actual_url_data, actual_host_data;
tables_->GetAllData(&actual_url_data, &actual_host_data);
EXPECT_TRUE(actual_url_data.empty());
EXPECT_TRUE(actual_host_data.empty());
}
void ResourcePrefetchPredictorTablesTest::TestPrefetchDataAreEqual(
const PrefetchDataMap& lhs,
const PrefetchDataMap& rhs) const {
EXPECT_EQ(lhs.size(), rhs.size());
for (PrefetchDataMap::const_iterator rhs_it = rhs.begin();
rhs_it != rhs.end(); ++rhs_it) {
PrefetchDataMap::const_iterator lhs_it = lhs.find(rhs_it->first);
EXPECT_TRUE(lhs_it != lhs.end()) << rhs_it->first;
TestResourceRowsAreEqual(lhs_it->second.resources,
rhs_it->second.resources);
}
}
void ResourcePrefetchPredictorTablesTest::TestResourceRowsAreEqual(
const ResourceRows& lhs,
const ResourceRows& rhs) const {
EXPECT_EQ(lhs.size(), rhs.size());
std::set<GURL> resources_seen;
for (ResourceRows::const_iterator rhs_it = rhs.begin();
rhs_it != rhs.end(); ++rhs_it) {
const GURL& resource = rhs_it->resource_url;
EXPECT_TRUE(resources_seen.find(resource) == resources_seen.end());
for (ResourceRows::const_iterator lhs_it = lhs.begin();
lhs_it != lhs.end(); ++lhs_it) {
if (*rhs_it == *lhs_it) {
resources_seen.insert(resource);
break;
}
}
EXPECT_TRUE(resources_seen.find(resource) != resources_seen.end());
}
EXPECT_EQ(lhs.size(), resources_seen.size());
}
void ResourcePrefetchPredictorTablesTest::AddKey(PrefetchDataMap* m,
const std::string& key) const {
PrefetchDataMap::const_iterator it = test_url_data_.find(key);
if (it != test_url_data_.end()) {
m->insert(std::make_pair(it->first, it->second));
return;
}
it = test_host_data_.find(key);
EXPECT_TRUE(it != test_host_data_.end());
m->insert(std::make_pair(it->first, it->second));
}
void ResourcePrefetchPredictorTablesTest::InitializeSampleData() {
{ // Url data.
PrefetchData google(PREFETCH_KEY_TYPE_URL, "http://www.google.com");
google.last_visit = base::Time::FromInternalValue(1);
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/style.css",
ResourceType::STYLESHEET,
5,
2,
1,
1.1));
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/script.js",
ResourceType::SCRIPT,
4,
0,
1,
2.1));
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/image.png",
ResourceType::IMAGE,
6,
3,
0,
2.2));
google.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/a.font",
ResourceType::LAST_TYPE,
2,
0,
0,
5.1));
google.resources
.push_back(ResourceRow(std::string(),
"http://www.resources.google.com/script.js",
ResourceType::SCRIPT,
11,
0,
0,
8.5));
PrefetchData reddit(PREFETCH_KEY_TYPE_URL, "http://www.reddit.com");
reddit.last_visit = base::Time::FromInternalValue(2);
reddit.resources
.push_back(ResourceRow(std::string(),
"http://reddit-resource.com/script1.js",
ResourceType::SCRIPT,
4,
0,
1,
1.0));
reddit.resources
.push_back(ResourceRow(std::string(),
"http://reddit-resource.com/script2.js",
ResourceType::SCRIPT,
2,
0,
0,
2.1));
PrefetchData yahoo(PREFETCH_KEY_TYPE_URL, "http://www.yahoo.com");
yahoo.last_visit = base::Time::FromInternalValue(3);
yahoo.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/image.png",
ResourceType::IMAGE,
20,
1,
0,
10.0));
test_url_data_.clear();
test_url_data_.insert(std::make_pair("http://www.google.com", google));
test_url_data_.insert(std::make_pair("http://www.reddit.com", reddit));
test_url_data_.insert(std::make_pair("http://www.yahoo.com", yahoo));
PrefetchData empty_host_data(PREFETCH_KEY_TYPE_HOST, std::string());
tables_->UpdateData(google, empty_host_data);
tables_->UpdateData(reddit, empty_host_data);
tables_->UpdateData(yahoo, empty_host_data);
}
{ // Host data.
PrefetchData facebook(PREFETCH_KEY_TYPE_HOST, "www.facebook.com");
facebook.last_visit = base::Time::FromInternalValue(4);
facebook.resources
.push_back(ResourceRow(std::string(),
"http://www.facebook.com/style.css",
ResourceType::STYLESHEET,
5,
2,
1,
1.1));
facebook.resources
.push_back(ResourceRow(std::string(),
"http://www.facebook.com/script.js",
ResourceType::SCRIPT,
4,
0,
1,
2.1));
facebook.resources
.push_back(ResourceRow(std::string(),
"http://www.facebook.com/image.png",
ResourceType::IMAGE,
6,
3,
0,
2.2));
facebook.resources.push_back(ResourceRow(std::string(),
"http://www.facebook.com/a.font",
ResourceType::LAST_TYPE,
2,
0,
0,
5.1));
facebook.resources
.push_back(ResourceRow(std::string(),
"http://www.resources.facebook.com/script.js",
ResourceType::SCRIPT,
11,
0,
0,
8.5));
PrefetchData yahoo(PREFETCH_KEY_TYPE_HOST, "www.yahoo.com");
yahoo.last_visit = base::Time::FromInternalValue(5);
yahoo.resources.push_back(ResourceRow(std::string(),
"http://www.google.com/image.png",
ResourceType::IMAGE,
20,
1,
0,
10.0));
test_host_data_.clear();
test_host_data_.insert(std::make_pair("www.facebook.com", facebook));
test_host_data_.insert(std::make_pair("www.yahoo.com", yahoo));
PrefetchData empty_url_data(PREFETCH_KEY_TYPE_URL, std::string());
tables_->UpdateData(empty_url_data, facebook);
tables_->UpdateData(empty_url_data, yahoo);
}
}
// Test cases.
TEST_F(ResourcePrefetchPredictorTablesTest, GetAllData) {
TestGetAllData();
}
TEST_F(ResourcePrefetchPredictorTablesTest, UpdateData) {
TestUpdateData();
}
TEST_F(ResourcePrefetchPredictorTablesTest, DeleteData) {
TestDeleteData();
}
TEST_F(ResourcePrefetchPredictorTablesTest, DeleteSingleDataPoint) {
TestDeleteSingleDataPoint();
}
TEST_F(ResourcePrefetchPredictorTablesTest, DeleteAllData) {
TestDeleteAllData();
}
TEST_F(ResourcePrefetchPredictorTablesReopenTest, GetAllData) {
TestGetAllData();
}
TEST_F(ResourcePrefetchPredictorTablesReopenTest, UpdateData) {
TestUpdateData();
}
TEST_F(ResourcePrefetchPredictorTablesReopenTest, DeleteData) {
TestDeleteData();
}
TEST_F(ResourcePrefetchPredictorTablesReopenTest, DeleteSingleDataPoint) {
TestDeleteSingleDataPoint();
}
TEST_F(ResourcePrefetchPredictorTablesReopenTest, DeleteAllData) {
TestDeleteAllData();
}
} // namespace predictors