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