1 // Copyright (c) 2012 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.
5 #include "base/files/file_path.h"
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/path_service.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/history/url_database.h"
11 #include "sql/connection.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 using base::TimeDelta;
21 bool IsURLRowEqual(const URLRow& a,
23 // TODO(brettw) when the database stores an actual Time value rather than
24 // a time_t, do a reaul comparison. Instead, we have to do a more rough
25 // comparison since the conversion reduces the precision.
26 return a.title() == b.title() &&
27 a.visit_count() == b.visit_count() &&
28 a.typed_count() == b.typed_count() &&
29 a.last_visit() - b.last_visit() <= TimeDelta::FromSeconds(1) &&
30 a.hidden() == b.hidden();
35 class URLDatabaseTest : public testing::Test,
42 // Provided for URL/VisitDatabase.
43 virtual sql::Connection& GetDB() OVERRIDE {
49 virtual void SetUp() {
50 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
51 base::FilePath db_file = temp_dir_.path().AppendASCII("URLTest.db");
53 EXPECT_TRUE(db_.Open(db_file));
55 // Initialize the tables for this test.
56 CreateURLTable(false);
58 InitKeywordSearchTermsTable();
59 CreateKeywordSearchTermsIndices();
61 virtual void TearDown() {
65 base::ScopedTempDir temp_dir_;
69 // Test add, update, upsert, and query for the URL table in the HistoryDatabase.
70 TEST_F(URLDatabaseTest, AddAndUpdateURL) {
71 // First, add two URLs.
72 const GURL url1("http://www.google.com/");
73 URLRow url_info1(url1);
74 url_info1.set_title(base::UTF8ToUTF16("Google"));
75 url_info1.set_visit_count(4);
76 url_info1.set_typed_count(2);
77 url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
78 url_info1.set_hidden(false);
79 URLID id1_initially = AddURL(url_info1);
80 EXPECT_TRUE(id1_initially);
82 const GURL url2("http://mail.google.com/");
83 URLRow url_info2(url2);
84 url_info2.set_title(base::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));
91 // Query both of them.
93 EXPECT_TRUE(GetRowForURL(url1, &info));
94 EXPECT_TRUE(IsURLRowEqual(url_info1, info));
95 URLID id2 = GetRowForURL(url2, &info);
97 EXPECT_TRUE(IsURLRowEqual(url_info2, info));
100 url_info2.set_title(base::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));
107 // Make sure it got updated.
109 EXPECT_TRUE(GetRowForURL(url2, &info2));
110 EXPECT_TRUE(IsURLRowEqual(url_info2, info2));
112 // Update an existing URL and insert a new one using the upsert operation.
113 url_info1.set_id(id1_initially);
114 url_info1.set_title(base::UTF8ToUTF16("Google Again!"));
115 url_info1.set_visit_count(5);
116 url_info1.set_typed_count(3);
117 url_info1.set_last_visit(Time::Now());
118 url_info1.set_hidden(true);
119 EXPECT_TRUE(InsertOrUpdateURLRowByID(url_info1));
121 const GURL url3("http://maps.google.com/");
122 URLRow url_info3(url3);
123 url_info3.set_id(42);
124 url_info3.set_title(base::UTF8ToUTF16("Google Maps"));
125 url_info3.set_visit_count(7);
126 url_info3.set_typed_count(6);
127 url_info3.set_last_visit(Time::Now() - TimeDelta::FromDays(3));
128 url_info3.set_hidden(false);
129 EXPECT_TRUE(InsertOrUpdateURLRowByID(url_info3));
131 // Query both of these as well.
132 URLID id1 = GetRowForURL(url1, &info);
134 EXPECT_TRUE(IsURLRowEqual(url_info1, info));
135 URLID id3 = GetRowForURL(url3, &info);
137 EXPECT_TRUE(IsURLRowEqual(url_info3, info));
139 // Query a nonexistent URL.
140 EXPECT_EQ(0, GetRowForURL(GURL("http://news.google.com/"), &info));
142 // Delete all urls in the domain.
143 // TODO(acw): test the new url based delete domain
144 // EXPECT_TRUE(db.DeleteDomain(kDomainID));
146 // Make sure the urls have been properly removed.
147 // TODO(acw): commented out because remove no longer works.
148 // EXPECT_TRUE(db.GetURLInfo(url1, NULL) == NULL);
149 // EXPECT_TRUE(db.GetURLInfo(url2, NULL) == NULL);
152 // Tests adding, querying and deleting keyword visits.
153 TEST_F(URLDatabaseTest, KeywordSearchTermVisit) {
154 URLRow url_info1(GURL("http://www.google.com/"));
155 url_info1.set_title(base::UTF8ToUTF16("Google"));
156 url_info1.set_visit_count(4);
157 url_info1.set_typed_count(2);
158 url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
159 url_info1.set_hidden(false);
160 URLID url_id = AddURL(url_info1);
161 ASSERT_NE(0, url_id);
163 // Add a keyword visit.
164 TemplateURLID keyword_id = 100;
165 base::string16 keyword = base::UTF8ToUTF16("visit");
166 ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id, keyword_id, keyword));
168 // Make sure we get it back.
169 std::vector<KeywordSearchTermVisit> matches;
170 GetMostRecentKeywordSearchTerms(keyword_id, keyword, 10, &matches);
171 ASSERT_EQ(1U, matches.size());
172 ASSERT_EQ(keyword, matches[0].term);
174 KeywordSearchTermRow keyword_search_term_row;
175 ASSERT_TRUE(GetKeywordSearchTermRow(url_id, &keyword_search_term_row));
176 EXPECT_EQ(keyword_id, keyword_search_term_row.keyword_id);
177 EXPECT_EQ(url_id, keyword_search_term_row.url_id);
178 EXPECT_EQ(keyword, keyword_search_term_row.term);
180 // Delete the keyword visit.
181 DeleteAllSearchTermsForKeyword(keyword_id);
183 // Make sure we don't get it back when querying.
185 GetMostRecentKeywordSearchTerms(keyword_id, keyword, 10, &matches);
186 ASSERT_EQ(0U, matches.size());
188 ASSERT_FALSE(GetKeywordSearchTermRow(url_id, &keyword_search_term_row));
191 // Make sure deleting a URL also deletes a keyword visit.
192 TEST_F(URLDatabaseTest, DeleteURLDeletesKeywordSearchTermVisit) {
193 URLRow url_info1(GURL("http://www.google.com/"));
194 url_info1.set_title(base::UTF8ToUTF16("Google"));
195 url_info1.set_visit_count(4);
196 url_info1.set_typed_count(2);
197 url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
198 url_info1.set_hidden(false);
199 URLID url_id = AddURL(url_info1);
200 ASSERT_NE(0, url_id);
202 // Add a keyword visit.
204 SetKeywordSearchTermsForURL(url_id, 1, base::UTF8ToUTF16("visit")));
207 ASSERT_TRUE(DeleteURLRow(url_id));
209 // Make sure the keyword visit was deleted.
210 std::vector<KeywordSearchTermVisit> matches;
211 GetMostRecentKeywordSearchTerms(1, base::UTF8ToUTF16("visit"), 10, &matches);
212 ASSERT_EQ(0U, matches.size());
215 TEST_F(URLDatabaseTest, EnumeratorForSignificant) {
216 std::set<std::string> good_urls;
217 // Add URLs which do and don't meet the criteria.
218 URLRow url_no_match(GURL("http://www.url_no_match.com/"));
219 EXPECT_TRUE(AddURL(url_no_match));
221 std::string url_string2("http://www.url_match_visit_count.com/");
222 good_urls.insert("http://www.url_match_visit_count.com/");
223 URLRow url_match_visit_count(GURL("http://www.url_match_visit_count.com/"));
224 url_match_visit_count.set_visit_count(kLowQualityMatchVisitLimit);
225 EXPECT_TRUE(AddURL(url_match_visit_count));
227 good_urls.insert("http://www.url_match_typed_count.com/");
228 URLRow url_match_typed_count(GURL("http://www.url_match_typed_count.com/"));
229 url_match_typed_count.set_typed_count(kLowQualityMatchTypedLimit);
230 EXPECT_TRUE(AddURL(url_match_typed_count));
232 good_urls.insert("http://www.url_match_last_visit.com/");
233 URLRow url_match_last_visit(GURL("http://www.url_match_last_visit.com/"));
234 url_match_last_visit.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
235 EXPECT_TRUE(AddURL(url_match_last_visit));
237 URLRow url_no_match_last_visit(GURL(
238 "http://www.url_no_match_last_visit.com/"));
239 url_no_match_last_visit.set_last_visit(Time::Now() -
240 TimeDelta::FromDays(kLowQualityMatchAgeLimitInDays + 1));
241 EXPECT_TRUE(AddURL(url_no_match_last_visit));
243 URLDatabase::URLEnumerator history_enum;
244 EXPECT_TRUE(InitURLEnumeratorForSignificant(&history_enum));
247 for (; history_enum.GetNextURL(&row); ++row_count)
248 EXPECT_EQ(1U, good_urls.count(row.url().spec()));
249 EXPECT_EQ(3, row_count);
252 // Test GetKeywordSearchTermRows and DeleteSearchTerm
253 TEST_F(URLDatabaseTest, GetAndDeleteKeywordSearchTermByTerm) {
254 URLRow url_info1(GURL("http://www.google.com/"));
255 url_info1.set_title(base::UTF8ToUTF16("Google"));
256 url_info1.set_visit_count(4);
257 url_info1.set_typed_count(2);
258 url_info1.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
259 url_info1.set_hidden(false);
260 URLID url_id1 = AddURL(url_info1);
261 ASSERT_NE(0, url_id1);
263 // Add a keyword visit.
264 TemplateURLID keyword_id = 100;
265 base::string16 keyword = base::UTF8ToUTF16("visit");
266 ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id1, keyword_id, keyword));
268 URLRow url_info2(GURL("https://www.google.com/"));
269 url_info2.set_title(base::UTF8ToUTF16("Google"));
270 url_info2.set_visit_count(4);
271 url_info2.set_typed_count(2);
272 url_info2.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
273 url_info2.set_hidden(false);
274 URLID url_id2 = AddURL(url_info2);
275 ASSERT_NE(0, url_id2);
276 // Add the same keyword for url_info2.
277 ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id2, keyword_id, keyword));
279 // Add another URL for different keyword.
280 URLRow url_info3(GURL("https://www.google.com/search"));
281 url_info3.set_title(base::UTF8ToUTF16("Google"));
282 url_info3.set_visit_count(4);
283 url_info3.set_typed_count(2);
284 url_info3.set_last_visit(Time::Now() - TimeDelta::FromDays(1));
285 url_info3.set_hidden(false);
286 URLID url_id3 = AddURL(url_info3);
287 ASSERT_NE(0, url_id3);
288 base::string16 keyword2 = base::UTF8ToUTF16("Search");
290 ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id3, keyword_id, keyword2));
292 // We should get 2 rows for |keyword|.
293 std::vector<KeywordSearchTermRow> rows;
294 ASSERT_TRUE(GetKeywordSearchTermRows(keyword, &rows));
295 ASSERT_EQ(2u, rows.size());
296 if (rows[0].url_id == url_id1) {
297 EXPECT_EQ(keyword, rows[0].term);
298 EXPECT_EQ(keyword, rows[1].term);
299 EXPECT_EQ(url_id2, rows[1].url_id);
301 EXPECT_EQ(keyword, rows[0].term);
302 EXPECT_EQ(url_id1, rows[1].url_id);
303 EXPECT_EQ(keyword, rows[1].term);
304 EXPECT_EQ(url_id2, rows[0].url_id);
307 // We should get 1 row for |keyword2|.
309 ASSERT_TRUE(GetKeywordSearchTermRows(keyword2, &rows));
310 ASSERT_EQ(1u, rows.size());
311 EXPECT_EQ(keyword2, rows[0].term);
312 EXPECT_EQ(url_id3, rows[0].url_id);
314 // Delete all rows have keyword.
315 ASSERT_TRUE(DeleteKeywordSearchTerm(keyword));
317 // We should still find keyword2.
318 ASSERT_TRUE(GetKeywordSearchTermRows(keyword2, &rows));
319 ASSERT_EQ(1u, rows.size());
320 EXPECT_EQ(keyword2, rows[0].term);
321 EXPECT_EQ(url_id3, rows[0].url_id);
323 // No row for keyword.
324 ASSERT_TRUE(GetKeywordSearchTermRows(keyword, &rows));
325 EXPECT_TRUE(rows.empty());
328 } // namespace history