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