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