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    : db_thread_(BrowserThread::DB, &loop_) {
75}
76
77AutocompleteActionPredictorTableTest::~AutocompleteActionPredictorTableTest() {
78}
79
80void AutocompleteActionPredictorTableTest::SetUp() {
81  db_.reset(new PredictorDatabase(&profile_));
82  loop_.RunUntilIdle();
83
84  test_db_.push_back(AutocompleteActionPredictorTable::Row(
85      "BD85DBA2-8C29-49F9-84AE-48E1E90880DF",
86      base::ASCIIToUTF16("goog"), GURL("http://www.google.com/"),
87      1, 0));
88  test_db_.push_back(AutocompleteActionPredictorTable::Row(
89      "BD85DBA2-8C29-49F9-84AE-48E1E90880E0",
90      base::ASCIIToUTF16("slash"), GURL("http://slashdot.org/"),
91      3, 2));
92  test_db_.push_back(AutocompleteActionPredictorTable::Row(
93      "BD85DBA2-8C29-49F9-84AE-48E1E90880E1",
94      base::ASCIIToUTF16("news"), GURL("http://slashdot.org/"),
95      0, 1));
96}
97
98void AutocompleteActionPredictorTableTest::TearDown() {
99  db_.reset(NULL);
100  loop_.RunUntilIdle();
101  test_db_.clear();
102}
103
104size_t AutocompleteActionPredictorTableTest::CountRecords() const {
105  sql::Statement s(db_->GetDatabase()->GetUniqueStatement(
106      "SELECT count(*) FROM network_action_predictor"));
107  EXPECT_TRUE(s.Step());
108  return static_cast<size_t>(s.ColumnInt(0));
109}
110
111void AutocompleteActionPredictorTableTest::AddAll() {
112  db_->autocomplete_table()->AddAndUpdateRows(
113      test_db_, AutocompleteActionPredictorTable::Rows());
114
115  EXPECT_EQ(test_db_.size(), CountRecords());
116}
117
118bool AutocompleteActionPredictorTableTest::RowsAreEqual(
119    const AutocompleteActionPredictorTable::Row& lhs,
120    const AutocompleteActionPredictorTable::Row& rhs) const {
121  return (lhs.id == rhs.id &&
122          lhs.user_text == rhs.user_text &&
123          lhs.url == rhs.url &&
124          lhs.number_of_hits == rhs.number_of_hits &&
125          lhs.number_of_misses == rhs.number_of_misses);
126}
127
128void AutocompleteActionPredictorTableTest::TestGetRow() {
129  db_->autocomplete_table()->AddAndUpdateRows(
130      AutocompleteActionPredictorTable::Rows(1, test_db_[0]),
131      AutocompleteActionPredictorTable::Rows());
132  AutocompleteActionPredictorTable::Row row;
133  db_->autocomplete_table()->GetRow(test_db_[0].id, &row);
134  EXPECT_TRUE(RowsAreEqual(test_db_[0], row))
135      << "Expected: Row with id " << test_db_[0].id << "\n"
136      << "Got:      Row with id " << row.id;
137}
138
139void AutocompleteActionPredictorTableTest::TestAddAndUpdateRows() {
140  EXPECT_EQ(0U, CountRecords());
141
142  AutocompleteActionPredictorTable::Rows rows_to_add;
143  rows_to_add.push_back(test_db_[0]);
144  rows_to_add.push_back(test_db_[1]);
145  db_->autocomplete_table()->AddAndUpdateRows(
146      rows_to_add,
147      AutocompleteActionPredictorTable::Rows());
148  EXPECT_EQ(2U, CountRecords());
149
150  AutocompleteActionPredictorTable::Row row1 = test_db_[1];
151  row1.number_of_hits = row1.number_of_hits + 1;
152  db_->autocomplete_table()->AddAndUpdateRows(
153      AutocompleteActionPredictorTable::Rows(1, test_db_[2]),
154      AutocompleteActionPredictorTable::Rows(1, row1));
155  EXPECT_EQ(3U, CountRecords());
156
157  AutocompleteActionPredictorTable::Row updated_row1;
158  db_->autocomplete_table()->GetRow(test_db_[1].id, &updated_row1);
159  EXPECT_TRUE(RowsAreEqual(row1, updated_row1))
160      << "Expected: Row with id " << row1.id << "\n"
161      << "Got:      Row with id " << updated_row1.id;
162
163  AutocompleteActionPredictorTable::Row row0 = test_db_[0];
164  row0.number_of_hits = row0.number_of_hits + 2;
165  AutocompleteActionPredictorTable::Row row2 = test_db_[2];
166  row2.number_of_hits = row2.number_of_hits + 2;
167  AutocompleteActionPredictorTable::Rows rows_to_update;
168  rows_to_update.push_back(row0);
169  rows_to_update.push_back(row2);
170  db_->autocomplete_table()->AddAndUpdateRows(
171      AutocompleteActionPredictorTable::Rows(),
172      rows_to_update);
173  EXPECT_EQ(3U, CountRecords());
174
175  AutocompleteActionPredictorTable::Row updated_row0, updated_row2;
176  db_->autocomplete_table()->GetRow(test_db_[0].id, &updated_row0);
177  db_->autocomplete_table()->GetRow(test_db_[2].id, &updated_row2);
178  EXPECT_TRUE(RowsAreEqual(row0, updated_row0))
179      << "Expected: Row with id " << row0.id << "\n"
180      << "Got:      Row with id " << updated_row0.id;
181  EXPECT_TRUE(RowsAreEqual(row2, updated_row2))
182      << "Expected: Row with id " << row2.id << "\n"
183      << "Got:      Row with id " << updated_row2.id;
184}
185
186void AutocompleteActionPredictorTableTest::TestDeleteRows() {
187  AddAll();
188  std::vector<AutocompleteActionPredictorTable::Row::Id> id_list;
189  id_list.push_back(test_db_[0].id);
190  id_list.push_back(test_db_[2].id);
191  db_->autocomplete_table()->DeleteRows(id_list);
192  EXPECT_EQ(test_db_.size() - 2, CountRecords());
193
194  AutocompleteActionPredictorTable::Row row;
195  db_->autocomplete_table()->GetRow(test_db_[1].id, &row);
196  EXPECT_TRUE(RowsAreEqual(test_db_[1], row));
197}
198
199void AutocompleteActionPredictorTableTest::TestDeleteAllRows() {
200  AddAll();
201  db_->autocomplete_table()->DeleteAllRows();
202  EXPECT_EQ(0U, CountRecords());
203}
204
205// AutocompleteActionPredictorTableTest tests
206TEST_F(AutocompleteActionPredictorTableTest, GetRow) {
207  TestGetRow();
208}
209
210TEST_F(AutocompleteActionPredictorTableTest, AddAndUpdateRows) {
211  TestAddAndUpdateRows();
212}
213
214TEST_F(AutocompleteActionPredictorTableTest, DeleteRows) {
215  TestDeleteRows();
216}
217
218TEST_F(AutocompleteActionPredictorTableTest, DeleteAllRows) {
219  TestDeleteAllRows();
220}
221
222// AutocompleteActionPredictorTableReopenTest tests
223TEST_F(AutocompleteActionPredictorTableReopenTest, GetRow) {
224  TestGetRow();
225}
226
227TEST_F(AutocompleteActionPredictorTableReopenTest, AddAndUpdateRows) {
228  TestAddAndUpdateRows();
229}
230
231TEST_F(AutocompleteActionPredictorTableReopenTest, DeleteRows) {
232  TestDeleteRows();
233}
234
235TEST_F(AutocompleteActionPredictorTableReopenTest, DeleteAllRows) {
236  TestDeleteAllRows();
237}
238
239}  // namespace predictors
240