| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/string16.h" | 8 #include "base/string16.h" |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 23 #include "content/public/browser/notification_registrar.h" | 23 #include "content/public/browser/notification_registrar.h" |
| 24 #include "content/public/browser/notification_source.h" | 24 #include "content/public/browser/notification_source.h" |
| 25 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
| 26 | 26 |
| 27 static std::ostream& operator<<(std::ostream& os, | 27 static std::ostream& operator<<(std::ostream& os, |
| 28 const AutocompleteResult::const_iterator& it) { | 28 const AutocompleteResult::const_iterator& it) { |
| 29 return os << static_cast<const AutocompleteMatch*>(&(*it)); | 29 return os << static_cast<const AutocompleteMatch*>(&(*it)); |
| 30 } | 30 } |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 const size_t kResultsPerProvider = 3; |
| 34 const size_t num_results_per_provider = 3; | 34 } |
| 35 | 35 |
| 36 // Autocomplete provider that provides known results. Note that this is | 36 // Autocomplete provider that provides known results. Note that this is |
| 37 // refcounted so that it can also be a task on the message loop. | 37 // refcounted so that it can also be a task on the message loop. |
| 38 class TestProvider : public AutocompleteProvider { | 38 class TestProvider : public AutocompleteProvider { |
| 39 public: | 39 public: |
| 40 TestProvider(int relevance, const string16& prefix) | 40 TestProvider(int relevance, const string16& prefix) |
| 41 : AutocompleteProvider(NULL, NULL, ""), | 41 : AutocompleteProvider(NULL, NULL, ""), |
| 42 relevance_(relevance), | 42 relevance_(relevance), |
| 43 prefix_(prefix) { | 43 prefix_(prefix) { |
| 44 } | 44 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 72 AddResults(0, 1); | 72 AddResults(0, 1); |
| 73 | 73 |
| 74 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { | 74 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { |
| 75 done_ = false; | 75 done_ = false; |
| 76 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&TestProvider::Run, | 76 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&TestProvider::Run, |
| 77 this)); | 77 this)); |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 | 80 |
| 81 void TestProvider::Run() { | 81 void TestProvider::Run() { |
| 82 DCHECK_GT(num_results_per_provider, 0U); | 82 DCHECK_GT(kResultsPerProvider, 0U); |
| 83 AddResults(1, num_results_per_provider); | 83 AddResults(1, kResultsPerProvider); |
| 84 done_ = true; | 84 done_ = true; |
| 85 DCHECK(listener_); | 85 DCHECK(listener_); |
| 86 listener_->OnProviderUpdate(true); | 86 listener_->OnProviderUpdate(true); |
| 87 } | 87 } |
| 88 | 88 |
| 89 void TestProvider::AddResults(int start_at, int num) { | 89 void TestProvider::AddResults(int start_at, int num) { |
| 90 for (int i = start_at; i < num; i++) { | 90 for (int i = start_at; i < num; i++) { |
| 91 AutocompleteMatch match(this, relevance_ - i, false, | 91 AutocompleteMatch match(this, relevance_ - i, false, |
| 92 AutocompleteMatch::URL_WHAT_YOU_TYPED); | 92 AutocompleteMatch::URL_WHAT_YOU_TYPED); |
| 93 | 93 |
| 94 match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); | 94 match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); |
| 95 match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit)); | 95 match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit)); |
| 96 | 96 |
| 97 match.contents = match.fill_into_edit; | 97 match.contents = match.fill_into_edit; |
| 98 match.contents_class.push_back( | 98 match.contents_class.push_back( |
| 99 ACMatchClassification(0, ACMatchClassification::NONE)); | 99 ACMatchClassification(0, ACMatchClassification::NONE)); |
| 100 match.description = match.fill_into_edit; | 100 match.description = match.fill_into_edit; |
| 101 match.description_class.push_back( | 101 match.description_class.push_back( |
| 102 ACMatchClassification(0, ACMatchClassification::NONE)); | 102 ACMatchClassification(0, ACMatchClassification::NONE)); |
| 103 | 103 |
| 104 matches_.push_back(match); | 104 matches_.push_back(match); |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 | 107 |
| 108 class AutocompleteProviderTest : public testing::Test, | 108 class AutocompleteProviderTest : public testing::Test, |
| 109 public content::NotificationObserver { | 109 public content::NotificationObserver { |
| 110 protected: | 110 protected: |
| 111 struct KeywordTestData { |
| 112 const string16 fill_into_edit; |
| 113 const string16 keyword; |
| 114 const bool expected_keyword_result; |
| 115 }; |
| 116 |
| 117 protected: |
| 111 void ResetControllerWithTestProviders(bool same_destinations); | 118 void ResetControllerWithTestProviders(bool same_destinations); |
| 112 | 119 |
| 113 // Runs a query on the input "a", and makes sure both providers' input is | 120 // Runs a query on the input "a", and makes sure both providers' input is |
| 114 // properly collected. | 121 // properly collected. |
| 115 void RunTest(); | 122 void RunTest(); |
| 116 | 123 |
| 124 void RunRedundantKeywordTest(const KeywordTestData* match_data, size_t size); |
| 125 |
| 126 void RunQuery(const string16 query); |
| 127 |
| 117 void ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); | 128 void ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); |
| 129 void ResetControllerWithKeywordProvider(); |
| 118 void RunExactKeymatchTest(bool allow_exact_keyword_match); | 130 void RunExactKeymatchTest(bool allow_exact_keyword_match); |
| 119 | 131 |
| 120 // These providers are owned by the controller once it's created. | 132 // These providers are owned by the controller once it's created. |
| 121 ACProviders providers_; | 133 ACProviders providers_; |
| 122 | 134 |
| 123 AutocompleteResult result_; | 135 AutocompleteResult result_; |
| 136 scoped_ptr<AutocompleteController> controller_; |
| 124 | 137 |
| 125 private: | 138 private: |
| 126 // content::NotificationObserver | 139 // content::NotificationObserver |
| 127 virtual void Observe(int type, | 140 virtual void Observe(int type, |
| 128 const content::NotificationSource& source, | 141 const content::NotificationSource& source, |
| 129 const content::NotificationDetails& details); | 142 const content::NotificationDetails& details); |
| 130 | 143 |
| 131 MessageLoopForUI message_loop_; | 144 MessageLoopForUI message_loop_; |
| 132 scoped_ptr<AutocompleteController> controller_; | |
| 133 content::NotificationRegistrar registrar_; | 145 content::NotificationRegistrar registrar_; |
| 134 TestingProfile profile_; | 146 TestingProfile profile_; |
| 135 }; | 147 }; |
| 136 | 148 |
| 137 void AutocompleteProviderTest::ResetControllerWithTestProviders( | 149 void AutocompleteProviderTest::ResetControllerWithTestProviders( |
| 138 bool same_destinations) { | 150 bool same_destinations) { |
| 139 // Forget about any existing providers. The controller owns them and will | 151 // Forget about any existing providers. The controller owns them and will |
| 140 // Release() them below, when we delete it during the call to reset(). | 152 // Release() them below, when we delete it during the call to reset(). |
| 141 providers_.clear(); | 153 providers_.clear(); |
| 142 | 154 |
| 143 // Construct two new providers, with either the same or different prefixes. | 155 // Construct two new providers, with either the same or different prefixes. |
| 144 TestProvider* providerA = new TestProvider(num_results_per_provider, | 156 TestProvider* providerA = new TestProvider(kResultsPerProvider, |
| 145 ASCIIToUTF16("http://a")); | 157 ASCIIToUTF16("http://a")); |
| 146 providerA->AddRef(); | 158 providerA->AddRef(); |
| 147 providers_.push_back(providerA); | 159 providers_.push_back(providerA); |
| 148 | 160 |
| 149 TestProvider* providerB = new TestProvider(num_results_per_provider * 2, | 161 TestProvider* providerB = new TestProvider(kResultsPerProvider * 2, |
| 150 same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b")); | 162 same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b")); |
| 151 providerB->AddRef(); | 163 providerB->AddRef(); |
| 152 providers_.push_back(providerB); | 164 providers_.push_back(providerB); |
| 153 | 165 |
| 154 // Reset the controller to contain our new providers. | 166 // Reset the controller to contain our new providers. |
| 155 AutocompleteController* controller = | 167 AutocompleteController* controller = |
| 156 new AutocompleteController(providers_, &profile_); | 168 new AutocompleteController(providers_, &profile_); |
| 157 controller_.reset(controller); | 169 controller_.reset(controller); |
| 158 providerA->set_listener(controller); | 170 providerA->set_listener(controller); |
| 159 providerB->set_listener(controller); | 171 providerB->set_listener(controller); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 // Create both a keyword and search provider, and add them in that order. | 206 // Create both a keyword and search provider, and add them in that order. |
| 195 // (Order is important; see comments in RunExactKeymatchTest().) | 207 // (Order is important; see comments in RunExactKeymatchTest().) |
| 196 AutocompleteProvider* keyword_provider = new KeywordProvider(NULL, | 208 AutocompleteProvider* keyword_provider = new KeywordProvider(NULL, |
| 197 &profile_); | 209 &profile_); |
| 198 keyword_provider->AddRef(); | 210 keyword_provider->AddRef(); |
| 199 providers_.push_back(keyword_provider); | 211 providers_.push_back(keyword_provider); |
| 200 AutocompleteProvider* search_provider = new SearchProvider(NULL, &profile_); | 212 AutocompleteProvider* search_provider = new SearchProvider(NULL, &profile_); |
| 201 search_provider->AddRef(); | 213 search_provider->AddRef(); |
| 202 providers_.push_back(search_provider); | 214 providers_.push_back(search_provider); |
| 203 | 215 |
| 216 controller_.reset(new AutocompleteController(providers_, &profile_)); |
| 217 } |
| 218 |
| 219 void AutocompleteProviderTest:: |
| 220 ResetControllerWithKeywordProvider() { |
| 221 profile_.CreateTemplateURLService(); |
| 222 |
| 223 TemplateURLService* turl_model = |
| 224 TemplateURLServiceFactory::GetForProfile(&profile_); |
| 225 |
| 226 // Create a TemplateURL for KeywordProvider. |
| 227 TemplateURL* keyword_t_url = new TemplateURL(); |
| 228 keyword_t_url->set_short_name(ASCIIToUTF16("foo.com")); |
| 229 keyword_t_url->set_keyword(ASCIIToUTF16("foo.com")); |
| 230 keyword_t_url->SetURL("http://foo.com/{searchTerms}", 0, 0); |
| 231 turl_model->Add(keyword_t_url); |
| 232 ASSERT_NE(0, keyword_t_url->id()); |
| 233 |
| 234 // Create another TemplateURL for KeywordProvider. |
| 235 keyword_t_url = new TemplateURL(); |
| 236 keyword_t_url->set_short_name(ASCIIToUTF16("bar.com")); |
| 237 keyword_t_url->set_keyword(ASCIIToUTF16("bar.com")); |
| 238 keyword_t_url->SetURL("http://bar.com/{searchTerms}", 0, 0); |
| 239 turl_model->Add(keyword_t_url); |
| 240 ASSERT_NE(0, keyword_t_url->id()); |
| 241 |
| 242 // Forget about any existing providers. The controller owns them and will |
| 243 // Release() them below, when we delete it during the call to reset(). |
| 244 providers_.clear(); |
| 245 |
| 246 // Create both a keyword and search provider, and add them in that order. |
| 247 // (Order is important; see comments in RunExactKeymatchTest().) |
| 248 KeywordProvider* keyword_provider = new KeywordProvider(NULL, |
| 249 &profile_); |
| 250 keyword_provider->AddRef(); |
| 251 providers_.push_back(keyword_provider); |
| 252 |
| 204 AutocompleteController* controller = | 253 AutocompleteController* controller = |
| 205 new AutocompleteController(providers_, &profile_); | 254 new AutocompleteController(providers_, &profile_); |
| 255 controller->set_keyword_provider(keyword_provider); |
| 206 controller_.reset(controller); | 256 controller_.reset(controller); |
| 207 } | 257 } |
| 208 | 258 |
| 209 void AutocompleteProviderTest::RunTest() { | 259 void AutocompleteProviderTest::RunTest() { |
| 260 RunQuery(ASCIIToUTF16("a")); |
| 261 } |
| 262 |
| 263 void AutocompleteProviderTest::RunRedundantKeywordTest( |
| 264 const KeywordTestData* match_data, |
| 265 size_t size) { |
| 266 ACMatches matches; |
| 267 for (size_t i = 0; i < size; ++i) { |
| 268 AutocompleteMatch match; |
| 269 match.fill_into_edit = match_data[i].fill_into_edit; |
| 270 match.keyword = match_data[i].keyword; |
| 271 matches.push_back(match); |
| 272 } |
| 273 |
| 274 AutocompleteResult result; |
| 275 result.AppendMatches(matches); |
| 276 controller_->UpdateAssociatedKeywords(&result); |
| 277 |
| 278 for (size_t j = 0; j < result.size(); ++j) { |
| 279 EXPECT_EQ(match_data[j].expected_keyword_result, |
| 280 result.match_at(j).associated_keyword.get() != NULL); |
| 281 } |
| 282 } |
| 283 |
| 284 |
| 285 void AutocompleteProviderTest::RunQuery(const string16 query) { |
| 210 result_.Reset(); | 286 result_.Reset(); |
| 211 controller_->Start(ASCIIToUTF16("a"), string16(), true, false, true, | 287 controller_->Start(query, string16(), true, false, true, |
| 212 AutocompleteInput::ALL_MATCHES); | 288 AutocompleteInput::ALL_MATCHES); |
| 213 | 289 |
| 214 // The message loop will terminate when all autocomplete input has been | 290 if (!controller_->done()) |
| 215 // collected. | 291 // The message loop will terminate when all autocomplete input has been |
| 216 MessageLoop::current()->Run(); | 292 // collected. |
| 293 MessageLoop::current()->Run(); |
| 217 } | 294 } |
| 218 | 295 |
| 219 void AutocompleteProviderTest::RunExactKeymatchTest( | 296 void AutocompleteProviderTest::RunExactKeymatchTest( |
| 220 bool allow_exact_keyword_match) { | 297 bool allow_exact_keyword_match) { |
| 221 // Send the controller input which exactly matches the keyword provider we | 298 // Send the controller input which exactly matches the keyword provider we |
| 222 // created in ResetControllerWithKeywordAndSearchProviders(). The default | 299 // created in ResetControllerWithKeywordAndSearchProviders(). The default |
| 223 // match should thus be a keyword match iff |allow_exact_keyword_match| is | 300 // match should thus be a keyword match iff |allow_exact_keyword_match| is |
| 224 // true. | 301 // true. |
| 225 controller_->Start(ASCIIToUTF16("k test"), string16(), true, false, | 302 controller_->Start(ASCIIToUTF16("k test"), string16(), true, false, |
| 226 allow_exact_keyword_match, | 303 allow_exact_keyword_match, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 243 } | 320 } |
| 244 } | 321 } |
| 245 | 322 |
| 246 // Tests that the default selection is set properly when updating results. | 323 // Tests that the default selection is set properly when updating results. |
| 247 TEST_F(AutocompleteProviderTest, Query) { | 324 TEST_F(AutocompleteProviderTest, Query) { |
| 248 ResetControllerWithTestProviders(false); | 325 ResetControllerWithTestProviders(false); |
| 249 RunTest(); | 326 RunTest(); |
| 250 | 327 |
| 251 // Make sure the default match gets set to the highest relevance match. The | 328 // Make sure the default match gets set to the highest relevance match. The |
| 252 // highest relevance matches should come from the second provider. | 329 // highest relevance matches should come from the second provider. |
| 253 EXPECT_EQ(num_results_per_provider * 2, result_.size()); // two providers | 330 EXPECT_EQ(kResultsPerProvider * 2, result_.size()); // two providers |
| 254 ASSERT_NE(result_.end(), result_.default_match()); | 331 ASSERT_NE(result_.end(), result_.default_match()); |
| 255 EXPECT_EQ(providers_[1], result_.default_match()->provider); | 332 EXPECT_EQ(providers_[1], result_.default_match()->provider); |
| 256 } | 333 } |
| 257 | 334 |
| 258 TEST_F(AutocompleteProviderTest, RemoveDuplicates) { | 335 TEST_F(AutocompleteProviderTest, RemoveDuplicates) { |
| 259 ResetControllerWithTestProviders(true); | 336 ResetControllerWithTestProviders(true); |
| 260 RunTest(); | 337 RunTest(); |
| 261 | 338 |
| 262 // Make sure all the first provider's results were eliminated by the second | 339 // Make sure all the first provider's results were eliminated by the second |
| 263 // provider's. | 340 // provider's. |
| 264 EXPECT_EQ(num_results_per_provider, result_.size()); | 341 EXPECT_EQ(kResultsPerProvider, result_.size()); |
| 265 for (AutocompleteResult::const_iterator i(result_.begin()); | 342 for (AutocompleteResult::const_iterator i(result_.begin()); |
| 266 i != result_.end(); ++i) | 343 i != result_.end(); ++i) |
| 267 EXPECT_EQ(providers_[1], i->provider); | 344 EXPECT_EQ(providers_[1], i->provider); |
| 268 } | 345 } |
| 269 | 346 |
| 270 TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { | 347 TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { |
| 271 ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); | 348 ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); |
| 272 RunExactKeymatchTest(true); | 349 RunExactKeymatchTest(true); |
| 273 RunExactKeymatchTest(false); | 350 RunExactKeymatchTest(false); |
| 274 } | 351 } |
| 275 | 352 |
| 353 // Test that redundant associated keywords are removed. |
| 354 TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) { |
| 355 ResetControllerWithKeywordProvider(); |
| 356 |
| 357 // Get the controller's internal members in the correct state. |
| 358 RunQuery(ASCIIToUTF16("fo")); |
| 359 |
| 360 { |
| 361 KeywordTestData duplicate_url[] = { |
| 362 { ASCIIToUTF16("fo"), string16(), false }, |
| 363 { ASCIIToUTF16("foo.com"), string16(), true }, |
| 364 { ASCIIToUTF16("foo.com"), string16(), false } |
| 365 }; |
| 366 |
| 367 SCOPED_TRACE("Duplicate url"); |
| 368 RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url)); |
| 369 } |
| 370 |
| 371 { |
| 372 KeywordTestData keyword_match[] = { |
| 373 { ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false }, |
| 374 { ASCIIToUTF16("foo.com"), string16(), false } |
| 375 }; |
| 376 |
| 377 SCOPED_TRACE("Duplicate url with keyword match"); |
| 378 RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match)); |
| 379 } |
| 380 |
| 381 { |
| 382 KeywordTestData multiple_keyword[] = { |
| 383 { ASCIIToUTF16("fo"), string16(), false }, |
| 384 { ASCIIToUTF16("foo.com"), string16(), true }, |
| 385 { ASCIIToUTF16("foo.com"), string16(), false }, |
| 386 { ASCIIToUTF16("bar.com"), string16(), true }, |
| 387 }; |
| 388 |
| 389 SCOPED_TRACE("Duplicate url with multiple keywords"); |
| 390 RunRedundantKeywordTest(multiple_keyword, |
| 391 ARRAYSIZE_UNSAFE(multiple_keyword)); |
| 392 } |
| 393 } |
| 394 |
| 276 typedef testing::Test AutocompleteTest; | 395 typedef testing::Test AutocompleteTest; |
| 277 | 396 |
| 278 TEST_F(AutocompleteTest, InputType) { | 397 TEST_F(AutocompleteTest, InputType) { |
| 279 struct test_data { | 398 struct test_data { |
| 280 const string16 input; | 399 const string16 input; |
| 281 const AutocompleteInput::Type type; | 400 const AutocompleteInput::Type type; |
| 282 } input_cases[] = { | 401 } input_cases[] = { |
| 283 { string16(), AutocompleteInput::INVALID }, | 402 { string16(), AutocompleteInput::INVALID }, |
| 284 { ASCIIToUTF16("?"), AutocompleteInput::FORCED_QUERY }, | 403 { ASCIIToUTF16("?"), AutocompleteInput::FORCED_QUERY }, |
| 285 { ASCIIToUTF16("?foo"), AutocompleteInput::FORCED_QUERY }, | 404 { ASCIIToUTF16("?foo"), AutocompleteInput::FORCED_QUERY }, |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 &scheme, | 596 &scheme, |
| 478 &host); | 597 &host); |
| 479 AutocompleteInput input(input_cases[i].input, string16(), true, false, | 598 AutocompleteInput input(input_cases[i].input, string16(), true, false, |
| 480 true, AutocompleteInput::ALL_MATCHES); | 599 true, AutocompleteInput::ALL_MATCHES); |
| 481 EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin); | 600 EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin); |
| 482 EXPECT_EQ(input_cases[i].scheme.len, scheme.len); | 601 EXPECT_EQ(input_cases[i].scheme.len, scheme.len); |
| 483 EXPECT_EQ(input_cases[i].host.begin, host.begin); | 602 EXPECT_EQ(input_cases[i].host.begin, host.begin); |
| 484 EXPECT_EQ(input_cases[i].host.len, host.len); | 603 EXPECT_EQ(input_cases[i].host.len, host.len); |
| 485 } | 604 } |
| 486 } | 605 } |
| 487 | |
| 488 } // namespace | |
| OLD | NEW |