Home | History | Annotate | Download | only in predictors
      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 <set>
      6 #include <utility>
      7 #include <vector>
      8 
      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"
     17 
     18 namespace predictors {
     19 
     20 class ResourcePrefetchPredictorTablesTest : public testing::Test {
     21  public:
     22   ResourcePrefetchPredictorTablesTest();
     23   virtual ~ResourcePrefetchPredictorTablesTest();
     24   virtual void SetUp() OVERRIDE;
     25   virtual void TearDown() OVERRIDE;
     26 
     27  protected:
     28   void TestGetAllData();
     29   void TestUpdateData();
     30   void TestDeleteData();
     31   void TestDeleteSingleDataPoint();
     32   void TestDeleteAllData();
     33 
     34   base::MessageLoop loop_;
     35   content::TestBrowserThread db_thread_;
     36   TestingProfile profile_;
     37   scoped_ptr<PredictorDatabase> db_;
     38   scoped_refptr<ResourcePrefetchPredictorTables> tables_;
     39 
     40  private:
     41   typedef ResourcePrefetchPredictorTables::ResourceRow ResourceRow;
     42   typedef std::vector<ResourceRow> ResourceRows;
     43   typedef ResourcePrefetchPredictorTables::PrefetchData PrefetchData;
     44   typedef ResourcePrefetchPredictorTables::PrefetchDataMap PrefetchDataMap;
     45 
     46   // Initializes the tables, |test_url_data_| and |test_host_data_|.
     47   void InitializeSampleData();
     48 
     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;
     55 
     56   void AddKey(PrefetchDataMap* m, const std::string& key) const;
     57 
     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
     68                  << "\t" << it->score;
     69     }
     70   }
     71 
     72   PrefetchDataMap test_url_data_;
     73   PrefetchDataMap test_host_data_;
     74 };
     75 
     76 class ResourcePrefetchPredictorTablesReopenTest
     77     : public ResourcePrefetchPredictorTablesTest {
     78  public:
     79   virtual void SetUp() OVERRIDE {
     80     // Write data to the table, and then reopen the db.
     81     ResourcePrefetchPredictorTablesTest::SetUp();
     82     ResourcePrefetchPredictorTablesTest::TearDown();
     83 
     84     db_.reset(new PredictorDatabase(&profile_));
     85     loop_.RunUntilIdle();
     86     tables_ = db_->resource_prefetch_tables();
     87   }
     88 };
     89 
     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()) {
     95   loop_.RunUntilIdle();
     96 }
     97 
     98 ResourcePrefetchPredictorTablesTest::~ResourcePrefetchPredictorTablesTest() {
     99 }
    100 
    101 void ResourcePrefetchPredictorTablesTest::SetUp() {
    102   tables_->DeleteAllData();
    103   InitializeSampleData();
    104 }
    105 
    106 void ResourcePrefetchPredictorTablesTest::TearDown() {
    107   tables_ = NULL;
    108   db_.reset();
    109   loop_.RunUntilIdle();
    110 }
    111 
    112 void ResourcePrefetchPredictorTablesTest::TestGetAllData() {
    113   PrefetchDataMap actual_url_data, actual_host_data;
    114   tables_->GetAllData(&actual_url_data, &actual_host_data);
    115 
    116   TestPrefetchDataAreEqual(test_url_data_, actual_url_data);
    117   TestPrefetchDataAreEqual(test_host_data_, actual_host_data);
    118 }
    119 
    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");
    125 
    126   tables_->DeleteData(urls_to_delete, hosts_to_delete);
    127 
    128   PrefetchDataMap actual_url_data, actual_host_data;
    129   tables_->GetAllData(&actual_url_data, &actual_host_data);
    130 
    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");
    134 
    135   TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
    136   TestPrefetchDataAreEqual(expected_host_data, actual_host_data);
    137 }
    138 
    139 void ResourcePrefetchPredictorTablesTest::TestDeleteSingleDataPoint() {
    140   // Delete a URL.
    141   tables_->DeleteSingleDataPoint("http://www.reddit.com",
    142                                  PREFETCH_KEY_TYPE_URL);
    143 
    144   PrefetchDataMap actual_url_data, actual_host_data;
    145   tables_->GetAllData(&actual_url_data, &actual_host_data);
    146 
    147   PrefetchDataMap expected_url_data;
    148   AddKey(&expected_url_data, "http://www.google.com");
    149   AddKey(&expected_url_data, "http://www.yahoo.com");
    150 
    151   TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
    152   TestPrefetchDataAreEqual(test_host_data_, actual_host_data);
    153 
    154   // Delete a host.
    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);
    159 
    160   PrefetchDataMap expected_host_data;
    161   AddKey(&expected_host_data, "www.yahoo.com");
    162 
    163   TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
    164   TestPrefetchDataAreEqual(expected_host_data, actual_host_data);
    165 }
    166 
    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,
    173                                          6,
    174                                          2,
    175                                          0,
    176                                          1.0));
    177   google.resources.push_back(ResourceRow(std::string(),
    178                                          "http://www.google.com/image.png",
    179                                          content::RESOURCE_TYPE_IMAGE,
    180                                          6,
    181                                          4,
    182                                          1,
    183                                          4.2));
    184   google.resources.push_back(ResourceRow(std::string(),
    185                                          "http://www.google.com/a.xml",
    186                                          content::RESOURCE_TYPE_LAST_TYPE,
    187                                          1,
    188                                          0,
    189                                          0,
    190                                          6.1));
    191   google.resources
    192       .push_back(ResourceRow(std::string(),
    193                              "http://www.resources.google.com/script.js",
    194                              content::RESOURCE_TYPE_SCRIPT,
    195                              12,
    196                              0,
    197                              0,
    198                              8.5));
    199 
    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,
    205                                         120,
    206                                         1,
    207                                         1,
    208                                         10.0));
    209 
    210   tables_->UpdateData(google, yahoo);
    211 
    212   PrefetchDataMap actual_url_data, actual_host_data;
    213   tables_->GetAllData(&actual_url_data, &actual_host_data);
    214 
    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));
    219 
    220   AddKey(&expected_host_data, "www.facebook.com");
    221   expected_host_data.insert(std::make_pair("www.yahoo.com", yahoo));
    222 
    223   TestPrefetchDataAreEqual(expected_url_data, actual_url_data);
    224   TestPrefetchDataAreEqual(expected_host_data, actual_host_data);
    225 }
    226 
    227 void ResourcePrefetchPredictorTablesTest::TestDeleteAllData() {
    228   tables_->DeleteAllData();
    229 
    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());
    234 }
    235 
    236 void ResourcePrefetchPredictorTablesTest::TestPrefetchDataAreEqual(
    237     const PrefetchDataMap& lhs,
    238     const PrefetchDataMap& rhs) const {
    239   EXPECT_EQ(lhs.size(), rhs.size());
    240 
    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;
    245 
    246     TestResourceRowsAreEqual(lhs_it->second.resources,
    247                              rhs_it->second.resources);
    248   }
    249 }
    250 
    251 void ResourcePrefetchPredictorTablesTest::TestResourceRowsAreEqual(
    252     const ResourceRows& lhs,
    253     const ResourceRows& rhs) const {
    254   EXPECT_EQ(lhs.size(), rhs.size());
    255 
    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));
    261 
    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);
    266         break;
    267       }
    268     }
    269     EXPECT_TRUE(ContainsKey(resources_seen, resource));
    270   }
    271   EXPECT_EQ(lhs.size(), resources_seen.size());
    272 }
    273 
    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));
    279     return;
    280   }
    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));
    284 }
    285 
    286 void ResourcePrefetchPredictorTablesTest::InitializeSampleData() {
    287   {  // Url data.
    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,
    293                                            5,
    294                                            2,
    295                                            1,
    296                                            1.1));
    297     google.resources.push_back(ResourceRow(std::string(),
    298                                            "http://www.google.com/script.js",
    299                                            content::RESOURCE_TYPE_SCRIPT,
    300                                            4,
    301                                            0,
    302                                            1,
    303                                            2.1));
    304     google.resources.push_back(ResourceRow(std::string(),
    305                                            "http://www.google.com/image.png",
    306                                            content::RESOURCE_TYPE_IMAGE,
    307                                            6,
    308                                            3,
    309                                            0,
    310                                            2.2));
    311     google.resources.push_back(ResourceRow(std::string(),
    312                                            "http://www.google.com/a.font",
    313                                            content::RESOURCE_TYPE_LAST_TYPE,
    314                                            2,
    315                                            0,
    316                                            0,
    317                                            5.1));
    318     google.resources
    319         .push_back(ResourceRow(std::string(),
    320                                "http://www.resources.google.com/script.js",
    321                                content::RESOURCE_TYPE_SCRIPT,
    322                                11,
    323                                0,
    324                                0,
    325                                8.5));
    326 
    327     PrefetchData reddit(PREFETCH_KEY_TYPE_URL, "http://www.reddit.com");
    328     reddit.last_visit = base::Time::FromInternalValue(2);
    329     reddit.resources
    330         .push_back(ResourceRow(std::string(),
    331                                "http://reddit-resource.com/script1.js",
    332                                content::RESOURCE_TYPE_SCRIPT,
    333                                4,
    334                                0,
    335                                1,
    336                                1.0));
    337     reddit.resources
    338         .push_back(ResourceRow(std::string(),
    339                                "http://reddit-resource.com/script2.js",
    340                                content::RESOURCE_TYPE_SCRIPT,
    341                                2,
    342                                0,
    343                                0,
    344                                2.1));
    345 
    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,
    351                                           20,
    352                                           1,
    353                                           0,
    354                                           10.0));
    355 
    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));
    360 
    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);
    365   }
    366 
    367   {  // Host data.
    368     PrefetchData facebook(PREFETCH_KEY_TYPE_HOST, "www.facebook.com");
    369     facebook.last_visit = base::Time::FromInternalValue(4);
    370     facebook.resources
    371         .push_back(ResourceRow(std::string(),
    372                                "http://www.facebook.com/style.css",
    373                                content::RESOURCE_TYPE_STYLESHEET,
    374                                5,
    375                                2,
    376                                1,
    377                                1.1));
    378     facebook.resources
    379         .push_back(ResourceRow(std::string(),
    380                                "http://www.facebook.com/script.js",
    381                                content::RESOURCE_TYPE_SCRIPT,
    382                                4,
    383                                0,
    384                                1,
    385                                2.1));
    386     facebook.resources
    387         .push_back(ResourceRow(std::string(),
    388                                "http://www.facebook.com/image.png",
    389                                content::RESOURCE_TYPE_IMAGE,
    390                                6,
    391                                3,
    392                                0,
    393                                2.2));
    394     facebook.resources.push_back(ResourceRow(std::string(),
    395                                              "http://www.facebook.com/a.font",
    396                                              content::RESOURCE_TYPE_LAST_TYPE,
    397                                              2,
    398                                              0,
    399                                              0,
    400                                              5.1));
    401     facebook.resources
    402         .push_back(ResourceRow(std::string(),
    403                                "http://www.resources.facebook.com/script.js",
    404                                content::RESOURCE_TYPE_SCRIPT,
    405                                11,
    406                                0,
    407                                0,
    408                                8.5));
    409 
    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,
    415                                           20,
    416                                           1,
    417                                           0,
    418                                           10.0));
    419 
    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));
    423 
    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);
    427   }
    428 }
    429 
    430 // Test cases.
    431 
    432 TEST_F(ResourcePrefetchPredictorTablesTest, GetAllData) {
    433   TestGetAllData();
    434 }
    435 
    436 TEST_F(ResourcePrefetchPredictorTablesTest, UpdateData) {
    437   TestUpdateData();
    438 }
    439 
    440 TEST_F(ResourcePrefetchPredictorTablesTest, DeleteData) {
    441   TestDeleteData();
    442 }
    443 
    444 TEST_F(ResourcePrefetchPredictorTablesTest, DeleteSingleDataPoint) {
    445   TestDeleteSingleDataPoint();
    446 }
    447 
    448 TEST_F(ResourcePrefetchPredictorTablesTest, DeleteAllData) {
    449   TestDeleteAllData();
    450 }
    451 
    452 TEST_F(ResourcePrefetchPredictorTablesReopenTest, GetAllData) {
    453   TestGetAllData();
    454 }
    455 
    456 TEST_F(ResourcePrefetchPredictorTablesReopenTest, UpdateData) {
    457   TestUpdateData();
    458 }
    459 
    460 TEST_F(ResourcePrefetchPredictorTablesReopenTest, DeleteData) {
    461   TestDeleteData();
    462 }
    463 
    464 TEST_F(ResourcePrefetchPredictorTablesReopenTest, DeleteSingleDataPoint) {
    465   TestDeleteSingleDataPoint();
    466 }
    467 
    468 TEST_F(ResourcePrefetchPredictorTablesReopenTest, DeleteAllData) {
    469   TestDeleteAllData();
    470 }
    471 
    472 }  // namespace predictors
    473