Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / predictors / autocomplete_action_predictor_unittest.cc
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 "chrome/browser/predictors/autocomplete_action_predictor.h"
6
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/guid.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/history/history_service.h"
16 #include "chrome/browser/history/history_service_factory.h"
17 #include "chrome/browser/prerender/prerender_field_trial.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "components/history/core/browser/in_memory_database.h"
21 #include "components/history/core/browser/url_database.h"
22 #include "components/omnibox/autocomplete_match.h"
23 #include "content/public/test/test_browser_thread.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using base::ASCIIToUTF16;
27 using content::BrowserThread;
28 using predictors::AutocompleteActionPredictor;
29
30 namespace {
31
32 struct TestUrlInfo {
33   GURL url;
34   base::string16 title;
35   int days_from_now;
36   base::string16 user_text;
37   int number_of_hits;
38   int number_of_misses;
39   AutocompleteActionPredictor::Action expected_action;
40 } test_url_db[] = {
41   { GURL("http://www.testsite.com/a.html"),
42     ASCIIToUTF16("Test - site - just a test"), 1,
43     ASCIIToUTF16("j"), 5, 0,
44     AutocompleteActionPredictor::ACTION_PRERENDER },
45   { GURL("http://www.testsite.com/b.html"),
46     ASCIIToUTF16("Test - site - just a test"), 1,
47     ASCIIToUTF16("ju"), 3, 0,
48     AutocompleteActionPredictor::ACTION_PRERENDER },
49   { GURL("http://www.testsite.com/c.html"),
50     ASCIIToUTF16("Test - site - just a test"), 5,
51     ASCIIToUTF16("just"), 3, 1,
52     AutocompleteActionPredictor::ACTION_PRECONNECT },
53   { GURL("http://www.testsite.com/d.html"),
54     ASCIIToUTF16("Test - site - just a test"), 5,
55     ASCIIToUTF16("just"), 3, 0,
56     AutocompleteActionPredictor::ACTION_PRERENDER },
57   { GURL("http://www.testsite.com/e.html"),
58     ASCIIToUTF16("Test - site - just a test"), 8,
59     ASCIIToUTF16("just"), 3, 1,
60     AutocompleteActionPredictor::ACTION_PRECONNECT },
61   { GURL("http://www.testsite.com/f.html"),
62     ASCIIToUTF16("Test - site - just a test"), 8,
63     ASCIIToUTF16("just"), 3, 0,
64     AutocompleteActionPredictor::ACTION_PRERENDER },
65   { GURL("http://www.testsite.com/g.html"),
66     ASCIIToUTF16("Test - site - just a test"), 12,
67     base::string16(), 5, 0,
68     AutocompleteActionPredictor::ACTION_NONE },
69   { GURL("http://www.testsite.com/h.html"),
70     ASCIIToUTF16("Test - site - just a test"), 21,
71     ASCIIToUTF16("just a test"), 2, 0,
72     AutocompleteActionPredictor::ACTION_NONE },
73   { GURL("http://www.testsite.com/i.html"),
74     ASCIIToUTF16("Test - site - just a test"), 28,
75     ASCIIToUTF16("just a test"), 2, 0,
76     AutocompleteActionPredictor::ACTION_NONE }
77 };
78
79 }  // end namespace
80
81 namespace predictors {
82
83 class AutocompleteActionPredictorTest : public testing::Test {
84  public:
85   AutocompleteActionPredictorTest()
86       : ui_thread_(BrowserThread::UI, &loop_),
87         db_thread_(BrowserThread::DB, &loop_),
88         file_thread_(BrowserThread::FILE, &loop_),
89         profile_(new TestingProfile()),
90         predictor_(new AutocompleteActionPredictor(profile_.get())) {
91   }
92
93   ~AutocompleteActionPredictorTest() override {
94     predictor_.reset(NULL);
95     profile_.reset(NULL);
96     loop_.RunUntilIdle();
97   }
98
99   void SetUp() override {
100     CommandLine::ForCurrentProcess()->AppendSwitchASCII(
101         switches::kPrerenderFromOmnibox,
102         switches::kPrerenderFromOmniboxSwitchValueEnabled);
103
104     predictor_->CreateLocalCachesFromDatabase();
105     ASSERT_TRUE(profile_->CreateHistoryService(true, false));
106     profile_->BlockUntilHistoryProcessesPendingRequests();
107
108     ASSERT_TRUE(predictor_->initialized_);
109     ASSERT_TRUE(db_cache()->empty());
110     ASSERT_TRUE(db_id_cache()->empty());
111   }
112
113   void TearDown() override {
114     profile_->DestroyHistoryService();
115     predictor_->Shutdown();
116   }
117
118  protected:
119   typedef AutocompleteActionPredictor::DBCacheKey DBCacheKey;
120   typedef AutocompleteActionPredictor::DBCacheValue DBCacheValue;
121   typedef AutocompleteActionPredictor::DBCacheMap DBCacheMap;
122   typedef AutocompleteActionPredictor::DBIdCacheMap DBIdCacheMap;
123
124   void AddAllRowsToHistory() {
125     for (size_t i = 0; i < arraysize(test_url_db); ++i)
126       ASSERT_TRUE(AddRowToHistory(test_url_db[i]));
127   }
128
129   history::URLID AddRowToHistory(const TestUrlInfo& test_row) {
130     HistoryService* history =
131         HistoryServiceFactory::GetForProfile(profile_.get(),
132                                              Profile::EXPLICIT_ACCESS);
133     CHECK(history);
134     history::URLDatabase* url_db = history->InMemoryDatabase();
135     CHECK(url_db);
136
137     const base::Time visit_time =
138         base::Time::Now() - base::TimeDelta::FromDays(
139             test_row.days_from_now);
140
141     history::URLRow row(test_row.url);
142     row.set_title(test_row.title);
143     row.set_last_visit(visit_time);
144
145     return url_db->AddURL(row);
146   }
147
148   AutocompleteActionPredictorTable::Row CreateRowFromTestUrlInfo(
149       const TestUrlInfo& test_row) const {
150     AutocompleteActionPredictorTable::Row row;
151     row.id = base::GenerateGUID();
152     row.user_text = test_row.user_text;
153     row.url = test_row.url;
154     row.number_of_hits = test_row.number_of_hits;
155     row.number_of_misses = test_row.number_of_misses;
156     return row;
157   }
158
159   void AddAllRows() {
160     for (size_t i = 0; i < arraysize(test_url_db); ++i)
161       AddRow(test_url_db[i]);
162   }
163
164   std::string AddRow(const TestUrlInfo& test_row) {
165     AutocompleteActionPredictorTable::Row row =
166         CreateRowFromTestUrlInfo(test_row);
167     predictor_->AddAndUpdateRows(
168         AutocompleteActionPredictorTable::Rows(1, row),
169         AutocompleteActionPredictorTable::Rows());
170
171     return row.id;
172   }
173
174   void UpdateRow(const AutocompleteActionPredictorTable::Row& row) {
175     AutocompleteActionPredictor::DBCacheKey key = { row.user_text, row.url };
176     ASSERT_TRUE(db_cache()->find(key) != db_cache()->end());
177     predictor_->AddAndUpdateRows(
178         AutocompleteActionPredictorTable::Rows(),
179         AutocompleteActionPredictorTable::Rows(1, row));
180   }
181
182   void DeleteAllRows() {
183     predictor_->DeleteAllRows();
184   }
185
186   void DeleteRowsWithURLs(const history::URLRows& rows) {
187     predictor_->DeleteRowsWithURLs(rows);
188   }
189
190   void DeleteOldIdsFromCaches(
191       std::vector<AutocompleteActionPredictorTable::Row::Id>* id_list) {
192     HistoryService* history_service =
193         HistoryServiceFactory::GetForProfile(profile_.get(),
194                                              Profile::EXPLICIT_ACCESS);
195     ASSERT_TRUE(history_service);
196
197     history::URLDatabase* url_db = history_service->InMemoryDatabase();
198     ASSERT_TRUE(url_db);
199
200     // Reset the predictor's |initialized_| flag for the life of this call,
201     // since outside of testing this function is only supposed to be reached
202     // before initialization is completed.
203     base::AutoReset<bool> initialized_reset(&predictor_->initialized_, false);
204     predictor_->DeleteOldIdsFromCaches(url_db, id_list);
205   }
206
207   AutocompleteActionPredictor* predictor() { return predictor_.get(); }
208
209   DBCacheMap* db_cache() { return &predictor_->db_cache_; }
210   DBIdCacheMap* db_id_cache() { return &predictor_->db_id_cache_; }
211
212   static int maximum_days_to_keep_entry() {
213     return AutocompleteActionPredictor::kMaximumDaysToKeepEntry;
214   }
215
216  private:
217   base::MessageLoop loop_;
218   content::TestBrowserThread ui_thread_;
219   content::TestBrowserThread db_thread_;
220   content::TestBrowserThread file_thread_;
221   scoped_ptr<TestingProfile> profile_;
222   scoped_ptr<AutocompleteActionPredictor> predictor_;
223 };
224
225
226 TEST_F(AutocompleteActionPredictorTest, AddRow) {
227   // Add a test entry to the predictor.
228   std::string guid = AddRow(test_url_db[0]);
229
230   // Get the data back out of the cache.
231   const DBCacheKey key = { test_url_db[0].user_text, test_url_db[0].url };
232   DBCacheMap::const_iterator it = db_cache()->find(key);
233   EXPECT_TRUE(it != db_cache()->end());
234
235   const DBCacheValue value = { test_url_db[0].number_of_hits,
236                                test_url_db[0].number_of_misses };
237   EXPECT_EQ(value.number_of_hits, it->second.number_of_hits);
238   EXPECT_EQ(value.number_of_misses, it->second.number_of_misses);
239
240   DBIdCacheMap::const_iterator id_it = db_id_cache()->find(key);
241   EXPECT_TRUE(id_it != db_id_cache()->end());
242   EXPECT_EQ(guid, id_it->second);
243 }
244
245 TEST_F(AutocompleteActionPredictorTest, UpdateRow) {
246   ASSERT_NO_FATAL_FAILURE(AddAllRows());
247
248   EXPECT_EQ(arraysize(test_url_db), db_cache()->size());
249   EXPECT_EQ(arraysize(test_url_db), db_id_cache()->size());
250
251   // Get the data back out of the cache.
252   const DBCacheKey key = { test_url_db[0].user_text, test_url_db[0].url };
253   DBCacheMap::const_iterator it = db_cache()->find(key);
254   EXPECT_TRUE(it != db_cache()->end());
255
256   DBIdCacheMap::const_iterator id_it = db_id_cache()->find(key);
257   EXPECT_TRUE(id_it != db_id_cache()->end());
258
259   AutocompleteActionPredictorTable::Row update_row;
260   update_row.id = id_it->second;
261   update_row.user_text = key.user_text;
262   update_row.url = key.url;
263   update_row.number_of_hits = it->second.number_of_hits + 1;
264   update_row.number_of_misses = it->second.number_of_misses + 2;
265
266   UpdateRow(update_row);
267
268   // Get the updated version.
269   DBCacheMap::const_iterator update_it = db_cache()->find(key);
270   EXPECT_TRUE(update_it != db_cache()->end());
271
272   EXPECT_EQ(update_row.number_of_hits, update_it->second.number_of_hits);
273   EXPECT_EQ(update_row.number_of_misses, update_it->second.number_of_misses);
274
275   DBIdCacheMap::const_iterator update_id_it = db_id_cache()->find(key);
276   EXPECT_TRUE(update_id_it != db_id_cache()->end());
277
278   EXPECT_EQ(id_it->second, update_id_it->second);
279 }
280
281 TEST_F(AutocompleteActionPredictorTest, DeleteAllRows) {
282   ASSERT_NO_FATAL_FAILURE(AddAllRows());
283
284   EXPECT_EQ(arraysize(test_url_db), db_cache()->size());
285   EXPECT_EQ(arraysize(test_url_db), db_id_cache()->size());
286
287   DeleteAllRows();
288
289   EXPECT_TRUE(db_cache()->empty());
290   EXPECT_TRUE(db_id_cache()->empty());
291 }
292
293 TEST_F(AutocompleteActionPredictorTest, DeleteRowsWithURLs) {
294   ASSERT_NO_FATAL_FAILURE(AddAllRows());
295
296   EXPECT_EQ(arraysize(test_url_db), db_cache()->size());
297   EXPECT_EQ(arraysize(test_url_db), db_id_cache()->size());
298
299   history::URLRows rows;
300   for (size_t i = 0; i < 2; ++i)
301     rows.push_back(history::URLRow(test_url_db[i].url));
302
303   DeleteRowsWithURLs(rows);
304
305   EXPECT_EQ(arraysize(test_url_db) - 2, db_cache()->size());
306   EXPECT_EQ(arraysize(test_url_db) - 2, db_id_cache()->size());
307
308   for (size_t i = 0; i < arraysize(test_url_db); ++i) {
309     DBCacheKey key = { test_url_db[i].user_text, test_url_db[i].url };
310
311     bool deleted = (i < 2);
312     EXPECT_EQ(deleted, db_cache()->find(key) == db_cache()->end());
313     EXPECT_EQ(deleted, db_id_cache()->find(key) == db_id_cache()->end());
314   }
315 }
316
317 TEST_F(AutocompleteActionPredictorTest, DeleteOldIdsFromCaches) {
318   std::vector<AutocompleteActionPredictorTable::Row::Id> expected;
319   std::vector<AutocompleteActionPredictorTable::Row::Id> all_ids;
320
321   for (size_t i = 0; i < arraysize(test_url_db); ++i) {
322     std::string row_id = AddRow(test_url_db[i]);
323     all_ids.push_back(row_id);
324
325     bool exclude_url = StartsWithASCII(test_url_db[i].url.path(), "/d", true) ||
326         (test_url_db[i].days_from_now > maximum_days_to_keep_entry());
327
328     if (exclude_url)
329       expected.push_back(row_id);
330     else
331       ASSERT_TRUE(AddRowToHistory(test_url_db[i]));
332   }
333
334   std::vector<AutocompleteActionPredictorTable::Row::Id> id_list;
335   DeleteOldIdsFromCaches(&id_list);
336   EXPECT_EQ(expected.size(), id_list.size());
337   EXPECT_EQ(all_ids.size() - expected.size(), db_cache()->size());
338   EXPECT_EQ(all_ids.size() - expected.size(), db_id_cache()->size());
339
340   for (std::vector<AutocompleteActionPredictorTable::Row::Id>::iterator it =
341        all_ids.begin();
342        it != all_ids.end(); ++it) {
343     bool in_expected =
344         (std::find(expected.begin(), expected.end(), *it) != expected.end());
345     bool in_list =
346         (std::find(id_list.begin(), id_list.end(), *it) != id_list.end());
347     EXPECT_EQ(in_expected, in_list);
348   }
349 }
350
351 TEST_F(AutocompleteActionPredictorTest, RecommendActionURL) {
352   ASSERT_NO_FATAL_FAILURE(AddAllRows());
353
354   AutocompleteMatch match;
355   match.type = AutocompleteMatchType::HISTORY_URL;
356
357   for (size_t i = 0; i < arraysize(test_url_db); ++i) {
358     match.destination_url = GURL(test_url_db[i].url);
359     EXPECT_EQ(test_url_db[i].expected_action,
360               predictor()->RecommendAction(test_url_db[i].user_text, match))
361         << "Unexpected action for " << match.destination_url;
362   }
363 }
364
365 TEST_F(AutocompleteActionPredictorTest, RecommendActionSearch) {
366   ASSERT_NO_FATAL_FAILURE(AddAllRows());
367
368   AutocompleteMatch match;
369   match.type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED;
370
371   for (size_t i = 0; i < arraysize(test_url_db); ++i) {
372     match.destination_url = GURL(test_url_db[i].url);
373     AutocompleteActionPredictor::Action expected_action =
374         (test_url_db[i].expected_action ==
375          AutocompleteActionPredictor::ACTION_PRERENDER) ?
376         AutocompleteActionPredictor::ACTION_PRECONNECT :
377         test_url_db[i].expected_action;
378     EXPECT_EQ(expected_action,
379               predictor()->RecommendAction(test_url_db[i].user_text, match))
380         << "Unexpected action for " << match.destination_url;
381   }
382 }
383
384 }  // namespace predictors