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