1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/sql/connection.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h"
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/text_database_manager.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/visit_database.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time;
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta;
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks;
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace history {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kURL1 = "http://www.google.com/asdf";
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kTitle1 = "Google A";
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kBody1 = "FOO page one.";
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kURL2 = "http://www.google.com/qwer";
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kTitle2 = "Google B";
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kBody2 = "FOO two.";
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kURL3 = "http://www.google.com/zxcv";
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kTitle3 = "Google C";
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kBody3 = "FOO drei";
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kURL4 = "http://www.google.com/hjkl";
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kTitle4 = "Google D";
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kBody4 = "FOO lalala four.";
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kURL5 = "http://www.google.com/uiop";
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kTitle5 = "Google cinq";
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kBody5 = "FOO page one.";
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This provides a simple implementation of a URL+VisitDatabase using an
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// in-memory sqlite connection. The text database manager expects to be able to
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// update the visit database to keep in sync.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass InMemDB : public URLDatabase, public VisitDatabase {
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB() {
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(db_.OpenInMemory());
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateURLTable(false);
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InitVisitTable();
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~InMemDB() {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual sql::Connection& GetDB() { return db_; }
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Connection db_;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(InMemDB);
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Adds all the pages once, and the first page once more in the next month.
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The times of all the pages will be filled into |*times|.
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddAllPages(TextDatabaseManager& manager, VisitDatabase* visit_db,
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 std::vector<Time>* times) {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time::Exploded exploded;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  memset(&exploded, 0, sizeof(Time::Exploded));
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Put the visits in two different months so it will query across databases.
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.year = 2008;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.month = 1;
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.day_of_month = 3;
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  VisitRow visit_row;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = 1;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = Time::FromUTCExploded(exploded);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.referring_visit = 0;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.transition = 0;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.segment_id = 0;
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.is_indexed = false;
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  VisitID visit_id = visit_db->AddVisit(&visit_row, SOURCE_BROWSED);
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  times->push_back(visit_row.visit_time);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageData(GURL(kURL1), visit_row.url_id, visit_row.visit_id,
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      visit_row.visit_time, UTF8ToUTF16(kTitle1),
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      UTF8ToUTF16(kBody1));
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.day_of_month++;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = 2;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = Time::FromUTCExploded(exploded);
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_id = visit_db->AddVisit(&visit_row, SOURCE_BROWSED);
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  times->push_back(visit_row.visit_time);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageData(GURL(kURL2), visit_row.url_id, visit_row.visit_id,
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      visit_row.visit_time, UTF8ToUTF16(kTitle2),
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      UTF8ToUTF16(kBody2));
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.day_of_month++;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = 2;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = Time::FromUTCExploded(exploded);
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_id = visit_db->AddVisit(&visit_row, SOURCE_BROWSED);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  times->push_back(visit_row.visit_time);
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageData(GURL(kURL3), visit_row.url_id, visit_row.visit_id,
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      visit_row.visit_time, UTF8ToUTF16(kTitle3),
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      UTF8ToUTF16(kBody3));
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Put the next ones in the next month.
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.month++;
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = 2;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = Time::FromUTCExploded(exploded);
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_id = visit_db->AddVisit(&visit_row, SOURCE_BROWSED);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  times->push_back(visit_row.visit_time);
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageData(GURL(kURL4), visit_row.url_id, visit_row.visit_id,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      visit_row.visit_time, UTF8ToUTF16(kTitle4),
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      UTF8ToUTF16(kBody4));
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.day_of_month++;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = 2;
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = Time::FromUTCExploded(exploded);
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_id = visit_db->AddVisit(&visit_row, SOURCE_BROWSED);
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  times->push_back(visit_row.visit_time);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageData(GURL(kURL5), visit_row.url_id, visit_row.visit_id,
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      visit_row.visit_time, UTF8ToUTF16(kTitle5),
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      UTF8ToUTF16(kBody5));
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Put the first one in again in the second month.
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.day_of_month++;
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = 2;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = Time::FromUTCExploded(exploded);
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_id = visit_db->AddVisit(&visit_row, SOURCE_BROWSED);
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  times->push_back(visit_row.visit_time);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageData(GURL(kURL1), visit_row.url_id, visit_row.visit_id,
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      visit_row.visit_time, UTF8ToUTF16(kTitle1),
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      UTF8ToUTF16(kBody1));
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ResultsHaveURL(const std::vector<TextDatabase::Match>& results,
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const char* url) {
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL gurl(url);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < results.size(); i++) {
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (results[i].url == gurl)
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TextDatabaseManagerTest : public testing::Test {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called manually by the test so it can report failure to initialize.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Init() {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return file_util::CreateNewTempDirectory(
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FILE_PATH_LITERAL("TestSearchTest"), &dir_);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetUp() {
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void TearDown() {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_util::Delete(dir_, true);
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop message_loop_;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Directory containing the databases.
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath dir_;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests basic querying.
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, InsertQuery) {
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<Time> times;
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllPages(manager, &visit_db, &times);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = times[0] - TimeDelta::FromDays(100);
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = times[times.size() - 1] + TimeDelta::FromDays(100);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("FOO"), options,
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We should have matched every page.
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(6U, results.size());
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL2));
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL3));
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL4));
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL5));
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The first time searched should have been the first page's time or before
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (it could have eliminated some time for us).
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(first_time_searched <= times[0]);
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that adding page components piecemeal will get them added properly.
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This does not supply a visit to update, this mode is used only by the unit
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// tests right now, but we test it anyway.
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, InsertCompleteNoVisit) {
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First add one without a visit.
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GURL url(kURL1);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageURL(url, 0, 0, Time::Now());
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageTitle(url, UTF8ToUTF16(kTitle1));
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageContents(url, UTF8ToUTF16(kBody1));
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that the page got added.
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("FOO"), options,
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(1U, results.size());
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kTitle1, UTF16ToUTF8(results[0].title));
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Like InsertCompleteNoVisit but specifies a visit to update. We check that the
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// visit was updated properly.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, InsertCompleteVisit) {
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First add a visit to a page. We can just make up a URL ID since there is
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // not actually any URL database around.
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  VisitRow visit;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit.url_id = 1;
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit.visit_time = Time::Now();
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit.referring_visit = 0;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit.transition = PageTransition::LINK;
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit.segment_id = 0;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit.is_indexed = false;
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_db.AddVisit(&visit, SOURCE_BROWSED);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add a full text indexed entry for that visit.
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const GURL url(kURL2);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageURL(url, visit.url_id, visit.visit_id, visit.visit_time);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageContents(url, UTF8ToUTF16(kBody2));
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageTitle(url, UTF8ToUTF16(kTitle2));
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that the page got added.
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("FOO"), options,
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(1U, results.size());
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kTitle2, UTF16ToUTF8(results[0].title));
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that the visit got updated for its new indexed state.
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  VisitRow out_visit;
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(visit_db.GetRowForVisit(visit.visit_id, &out_visit));
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(out_visit.is_indexed);
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that partial inserts that expire are added to the database.
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, InsertPartial) {
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add the first one with just a URL.
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url1(kURL1);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageURL(url1, 0, 0, Time::Now());
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now add a second one with a URL and title.
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url2(kURL2);
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageURL(url2, 0, 0, Time::Now());
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageTitle(url2, UTF8ToUTF16(kTitle2));
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The third one has a URL and body.
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url3(kURL3);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageURL(url3, 0, 0, Time::Now());
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageContents(url3, UTF8ToUTF16(kBody3));
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Expire stuff very fast. This assumes that the time between the first
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // AddPageURL and this line is less than the expiration time (20 seconds).
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks added_time = TimeTicks::Now();
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks expire_time = added_time + TimeDelta::FromSeconds(5);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.FlushOldChangesForTime(expire_time);
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do a query, nothing should be added yet.
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("google"), options,
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(0U, results.size());
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Compute a time threshold that will cause everything to be flushed, and
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // poke at the manager's internals to cause this to happen.
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  expire_time = added_time + TimeDelta::FromDays(1);
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.FlushOldChangesForTime(expire_time);
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now we should have all 3 URLs added.
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("google"), options,
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(3U, results.size());
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL2));
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL3));
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that partial inserts (due to timeouts) will still get updated if the
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// data comes in later.
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, PartialComplete) {
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time added_time = Time::Now();
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url(kURL1);
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We have to have the URL in the URL and visit databases for this test to
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // work.
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLRow url_row(url);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_row.set_title(UTF8ToUTF16("chocolate"));
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLID url_id = visit_db.AddURL(url_row);
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(url_id);
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  VisitRow visit_row;
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.url_id = url_id;
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  visit_row.visit_time = added_time;
3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  visit_db.AddVisit(&visit_row, SOURCE_BROWSED);
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add a URL with no title or body, and say that it expired.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageURL(url, 0, 0, added_time);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks expire_time = TimeTicks::Now() + TimeDelta::FromDays(1);
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.FlushOldChangesForTime(expire_time);
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add the title. We should be able to query based on that. The title in the
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // URL row we set above should not come into the picture.
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageTitle(url, UTF8ToUTF16("Some unique title"));
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("unique"), options,
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(1U, results.size());
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("chocolate"), options,
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         &results, &first_time_searched);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0U, results.size());
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now add the body, which should be queryable.
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.AddPageContents(url, UTF8ToUTF16("Very awesome body"));
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("awesome"), options, &results, &first_time_searched);
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(1U, results.size());
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Adding the body will actually copy the title from the URL table rather
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // than the previously indexed row (we made them not match above). This isn't
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // necessarily what we want, but it's how it's implemented, and we don't want
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to regress it.
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(UTF8ToUTF16("chocolate"), options, &results, &first_time_searched);
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(1U, results.size());
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that changes get properly committed to disk.
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, Writing) {
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create the manager and write some stuff to it.
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TextDatabaseManager manager(dir_, &visit_db, &visit_db);
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(manager.Init(NULL));
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<Time> times;
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddAllPages(manager, &visit_db, &times);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We should have matched every page.
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manager.GetTextMatches(UTF8ToUTF16("FOO"), options, &results, &first_time_searched);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(6U, results.size());
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results.clear();
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Recreate the manager and make sure it finds the written stuff.
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TextDatabaseManager manager(dir_, &visit_db, &visit_db);
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(manager.Init(NULL));
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We should have matched every page again.
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manager.GetTextMatches(UTF8ToUTF16("FOO"), options,
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &results, &first_time_searched);
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(6U, results.size());
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests that changes get properly committed to disk, as in the Writing test
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// above, but when there is a transaction around the adds.
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, WritingTransaction) {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create the manager and write some stuff to it.
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TextDatabaseManager manager(dir_, &visit_db, &visit_db);
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(manager.Init(NULL));
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<Time> times;
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manager.BeginTransaction();
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddAllPages(manager, &visit_db, &times);
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // "Forget" to commit, it should be autocommittedd for us.
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We should have matched every page.
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manager.GetTextMatches(UTF8ToUTF16("FOO"), options,
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &results, &first_time_searched);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(6U, results.size());
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results.clear();
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Recreate the manager and make sure it finds the written stuff.
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TextDatabaseManager manager(dir_, &visit_db, &visit_db);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(manager.Init(NULL));
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We should have matched every page again.
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    manager.GetTextMatches(UTF8ToUTF16("FOO"), options,
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &results, &first_time_searched);
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(6U, results.size());
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests querying where the maximum number of items is met.
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, QueryMax) {
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<Time> times;
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllPages(manager, &visit_db, &times);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 foo = UTF8ToUTF16("FOO");
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = times[0] - TimeDelta::FromDays(100);
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = times[times.size() - 1] + TimeDelta::FromDays(100);
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.max_count = 2;
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(foo, options, &results, &first_time_searched);
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We should have gotten the last two pages as results (the first page is
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // also the last).
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, results.size());
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(first_time_searched <= times[4]);
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL5));
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Asking for 4 pages, the first one should be in another DB.
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.max_count = 4;
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(foo, options, &results, &first_time_searched);
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(4U, results.size());
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(first_time_searched <= times[4]);
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL3));
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL4));
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL5));
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests querying backwards in time in chunks.
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseManagerTest, QueryBackwards) {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(Init());
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InMemDB visit_db;
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabaseManager manager(dir_, &visit_db, &visit_db);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(manager.Init(NULL));
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<Time> times;
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllPages(manager, &visit_db, &times);
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 foo = UTF8ToUTF16("FOO");
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First do a query for all time, but with a max of 2. This will give us the
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // last two results and will tell us where to start searching when we want
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to go back in time.
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = times[0] - TimeDelta::FromDays(100);
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = times[times.size() - 1] + TimeDelta::FromDays(100);
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.max_count = 2;
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(foo, options, &results, &first_time_searched);
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that we got the last two results.
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, results.size());
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(first_time_searched <= times[4]);
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL5));
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Query the previous two URLs and make sure we got the correct ones.
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = first_time_searched;
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(foo, options, &results, &first_time_searched);
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, results.size());
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(first_time_searched <= times[2]);
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL3));
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL4));
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Query the previous two URLs...
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = first_time_searched;
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(foo, options, &results, &first_time_searched);
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, results.size());
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(first_time_searched <= times[0]);
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL2));
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Try to query some more, there should be no results.
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = first_time_searched;
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  manager.GetTextMatches(foo, options, &results, &first_time_searched);
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0U, results.size());
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace history
538