• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/path_service.h"
9 #include "base/string_util.h"
10 #include "base/memory/scoped_temp_dir.h"
11 #include "chrome/browser/history/url_database.h"
12 #include "chrome/browser/history/visit_database.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "testing/platform_test.h"
15 
16 using base::Time;
17 using base::TimeDelta;
18 
19 namespace history {
20 
21 namespace {
22 
IsVisitInfoEqual(const VisitRow & a,const VisitRow & b)23 bool IsVisitInfoEqual(const VisitRow& a,
24                       const VisitRow& b) {
25   return a.visit_id == b.visit_id &&
26          a.url_id == b.url_id &&
27          a.visit_time == b.visit_time &&
28          a.referring_visit == b.referring_visit &&
29          a.transition == b.transition &&
30          a.is_indexed == b.is_indexed;
31 }
32 
33 }  // namespace
34 
35 class VisitDatabaseTest : public PlatformTest,
36                           public URLDatabase,
37                           public VisitDatabase {
38  public:
VisitDatabaseTest()39   VisitDatabaseTest() {
40   }
41 
42  private:
43   // Test setup.
SetUp()44   void SetUp() {
45     PlatformTest::SetUp();
46     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
47     FilePath db_file = temp_dir_.path().AppendASCII("VisitTest.db");
48 
49     EXPECT_TRUE(db_.Open(db_file));
50 
51     // Initialize the tables for this test.
52     CreateURLTable(false);
53     CreateMainURLIndex();
54     InitVisitTable();
55   }
TearDown()56   void TearDown() {
57     db_.Close();
58     PlatformTest::TearDown();
59   }
60 
61   // Provided for URL/VisitDatabase.
GetDB()62   virtual sql::Connection& GetDB() {
63     return db_;
64   }
65 
66   ScopedTempDir temp_dir_;
67   sql::Connection db_;
68 };
69 
TEST_F(VisitDatabaseTest,Add)70 TEST_F(VisitDatabaseTest, Add) {
71   // Add one visit.
72   VisitRow visit_info1(1, Time::Now(), 0, PageTransition::LINK, 0);
73   EXPECT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
74 
75   // Add second visit for the same page.
76   VisitRow visit_info2(visit_info1.url_id,
77       visit_info1.visit_time + TimeDelta::FromSeconds(1), 1,
78       PageTransition::TYPED, 0);
79   EXPECT_TRUE(AddVisit(&visit_info2, SOURCE_BROWSED));
80 
81   // Add third visit for a different page.
82   VisitRow visit_info3(2,
83       visit_info1.visit_time + TimeDelta::FromSeconds(2), 0,
84       PageTransition::LINK, 0);
85   EXPECT_TRUE(AddVisit(&visit_info3, SOURCE_BROWSED));
86 
87   // Query the first two.
88   std::vector<VisitRow> matches;
89   EXPECT_TRUE(GetVisitsForURL(visit_info1.url_id, &matches));
90   EXPECT_EQ(static_cast<size_t>(2), matches.size());
91 
92   // Make sure we got both (order in result set is visit time).
93   EXPECT_TRUE(IsVisitInfoEqual(matches[0], visit_info1) &&
94               IsVisitInfoEqual(matches[1], visit_info2));
95 }
96 
TEST_F(VisitDatabaseTest,Delete)97 TEST_F(VisitDatabaseTest, Delete) {
98   // Add three visits that form a chain of navigation, and then delete the
99   // middle one. We should be left with the outer two visits, and the chain
100   // should link them.
101   static const int kTime1 = 1000;
102   VisitRow visit_info1(1, Time::FromInternalValue(kTime1), 0,
103                        PageTransition::LINK, 0);
104   EXPECT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
105 
106   static const int kTime2 = kTime1 + 1;
107   VisitRow visit_info2(1, Time::FromInternalValue(kTime2),
108                        visit_info1.visit_id, PageTransition::LINK, 0);
109   EXPECT_TRUE(AddVisit(&visit_info2, SOURCE_BROWSED));
110 
111   static const int kTime3 = kTime2 + 1;
112   VisitRow visit_info3(1, Time::FromInternalValue(kTime3),
113                        visit_info2.visit_id, PageTransition::LINK, 0);
114   EXPECT_TRUE(AddVisit(&visit_info3, SOURCE_BROWSED));
115 
116   // First make sure all the visits are there.
117   std::vector<VisitRow> matches;
118   EXPECT_TRUE(GetVisitsForURL(visit_info1.url_id, &matches));
119   EXPECT_EQ(static_cast<size_t>(3), matches.size());
120   EXPECT_TRUE(IsVisitInfoEqual(matches[0], visit_info1) &&
121               IsVisitInfoEqual(matches[1], visit_info2) &&
122               IsVisitInfoEqual(matches[2], visit_info3));
123 
124   // Delete the middle one.
125   DeleteVisit(visit_info2);
126 
127   // The outer two should be left, and the last one should have the first as
128   // the referrer.
129   visit_info3.referring_visit = visit_info1.visit_id;
130   matches.clear();
131   EXPECT_TRUE(GetVisitsForURL(visit_info1.url_id, &matches));
132   EXPECT_EQ(static_cast<size_t>(2), matches.size());
133   EXPECT_TRUE(IsVisitInfoEqual(matches[0], visit_info1) &&
134               IsVisitInfoEqual(matches[1], visit_info3));
135 }
136 
TEST_F(VisitDatabaseTest,Update)137 TEST_F(VisitDatabaseTest, Update) {
138   // Make something in the database.
139   VisitRow original(1, Time::Now(), 23, 22, 19);
140   AddVisit(&original, SOURCE_BROWSED);
141 
142   // Mutate that row.
143   VisitRow modification(original);
144   modification.url_id = 2;
145   modification.transition = PageTransition::TYPED;
146   modification.visit_time = Time::Now() + TimeDelta::FromDays(1);
147   modification.referring_visit = 9292;
148   modification.is_indexed = true;
149   UpdateVisitRow(modification);
150 
151   // Check that the mutated version was written.
152   VisitRow final;
153   GetRowForVisit(original.visit_id, &final);
154   EXPECT_TRUE(IsVisitInfoEqual(modification, final));
155 }
156 
157 // TODO(brettw) write test for GetMostRecentVisitForURL!
158 
TEST_F(VisitDatabaseTest,GetVisibleVisitsInRange)159 TEST_F(VisitDatabaseTest, GetVisibleVisitsInRange) {
160   // Add one visit.
161   VisitRow visit_info1(1, Time::Now(), 0,
162       static_cast<PageTransition::Type>(PageTransition::LINK |
163                                         PageTransition::CHAIN_START |
164                                         PageTransition::CHAIN_END),
165       0);
166   visit_info1.visit_id = 1;
167   EXPECT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
168 
169   // Add second visit for the same page.
170   VisitRow visit_info2(visit_info1.url_id,
171       visit_info1.visit_time + TimeDelta::FromSeconds(1), 1,
172       static_cast<PageTransition::Type>(PageTransition::TYPED |
173                                         PageTransition::CHAIN_START |
174                                         PageTransition::CHAIN_END),
175       0);
176   visit_info2.visit_id = 2;
177   EXPECT_TRUE(AddVisit(&visit_info2, SOURCE_BROWSED));
178 
179   // Add third visit for a different page.
180   VisitRow visit_info3(2,
181       visit_info1.visit_time + TimeDelta::FromSeconds(2), 0,
182       static_cast<PageTransition::Type>(PageTransition::LINK |
183                                         PageTransition::CHAIN_START),
184       0);
185   visit_info3.visit_id = 3;
186   EXPECT_TRUE(AddVisit(&visit_info3, SOURCE_BROWSED));
187 
188   // Add a redirect visit from the last page.
189   VisitRow visit_info4(3,
190       visit_info1.visit_time + TimeDelta::FromSeconds(3), visit_info3.visit_id,
191       static_cast<PageTransition::Type>(PageTransition::SERVER_REDIRECT |
192                                         PageTransition::CHAIN_END),
193       0);
194   visit_info4.visit_id = 4;
195   EXPECT_TRUE(AddVisit(&visit_info4, SOURCE_BROWSED));
196 
197   // Add a subframe visit.
198   VisitRow visit_info5(4,
199       visit_info1.visit_time + TimeDelta::FromSeconds(4), visit_info4.visit_id,
200       static_cast<PageTransition::Type>(PageTransition::AUTO_SUBFRAME |
201                                         PageTransition::CHAIN_START |
202                                         PageTransition::CHAIN_END),
203       0);
204   visit_info5.visit_id = 5;
205   EXPECT_TRUE(AddVisit(&visit_info5, SOURCE_BROWSED));
206 
207   // Query the visits for all time, we should not get the first (duplicate of
208   // the second) or the redirect or subframe visits.
209   VisitVector results;
210   GetVisibleVisitsInRange(Time(), Time(), 0, &results);
211   ASSERT_EQ(static_cast<size_t>(2), results.size());
212   EXPECT_TRUE(IsVisitInfoEqual(results[0], visit_info4) &&
213               IsVisitInfoEqual(results[1], visit_info2));
214 
215   // Query a time range and make sure beginning is inclusive and ending is
216   // exclusive.
217   GetVisibleVisitsInRange(visit_info2.visit_time, visit_info4.visit_time, 0,
218                           &results);
219   ASSERT_EQ(static_cast<size_t>(1), results.size());
220   EXPECT_TRUE(IsVisitInfoEqual(results[0], visit_info2));
221 
222   // Query for a max count and make sure we get only that number.
223   GetVisibleVisitsInRange(Time(), Time(), 1, &results);
224   ASSERT_EQ(static_cast<size_t>(1), results.size());
225   EXPECT_TRUE(IsVisitInfoEqual(results[0], visit_info4));
226 }
227 
TEST_F(VisitDatabaseTest,VisitSource)228 TEST_F(VisitDatabaseTest, VisitSource) {
229   // Add visits.
230   VisitRow visit_info1(111, Time::Now(), 0, PageTransition::LINK, 0);
231   ASSERT_TRUE(AddVisit(&visit_info1, SOURCE_BROWSED));
232 
233   VisitRow visit_info2(112, Time::Now(), 1, PageTransition::TYPED, 0);
234   ASSERT_TRUE(AddVisit(&visit_info2, SOURCE_SYNCED));
235 
236   VisitRow visit_info3(113, Time::Now(), 0, PageTransition::TYPED, 0);
237   ASSERT_TRUE(AddVisit(&visit_info3, SOURCE_EXTENSION));
238 
239   // Query each visit.
240   std::vector<VisitRow> matches;
241   ASSERT_TRUE(GetVisitsForURL(111, &matches));
242   ASSERT_EQ(1U, matches.size());
243   VisitSourceMap sources;
244   GetVisitsSource(matches, &sources);
245   EXPECT_EQ(0U, sources.size());
246 
247   ASSERT_TRUE(GetVisitsForURL(112, &matches));
248   ASSERT_EQ(1U, matches.size());
249   GetVisitsSource(matches, &sources);
250   ASSERT_EQ(1U, sources.size());
251   EXPECT_EQ(SOURCE_SYNCED, sources[matches[0].visit_id]);
252 
253   ASSERT_TRUE(GetVisitsForURL(113, &matches));
254   ASSERT_EQ(1U, matches.size());
255   GetVisitsSource(matches, &sources);
256   ASSERT_EQ(1U, sources.size());
257   EXPECT_EQ(SOURCE_EXTENSION, sources[matches[0].visit_id]);
258 }
259 
260 }  // namespace history
261