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