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