Home | History | Annotate | Download | only in history
      1 // Copyright (c) 2011 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 "app/sql/connection.h"
      6 #include "base/file_path.h"
      7 #include "base/file_util.h"
      8 #include "base/memory/scoped_temp_dir.h"
      9 #include "base/path_service.h"
     10 #include "base/string_util.h"
     11 #include "base/utf_string_conversions.h"
     12 #include "chrome/browser/history/url_database.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 using base::Time;
     16 using base::TimeDelta;
     17 
     18 namespace history {
     19 
     20 namespace {
     21 
     22 bool IsURLRowEqual(const URLRow& a,
     23                    const URLRow& b) {
     24   // TODO(brettw) when the database stores an actual Time value rather than
     25   // a time_t, do a reaul comparison. Instead, we have to do a more rough
     26   // comparison since the conversion reduces the precision.
     27   return a.title() == b.title() &&
     28       a.visit_count() == b.visit_count() &&
     29       a.typed_count() == b.typed_count() &&
     30       a.last_visit() - b.last_visit() <= TimeDelta::FromSeconds(1) &&
     31       a.hidden() == b.hidden();
     32 }
     33 
     34 }  // namespace
     35 
     36 class URLDatabaseTest : public testing::Test,
     37                         public URLDatabase {
     38  public:
     39   URLDatabaseTest() {
     40   }
     41 
     42  protected:
     43   // Provided for URL/VisitDatabase.
     44   virtual sql::Connection& GetDB() {
     45     return db_;
     46   }
     47 
     48  private:
     49   // Test setup.
     50   void SetUp() {
     51     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     52     FilePath db_file = temp_dir_.path().AppendASCII("URLTest.db");
     53 
     54     EXPECT_TRUE(db_.Open(db_file));
     55 
     56     // Initialize the tables for this test.
     57     CreateURLTable(false);
     58     CreateMainURLIndex();
     59     InitKeywordSearchTermsTable();
     60     CreateKeywordSearchTermsIndices();
     61   }
     62   void TearDown() {
     63     db_.Close();
     64   }
     65 
     66   ScopedTempDir temp_dir_;
     67   sql::Connection db_;
     68 };
     69 
     70 // Test add and query for the URL table in the HistoryDatabase.
     71 TEST_F(URLDatabaseTest, AddURL) {
     72   // First, add two URLs.
     73   const GURL url1("http://www.google.com/");
     74   URLRow url_info1(url1);
     75   url_info1.set_title(UTF8ToUTF16("Google"));
     76   url_info1.set_visit_count(4);
     77   url_info1.set_typed_count(2);
     78   url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
     79   url_info1.set_hidden(false);
     80   EXPECT_TRUE(AddURL(url_info1));
     81 
     82   const GURL url2("http://mail.google.com/");
     83   URLRow url_info2(url2);
     84   url_info2.set_title(UTF8ToUTF16("Google Mail"));
     85   url_info2.set_visit_count(3);
     86   url_info2.set_typed_count(0);
     87   url_info2.set_last_visit(Time::Now() - TimeDelta::FromDays(2));
     88   url_info2.set_hidden(true);
     89   EXPECT_TRUE(AddURL(url_info2));
     90 
     91   // Query both of them.
     92   URLRow info;
     93   EXPECT_TRUE(GetRowForURL(url1, &info));
     94   EXPECT_TRUE(IsURLRowEqual(url_info1, info));
     95   URLID id2 = GetRowForURL(url2, &info);
     96   EXPECT_TRUE(id2);
     97   EXPECT_TRUE(IsURLRowEqual(url_info2, info));
     98 
     99   // Update the second.
    100   url_info2.set_title(UTF8ToUTF16("Google Mail Too"));
    101   url_info2.set_visit_count(4);
    102   url_info2.set_typed_count(1);
    103   url_info2.set_typed_count(91011);
    104   url_info2.set_hidden(false);
    105   EXPECT_TRUE(UpdateURLRow(id2, url_info2));
    106 
    107   // Make sure it got updated.
    108   URLRow info2;
    109   EXPECT_TRUE(GetRowForURL(url2, &info2));
    110   EXPECT_TRUE(IsURLRowEqual(url_info2, info2));
    111 
    112   // Query a nonexistent URL.
    113   EXPECT_EQ(0, GetRowForURL(GURL("http://news.google.com/"), &info));
    114 
    115   // Delete all urls in the domain.
    116   // TODO(acw): test the new url based delete domain
    117   // EXPECT_TRUE(db.DeleteDomain(kDomainID));
    118 
    119   // Make sure the urls have been properly removed.
    120   // TODO(acw): commented out because remove no longer works.
    121   // EXPECT_TRUE(db.GetURLInfo(url1, NULL) == NULL);
    122   // EXPECT_TRUE(db.GetURLInfo(url2, NULL) == NULL);
    123 }
    124 
    125 // Tests adding, querying and deleting keyword visits.
    126 TEST_F(URLDatabaseTest, KeywordSearchTermVisit) {
    127   URLRow url_info1(GURL("http://www.google.com/"));
    128   url_info1.set_title(UTF8ToUTF16("Google"));
    129   url_info1.set_visit_count(4);
    130   url_info1.set_typed_count(2);
    131   url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
    132   url_info1.set_hidden(false);
    133   URLID url_id = AddURL(url_info1);
    134   ASSERT_TRUE(url_id != 0);
    135 
    136   // Add a keyword visit.
    137   TemplateURLID keyword_id = 100;
    138   string16 keyword = UTF8ToUTF16("visit");
    139   ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id, keyword_id, keyword));
    140 
    141   // Make sure we get it back.
    142   std::vector<KeywordSearchTermVisit> matches;
    143   GetMostRecentKeywordSearchTerms(keyword_id, keyword, 10, &matches);
    144   ASSERT_EQ(1U, matches.size());
    145   ASSERT_EQ(keyword, matches[0].term);
    146 
    147   KeywordSearchTermRow keyword_search_term_row;
    148   ASSERT_TRUE(GetKeywordSearchTermRow(url_id, &keyword_search_term_row));
    149   EXPECT_EQ(keyword_id, keyword_search_term_row.keyword_id);
    150   EXPECT_EQ(url_id, keyword_search_term_row.url_id);
    151   EXPECT_EQ(keyword, keyword_search_term_row.term);
    152 
    153   // Delete the keyword visit.
    154   DeleteAllSearchTermsForKeyword(keyword_id);
    155 
    156   // Make sure we don't get it back when querying.
    157   matches.clear();
    158   GetMostRecentKeywordSearchTerms(keyword_id, keyword, 10, &matches);
    159   ASSERT_EQ(0U, matches.size());
    160 
    161   ASSERT_FALSE(GetKeywordSearchTermRow(url_id, &keyword_search_term_row));
    162 }
    163 
    164 // Make sure deleting a URL also deletes a keyword visit.
    165 TEST_F(URLDatabaseTest, DeleteURLDeletesKeywordSearchTermVisit) {
    166   URLRow url_info1(GURL("http://www.google.com/"));
    167   url_info1.set_title(UTF8ToUTF16("Google"));
    168   url_info1.set_visit_count(4);
    169   url_info1.set_typed_count(2);
    170   url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
    171   url_info1.set_hidden(false);
    172   URLID url_id = AddURL(url_info1);
    173   ASSERT_TRUE(url_id != 0);
    174 
    175   // Add a keyword visit.
    176   ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id, 1, UTF8ToUTF16("visit")));
    177 
    178   // Delete the url.
    179   ASSERT_TRUE(DeleteURLRow(url_id));
    180 
    181   // Make sure the keyword visit was deleted.
    182   std::vector<KeywordSearchTermVisit> matches;
    183   GetMostRecentKeywordSearchTerms(1, UTF8ToUTF16("visit"), 10, &matches);
    184   ASSERT_EQ(0U, matches.size());
    185 }
    186 
    187 TEST_F(URLDatabaseTest, EnumeratorForSignificant) {
    188   std::set<std::string> good_urls;
    189   // Add URLs which do and don't meet the criteria.
    190   URLRow url_no_match(GURL("http://www.url_no_match.com/"));
    191   EXPECT_TRUE(AddURL(url_no_match));
    192 
    193   std::string url_string2("http://www.url_match_visit_count.com/");
    194   good_urls.insert("http://www.url_match_visit_count.com/");
    195   URLRow url_match_visit_count(GURL("http://www.url_match_visit_count.com/"));
    196   url_match_visit_count.set_visit_count(kLowQualityMatchVisitLimit + 1);
    197   EXPECT_TRUE(AddURL(url_match_visit_count));
    198 
    199   good_urls.insert("http://www.url_match_typed_count.com/");
    200   URLRow url_match_typed_count(GURL("http://www.url_match_typed_count.com/"));
    201   url_match_typed_count.set_typed_count(kLowQualityMatchTypedLimit + 1);
    202   EXPECT_TRUE(AddURL(url_match_typed_count));
    203 
    204   good_urls.insert("http://www.url_match_last_visit.com/");
    205   URLRow url_match_last_visit(GURL("http://www.url_match_last_visit.com/"));
    206   url_match_last_visit.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
    207   EXPECT_TRUE(AddURL(url_match_last_visit));
    208 
    209   URLRow url_no_match_last_visit(GURL(
    210       "http://www.url_no_match_last_visit.com/"));
    211   url_no_match_last_visit.set_last_visit(Time::Now() -
    212       TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays + 1));
    213   EXPECT_TRUE(AddURL(url_no_match_last_visit));
    214 
    215   URLDatabase::URLEnumerator history_enum;
    216   EXPECT_TRUE(InitURLEnumeratorForSignificant(&history_enum));
    217   URLRow row;
    218   int row_count = 0;
    219   for (; history_enum.GetNextURL(&row); ++row_count)
    220     EXPECT_EQ(1U, good_urls.count(row.url().spec()));
    221   EXPECT_EQ(3, row_count);
    222 }
    223 
    224 TEST_F(URLDatabaseTest, IconMappingEnumerator) {
    225   const GURL url1("http://www.google.com/");
    226   URLRow url_info1(url1);
    227   url_info1.set_title(UTF8ToUTF16("Google"));
    228   url_info1.set_visit_count(4);
    229   url_info1.set_typed_count(2);
    230   url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
    231   url_info1.set_hidden(false);
    232 
    233   // Insert a row with favicon
    234   URLID url_id1 = AddURL(url_info1);
    235   ASSERT_TRUE(url_id1 != 0);
    236 
    237   FaviconID icon_id = 1;
    238   sql::Statement statement(GetDB().GetCachedStatement(
    239       SQL_FROM_HERE,
    240       "UPDATE urls SET favicon_id =? WHERE id=?"));
    241 
    242   ASSERT_TRUE(statement);
    243 
    244   statement.BindInt64(0, icon_id);
    245   statement.BindInt64(1, url_id1);
    246   ASSERT_TRUE(statement.Run());
    247 
    248   // Insert another row without favicon
    249   const GURL url2("http://www.google.com/no_icon");
    250   URLRow url_info2(url2);
    251   url_info2.set_title(UTF8ToUTF16("Google"));
    252   url_info2.set_visit_count(4);
    253   url_info2.set_typed_count(2);
    254   url_info2.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
    255   url_info2.set_hidden(false);
    256 
    257   // Insert a row with favicon
    258   URLID url_id2 = AddURL(url_info2);
    259   ASSERT_TRUE(url_id2 != 0);
    260 
    261   IconMappingEnumerator e;
    262   InitIconMappingEnumeratorForEverything(&e);
    263   IconMapping icon_mapping;
    264   ASSERT_TRUE(e.GetNextIconMapping(&icon_mapping));
    265   ASSERT_EQ(url1, icon_mapping.page_url);
    266   ASSERT_EQ(icon_id, icon_mapping.icon_id);
    267   ASSERT_FALSE(e.GetNextIconMapping(&icon_mapping));
    268 }
    269 
    270 }  // namespace history
    271