autocomplete_provider_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved.
293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Use of this source code is governed by a BSD-style license that can be
393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// found in the LICENSE file.
493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/autocomplete_provider.h"
693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/bind.h"
893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/memory/scoped_ptr.h"
993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/message_loop.h"
1093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/string16.h"
1193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/string_number_conversions.h"
1293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/string_util.h"
1393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "base/utf_string_conversions.h"
1493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/autocomplete_controller.h"
1593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/autocomplete_input.h"
1693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/autocomplete_match.h"
1793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
1893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/keyword_provider.h"
1993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/autocomplete/search_provider.h"
2093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/search_engines/template_url.h"
2193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/search_engines/template_url_service.h"
2293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/browser/search_engines/template_url_service_factory.h"
2393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/common/chrome_notification_types.h"
2493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/test/base/testing_browser_process.h"
2593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "chrome/test/base/testing_profile.h"
2693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "content/public/browser/notification_observer.h"
2793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "content/public/browser/notification_registrar.h"
2893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "content/public/browser/notification_source.h"
2993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "testing/gtest/include/gtest/gtest.h"
3093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgstatic std::ostream& operator<<(std::ostream& os,
3293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                                const AutocompleteResult::const_iterator& it) {
3393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  return os << static_cast<const AutocompleteMatch*>(&(*it));
3493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
3593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
3693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgnamespace {
3793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgconst size_t kResultsPerProvider = 3;
3893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgconst char kTestTemplateURLKeyword[] = "t";
3993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org}
4093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
4193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// Autocomplete provider that provides known results. Note that this is
4293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org// refcounted so that it can also be a task on the message loop.
4393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.orgclass TestProvider : public AutocompleteProvider {
4493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org public:
4593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  TestProvider(int relevance, const string16& prefix,
4693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org               Profile* profile,
4793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org               const string16 match_keyword)
4893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org      : AutocompleteProvider(NULL, profile, AutocompleteProvider::TYPE_SEARCH),
4993a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        relevance_(relevance),
5093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        prefix_(prefix),
5193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org        match_keyword_(match_keyword) {
5293a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  }
5393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  virtual void Start(const AutocompleteInput& input,
5593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org                     bool minimal_changes);
5693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
5793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org  void set_listener(AutocompleteProviderListener* listener) {
58    listener_ = listener;
59  }
60
61 private:
62  ~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, AutocompleteMatch::SEARCH_WHAT_YOU_TYPED,
89      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("echo")));
90  AddResultsWithSearchTermsArgs(
91      2, 1, AutocompleteMatch::NAVSUGGEST,
92      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("nav")));
93  AddResultsWithSearchTermsArgs(
94      3, 1, AutocompleteMatch::SEARCH_SUGGEST,
95      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("query")));
96
97  if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) {
98    done_ = false;
99    MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&TestProvider::Run,
100                                                           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                                AutocompleteMatch::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);
196
197  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  controller_->providers_.swap(providers);
259  provider1->set_listener(controller_.get());
260  provider2->set_listener(controller_.get());
261
262  // The providers don't complete synchronously, so listen for "result updated"
263  // notifications.
264  registrar_.Add(this,
265                 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
266                 content::Source<AutocompleteController>(controller_.get()));
267
268  if (provider1_ptr)
269    *provider1_ptr = provider1;
270  if (provider2_ptr)
271    *provider2_ptr = provider2;
272}
273
274void AutocompleteProviderTest::
275    ResetControllerWithKeywordAndSearchProviders() {
276  TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
277      &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
278
279  // Reset the default TemplateURL.
280  TemplateURLData data;
281  data.SetURL("http://defaultturl/{searchTerms}");
282  TemplateURL* default_t_url = new TemplateURL(&profile_, data);
283  TemplateURLService* turl_model =
284      TemplateURLServiceFactory::GetForProfile(&profile_);
285  turl_model->Add(default_t_url);
286  turl_model->SetDefaultSearchProvider(default_t_url);
287  TemplateURLID default_provider_id = default_t_url->id();
288  ASSERT_NE(0, default_provider_id);
289
290  // Create another TemplateURL for KeywordProvider.
291  data.short_name = ASCIIToUTF16("k");
292  data.SetKeyword(ASCIIToUTF16("k"));
293  data.SetURL("http://keyword/{searchTerms}");
294  TemplateURL* keyword_t_url = new TemplateURL(&profile_, data);
295  turl_model->Add(keyword_t_url);
296  ASSERT_NE(0, keyword_t_url->id());
297
298  controller_.reset(new AutocompleteController(
299      &profile_, NULL,
300      AutocompleteProvider::TYPE_KEYWORD | AutocompleteProvider::TYPE_SEARCH));
301}
302
303void AutocompleteProviderTest::ResetControllerWithKeywordProvider() {
304  TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
305      &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
306
307  TemplateURLService* turl_model =
308      TemplateURLServiceFactory::GetForProfile(&profile_);
309
310  // Create a TemplateURL for KeywordProvider.
311  TemplateURLData data;
312  data.short_name = ASCIIToUTF16("foo.com");
313  data.SetKeyword(ASCIIToUTF16("foo.com"));
314  data.SetURL("http://foo.com/{searchTerms}");
315  TemplateURL* keyword_t_url = new TemplateURL(&profile_, data);
316  turl_model->Add(keyword_t_url);
317  ASSERT_NE(0, keyword_t_url->id());
318
319  // Create another TemplateURL for KeywordProvider.
320  data.short_name = ASCIIToUTF16("bar.com");
321  data.SetKeyword(ASCIIToUTF16("bar.com"));
322  data.SetURL("http://bar.com/{searchTerms}");
323  keyword_t_url = new TemplateURL(&profile_, data);
324  turl_model->Add(keyword_t_url);
325  ASSERT_NE(0, keyword_t_url->id());
326
327  controller_.reset(new AutocompleteController(
328      &profile_, NULL, AutocompleteProvider::TYPE_KEYWORD));
329}
330
331void AutocompleteProviderTest::RunTest() {
332  RunQuery(ASCIIToUTF16("a"));
333}
334
335void AutocompleteProviderTest::RunRedundantKeywordTest(
336    const KeywordTestData* match_data,
337    size_t size) {
338  ACMatches matches;
339  for (size_t i = 0; i < size; ++i) {
340    AutocompleteMatch match;
341    match.fill_into_edit = match_data[i].fill_into_edit;
342    match.transition = content::PAGE_TRANSITION_KEYWORD;
343    match.keyword = match_data[i].keyword;
344    matches.push_back(match);
345  }
346
347  AutocompleteResult result;
348  result.AppendMatches(matches);
349  controller_->UpdateAssociatedKeywords(&result);
350
351  for (size_t j = 0; j < result.size(); ++j) {
352    EXPECT_EQ(match_data[j].expected_keyword_result,
353        result.match_at(j)->associated_keyword.get() != NULL);
354  }
355}
356
357void AutocompleteProviderTest::RunAssistedQueryStatsTest(
358    const AssistedQueryStatsTestData* aqs_test_data,
359    size_t size) {
360  // Prepare input.
361  const size_t kMaxRelevance = 1000;
362  ACMatches matches;
363  for (size_t i = 0; i < size; ++i) {
364    AutocompleteMatch match(NULL, kMaxRelevance - i, false,
365                            aqs_test_data[i].match_type);
366    match.keyword = ASCIIToUTF16(kTestTemplateURLKeyword);
367    match.search_terms_args.reset(
368        new TemplateURLRef::SearchTermsArgs(string16()));
369    matches.push_back(match);
370  }
371  result_.Reset();
372  result_.AppendMatches(matches);
373
374  // Update AQS.
375  controller_->UpdateAssistedQueryStats(&result_);
376
377  // Verify data.
378  for (size_t i = 0; i < size; ++i) {
379    EXPECT_EQ(aqs_test_data[i].expected_aqs,
380              result_.match_at(i)->search_terms_args->assisted_query_stats);
381  }
382}
383
384void AutocompleteProviderTest::RunQuery(const string16 query) {
385  result_.Reset();
386  controller_->Start(query, string16(), true, false, true,
387      AutocompleteInput::ALL_MATCHES);
388
389  if (!controller_->done())
390    // The message loop will terminate when all autocomplete input has been
391    // collected.
392    MessageLoop::current()->Run();
393}
394
395void AutocompleteProviderTest::RunExactKeymatchTest(
396    bool allow_exact_keyword_match) {
397  // Send the controller input which exactly matches the keyword provider we
398  // created in ResetControllerWithKeywordAndSearchProviders().  The default
399  // match should thus be a keyword match iff |allow_exact_keyword_match| is
400  // true.
401  controller_->Start(ASCIIToUTF16("k test"), string16(), true, false,
402                     allow_exact_keyword_match,
403                     AutocompleteInput::SYNCHRONOUS_MATCHES);
404  EXPECT_TRUE(controller_->done());
405  EXPECT_EQ(allow_exact_keyword_match ?
406      AutocompleteProvider::TYPE_KEYWORD : AutocompleteProvider::TYPE_SEARCH,
407      controller_->result().default_match()->provider->type());
408}
409
410void AutocompleteProviderTest::Observe(
411    int type,
412    const content::NotificationSource& source,
413    const content::NotificationDetails& details) {
414  if (controller_->done()) {
415    result_.CopyFrom(controller_->result());
416    MessageLoop::current()->Quit();
417  }
418}
419
420// Tests that the default selection is set properly when updating results.
421TEST_F(AutocompleteProviderTest, Query) {
422  TestProvider* provider1 = NULL;
423  TestProvider* provider2 = NULL;
424  ResetControllerWithTestProviders(false, &provider1, &provider2);
425  RunTest();
426
427  // Make sure the default match gets set to the highest relevance match.  The
428  // highest relevance matches should come from the second provider.
429  EXPECT_EQ(kResultsPerProvider * 2, result_.size());  // two providers
430  ASSERT_NE(result_.end(), result_.default_match());
431  EXPECT_EQ(provider2, result_.default_match()->provider);
432}
433
434// Tests assisted query stats.
435TEST_F(AutocompleteProviderTest, AssistedQueryStats) {
436  ResetControllerWithTestProviders(false, NULL, NULL);
437  RunTest();
438
439  EXPECT_EQ(kResultsPerProvider * 2, result_.size());  // two providers
440
441  // Now, check the results from the second provider, as they should not have
442  // assisted query stats set.
443  for (size_t i = 0; i < kResultsPerProvider; ++i) {
444    EXPECT_TRUE(
445        result_.match_at(i)->search_terms_args->assisted_query_stats.empty());
446  }
447  // The first provider has a test keyword, so AQS should be non-empty.
448  for (size_t i = kResultsPerProvider; i < kResultsPerProvider * 2; ++i) {
449    EXPECT_FALSE(
450        result_.match_at(i)->search_terms_args->assisted_query_stats.empty());
451  }
452}
453
454TEST_F(AutocompleteProviderTest, RemoveDuplicates) {
455  TestProvider* provider1 = NULL;
456  TestProvider* provider2 = NULL;
457  ResetControllerWithTestProviders(true, &provider1, &provider2);
458  RunTest();
459
460  // Make sure all the first provider's results were eliminated by the second
461  // provider's.
462  EXPECT_EQ(kResultsPerProvider, result_.size());
463  for (AutocompleteResult::const_iterator i(result_.begin());
464       i != result_.end(); ++i)
465    EXPECT_EQ(provider2, i->provider);
466}
467
468TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) {
469  ResetControllerWithKeywordAndSearchProviders();
470  RunExactKeymatchTest(true);
471  RunExactKeymatchTest(false);
472}
473
474// Test that redundant associated keywords are removed.
475TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) {
476  ResetControllerWithKeywordProvider();
477
478  // Get the controller's internal members in the correct state.
479  RunQuery(ASCIIToUTF16("fo"));
480
481  {
482    KeywordTestData duplicate_url[] = {
483      { ASCIIToUTF16("fo"), string16(), false },
484      { ASCIIToUTF16("foo.com"), string16(), true },
485      { ASCIIToUTF16("foo.com"), string16(), false }
486    };
487
488    SCOPED_TRACE("Duplicate url");
489    RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url));
490  }
491
492  {
493    KeywordTestData keyword_match[] = {
494      { ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false },
495      { ASCIIToUTF16("foo.com"), string16(), false }
496    };
497
498    SCOPED_TRACE("Duplicate url with keyword match");
499    RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match));
500  }
501
502  {
503    KeywordTestData multiple_keyword[] = {
504      { ASCIIToUTF16("fo"), string16(), false },
505      { ASCIIToUTF16("foo.com"), string16(), true },
506      { ASCIIToUTF16("foo.com"), string16(), false },
507      { ASCIIToUTF16("bar.com"), string16(), true },
508    };
509
510    SCOPED_TRACE("Duplicate url with multiple keywords");
511    RunRedundantKeywordTest(multiple_keyword,
512        ARRAYSIZE_UNSAFE(multiple_keyword));
513  }
514}
515
516TEST_F(AutocompleteProviderTest, UpdateAssistedQueryStats) {
517  ResetControllerWithTestProviders(false, NULL, NULL);
518
519  {
520    AssistedQueryStatsTestData test_data[] = {
521      //  MSVC doesn't support zero-length arrays, so supply some dummy data.
522      { AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, "" }
523    };
524    SCOPED_TRACE("No matches");
525    // Note: We pass 0 here to ignore the dummy data above.
526    RunAssistedQueryStatsTest(test_data, 0);
527  }
528
529  {
530    AssistedQueryStatsTestData test_data[] = {
531      { AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, "chrome.0.57" }
532    };
533    SCOPED_TRACE("One match");
534    RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data));
535  }
536
537  {
538    AssistedQueryStatsTestData test_data[] = {
539      { AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, "chrome.0.57j58j5l2j0l3j59" },
540      { AutocompleteMatch::URL_WHAT_YOU_TYPED, "chrome.1.57j58j5l2j0l3j59" },
541      { AutocompleteMatch::NAVSUGGEST, "chrome.2.57j58j5l2j0l3j59" },
542      { AutocompleteMatch::NAVSUGGEST, "chrome.3.57j58j5l2j0l3j59" },
543      { AutocompleteMatch::SEARCH_SUGGEST, "chrome.4.57j58j5l2j0l3j59" },
544      { AutocompleteMatch::SEARCH_SUGGEST, "chrome.5.57j58j5l2j0l3j59" },
545      { AutocompleteMatch::SEARCH_SUGGEST, "chrome.6.57j58j5l2j0l3j59" },
546      { AutocompleteMatch::SEARCH_HISTORY, "chrome.7.57j58j5l2j0l3j59" },
547    };
548    SCOPED_TRACE("Multiple matches");
549    RunAssistedQueryStatsTest(test_data, ARRAYSIZE_UNSAFE(test_data));
550  }
551}
552