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.
5 #include "chrome/browser/autocomplete/shortcuts_backend.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
12 #include "chrome/browser/history/shortcuts_database.h"
13 #include "chrome/browser/search_engines/template_url_service_factory.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "components/search_engines/template_url_service.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "sql/statement.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 // ShortcutsBackendTest -------------------------------------------------------
25 class ShortcutsBackendTest : public testing::Test,
26 public ShortcutsBackend::ShortcutsBackendObserver {
28 ShortcutsBackendTest();
30 history::ShortcutsDatabase::Shortcut::MatchCore MatchCoreForTesting(
31 const std::string& url,
32 const std::string& contents_class = std::string(),
33 const std::string& description_class = std::string(),
34 AutocompleteMatch::Type type = AutocompleteMatchType::URL_WHAT_YOU_TYPED);
35 void SetSearchProvider();
37 void SetUp() override;
38 void TearDown() override;
40 void OnShortcutsLoaded() override;
41 void OnShortcutsChanged() override;
43 const ShortcutsBackend::ShortcutMap& shortcuts_map() const {
44 return backend_->shortcuts_map();
46 bool changed_notified() const { return changed_notified_; }
47 void set_changed_notified(bool changed_notified) {
48 changed_notified_ = changed_notified;
52 bool AddShortcut(const history::ShortcutsDatabase::Shortcut& shortcut);
53 bool UpdateShortcut(const history::ShortcutsDatabase::Shortcut& shortcut);
54 bool DeleteShortcutsWithURL(const GURL& url);
55 bool DeleteShortcutsWithIDs(
56 const history::ShortcutsDatabase::ShortcutIDs& deleted_ids);
59 TestingProfile profile_;
62 scoped_refptr<ShortcutsBackend> backend_;
63 base::MessageLoopForUI ui_message_loop_;
64 content::TestBrowserThread ui_thread_;
65 content::TestBrowserThread db_thread_;
68 bool changed_notified_;
70 DISALLOW_COPY_AND_ASSIGN(ShortcutsBackendTest);
73 ShortcutsBackendTest::ShortcutsBackendTest()
74 : ui_thread_(content::BrowserThread::UI, &ui_message_loop_),
75 db_thread_(content::BrowserThread::DB),
76 load_notified_(false),
77 changed_notified_(false) {
80 history::ShortcutsDatabase::Shortcut::MatchCore
81 ShortcutsBackendTest::MatchCoreForTesting(
82 const std::string& url,
83 const std::string& contents_class,
84 const std::string& description_class,
85 AutocompleteMatch::Type type) {
86 AutocompleteMatch match(NULL, 0, 0, type);
87 match.destination_url = GURL(url);
88 match.contents = base::ASCIIToUTF16("test");
89 match.contents_class =
90 AutocompleteMatch::ClassificationsFromString(contents_class);
91 match.description_class =
92 AutocompleteMatch::ClassificationsFromString(description_class);
93 match.search_terms_args.reset(
94 new TemplateURLRef::SearchTermsArgs(match.contents));
95 return ShortcutsBackend::MatchToMatchCore(match, &profile_);
98 void ShortcutsBackendTest::SetSearchProvider() {
99 TemplateURLService* template_url_service =
100 TemplateURLServiceFactory::GetForProfile(&profile_);
101 TemplateURLData data;
102 data.SetURL("http://foo.com/search?bar={searchTerms}");
103 data.SetKeyword(base::UTF8ToUTF16("foo"));
105 TemplateURL* template_url = new TemplateURL(data);
106 // Takes ownership of |template_url|.
107 template_url_service->Add(template_url);
108 template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
111 void ShortcutsBackendTest::SetUp() {
113 ShortcutsBackendFactory::GetInstance()->SetTestingFactoryAndUse(
114 &profile_, &ShortcutsBackendFactory::BuildProfileForTesting);
115 backend_ = ShortcutsBackendFactory::GetForProfile(&profile_);
116 ASSERT_TRUE(backend_.get());
117 backend_->AddObserver(this);
119 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
120 &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
121 TemplateURLService* template_url_service =
122 TemplateURLServiceFactory::GetForProfile(&profile_);
123 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
126 void ShortcutsBackendTest::TearDown() {
127 backend_->RemoveObserver(this);
131 void ShortcutsBackendTest::OnShortcutsLoaded() {
132 load_notified_ = true;
133 base::MessageLoop::current()->Quit();
136 void ShortcutsBackendTest::OnShortcutsChanged() {
137 changed_notified_ = true;
140 void ShortcutsBackendTest::InitBackend() {
141 ShortcutsBackend* backend =
142 ShortcutsBackendFactory::GetForProfile(&profile_).get();
143 ASSERT_TRUE(backend);
144 ASSERT_FALSE(load_notified_);
145 ASSERT_FALSE(backend_->initialized());
146 base::MessageLoop::current()->Run();
147 EXPECT_TRUE(load_notified_);
148 EXPECT_TRUE(backend_->initialized());
151 bool ShortcutsBackendTest::AddShortcut(
152 const history::ShortcutsDatabase::Shortcut& shortcut) {
153 return backend_->AddShortcut(shortcut);
156 bool ShortcutsBackendTest::UpdateShortcut(
157 const history::ShortcutsDatabase::Shortcut& shortcut) {
158 return backend_->UpdateShortcut(shortcut);
161 bool ShortcutsBackendTest::DeleteShortcutsWithURL(const GURL& url) {
162 return backend_->DeleteShortcutsWithURL(url);
165 bool ShortcutsBackendTest::DeleteShortcutsWithIDs(
166 const history::ShortcutsDatabase::ShortcutIDs& deleted_ids) {
167 return backend_->DeleteShortcutsWithIDs(deleted_ids);
171 // Actual tests ---------------------------------------------------------------
173 // Verifies that creating MatchCores strips classifications and sanitizes match
175 TEST_F(ShortcutsBackendTest, SanitizeMatchCore) {
177 std::string input_contents_class;
178 std::string input_description_class;
179 AutocompleteMatch::Type input_type;
180 std::string output_contents_class;
181 std::string output_description_class;
182 AutocompleteMatch::Type output_type;
184 { "0,1,4,0", "0,3,4,1", AutocompleteMatchType::URL_WHAT_YOU_TYPED,
185 "0,1,4,0", "0,1", AutocompleteMatchType::HISTORY_URL },
186 { "0,3,5,1", "0,2,5,0", AutocompleteMatchType::NAVSUGGEST,
187 "0,1", "0,0", AutocompleteMatchType::HISTORY_URL },
188 { "0,1", "0,0,11,2,15,0",
189 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
190 "0,1", "0,0", AutocompleteMatchType::SEARCH_HISTORY },
191 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST,
192 "0,1", "0,0", AutocompleteMatchType::SEARCH_HISTORY },
193 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_ENTITY,
194 "", "", AutocompleteMatchType::SEARCH_HISTORY },
195 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_INFINITE,
196 "", "", AutocompleteMatchType::SEARCH_HISTORY },
197 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED,
198 "", "", AutocompleteMatchType::SEARCH_HISTORY },
199 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_PROFILE,
200 "", "", AutocompleteMatchType::SEARCH_HISTORY },
201 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_ANSWER,
202 "", "", AutocompleteMatchType::SEARCH_HISTORY },
205 for (size_t i = 0; i < arraysize(cases); ++i) {
206 history::ShortcutsDatabase::Shortcut::MatchCore match_core(
207 MatchCoreForTesting(std::string(), cases[i].input_contents_class,
208 cases[i].input_description_class,
209 cases[i].input_type));
210 EXPECT_EQ(cases[i].output_contents_class, match_core.contents_class)
211 << ":i:" << i << ":type:" << cases[i].input_type;
212 EXPECT_EQ(cases[i].output_description_class, match_core.description_class)
213 << ":i:" << i << ":type:" << cases[i].input_type;
214 EXPECT_EQ(cases[i].output_type, match_core.type)
215 << ":i:" << i << ":type:" << cases[i].input_type;
219 TEST_F(ShortcutsBackendTest, EntitySuggestionTest) {
221 AutocompleteMatch match;
222 match.fill_into_edit = base::UTF8ToUTF16("franklin d roosevelt");
223 match.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
224 match.contents = base::UTF8ToUTF16("roosevelt");
225 match.contents_class =
226 AutocompleteMatch::ClassificationsFromString("0,0,5,2");
227 match.description = base::UTF8ToUTF16("Franklin D. Roosevelt");
228 match.description_class = AutocompleteMatch::ClassificationsFromString("0,4");
229 match.destination_url = GURL(
230 "http://www.foo.com/search?bar=franklin+d+roosevelt&gs_ssp=1234");
231 match.keyword = base::UTF8ToUTF16("foo");
232 match.search_terms_args.reset(
233 new TemplateURLRef::SearchTermsArgs(match.fill_into_edit));
235 history::ShortcutsDatabase::Shortcut::MatchCore match_core =
236 ShortcutsBackend::MatchToMatchCore(match, &profile_);
238 EXPECT_EQ("http://foo.com/search?bar=franklin+d+roosevelt",
239 match_core.destination_url.spec());
240 EXPECT_EQ(match.fill_into_edit, match_core.contents);
241 EXPECT_EQ("0,0", match_core.contents_class);
242 EXPECT_EQ(base::string16(), match_core.description);
243 EXPECT_TRUE(match_core.description_class.empty());
246 TEST_F(ShortcutsBackendTest, AddAndUpdateShortcut) {
248 EXPECT_FALSE(changed_notified());
250 history::ShortcutsDatabase::Shortcut shortcut(
251 "BD85DBA2-8C29-49F9-84AE-48E1E90880DF", base::ASCIIToUTF16("goog"),
252 MatchCoreForTesting("http://www.google.com"), base::Time::Now(), 100);
253 EXPECT_TRUE(AddShortcut(shortcut));
254 EXPECT_TRUE(changed_notified());
255 ShortcutsBackend::ShortcutMap::const_iterator shortcut_iter(
256 shortcuts_map().find(shortcut.text));
257 ASSERT_TRUE(shortcut_iter != shortcuts_map().end());
258 EXPECT_EQ(shortcut.id, shortcut_iter->second.id);
259 EXPECT_EQ(shortcut.match_core.contents,
260 shortcut_iter->second.match_core.contents);
262 set_changed_notified(false);
263 shortcut.match_core.contents = base::ASCIIToUTF16("Google Web Search");
264 EXPECT_TRUE(UpdateShortcut(shortcut));
265 EXPECT_TRUE(changed_notified());
266 shortcut_iter = shortcuts_map().find(shortcut.text);
267 ASSERT_TRUE(shortcut_iter != shortcuts_map().end());
268 EXPECT_EQ(shortcut.id, shortcut_iter->second.id);
269 EXPECT_EQ(shortcut.match_core.contents,
270 shortcut_iter->second.match_core.contents);
273 TEST_F(ShortcutsBackendTest, DeleteShortcuts) {
275 history::ShortcutsDatabase::Shortcut shortcut1(
276 "BD85DBA2-8C29-49F9-84AE-48E1E90880DF", base::ASCIIToUTF16("goog"),
277 MatchCoreForTesting("http://www.google.com"), base::Time::Now(), 100);
278 EXPECT_TRUE(AddShortcut(shortcut1));
280 history::ShortcutsDatabase::Shortcut shortcut2(
281 "BD85DBA2-8C29-49F9-84AE-48E1E90880E0", base::ASCIIToUTF16("gle"),
282 MatchCoreForTesting("http://www.google.com"), base::Time::Now(), 100);
283 EXPECT_TRUE(AddShortcut(shortcut2));
285 history::ShortcutsDatabase::Shortcut shortcut3(
286 "BD85DBA2-8C29-49F9-84AE-48E1E90880E1", base::ASCIIToUTF16("sp"),
287 MatchCoreForTesting("http://www.sport.com"), base::Time::Now(), 10);
288 EXPECT_TRUE(AddShortcut(shortcut3));
290 history::ShortcutsDatabase::Shortcut shortcut4(
291 "BD85DBA2-8C29-49F9-84AE-48E1E90880E2", base::ASCIIToUTF16("mov"),
292 MatchCoreForTesting("http://www.film.com"), base::Time::Now(), 10);
293 EXPECT_TRUE(AddShortcut(shortcut4));
295 ASSERT_EQ(4U, shortcuts_map().size());
296 EXPECT_EQ(shortcut1.id, shortcuts_map().find(shortcut1.text)->second.id);
297 EXPECT_EQ(shortcut2.id, shortcuts_map().find(shortcut2.text)->second.id);
298 EXPECT_EQ(shortcut3.id, shortcuts_map().find(shortcut3.text)->second.id);
299 EXPECT_EQ(shortcut4.id, shortcuts_map().find(shortcut4.text)->second.id);
301 EXPECT_TRUE(DeleteShortcutsWithURL(shortcut1.match_core.destination_url));
303 ASSERT_EQ(2U, shortcuts_map().size());
304 EXPECT_EQ(0U, shortcuts_map().count(shortcut1.text));
305 EXPECT_EQ(0U, shortcuts_map().count(shortcut2.text));
306 const ShortcutsBackend::ShortcutMap::const_iterator shortcut3_iter(
307 shortcuts_map().find(shortcut3.text));
308 ASSERT_TRUE(shortcut3_iter != shortcuts_map().end());
309 EXPECT_EQ(shortcut3.id, shortcut3_iter->second.id);
310 const ShortcutsBackend::ShortcutMap::const_iterator shortcut4_iter(
311 shortcuts_map().find(shortcut4.text));
312 ASSERT_TRUE(shortcut4_iter != shortcuts_map().end());
313 EXPECT_EQ(shortcut4.id, shortcut4_iter->second.id);
315 history::ShortcutsDatabase::ShortcutIDs deleted_ids;
316 deleted_ids.push_back(shortcut3.id);
317 deleted_ids.push_back(shortcut4.id);
318 EXPECT_TRUE(DeleteShortcutsWithIDs(deleted_ids));
320 ASSERT_EQ(0U, shortcuts_map().size());