autocomplete_provider_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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.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(), true, false, true,
395      AutocompleteInput::ALL_MATCHES));
396
397  if (!controller_->done())
398    // The message loop will terminate when all autocomplete input has been
399    // collected.
400    base::MessageLoop::current()->Run();
401}
402
403void AutocompleteProviderTest::RunExactKeymatchTest(
404    bool allow_exact_keyword_match) {
405  // Send the controller input which exactly matches the keyword provider we
406  // created in ResetControllerWithKeywordAndSearchProviders().  The default
407  // match should thus be a search-other-engine match iff
408  // |allow_exact_keyword_match| is true.  Regardless, the match should
409  // be from SearchProvider.  (It provides all verbatim search matches,
410  // keyword or not.)
411  controller_->Start(AutocompleteInput(
412      ASCIIToUTF16("k test"), string16::npos, string16(), GURL(), true, false,
413      allow_exact_keyword_match, AutocompleteInput::SYNCHRONOUS_MATCHES));
414  EXPECT_TRUE(controller_->done());
415  EXPECT_EQ(AutocompleteProvider::TYPE_SEARCH,
416      controller_->result().default_match()->provider->type());
417  EXPECT_EQ(allow_exact_keyword_match ?
418      AutocompleteMatchType::SEARCH_OTHER_ENGINE :
419      AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
420      controller_->result().default_match()->type);
421}
422
423void AutocompleteProviderTest::CopyResults() {
424  result_.CopyFrom(controller_->result());
425}
426
427void AutocompleteProviderTest::Observe(
428    int type,
429    const content::NotificationSource& source,
430    const content::NotificationDetails& details) {
431  if (controller_->done()) {
432    CopyResults();
433    base::MessageLoop::current()->Quit();
434  }
435}
436
437// Tests that the default selection is set properly when updating results.
438TEST_F(AutocompleteProviderTest, Query) {
439  TestProvider* provider1 = NULL;
440  TestProvider* provider2 = NULL;
441  ResetControllerWithTestProviders(false, &provider1, &provider2);
442  RunTest();
443
444  // Make sure the default match gets set to the highest relevance match.  The
445  // highest relevance matches should come from the second provider.
446  EXPECT_EQ(kResultsPerProvider * 2, result_.size());
447  ASSERT_NE(result_.end(), result_.default_match());
448  EXPECT_EQ(provider2, result_.default_match()->provider);
449}
450
451// Tests assisted query stats.
452TEST_F(AutocompleteProviderTest, AssistedQueryStats) {
453  ResetControllerWithTestProviders(false, NULL, NULL);
454  RunTest();
455
456  ASSERT_EQ(kResultsPerProvider * 2, result_.size());
457
458  // Now, check the results from the second provider, as they should not have
459  // assisted query stats set.
460  for (size_t i = 0; i < kResultsPerProvider; ++i) {
461    EXPECT_TRUE(
462        result_.match_at(i)->search_terms_args->assisted_query_stats.empty());
463  }
464  // The first provider has a test keyword, so AQS should be non-empty.
465  for (size_t i = kResultsPerProvider; i < kResultsPerProvider * 2; ++i) {
466    EXPECT_FALSE(
467        result_.match_at(i)->search_terms_args->assisted_query_stats.empty());
468  }
469}
470
471TEST_F(AutocompleteProviderTest, RemoveDuplicates) {
472  TestProvider* provider1 = NULL;
473  TestProvider* provider2 = NULL;
474  ResetControllerWithTestProviders(true, &provider1, &provider2);
475  RunTest();
476
477  // Make sure all the first provider's results were eliminated by the second
478  // provider's.
479  EXPECT_EQ(kResultsPerProvider, result_.size());
480  for (AutocompleteResult::const_iterator i(result_.begin());
481       i != result_.end(); ++i)
482    EXPECT_EQ(provider2, i->provider);
483}
484
485TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) {
486  ResetControllerWithKeywordAndSearchProviders();
487  RunExactKeymatchTest(true);
488  RunExactKeymatchTest(false);
489}
490
491// Ensures matches from (only) the default search provider respect any extra
492// query params set on the command line.
493TEST_F(AutocompleteProviderTest, ExtraQueryParams) {
494  ResetControllerWithKeywordAndSearchProviders();
495  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
496      switches::kExtraSearchQueryParams, "a=b");
497  RunExactKeymatchTest(true);
498  CopyResults();
499  ASSERT_EQ(2U, result_.size());
500  EXPECT_EQ("http://keyword/test",
501            result_.match_at(0)->destination_url.possibly_invalid_spec());
502  EXPECT_EQ("http://defaultturl/k%20test?a=b",
503            result_.match_at(1)->destination_url.possibly_invalid_spec());
504}
505
506// Test that redundant associated keywords are removed.
507TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) {
508  ResetControllerWithKeywordProvider();
509
510  // Get the controller's internal members in the correct state.
511  RunQuery(ASCIIToUTF16("fo"));
512
513  {
514    KeywordTestData duplicate_url[] = {
515      { ASCIIToUTF16("fo"), string16(), false },
516      { ASCIIToUTF16("foo.com"), string16(), true },
517      { ASCIIToUTF16("foo.com"), string16(), false }
518    };
519
520    SCOPED_TRACE("Duplicate url");
521    RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url));
522  }
523
524  {
525    KeywordTestData keyword_match[] = {
526      { ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false },
527      { ASCIIToUTF16("foo.com"), string16(), false }
528    };
529
530    SCOPED_TRACE("Duplicate url with keyword match");
531    RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match));
532  }
533
534  {
535    KeywordTestData multiple_keyword[] = {
536      { ASCIIToUTF16("fo"), string16(), false },
537      { ASCIIToUTF16("foo.com"), string16(), true },
538      { ASCIIToUTF16("foo.com"), string16(), false },
539      { ASCIIToUTF16("bar.com"), string16(), true },
540    };
541
542    SCOPED_TRACE("Duplicate url with multiple keywords");
543    RunRedundantKeywordTest(multiple_keyword,
544        ARRAYSIZE_UNSAFE(multiple_keyword));
545  }
546}
547
548TEST_F(AutocompleteProviderTest, UpdateAssistedQueryStats) {
549  ResetControllerWithTestProviders(false, NULL, NULL);
550
551  {
552    AssistedQueryStatsTestData test_data[] = {
553      //  MSVC doesn't support zero-length arrays, so supply some dummy data.
554      { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "" }
555    };
556    SCOPED_TRACE("No matches");
557    // Note: We pass 0 here to ignore the dummy data above.
558    RunAssistedQueryStatsTest(test_data, 0);
559  }
560
561  {
562    AssistedQueryStatsTestData test_data[] = {
563      { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "chrome..69i57" }
564    };
565    SCOPED_TRACE("One match");
566    RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data));
567  }
568
569  {
570    AssistedQueryStatsTestData test_data[] = {
571      { AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
572        "chrome..69i57j69i58j5l2j0l3j69i59" },
573      { AutocompleteMatchType::URL_WHAT_YOU_TYPED,
574        "chrome..69i57j69i58j5l2j0l3j69i59" },
575      { AutocompleteMatchType::NAVSUGGEST,
576        "chrome.2.69i57j69i58j5l2j0l3j69i59" },
577      { AutocompleteMatchType::NAVSUGGEST,
578        "chrome.3.69i57j69i58j5l2j0l3j69i59" },
579      { AutocompleteMatchType::SEARCH_SUGGEST,
580        "chrome.4.69i57j69i58j5l2j0l3j69i59" },
581      { AutocompleteMatchType::SEARCH_SUGGEST,
582        "chrome.5.69i57j69i58j5l2j0l3j69i59" },
583      { AutocompleteMatchType::SEARCH_SUGGEST,
584        "chrome.6.69i57j69i58j5l2j0l3j69i59" },
585      { AutocompleteMatchType::SEARCH_HISTORY,
586        "chrome.7.69i57j69i58j5l2j0l3j69i59" },
587    };
588    SCOPED_TRACE("Multiple matches");
589    RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data));
590  }
591}
592
593TEST_F(AutocompleteProviderTest, GetDestinationURL) {
594  ResetControllerWithKeywordAndSearchProviders();
595
596  // For the destination URL to have aqs parameters for query formulation time
597  // and the field trial triggered bit, many conditions need to be satisfied.
598  AutocompleteMatch match(NULL, 1100, false,
599                          AutocompleteMatchType::SEARCH_SUGGEST);
600  GURL url = controller_->
601      GetDestinationURL(match, base::TimeDelta::FromMilliseconds(2456));
602  EXPECT_TRUE(url.path().empty());
603
604  // The protocol needs to be https.
605  RegisterTemplateURL(ASCIIToUTF16(kTestTemplateURLKeyword),
606                      "https://aqs/{searchTerms}/{google:assistedQueryStats}");
607  url = controller_->GetDestinationURL(match,
608                                       base::TimeDelta::FromMilliseconds(2456));
609  EXPECT_TRUE(url.path().empty());
610
611  // There needs to be a keyword provider.
612  match.keyword = ASCIIToUTF16(kTestTemplateURLKeyword);
613  url = controller_->GetDestinationURL(match,
614                                       base::TimeDelta::FromMilliseconds(2456));
615  EXPECT_TRUE(url.path().empty());
616
617  // search_terms_args needs to be set.
618  match.search_terms_args.reset(
619      new TemplateURLRef::SearchTermsArgs(string16()));
620  url = controller_->GetDestinationURL(match,
621                                       base::TimeDelta::FromMilliseconds(2456));
622  EXPECT_TRUE(url.path().empty());
623
624  // assisted_query_stats needs to have been previously set.
625  match.search_terms_args->assisted_query_stats =
626      "chrome.0.69i57j69i58j5l2j0l3j69i59";
627  url = controller_->GetDestinationURL(match,
628                                       base::TimeDelta::FromMilliseconds(2456));
629  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0&", url.path());
630
631  // Test field trial triggered bit set.
632  controller_->search_provider_->field_trial_triggered_in_session_ = true;
633  EXPECT_TRUE(
634      controller_->search_provider_->field_trial_triggered_in_session());
635  url = controller_->GetDestinationURL(match,
636                                       base::TimeDelta::FromMilliseconds(2456));
637  EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1&", url.path());
638}
639