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.
4
5#include <vector>
6
7#include "base/message_loop/message_loop.h"
8#include "base/strings/utf_string_conversions.h"
9#include "base/time/time.h"
10#include "chrome/browser/predictors/autocomplete_action_predictor_table.h"
11#include "chrome/browser/predictors/predictor_database.h"
12#include "chrome/browser/predictors/predictor_database_factory.h"
13#include "chrome/test/base/testing_profile.h"
14#include "content/public/test/test_browser_thread.h"
15#include "sql/statement.h"
16
17#include "testing/gtest/include/gtest/gtest.h"
18
19using base::Time;
20using base::TimeDelta;
21using content::BrowserThread;
22using predictors::AutocompleteActionPredictorTable;
23
24namespace predictors {
25
26class AutocompleteActionPredictorTableTest : public testing::Test {
27 public:
28  AutocompleteActionPredictorTableTest();
29  virtual ~AutocompleteActionPredictorTableTest();
30
31  virtual void SetUp();
32  virtual void TearDown();
33
34  size_t CountRecords() const;
35
36  void AddAll();
37
38  bool RowsAreEqual(const AutocompleteActionPredictorTable::Row& lhs,
39                    const AutocompleteActionPredictorTable::Row& rhs) const;
40
41  TestingProfile* profile() { return &profile_; }
42
43 protected:
44
45  // Test functions that can be run against this text fixture or
46  // AutocompleteActionPredictorTableReopenTest that inherits from this.
47  void TestGetRow();
48  void TestAddAndUpdateRows();
49  void TestDeleteRows();
50  void TestDeleteAllRows();
51
52  AutocompleteActionPredictorTable::Rows test_db_;
53
54 private:
55  TestingProfile profile_;
56  scoped_ptr<PredictorDatabase> db_;
57  base::MessageLoop loop_;
58  content::TestBrowserThread db_thread_;
59};
60
61class AutocompleteActionPredictorTableReopenTest
62    : public AutocompleteActionPredictorTableTest {
63 public:
64  virtual void SetUp() {
65    // By calling SetUp twice, we make sure that the table already exists for
66    // this fixture.
67    AutocompleteActionPredictorTableTest::SetUp();
68    AutocompleteActionPredictorTableTest::TearDown();
69    AutocompleteActionPredictorTableTest::SetUp();
70  }
71};
72
73AutocompleteActionPredictorTableTest::AutocompleteActionPredictorTableTest()
74    : loop_(base::MessageLoop::TYPE_DEFAULT),
75      db_thread_(BrowserThread::DB, &loop_) {
76}
77
78AutocompleteActionPredictorTableTest::~AutocompleteActionPredictorTableTest() {
79}
80
81void AutocompleteActionPredictorTableTest::SetUp() {
82  db_.reset(new PredictorDatabase(&profile_));
83  loop_.RunUntilIdle();
84
85  test_db_.push_back(AutocompleteActionPredictorTable::Row(
86      "BD85DBA2-8C29-49F9-84AE-48E1E90880DF",
87      ASCIIToUTF16("goog"), GURL("http://www.google.com/"),
88      1, 0));
89  test_db_.push_back(AutocompleteActionPredictorTable::Row(
90      "BD85DBA2-8C29-49F9-84AE-48E1E90880E0",
91      ASCIIToUTF16("slash"), GURL("http://slashdot.org/"),
92      3, 2));
93  test_db_.push_back(AutocompleteActionPredictorTable::Row(
94      "BD85DBA2-8C29-49F9-84AE-48E1E90880E1",
95      ASCIIToUTF16("news"), GURL("http://slashdot.org/"),
96      0, 1));
97}
98
99void AutocompleteActionPredictorTableTest::TearDown() {
100  db_.reset(NULL);
101  loop_.RunUntilIdle();
102  test_db_.clear();
103}
104
105size_t AutocompleteActionPredictorTableTest::CountRecords() const {
106  sql::Statement s(db_->GetDatabase()->GetUniqueStatement(
107      "SELECT count(*) FROM network_action_predictor"));
108  EXPECT_TRUE(s.Step());
109  return static_cast<size_t>(s.ColumnInt(0));
110}
111
112void AutocompleteActionPredictorTableTest::AddAll() {
113  db_->autocomplete_table()->AddAndUpdateRows(
114      test_db_, AutocompleteActionPredictorTable::Rows());
115
116  EXPECT_EQ(test_db_.size(), CountRecords());
117}
118
119bool AutocompleteActionPredictorTableTest::RowsAreEqual(
120    const AutocompleteActionPredictorTable::Row& lhs,
121    const AutocompleteActionPredictorTable::Row& rhs) const {
122  return (lhs.id == rhs.id &&
123          lhs.user_text == rhs.user_text &&
124          lhs.url == rhs.url &&
125          lhs.number_of_hits == rhs.number_of_hits &&
126          lhs.number_of_misses == rhs.number_of_misses);
127}
128
129void AutocompleteActionPredictorTableTest::TestGetRow() {
130  db_->autocomplete_table()->AddAndUpdateRows(
131      AutocompleteActionPredictorTable::Rows(1, test_db_[0]),
132      AutocompleteActionPredictorTable::Rows());
133  AutocompleteActionPredictorTable::Row row;
134  db_->autocomplete_table()->GetRow(test_db_[0].id, &row);
135  EXPECT_TRUE(RowsAreEqual(test_db_[0], row))
136      << "Expected: Row with id " << test_db_[0].id << "\n"
137      << "Got:      Row with id " << row.id;
138}
139
140void AutocompleteActionPredictorTableTest::TestAddAndUpdateRows() {
141  EXPECT_EQ(0U, CountRecords());
142
143  AutocompleteActionPredictorTable::Rows rows_to_add;
144  rows_to_add.push_back(test_db_[0]);
145  rows_to_add.push_back(test_db_[1]);
146  db_->autocomplete_table()->AddAndUpdateRows(
147      rows_to_add,
148      AutocompleteActionPredictorTable::Rows());
149  EXPECT_EQ(2U, CountRecords());
150
151  AutocompleteActionPredictorTable::Row row1 = test_db_[1];
152  row1.number_of_hits = row1.number_of_hits + 1;
153  db_->autocomplete_table()->AddAndUpdateRows(
154      AutocompleteActionPredictorTable::Rows(1, test_db_[2]),
155      AutocompleteActionPredictorTable::Rows(1, row1));
156  EXPECT_EQ(3U, CountRecords());
157
158  AutocompleteActionPredictorTable::Row updated_row1;
159  db_->autocomplete_table()->GetRow(test_db_[1].id, &updated_row1);
160  EXPECT_TRUE(RowsAreEqual(row1, updated_row1))
161      << "Expected: Row with id " << row1.id << "\n"
162      << "Got:      Row with id " << updated_row1.id;
163
164  AutocompleteActionPredictorTable::Row row0 = test_db_[0];
165  row0.number_of_hits = row0.number_of_hits + 2;
166  AutocompleteActionPredictorTable::Row row2 = test_db_[2];
167  row2.number_of_hits = row2.number_of_hits + 2;
168  AutocompleteActionPredictorTable::Rows rows_to_update;
169  rows_to_update.push_back(row0);
170  rows_to_update.push_back(row2);
171  db_->autocomplete_table()->AddAndUpdateRows(
172      AutocompleteActionPredictorTable::Rows(),
173      rows_to_update);
174  EXPECT_EQ(3U, CountRecords());
175
176  AutocompleteActionPredictorTable::Row updated_row0, updated_row2;
177  db_->autocomplete_table()->GetRow(test_db_[0].id, &updated_row0);
178  db_->autocomplete_table()->GetRow(test_db_[2].id, &updated_row2);
179  EXPECT_TRUE(RowsAreEqual(row0, updated_row0))
180      << "Expected: Row with id " << row0.id << "\n"
181      << "Got:      Row with id " << updated_row0.id;
182  EXPECT_TRUE(RowsAreEqual(row2, updated_row2))
183      << "Expected: Row with id " << row2.id << "\n"
184      << "Got:      Row with id " << updated_row2.id;
185}
186
187void AutocompleteActionPredictorTableTest::TestDeleteRows() {
188  AddAll();
189  std::vector<AutocompleteActionPredictorTable::Row::Id> id_list;
190  id_list.push_back(test_db_[0].id);
191  id_list.push_back(test_db_[2].id);
192  db_->autocomplete_table()->DeleteRows(id_list);
193  EXPECT_EQ(test_db_.size() - 2, CountRecords());
194
195  AutocompleteActionPredictorTable::Row row;
196  db_->autocomplete_table()->GetRow(test_db_[1].id, &row);
197  EXPECT_TRUE(RowsAreEqual(test_db_[1], row));
198}
199
200void AutocompleteActionPredictorTableTest::TestDeleteAllRows() {
201  AddAll();
202  db_->autocomplete_table()->DeleteAllRows();
203  EXPECT_EQ(0U, CountRecords());
204}
205
206// AutocompleteActionPredictorTableTest tests
207TEST_F(AutocompleteActionPredictorTableTest, GetRow) {
208  TestGetRow();
209}
210
211TEST_F(AutocompleteActionPredictorTableTest, AddAndUpdateRows) {
212  TestAddAndUpdateRows();
213}
214
215TEST_F(AutocompleteActionPredictorTableTest, DeleteRows) {
216  TestDeleteRows();
217}
218
219TEST_F(AutocompleteActionPredictorTableTest, DeleteAllRows) {
220  TestDeleteAllRows();
221}
222
223// AutocompleteActionPredictorTableReopenTest tests
224TEST_F(AutocompleteActionPredictorTableReopenTest, GetRow) {
225  TestGetRow();
226}
227
228TEST_F(AutocompleteActionPredictorTableReopenTest, AddAndUpdateRows) {
229  TestAddAndUpdateRows();
230}
231
232TEST_F(AutocompleteActionPredictorTableReopenTest, DeleteRows) {
233  TestDeleteRows();
234}
235
236TEST_F(AutocompleteActionPredictorTableReopenTest, DeleteAllRows) {
237  TestDeleteAllRows();
238}
239
240}  // namespace predictors
241