1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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 <string>
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/text_database.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time;
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace history {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Note that all pages have "COUNTTAG" which allows us to count the number of
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// pages in the database withoujt adding any extra functions to the DB object.
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kURL1[] = "http://www.google.com/";
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTime1 = 1000;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kTitle1[] = "Google";
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kBody1[] =
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "COUNTTAG Web Images Maps News Shopping Gmail more My Account | "
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Sign out Advanced Search Preferences Language Tools Advertising Programs "
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "- Business Solutions - About Google, 2008 Google";
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kURL2[] = "http://images.google.com/";
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTime2 = 2000;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kTitle2[] = "Google Image Search";
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kBody2[] =
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "COUNTTAG Web Images Maps News Shopping Gmail more My Account | "
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Sign out Advanced Image Search Preferences The most comprehensive image "
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "search on the web. Want to help improve Google Image Search? Try Google "
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Image Labeler. Advertising Programs - Business Solutions - About Google "
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "2008 Google";
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kURL3[] = "http://slashdot.org/";
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTime3 = 3000;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kTitle3[] = "Slashdot: News for nerds, stuff that matters";
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kBody3[] =
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "COUNTTAG Slashdot Log In Create Account Subscribe Firehose Why "
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Log In? Why Subscribe? Nickname Password Public Terminal Sections "
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Main Apple AskSlashdot Backslash Books Developers Games Hardware "
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "Interviews IT Linux Mobile Politics Science YRO";
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the number of rows currently in the database.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint RowCount(TextDatabase* db) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = Time::FromInternalValue(0);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Leave end_time at now.
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabase::URLSet unique_urls;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->GetTextMatches("COUNTTAG", options, &results, &unique_urls,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &first_time_searched);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return static_cast<int>(results.size());
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Adds each of the test pages to the database.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddAllTestData(TextDatabase* db) {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(db->AddPageData(
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime1), kURL1, kTitle1, kBody1));
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(db->AddPageData(
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime2), kURL2, kTitle2, kBody2));
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(db->AddPageData(
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime3), kURL3, kTitle3, kBody3));
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3, RowCount(db));
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ResultsHaveURL(const std::vector<TextDatabase::Match>& results,
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const char* url) {
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL gurl(url);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < results.size(); i++) {
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (results[i].url == gurl)
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TextDatabaseTest : public PlatformTest {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TextDatabaseTest() {}
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetUp() {
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PlatformTest::SetUp();
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create databases with this function, which will ensure that the files are
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // deleted on shutdown. Only open one database for each file. Returns NULL on
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // failure.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set |delete_file| to delete any existing file. If we are trying to create
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the file for the first time, we don't want a previous test left in a
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // weird state to have left a file that would affect us.
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabase* CreateDB(TextDatabase::DBIdent id,
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         bool allow_create,
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         bool delete_file) {
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TextDatabase* db = new TextDatabase(temp_dir_.path(), id, allow_create);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (delete_file)
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_util::Delete(db->file_name(), false);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!db->Init()) {
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete db;
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return NULL;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return db;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Directory containing the databases.
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ScopedTempDir temp_dir_;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Name of the main database file.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath file_name_;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseTest, AttachDetach) {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First database with one page.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdee1 = 200801;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db1(CreateDB(kIdee1, true, true));
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(!!db1.get());
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(db1->AddPageData(
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime1), kURL1, kTitle1, kBody1));
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Second database with one page.
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdee2 = 200802;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db2(CreateDB(kIdee2, true, true));
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(!!db2.get());
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(db2->AddPageData(
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime2), kURL2, kTitle2, kBody2));
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Detach, then reattach database one. The file should exist, so we force
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // opening an existing file.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db1.reset();
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db1.reset(CreateDB(kIdee1, false, false));
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(!!db1.get());
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We should not be able to attach this random database for which no file
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // exists.
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdeeNoExisto = 999999999;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db3(CreateDB(kIdeeNoExisto, false, true));
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_FALSE(!!db3.get());
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseTest, AddRemove) {
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a database and add some pages to it.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdee1 = 200801;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(!!db.get());
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLID id1 = db->AddPageData(
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime1), kURL1, kTitle1, kBody1);
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_NE(0, id1);
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLID id2 = db->AddPageData(
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime2), kURL2, kTitle2, kBody2);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_NE(0, id2);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLID id3 = db->AddPageData(
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Time::FromInternalValue(kTime3), kURL3, kTitle3, kBody3);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_NE(0, id3);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3, RowCount(db.get()));
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure we can delete some of the data.
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->DeletePageData(Time::FromInternalValue(kTime1), kURL1);
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2, RowCount(db.get()));
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Close and reopen.
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  db.reset(new TextDatabase(temp_dir_.path(), kIdee1, false));
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(db->Init());
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that the deleted ID is gone and try to delete another one.
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2, RowCount(db.get()));
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->DeletePageData(Time::FromInternalValue(kTime2), kURL2);
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(1, RowCount(db.get()));
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseTest, Query) {
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a database with some pages.
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdee1 = 200801;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(!!db.get());
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllTestData(db.get());
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get all the results.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = Time::FromInternalValue(0);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabase::URLSet unique_urls;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->GetTextMatches("COUNTTAG", options, &results, &unique_urls,
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &first_time_searched);
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // All 3 sites should be returned in order.
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(3U, results.size());
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(GURL(kURL1), results[2].url);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(GURL(kURL2), results[1].url);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(GURL(kURL3), results[0].url);
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify the info on those results.
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(Time::FromInternalValue(kTime1) == results[2].time);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(Time::FromInternalValue(kTime2) == results[1].time);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(Time::FromInternalValue(kTime3) == results[0].time);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(std::string(kTitle1), UTF16ToUTF8(results[2].title));
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(std::string(kTitle2), UTF16ToUTF8(results[1].title));
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(std::string(kTitle3), UTF16ToUTF8(results[0].title));
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Should have no matches in the title.
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0U, results[0].title_match_positions.size());
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0U, results[1].title_match_positions.size());
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0U, results[2].title_match_positions.size());
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't want to be dependent on the exact snippet algorithm, but we know
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // since we searched for "COUNTTAG" which occurs at the beginning of each
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // document, that each snippet should start with that.
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(StartsWithASCII(UTF16ToUTF8(results[0].snippet.text()),
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              "COUNTTAG", false));
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(StartsWithASCII(UTF16ToUTF8(results[1].snippet.text()),
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              "COUNTTAG", false));
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(StartsWithASCII(UTF16ToUTF8(results[2].snippet.text()),
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              "COUNTTAG", false));
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseTest, TimeRange) {
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a database with some pages.
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdee1 = 200801;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(!!db.get());
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllTestData(db.get());
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Beginning should be inclusive, and the ending exclusive.
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get all the results.
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = Time::FromInternalValue(kTime1);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = Time::FromInternalValue(kTime3);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabase::URLSet unique_urls;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->GetTextMatches("COUNTTAG", options, &results,  &unique_urls,
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &first_time_searched);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The first and second should have been returned.
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, results.size());
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL1));
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL2));
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_FALSE(ResultsHaveURL(results, kURL3));
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kTime1, first_time_searched.ToInternalValue());
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ---------------------------------------------------------------------------
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do a query where there isn't a result on the begin boundary, so we can
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // test that the first time searched is set to the minimum time considered
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // instead of the min value.
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = Time::FromInternalValue((kTime2 - kTime1) / 2 + kTime1);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = Time::FromInternalValue(kTime3 + 1);
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results.clear();  // GetTextMatches does *not* clear the results.
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->GetTextMatches("COUNTTAG", options, &results, &unique_urls,
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &first_time_searched);
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(options.begin_time.ToInternalValue(),
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            first_time_searched.ToInternalValue());
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Should have two results, the second and third.
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, results.size());
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_FALSE(ResultsHaveURL(results, kURL1));
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL2));
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL3));
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // No results should also set the first_time_searched.
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = Time::FromInternalValue(kTime3 + 1);
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = Time::FromInternalValue(kTime3 * 100);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results.clear();
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->GetTextMatches("COUNTTAG", options, &results, &unique_urls,
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &first_time_searched);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(options.begin_time.ToInternalValue(),
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            first_time_searched.ToInternalValue());
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Make sure that max_count works.
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(TextDatabaseTest, MaxCount) {
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a database with some pages.
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kIdee1 = 200801;
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TextDatabase> db(CreateDB(kIdee1, true, true));
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_TRUE(!!db.get());
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllTestData(db.get());
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set up the query to return all the results with "Google" (should be 2), but
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // with a maximum of 1.
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryOptions options;
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = Time::FromInternalValue(kTime1);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = Time::FromInternalValue(kTime3 + 1);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.max_count = 1;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<TextDatabase::Match> results;
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Time first_time_searched;
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TextDatabase::URLSet unique_urls;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->GetTextMatches("google", options, &results, &unique_urls,
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     &first_time_searched);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(unique_urls.empty()) << "Didn't ask for unique URLs";
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // There should be one result, the most recent one.
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(1U, results.size());
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(ResultsHaveURL(results, kURL2));
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The max time considered should be the date of the returned item.
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kTime2, first_time_searched.ToInternalValue());
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace history
321