autocomplete_provider_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/autocomplete_provider.h" 6 7#include "base/bind.h" 8#include "base/command_line.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "base/strings/string16.h" 12#include "base/strings/string_number_conversions.h" 13#include "base/strings/string_util.h" 14#include "base/strings/utf_string_conversions.h" 15#include "chrome/browser/autocomplete/autocomplete_controller.h" 16#include "chrome/browser/autocomplete/autocomplete_input.h" 17#include "chrome/browser/autocomplete/autocomplete_match.h" 18#include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 19#include "chrome/browser/autocomplete/keyword_provider.h" 20#include "chrome/browser/autocomplete/search_provider.h" 21#include "chrome/browser/chrome_notification_types.h" 22#include "chrome/browser/search_engines/template_url.h" 23#include "chrome/browser/search_engines/template_url_service.h" 24#include "chrome/browser/search_engines/template_url_service_factory.h" 25#include "chrome/common/chrome_switches.h" 26#include "chrome/test/base/testing_browser_process.h" 27#include "chrome/test/base/testing_profile.h" 28#include "content/public/browser/notification_observer.h" 29#include "content/public/browser/notification_registrar.h" 30#include "content/public/browser/notification_source.h" 31#include "testing/gtest/include/gtest/gtest.h" 32 33static std::ostream& operator<<(std::ostream& os, 34 const AutocompleteResult::const_iterator& it) { 35 return os << static_cast<const AutocompleteMatch*>(&(*it)); 36} 37 38namespace { 39const size_t kResultsPerProvider = 3; 40const char kTestTemplateURLKeyword[] = "t"; 41} 42 43// Autocomplete provider that provides known results. Note that this is 44// refcounted so that it can also be a task on the message loop. 45class TestProvider : public AutocompleteProvider { 46 public: 47 TestProvider(int relevance, const string16& prefix, 48 Profile* profile, 49 const string16 match_keyword) 50 : AutocompleteProvider(NULL, profile, AutocompleteProvider::TYPE_SEARCH), 51 relevance_(relevance), 52 prefix_(prefix), 53 match_keyword_(match_keyword) { 54 } 55 56 virtual void Start(const AutocompleteInput& input, 57 bool minimal_changes) OVERRIDE; 58 59 void set_listener(AutocompleteProviderListener* listener) { 60 listener_ = listener; 61 } 62 63 private: 64 virtual ~TestProvider() {} 65 66 void Run(); 67 68 void AddResults(int start_at, int num); 69 void AddResultsWithSearchTermsArgs( 70 int start_at, 71 int num, 72 AutocompleteMatch::Type type, 73 const TemplateURLRef::SearchTermsArgs& search_terms_args); 74 75 int relevance_; 76 const string16 prefix_; 77 const string16 match_keyword_; 78}; 79 80void TestProvider::Start(const AutocompleteInput& input, 81 bool minimal_changes) { 82 if (minimal_changes) 83 return; 84 85 matches_.clear(); 86 87 // Generate 4 results synchronously, the rest later. 88 AddResults(0, 1); 89 AddResultsWithSearchTermsArgs( 90 1, 1, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 91 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("echo"))); 92 AddResultsWithSearchTermsArgs( 93 2, 1, AutocompleteMatchType::NAVSUGGEST, 94 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("nav"))); 95 AddResultsWithSearchTermsArgs( 96 3, 1, AutocompleteMatchType::SEARCH_SUGGEST, 97 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("query"))); 98 99 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { 100 done_ = false; 101 base::MessageLoop::current()->PostTask( 102 FROM_HERE, base::Bind(&TestProvider::Run, this)); 103 } 104} 105 106void TestProvider::Run() { 107 DCHECK_GT(kResultsPerProvider, 0U); 108 AddResults(1, kResultsPerProvider); 109 done_ = true; 110 DCHECK(listener_); 111 listener_->OnProviderUpdate(true); 112} 113 114void TestProvider::AddResults(int start_at, int num) { 115 AddResultsWithSearchTermsArgs(start_at, 116 num, 117 AutocompleteMatchType::URL_WHAT_YOU_TYPED, 118 TemplateURLRef::SearchTermsArgs(string16())); 119} 120 121void TestProvider::AddResultsWithSearchTermsArgs( 122 int start_at, 123 int num, 124 AutocompleteMatch::Type type, 125 const TemplateURLRef::SearchTermsArgs& search_terms_args) { 126 for (int i = start_at; i < num; i++) { 127 AutocompleteMatch match(this, relevance_ - i, false, type); 128 129 match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); 130 match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit)); 131 match.allowed_to_be_default_match = true; 132 133 match.contents = match.fill_into_edit; 134 match.contents_class.push_back( 135 ACMatchClassification(0, ACMatchClassification::NONE)); 136 match.description = match.fill_into_edit; 137 match.description_class.push_back( 138 ACMatchClassification(0, ACMatchClassification::NONE)); 139 match.search_terms_args.reset( 140 new TemplateURLRef::SearchTermsArgs(search_terms_args)); 141 if (!match_keyword_.empty()) { 142 match.keyword = match_keyword_; 143 ASSERT_TRUE(match.GetTemplateURL(profile_, false) != NULL); 144 } 145 146 matches_.push_back(match); 147 } 148} 149 150class AutocompleteProviderTest : public testing::Test, 151 public content::NotificationObserver { 152 protected: 153 struct KeywordTestData { 154 const string16 fill_into_edit; 155 const string16 keyword; 156 const bool expected_keyword_result; 157 }; 158 159 struct AssistedQueryStatsTestData { 160 const AutocompleteMatch::Type match_type; 161 const std::string expected_aqs; 162 }; 163 164 protected: 165 // Registers a test TemplateURL under the given keyword. 166 void RegisterTemplateURL(const string16 keyword, 167 const std::string& template_url); 168 169 // Resets |controller_| with two TestProviders. |provider1_ptr| and 170 // |provider2_ptr| are updated to point to the new providers if non-NULL. 171 void ResetControllerWithTestProviders(bool same_destinations, 172 TestProvider** provider1_ptr, 173 TestProvider** provider2_ptr); 174 175 // Runs a query on the input "a", and makes sure both providers' input is 176 // properly collected. 177 void RunTest(); 178 179 void RunRedundantKeywordTest(const KeywordTestData* match_data, size_t size); 180 181 void RunAssistedQueryStatsTest( 182 const AssistedQueryStatsTestData* aqs_test_data, 183 size_t size); 184 185 void RunQuery(const string16 query); 186 187 void ResetControllerWithKeywordAndSearchProviders(); 188 void ResetControllerWithKeywordProvider(); 189 void RunExactKeymatchTest(bool allow_exact_keyword_match); 190 191 void CopyResults(); 192 193 // Returns match.destination_url as it would be set by 194 // AutocompleteController::UpdateMatchDestinationURL(). 195 GURL GetDestinationURL(AutocompleteMatch match, 196 base::TimeDelta query_formulation_time) const; 197 198 AutocompleteResult result_; 199 scoped_ptr<AutocompleteController> controller_; 200 201 private: 202 // content::NotificationObserver: 203 virtual void Observe(int type, 204 const content::NotificationSource& source, 205 const content::NotificationDetails& details) OVERRIDE; 206 207 base::MessageLoopForUI message_loop_; 208 content::NotificationRegistrar registrar_; 209 TestingProfile profile_; 210}; 211 212void AutocompleteProviderTest::RegisterTemplateURL( 213 const string16 keyword, 214 const std::string& template_url) { 215 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 216 &profile_, &TemplateURLServiceFactory::BuildInstanceFor); 217 TemplateURLData data; 218 data.SetURL(template_url); 219 data.SetKeyword(keyword); 220 TemplateURL* default_t_url = new TemplateURL(&profile_, data); 221 TemplateURLService* turl_model = 222 TemplateURLServiceFactory::GetForProfile(&profile_); 223 turl_model->Add(default_t_url); 224 turl_model->SetDefaultSearchProvider(default_t_url); 225 turl_model->Load(); 226 TemplateURLID default_provider_id = default_t_url->id(); 227 ASSERT_NE(0, default_provider_id); 228} 229 230void AutocompleteProviderTest::ResetControllerWithTestProviders( 231 bool same_destinations, 232 TestProvider** provider1_ptr, 233 TestProvider** provider2_ptr) { 234 // TODO: Move it outside this method, after refactoring the existing 235 // unit tests. Specifically: 236 // (1) Make sure that AutocompleteMatch.keyword is set iff there is 237 // a corresponding call to RegisterTemplateURL; otherwise the 238 // controller flow will crash; this practically means that 239 // RunTests/ResetControllerXXX/RegisterTemplateURL should 240 // be coordinated with each other. 241 // (2) Inject test arguments rather than rely on the hardcoded values, e.g. 242 // don't rely on kResultsPerProvided and default relevance ordering 243 // (B > A). 244 RegisterTemplateURL(ASCIIToUTF16(kTestTemplateURLKeyword), 245 "http://aqs/{searchTerms}/{google:assistedQueryStats}"); 246 247 ACProviders providers; 248 249 // Construct two new providers, with either the same or different prefixes. 250 TestProvider* provider1 = new TestProvider( 251 kResultsPerProvider, 252 ASCIIToUTF16("http://a"), 253 &profile_, 254 ASCIIToUTF16(kTestTemplateURLKeyword)); 255 provider1->AddRef(); 256 providers.push_back(provider1); 257 258 TestProvider* provider2 = new TestProvider( 259 kResultsPerProvider * 2, 260 same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b"), 261 &profile_, 262 string16()); 263 provider2->AddRef(); 264 providers.push_back(provider2); 265 266 // Reset the controller to contain our new providers. 267 controller_.reset(new AutocompleteController(&profile_, NULL, 0)); 268 // We're going to swap the providers vector, but the old vector should be 269 // empty so no elements need to be freed at this point. 270 EXPECT_TRUE(controller_->providers_.empty()); 271 controller_->providers_.swap(providers); 272 provider1->set_listener(controller_.get()); 273 provider2->set_listener(controller_.get()); 274 275 // The providers don't complete synchronously, so listen for "result updated" 276 // notifications. 277 registrar_.Add(this, 278 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY, 279 content::Source<AutocompleteController>(controller_.get())); 280 281 if (provider1_ptr) 282 *provider1_ptr = provider1; 283 if (provider2_ptr) 284 *provider2_ptr = provider2; 285} 286 287void AutocompleteProviderTest:: 288 ResetControllerWithKeywordAndSearchProviders() { 289 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 290 &profile_, &TemplateURLServiceFactory::BuildInstanceFor); 291 292 // Reset the default TemplateURL. 293 TemplateURLData data; 294 data.SetURL("http://defaultturl/{searchTerms}"); 295 TemplateURL* default_t_url = new TemplateURL(&profile_, data); 296 TemplateURLService* turl_model = 297 TemplateURLServiceFactory::GetForProfile(&profile_); 298 turl_model->Add(default_t_url); 299 turl_model->SetDefaultSearchProvider(default_t_url); 300 TemplateURLID default_provider_id = default_t_url->id(); 301 ASSERT_NE(0, default_provider_id); 302 303 // Create another TemplateURL for KeywordProvider. 304 data.short_name = ASCIIToUTF16("k"); 305 data.SetKeyword(ASCIIToUTF16("k")); 306 data.SetURL("http://keyword/{searchTerms}"); 307 TemplateURL* keyword_t_url = new TemplateURL(&profile_, data); 308 turl_model->Add(keyword_t_url); 309 ASSERT_NE(0, keyword_t_url->id()); 310 311 controller_.reset(new AutocompleteController( 312 &profile_, NULL, 313 AutocompleteProvider::TYPE_KEYWORD | AutocompleteProvider::TYPE_SEARCH)); 314} 315 316void AutocompleteProviderTest::ResetControllerWithKeywordProvider() { 317 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 318 &profile_, &TemplateURLServiceFactory::BuildInstanceFor); 319 320 TemplateURLService* turl_model = 321 TemplateURLServiceFactory::GetForProfile(&profile_); 322 323 // Create a TemplateURL for KeywordProvider. 324 TemplateURLData data; 325 data.short_name = ASCIIToUTF16("foo.com"); 326 data.SetKeyword(ASCIIToUTF16("foo.com")); 327 data.SetURL("http://foo.com/{searchTerms}"); 328 TemplateURL* keyword_t_url = new TemplateURL(&profile_, data); 329 turl_model->Add(keyword_t_url); 330 ASSERT_NE(0, keyword_t_url->id()); 331 332 // Create another TemplateURL for KeywordProvider. 333 data.short_name = ASCIIToUTF16("bar.com"); 334 data.SetKeyword(ASCIIToUTF16("bar.com")); 335 data.SetURL("http://bar.com/{searchTerms}"); 336 keyword_t_url = new TemplateURL(&profile_, data); 337 turl_model->Add(keyword_t_url); 338 ASSERT_NE(0, keyword_t_url->id()); 339 340 controller_.reset(new AutocompleteController( 341 &profile_, NULL, AutocompleteProvider::TYPE_KEYWORD)); 342} 343 344void AutocompleteProviderTest::RunTest() { 345 RunQuery(ASCIIToUTF16("a")); 346} 347 348void AutocompleteProviderTest::RunRedundantKeywordTest( 349 const KeywordTestData* match_data, 350 size_t size) { 351 ACMatches matches; 352 for (size_t i = 0; i < size; ++i) { 353 AutocompleteMatch match; 354 match.relevance = 1000; // Arbitrary non-zero value. 355 match.allowed_to_be_default_match = true; 356 match.fill_into_edit = match_data[i].fill_into_edit; 357 match.transition = content::PAGE_TRANSITION_KEYWORD; 358 match.keyword = match_data[i].keyword; 359 matches.push_back(match); 360 } 361 362 AutocompleteResult result; 363 result.AppendMatches(matches); 364 controller_->UpdateAssociatedKeywords(&result); 365 366 for (size_t j = 0; j < result.size(); ++j) { 367 EXPECT_EQ(match_data[j].expected_keyword_result, 368 result.match_at(j)->associated_keyword.get() != NULL); 369 } 370} 371 372void AutocompleteProviderTest::RunAssistedQueryStatsTest( 373 const AssistedQueryStatsTestData* aqs_test_data, 374 size_t size) { 375 // Prepare input. 376 const size_t kMaxRelevance = 1000; 377 ACMatches matches; 378 for (size_t i = 0; i < size; ++i) { 379 AutocompleteMatch match(NULL, kMaxRelevance - i, false, 380 aqs_test_data[i].match_type); 381 match.allowed_to_be_default_match = true; 382 match.keyword = ASCIIToUTF16(kTestTemplateURLKeyword); 383 match.search_terms_args.reset( 384 new TemplateURLRef::SearchTermsArgs(string16())); 385 matches.push_back(match); 386 } 387 result_.Reset(); 388 result_.AppendMatches(matches); 389 390 // Update AQS. 391 controller_->UpdateAssistedQueryStats(&result_); 392 393 // Verify data. 394 for (size_t i = 0; i < size; ++i) { 395 EXPECT_EQ(aqs_test_data[i].expected_aqs, 396 result_.match_at(i)->search_terms_args->assisted_query_stats); 397 } 398} 399 400void AutocompleteProviderTest::RunQuery(const string16 query) { 401 result_.Reset(); 402 controller_->Start(AutocompleteInput( 403 query, string16::npos, string16(), GURL(), 404 AutocompleteInput::INVALID_SPEC, true, false, true, 405 AutocompleteInput::ALL_MATCHES)); 406 407 if (!controller_->done()) 408 // The message loop will terminate when all autocomplete input has been 409 // collected. 410 base::MessageLoop::current()->Run(); 411} 412 413void AutocompleteProviderTest::RunExactKeymatchTest( 414 bool allow_exact_keyword_match) { 415 // Send the controller input which exactly matches the keyword provider we 416 // created in ResetControllerWithKeywordAndSearchProviders(). The default 417 // match should thus be a search-other-engine match iff 418 // |allow_exact_keyword_match| is true. Regardless, the match should 419 // be from SearchProvider. (It provides all verbatim search matches, 420 // keyword or not.) 421 controller_->Start(AutocompleteInput( 422 ASCIIToUTF16("k test"), string16::npos, string16(), GURL(), 423 AutocompleteInput::INVALID_SPEC, true, false, allow_exact_keyword_match, 424 AutocompleteInput::SYNCHRONOUS_MATCHES)); 425 EXPECT_TRUE(controller_->done()); 426 EXPECT_EQ(AutocompleteProvider::TYPE_SEARCH, 427 controller_->result().default_match()->provider->type()); 428 EXPECT_EQ(allow_exact_keyword_match ? 429 AutocompleteMatchType::SEARCH_OTHER_ENGINE : 430 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 431 controller_->result().default_match()->type); 432} 433 434void AutocompleteProviderTest::CopyResults() { 435 result_.CopyFrom(controller_->result()); 436} 437 438GURL AutocompleteProviderTest::GetDestinationURL( 439 AutocompleteMatch match, 440 base::TimeDelta query_formulation_time) const { 441 controller_->UpdateMatchDestinationURL(query_formulation_time, &match); 442 return match.destination_url; 443} 444 445void AutocompleteProviderTest::Observe( 446 int type, 447 const content::NotificationSource& source, 448 const content::NotificationDetails& details) { 449 if (controller_->done()) { 450 CopyResults(); 451 base::MessageLoop::current()->Quit(); 452 } 453} 454 455// Tests that the default selection is set properly when updating results. 456TEST_F(AutocompleteProviderTest, Query) { 457 TestProvider* provider1 = NULL; 458 TestProvider* provider2 = NULL; 459 ResetControllerWithTestProviders(false, &provider1, &provider2); 460 RunTest(); 461 462 // Make sure the default match gets set to the highest relevance match. The 463 // highest relevance matches should come from the second provider. 464 EXPECT_EQ(kResultsPerProvider * 2, result_.size()); 465 ASSERT_NE(result_.end(), result_.default_match()); 466 EXPECT_EQ(provider2, result_.default_match()->provider); 467} 468 469// Tests assisted query stats. 470TEST_F(AutocompleteProviderTest, AssistedQueryStats) { 471 ResetControllerWithTestProviders(false, NULL, NULL); 472 RunTest(); 473 474 ASSERT_EQ(kResultsPerProvider * 2, result_.size()); 475 476 // Now, check the results from the second provider, as they should not have 477 // assisted query stats set. 478 for (size_t i = 0; i < kResultsPerProvider; ++i) { 479 EXPECT_TRUE( 480 result_.match_at(i)->search_terms_args->assisted_query_stats.empty()); 481 } 482 // The first provider has a test keyword, so AQS should be non-empty. 483 for (size_t i = kResultsPerProvider; i < kResultsPerProvider * 2; ++i) { 484 EXPECT_FALSE( 485 result_.match_at(i)->search_terms_args->assisted_query_stats.empty()); 486 } 487} 488 489TEST_F(AutocompleteProviderTest, RemoveDuplicates) { 490 TestProvider* provider1 = NULL; 491 TestProvider* provider2 = NULL; 492 ResetControllerWithTestProviders(true, &provider1, &provider2); 493 RunTest(); 494 495 // Make sure all the first provider's results were eliminated by the second 496 // provider's. 497 EXPECT_EQ(kResultsPerProvider, result_.size()); 498 for (AutocompleteResult::const_iterator i(result_.begin()); 499 i != result_.end(); ++i) 500 EXPECT_EQ(provider2, i->provider); 501} 502 503TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { 504 ResetControllerWithKeywordAndSearchProviders(); 505 RunExactKeymatchTest(true); 506 RunExactKeymatchTest(false); 507} 508 509// Ensures matches from (only) the default search provider respect any extra 510// query params set on the command line. 511TEST_F(AutocompleteProviderTest, ExtraQueryParams) { 512 ResetControllerWithKeywordAndSearchProviders(); 513 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 514 switches::kExtraSearchQueryParams, "a=b"); 515 RunExactKeymatchTest(true); 516 CopyResults(); 517 ASSERT_EQ(2U, result_.size()); 518 EXPECT_EQ("http://keyword/test", 519 result_.match_at(0)->destination_url.possibly_invalid_spec()); 520 EXPECT_EQ("http://defaultturl/k%20test?a=b", 521 result_.match_at(1)->destination_url.possibly_invalid_spec()); 522} 523 524// Test that redundant associated keywords are removed. 525TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) { 526 ResetControllerWithKeywordProvider(); 527 528 { 529 KeywordTestData duplicate_url[] = { 530 { ASCIIToUTF16("fo"), string16(), false }, 531 { ASCIIToUTF16("foo.com"), string16(), true }, 532 { ASCIIToUTF16("foo.com"), string16(), false } 533 }; 534 535 SCOPED_TRACE("Duplicate url"); 536 RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url)); 537 } 538 539 { 540 KeywordTestData keyword_match[] = { 541 { ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false }, 542 { ASCIIToUTF16("foo.com"), string16(), false } 543 }; 544 545 SCOPED_TRACE("Duplicate url with keyword match"); 546 RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match)); 547 } 548 549 { 550 KeywordTestData multiple_keyword[] = { 551 { ASCIIToUTF16("fo"), string16(), false }, 552 { ASCIIToUTF16("foo.com"), string16(), true }, 553 { ASCIIToUTF16("foo.com"), string16(), false }, 554 { ASCIIToUTF16("bar.com"), string16(), true }, 555 }; 556 557 SCOPED_TRACE("Duplicate url with multiple keywords"); 558 RunRedundantKeywordTest(multiple_keyword, 559 ARRAYSIZE_UNSAFE(multiple_keyword)); 560 } 561} 562 563TEST_F(AutocompleteProviderTest, UpdateAssistedQueryStats) { 564 ResetControllerWithTestProviders(false, NULL, NULL); 565 566 { 567 AssistedQueryStatsTestData test_data[] = { 568 // MSVC doesn't support zero-length arrays, so supply some dummy data. 569 { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "" } 570 }; 571 SCOPED_TRACE("No matches"); 572 // Note: We pass 0 here to ignore the dummy data above. 573 RunAssistedQueryStatsTest(test_data, 0); 574 } 575 576 { 577 AssistedQueryStatsTestData test_data[] = { 578 { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "chrome..69i57" } 579 }; 580 SCOPED_TRACE("One match"); 581 RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data)); 582 } 583 584 { 585 AssistedQueryStatsTestData test_data[] = { 586 { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 587 "chrome..69i57j69i58j5l2j0l3j69i59" }, 588 { AutocompleteMatchType::URL_WHAT_YOU_TYPED, 589 "chrome..69i57j69i58j5l2j0l3j69i59" }, 590 { AutocompleteMatchType::NAVSUGGEST, 591 "chrome.2.69i57j69i58j5l2j0l3j69i59" }, 592 { AutocompleteMatchType::NAVSUGGEST, 593 "chrome.3.69i57j69i58j5l2j0l3j69i59" }, 594 { AutocompleteMatchType::SEARCH_SUGGEST, 595 "chrome.4.69i57j69i58j5l2j0l3j69i59" }, 596 { AutocompleteMatchType::SEARCH_SUGGEST, 597 "chrome.5.69i57j69i58j5l2j0l3j69i59" }, 598 { AutocompleteMatchType::SEARCH_SUGGEST, 599 "chrome.6.69i57j69i58j5l2j0l3j69i59" }, 600 { AutocompleteMatchType::SEARCH_HISTORY, 601 "chrome.7.69i57j69i58j5l2j0l3j69i59" }, 602 }; 603 SCOPED_TRACE("Multiple matches"); 604 RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data)); 605 } 606} 607 608TEST_F(AutocompleteProviderTest, GetDestinationURL) { 609 ResetControllerWithKeywordAndSearchProviders(); 610 611 // For the destination URL to have aqs parameters for query formulation time 612 // and the field trial triggered bit, many conditions need to be satisfied. 613 AutocompleteMatch match(NULL, 1100, false, 614 AutocompleteMatchType::SEARCH_SUGGEST); 615 GURL url(GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456))); 616 EXPECT_TRUE(url.path().empty()); 617 618 // The protocol needs to be https. 619 RegisterTemplateURL(ASCIIToUTF16(kTestTemplateURLKeyword), 620 "https://aqs/{searchTerms}/{google:assistedQueryStats}"); 621 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 622 EXPECT_TRUE(url.path().empty()); 623 624 // There needs to be a keyword provider. 625 match.keyword = ASCIIToUTF16(kTestTemplateURLKeyword); 626 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 627 EXPECT_TRUE(url.path().empty()); 628 629 // search_terms_args needs to be set. 630 match.search_terms_args.reset( 631 new TemplateURLRef::SearchTermsArgs(string16())); 632 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 633 EXPECT_TRUE(url.path().empty()); 634 635 // assisted_query_stats needs to have been previously set. 636 match.search_terms_args->assisted_query_stats = 637 "chrome.0.69i57j69i58j5l2j0l3j69i59"; 638 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 639 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j0&", url.path()); 640 641 // Test field trial triggered bit set. 642 controller_->search_provider_->field_trial_triggered_in_session_ = true; 643 EXPECT_TRUE( 644 controller_->search_provider_->field_trial_triggered_in_session()); 645 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 646 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j0&", url.path()); 647 648 // Test page classification set. 649 controller_->input_.current_page_classification_ = AutocompleteInput::OTHER; 650 controller_->search_provider_->field_trial_triggered_in_session_ = false; 651 EXPECT_FALSE( 652 controller_->search_provider_->field_trial_triggered_in_session()); 653 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 654 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j4&", url.path()); 655 656 // Test page classification and field trial triggered set. 657 controller_->search_provider_->field_trial_triggered_in_session_ = true; 658 EXPECT_TRUE( 659 controller_->search_provider_->field_trial_triggered_in_session()); 660 url = GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456)); 661 EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j4&", url.path()); 662} 663