Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / components / omnibox / autocomplete_result_unittest.cc
blob402ee3639aca08471d2a23373a32b3740a3c2c08
1 // Copyright 2014 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.
5 #include "components/omnibox/autocomplete_result.h"
7 #include <vector>
9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/metrics/proto/omnibox_event.pb.h"
15 #include "components/omnibox/autocomplete_input.h"
16 #include "components/omnibox/autocomplete_match.h"
17 #include "components/omnibox/autocomplete_match_type.h"
18 #include "components/omnibox/autocomplete_provider.h"
19 #include "components/omnibox/omnibox_field_trial.h"
20 #include "components/omnibox/test_scheme_classifier.h"
21 #include "components/search_engines/template_url_service.h"
22 #include "components/variations/entropy_provider.h"
23 #include "components/variations/variations_associated_data.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using metrics::OmniboxEventProto;
28 namespace {
30 struct AutocompleteMatchTestData {
31 std::string destination_url;
32 AutocompleteMatch::Type type;
35 const AutocompleteMatchTestData kVerbatimMatches[] = {
36 { "http://search-what-you-typed/",
37 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
38 { "http://url-what-you-typed/", AutocompleteMatchType::URL_WHAT_YOU_TYPED },
41 const AutocompleteMatchTestData kNonVerbatimMatches[] = {
42 { "http://search-history/", AutocompleteMatchType::SEARCH_HISTORY },
43 { "http://history-title/", AutocompleteMatchType::HISTORY_TITLE },
46 // Adds |count| AutocompleteMatches to |matches|.
47 void PopulateAutocompleteMatchesFromTestData(
48 const AutocompleteMatchTestData* data,
49 size_t count,
50 ACMatches* matches) {
51 ASSERT_TRUE(matches != NULL);
52 for (size_t i = 0; i < count; ++i) {
53 AutocompleteMatch match;
54 match.destination_url = GURL(data[i].destination_url);
55 match.relevance =
56 matches->empty() ? 1300 : (matches->back().relevance - 100);
57 match.allowed_to_be_default_match = true;
58 match.type = data[i].type;
59 matches->push_back(match);
63 // A simple AutocompleteProvider that does nothing.
64 class MockAutocompleteProvider : public AutocompleteProvider {
65 public:
66 MockAutocompleteProvider(Type type): AutocompleteProvider(type) {}
68 void Start(const AutocompleteInput& input,
69 bool minimal_changes,
70 bool called_due_to_focus) override {}
72 private:
73 ~MockAutocompleteProvider() override {}
76 } // namespace
78 class AutocompleteResultTest : public testing::Test {
79 public:
80 struct TestData {
81 // Used to build a url for the AutocompleteMatch. The URL becomes
82 // "http://" + ('a' + |url_id|) (e.g. an ID of 2 yields "http://b").
83 int url_id;
85 // ID of the provider.
86 int provider_id;
88 // Relevance score.
89 int relevance;
91 // Allowed to be default match status.
92 bool allowed_to_be_default_match;
94 // Duplicate matches.
95 std::vector<AutocompleteMatch> duplicate_matches;
98 AutocompleteResultTest() {
99 // Destroy the existing FieldTrialList before creating a new one to avoid
100 // a DCHECK.
101 field_trial_list_.reset();
102 field_trial_list_.reset(new base::FieldTrialList(
103 new metrics::SHA1EntropyProvider("foo")));
104 variations::testing::ClearAllVariationParams();
106 // Create the list of mock providers. 5 is enough.
107 for (size_t i = 0; i < 5; ++i) {
108 mock_provider_list_.push_back(new MockAutocompleteProvider(
109 static_cast<AutocompleteProvider::Type>(i)));
113 void SetUp() override {
114 template_url_service_.reset(new TemplateURLService(NULL, 0));
115 template_url_service_->Load();
118 // Configures |match| from |data|.
119 void PopulateAutocompleteMatch(const TestData& data,
120 AutocompleteMatch* match);
122 // Adds |count| AutocompleteMatches to |matches|.
123 void PopulateAutocompleteMatches(const TestData* data,
124 size_t count,
125 ACMatches* matches);
127 // Asserts that |result| has |expected_count| matches matching |expected|.
128 void AssertResultMatches(const AutocompleteResult& result,
129 const TestData* expected,
130 size_t expected_count);
132 // Creates an AutocompleteResult from |last| and |current|. The two are
133 // merged by |CopyOldMatches| and compared by |AssertResultMatches|.
134 void RunCopyOldMatchesTest(const TestData* last, size_t last_size,
135 const TestData* current, size_t current_size,
136 const TestData* expected, size_t expected_size);
138 // Returns a (mock) AutocompleteProvider of given |provider_id|.
139 MockAutocompleteProvider* GetProvider(int provider_id) {
140 EXPECT_LT(provider_id, static_cast<int>(mock_provider_list_.size()));
141 return mock_provider_list_[provider_id].get();
144 protected:
145 scoped_ptr<TemplateURLService> template_url_service_;
147 private:
148 scoped_ptr<base::FieldTrialList> field_trial_list_;
150 // For every provider mentioned in TestData, we need a mock provider.
151 std::vector<scoped_refptr<MockAutocompleteProvider> > mock_provider_list_;
153 DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest);
156 void AutocompleteResultTest::PopulateAutocompleteMatch(
157 const TestData& data,
158 AutocompleteMatch* match) {
159 match->provider = GetProvider(data.provider_id);
160 match->fill_into_edit = base::IntToString16(data.url_id);
161 std::string url_id(1, data.url_id + 'a');
162 match->destination_url = GURL("http://" + url_id);
163 match->relevance = data.relevance;
164 match->allowed_to_be_default_match = data.allowed_to_be_default_match;
165 match->duplicate_matches = data.duplicate_matches;
168 void AutocompleteResultTest::PopulateAutocompleteMatches(
169 const TestData* data,
170 size_t count,
171 ACMatches* matches) {
172 for (size_t i = 0; i < count; ++i) {
173 AutocompleteMatch match;
174 PopulateAutocompleteMatch(data[i], &match);
175 matches->push_back(match);
179 void AutocompleteResultTest::AssertResultMatches(
180 const AutocompleteResult& result,
181 const TestData* expected,
182 size_t expected_count) {
183 ASSERT_EQ(expected_count, result.size());
184 for (size_t i = 0; i < expected_count; ++i) {
185 AutocompleteMatch expected_match;
186 PopulateAutocompleteMatch(expected[i], &expected_match);
187 const AutocompleteMatch& match = *(result.begin() + i);
188 EXPECT_EQ(expected_match.provider, match.provider) << i;
189 EXPECT_EQ(expected_match.relevance, match.relevance) << i;
190 EXPECT_EQ(expected_match.allowed_to_be_default_match,
191 match.allowed_to_be_default_match) << i;
192 EXPECT_EQ(expected_match.destination_url.spec(),
193 match.destination_url.spec()) << i;
197 void AutocompleteResultTest::RunCopyOldMatchesTest(
198 const TestData* last, size_t last_size,
199 const TestData* current, size_t current_size,
200 const TestData* expected, size_t expected_size) {
201 AutocompleteInput input(base::ASCIIToUTF16("a"), base::string16::npos,
202 std::string(), GURL(),
203 OmniboxEventProto::INVALID_SPEC, false, false, false,
204 true,
205 TestSchemeClassifier());
207 ACMatches last_matches;
208 PopulateAutocompleteMatches(last, last_size, &last_matches);
209 AutocompleteResult last_result;
210 last_result.AppendMatches(last_matches);
211 last_result.SortAndCull(input, template_url_service_.get());
213 ACMatches current_matches;
214 PopulateAutocompleteMatches(current, current_size, &current_matches);
215 AutocompleteResult current_result;
216 current_result.AppendMatches(current_matches);
217 current_result.SortAndCull(input, template_url_service_.get());
218 current_result.CopyOldMatches(
219 input, last_result, template_url_service_.get());
221 AssertResultMatches(current_result, expected, expected_size);
224 // Assertion testing for AutocompleteResult::Swap.
225 TEST_F(AutocompleteResultTest, Swap) {
226 AutocompleteResult r1;
227 AutocompleteResult r2;
229 // Swap with empty shouldn't do anything interesting.
230 r1.Swap(&r2);
231 EXPECT_EQ(r1.end(), r1.default_match());
232 EXPECT_EQ(r2.end(), r2.default_match());
234 // Swap with a single match.
235 ACMatches matches;
236 AutocompleteMatch match;
237 match.relevance = 1;
238 match.allowed_to_be_default_match = true;
239 AutocompleteInput input(base::ASCIIToUTF16("a"), base::string16::npos,
240 std::string(), GURL(),
241 OmniboxEventProto::INVALID_SPEC, false, false, false,
242 true, TestSchemeClassifier());
243 matches.push_back(match);
244 r1.AppendMatches(matches);
245 r1.SortAndCull(input, template_url_service_.get());
246 EXPECT_EQ(r1.begin(), r1.default_match());
247 EXPECT_EQ("http://a/", r1.alternate_nav_url().spec());
248 r1.Swap(&r2);
249 EXPECT_TRUE(r1.empty());
250 EXPECT_EQ(r1.end(), r1.default_match());
251 EXPECT_TRUE(r1.alternate_nav_url().is_empty());
252 ASSERT_FALSE(r2.empty());
253 EXPECT_EQ(r2.begin(), r2.default_match());
254 EXPECT_EQ("http://a/", r2.alternate_nav_url().spec());
257 // Tests that if the new results have a lower max relevance score than last,
258 // any copied results have their relevance shifted down.
259 TEST_F(AutocompleteResultTest, CopyOldMatches) {
260 TestData last[] = {
261 { 0, 1, 1000, true },
262 { 1, 1, 500, true },
264 TestData current[] = {
265 { 2, 1, 400, true },
267 TestData result[] = {
268 { 2, 1, 400, true },
269 { 1, 1, 399, true },
272 ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, arraysize(last),
273 current, arraysize(current),
274 result, arraysize(result)));
277 // Tests that if the new results have a lower max relevance score than last,
278 // any copied results have their relevance shifted down when the allowed to
279 // be default constraint comes into play.
280 TEST_F(AutocompleteResultTest, CopyOldMatchesAllowedToBeDefault) {
281 TestData last[] = {
282 { 0, 1, 1300, true },
283 { 1, 1, 1200, true },
284 { 2, 1, 1100, true },
286 TestData current[] = {
287 { 3, 1, 1000, false },
288 { 4, 1, 900, true },
290 // The expected results are out of relevance order because the top-scoring
291 // allowed to be default match is always pulled to the top.
292 TestData result[] = {
293 { 4, 1, 900, true },
294 { 3, 1, 1000, false },
295 { 2, 1, 899, true },
298 ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, arraysize(last),
299 current, arraysize(current),
300 result, arraysize(result)));
303 // Tests that matches are copied correctly from two distinct providers.
304 TEST_F(AutocompleteResultTest, CopyOldMatchesMultipleProviders) {
305 TestData last[] = {
306 { 0, 1, 1300, false },
307 { 1, 2, 1250, true },
308 { 2, 1, 1200, false },
309 { 3, 2, 1150, true },
310 { 4, 1, 1100, false },
312 TestData current[] = {
313 { 5, 1, 1000, false },
314 { 6, 2, 800, true },
315 { 7, 1, 500, true },
317 // The expected results are out of relevance order because the top-scoring
318 // allowed to be default match is always pulled to the top.
319 TestData result[] = {
320 { 6, 2, 800, true },
321 { 5, 1, 1000, false },
322 { 3, 2, 799, true },
323 { 7, 1, 500, true },
324 { 4, 1, 499, false },
327 ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, arraysize(last),
328 current, arraysize(current),
329 result, arraysize(result)));
332 // Tests that matches are copied correctly from two distinct providers when
333 // one provider doesn't have a current legal default match.
334 TEST_F(AutocompleteResultTest, CopyOldMatchesWithOneProviderWithoutDefault) {
335 TestData last[] = {
336 { 0, 2, 1250, true },
337 { 1, 2, 1150, true },
338 { 2, 1, 900, false },
339 { 3, 1, 800, false },
340 { 4, 1, 700, false },
342 TestData current[] = {
343 { 5, 1, 1000, true },
344 { 6, 2, 800, false },
345 { 7, 1, 500, true },
347 TestData result[] = {
348 { 5, 1, 1000, true },
349 { 1, 2, 999, true },
350 { 6, 2, 800, false },
351 { 4, 1, 700, false },
352 { 7, 1, 500, true },
355 ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last, arraysize(last),
356 current, arraysize(current),
357 result, arraysize(result)));
360 // Tests that matches with empty destination URLs aren't treated as duplicates
361 // and culled.
362 TEST_F(AutocompleteResultTest, SortAndCullEmptyDestinationURLs) {
363 TestData data[] = {
364 { 1, 1, 500, true },
365 { 0, 1, 1100, true },
366 { 1, 1, 1000, true },
367 { 0, 1, 1300, true },
368 { 0, 1, 1200, true },
371 ACMatches matches;
372 PopulateAutocompleteMatches(data, arraysize(data), &matches);
373 matches[1].destination_url = GURL();
374 matches[3].destination_url = GURL();
375 matches[4].destination_url = GURL();
377 AutocompleteResult result;
378 result.AppendMatches(matches);
379 AutocompleteInput input(base::string16(), base::string16::npos,
380 std::string(), GURL(),
381 OmniboxEventProto::INVALID_SPEC, false, false, false,
382 true,
383 TestSchemeClassifier());
384 result.SortAndCull(input, template_url_service_.get());
386 // Of the two results with the same non-empty destination URL, the
387 // lower-relevance one should be dropped. All of the results with empty URLs
388 // should be kept.
389 ASSERT_EQ(4U, result.size());
390 EXPECT_TRUE(result.match_at(0)->destination_url.is_empty());
391 EXPECT_EQ(1300, result.match_at(0)->relevance);
392 EXPECT_TRUE(result.match_at(1)->destination_url.is_empty());
393 EXPECT_EQ(1200, result.match_at(1)->relevance);
394 EXPECT_TRUE(result.match_at(2)->destination_url.is_empty());
395 EXPECT_EQ(1100, result.match_at(2)->relevance);
396 EXPECT_EQ("http://b/", result.match_at(3)->destination_url.spec());
397 EXPECT_EQ(1000, result.match_at(3)->relevance);
400 TEST_F(AutocompleteResultTest, SortAndCullDuplicateSearchURLs) {
401 // Register a template URL that corresponds to 'foo' search engine.
402 TemplateURLData url_data;
403 url_data.short_name = base::ASCIIToUTF16("unittest");
404 url_data.SetKeyword(base::ASCIIToUTF16("foo"));
405 url_data.SetURL("http://www.foo.com/s?q={searchTerms}");
406 template_url_service_.get()->Add(new TemplateURL(url_data));
408 TestData data[] = {
409 { 0, 1, 1300, true },
410 { 1, 1, 1200, true },
411 { 2, 1, 1100, true },
412 { 3, 1, 1000, true },
413 { 4, 2, 900, true },
416 ACMatches matches;
417 PopulateAutocompleteMatches(data, arraysize(data), &matches);
418 matches[0].destination_url = GURL("http://www.foo.com/s?q=foo");
419 matches[1].destination_url = GURL("http://www.foo.com/s?q=foo2");
420 matches[2].destination_url = GURL("http://www.foo.com/s?q=foo&oq=f");
421 matches[3].destination_url = GURL("http://www.foo.com/s?q=foo&aqs=0");
422 matches[4].destination_url = GURL("http://www.foo.com/");
424 AutocompleteResult result;
425 result.AppendMatches(matches);
426 AutocompleteInput input(base::string16(), base::string16::npos,
427 std::string(), GURL(),
428 OmniboxEventProto::INVALID_SPEC, false, false, false,
429 true,
430 TestSchemeClassifier());
431 result.SortAndCull(input, template_url_service_.get());
433 // We expect the 3rd and 4th results to be removed.
434 ASSERT_EQ(3U, result.size());
435 EXPECT_EQ("http://www.foo.com/s?q=foo",
436 result.match_at(0)->destination_url.spec());
437 EXPECT_EQ(1300, result.match_at(0)->relevance);
438 EXPECT_EQ("http://www.foo.com/s?q=foo2",
439 result.match_at(1)->destination_url.spec());
440 EXPECT_EQ(1200, result.match_at(1)->relevance);
441 EXPECT_EQ("http://www.foo.com/",
442 result.match_at(2)->destination_url.spec());
443 EXPECT_EQ(900, result.match_at(2)->relevance);
446 TEST_F(AutocompleteResultTest, SortAndCullWithMatchDups) {
447 // Register a template URL that corresponds to 'foo' search engine.
448 TemplateURLData url_data;
449 url_data.short_name = base::ASCIIToUTF16("unittest");
450 url_data.SetKeyword(base::ASCIIToUTF16("foo"));
451 url_data.SetURL("http://www.foo.com/s?q={searchTerms}");
452 template_url_service_.get()->Add(new TemplateURL(url_data));
454 AutocompleteMatch dup_match;
455 dup_match.destination_url = GURL("http://www.foo.com/s?q=foo&oq=dup");
456 std::vector<AutocompleteMatch> dups;
457 dups.push_back(dup_match);
459 TestData data[] = {
460 { 0, 1, 1300, true, dups },
461 { 1, 1, 1200, true },
462 { 2, 1, 1100, true },
463 { 3, 1, 1000, true, dups },
464 { 4, 2, 900, true },
465 { 5, 1, 800, true },
468 ACMatches matches;
469 PopulateAutocompleteMatches(data, arraysize(data), &matches);
470 matches[0].destination_url = GURL("http://www.foo.com/s?q=foo");
471 matches[1].destination_url = GURL("http://www.foo.com/s?q=foo2");
472 matches[2].destination_url = GURL("http://www.foo.com/s?q=foo&oq=f");
473 matches[3].destination_url = GURL("http://www.foo.com/s?q=foo&aqs=0");
474 matches[4].destination_url = GURL("http://www.foo.com/");
475 matches[5].destination_url = GURL("http://www.foo.com/s?q=foo2&oq=f");
477 AutocompleteResult result;
478 result.AppendMatches(matches);
479 AutocompleteInput input(base::string16(), base::string16::npos,
480 std::string(), GURL(),
481 OmniboxEventProto::INVALID_SPEC, false, false, false,
482 true,
483 TestSchemeClassifier());
484 result.SortAndCull(input, template_url_service_.get());
486 // Expect 3 unique results after SortAndCull().
487 ASSERT_EQ(3U, result.size());
489 // Check that 3rd and 4th result got added to the first result as dups
490 // and also duplicates of the 4th match got copied.
491 ASSERT_EQ(4U, result.match_at(0)->duplicate_matches.size());
492 const AutocompleteMatch* first_match = result.match_at(0);
493 EXPECT_EQ(matches[2].destination_url,
494 first_match->duplicate_matches.at(1).destination_url);
495 EXPECT_EQ(dup_match.destination_url,
496 first_match->duplicate_matches.at(2).destination_url);
497 EXPECT_EQ(matches[3].destination_url,
498 first_match->duplicate_matches.at(3).destination_url);
500 // Check that 6th result started a new list of dups for the second result.
501 ASSERT_EQ(1U, result.match_at(1)->duplicate_matches.size());
502 EXPECT_EQ(matches[5].destination_url,
503 result.match_at(1)->duplicate_matches.at(0).destination_url);
506 TEST_F(AutocompleteResultTest, SortAndCullWithDemotionsByType) {
507 // Add some matches.
508 ACMatches matches;
509 const AutocompleteMatchTestData data[] = {
510 { "http://history-url/", AutocompleteMatchType::HISTORY_URL },
511 { "http://search-what-you-typed/",
512 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
513 { "http://history-title/", AutocompleteMatchType::HISTORY_TITLE },
514 { "http://search-history/", AutocompleteMatchType::SEARCH_HISTORY },
516 PopulateAutocompleteMatchesFromTestData(data, arraysize(data), &matches);
518 // Demote the search history match relevance score.
519 matches.back().relevance = 500;
521 // Add a rule demoting history-url and killing history-title.
523 std::map<std::string, std::string> params;
524 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":3:*"] =
525 "1:50,7:100,2:0"; // 3 == HOME_PAGE
526 ASSERT_TRUE(variations::AssociateVariationParams(
527 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params));
529 base::FieldTrialList::CreateFieldTrial(
530 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A");
532 AutocompleteResult result;
533 result.AppendMatches(matches);
534 AutocompleteInput input(base::string16(), base::string16::npos,
535 std::string(), GURL(),
536 OmniboxEventProto::HOME_PAGE, false, false, false,
537 true,
538 TestSchemeClassifier());
539 result.SortAndCull(input, template_url_service_.get());
541 // Check the new ordering. The history-title results should be omitted.
542 // We cannot check relevance scores because the matches are sorted by
543 // demoted relevance but the actual relevance scores are not modified.
544 ASSERT_EQ(3u, result.size());
545 EXPECT_EQ("http://search-what-you-typed/",
546 result.match_at(0)->destination_url.spec());
547 EXPECT_EQ("http://history-url/",
548 result.match_at(1)->destination_url.spec());
549 EXPECT_EQ("http://search-history/",
550 result.match_at(2)->destination_url.spec());
553 TEST_F(AutocompleteResultTest, SortAndCullWithMatchDupsAndDemotionsByType) {
554 // Add some matches.
555 ACMatches matches;
556 const AutocompleteMatchTestData data[] = {
557 { "http://search-what-you-typed/",
558 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED },
559 { "http://dup-url/", AutocompleteMatchType::HISTORY_URL },
560 { "http://dup-url/", AutocompleteMatchType::NAVSUGGEST },
561 { "http://search-url/", AutocompleteMatchType::SEARCH_SUGGEST },
562 { "http://history-url/", AutocompleteMatchType::HISTORY_URL },
564 PopulateAutocompleteMatchesFromTestData(data, arraysize(data), &matches);
566 // Add a rule demoting HISTORY_URL.
568 std::map<std::string, std::string> params;
569 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":8:*"] =
570 "1:50"; // 8 == INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS
571 ASSERT_TRUE(variations::AssociateVariationParams(
572 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "C", params));
574 base::FieldTrialList::CreateFieldTrial(
575 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "C");
578 AutocompleteResult result;
579 result.AppendMatches(matches);
580 AutocompleteInput input(
581 base::string16(), base::string16::npos, std::string(), GURL(),
582 OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS, false,
583 false, false, true,
584 TestSchemeClassifier());
585 result.SortAndCull(input, template_url_service_.get());
587 // The NAVSUGGEST dup-url stay above search-url since the navsuggest
588 // variant should not be demoted.
589 ASSERT_EQ(4u, result.size());
590 EXPECT_EQ("http://search-what-you-typed/",
591 result.match_at(0)->destination_url.spec());
592 EXPECT_EQ("http://dup-url/",
593 result.match_at(1)->destination_url.spec());
594 EXPECT_EQ(AutocompleteMatchType::NAVSUGGEST,
595 result.match_at(1)->type);
596 EXPECT_EQ("http://search-url/",
597 result.match_at(2)->destination_url.spec());
598 EXPECT_EQ("http://history-url/",
599 result.match_at(3)->destination_url.spec());
603 TEST_F(AutocompleteResultTest, SortAndCullReorderForDefaultMatch) {
604 TestData data[] = {
605 { 0, 1, 1300, true },
606 { 1, 1, 1200, true },
607 { 2, 1, 1100, true },
608 { 3, 1, 1000, true }
612 // Check that reorder doesn't do anything if the top result
613 // is already a legal default match (which is the default from
614 // PopulateAutocompleteMatches()).
615 ACMatches matches;
616 PopulateAutocompleteMatches(data, arraysize(data), &matches);
617 AutocompleteResult result;
618 result.AppendMatches(matches);
619 AutocompleteInput input(base::string16(), base::string16::npos,
620 std::string(), GURL(),
621 OmniboxEventProto::HOME_PAGE, false, false, false,
622 true,
623 TestSchemeClassifier());
624 result.SortAndCull(input, template_url_service_.get());
625 AssertResultMatches(result, data, 4);
629 // Check that reorder swaps up a result appropriately.
630 ACMatches matches;
631 PopulateAutocompleteMatches(data, arraysize(data), &matches);
632 matches[0].allowed_to_be_default_match = false;
633 matches[1].allowed_to_be_default_match = false;
634 AutocompleteResult result;
635 result.AppendMatches(matches);
636 AutocompleteInput input(base::string16(), base::string16::npos,
637 std::string(), GURL(),
638 OmniboxEventProto::HOME_PAGE, false, false, false,
639 true,
640 TestSchemeClassifier());
641 result.SortAndCull(input, template_url_service_.get());
642 ASSERT_EQ(4U, result.size());
643 EXPECT_EQ("http://c/", result.match_at(0)->destination_url.spec());
644 EXPECT_EQ("http://a/", result.match_at(1)->destination_url.spec());
645 EXPECT_EQ("http://b/", result.match_at(2)->destination_url.spec());
646 EXPECT_EQ("http://d/", result.match_at(3)->destination_url.spec());
650 TEST_F(AutocompleteResultTest, ShouldHideTopMatch) {
651 base::FieldTrialList::CreateFieldTrial("InstantExtended",
652 "Group1 hide_verbatim:1");
653 ACMatches matches;
655 // Case 1: Top match is a verbatim match.
656 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
657 AutocompleteResult result;
658 result.AppendMatches(matches);
659 EXPECT_TRUE(result.ShouldHideTopMatch());
660 matches.clear();
661 result.Reset();
663 // Case 2: If the verbatim first match is followed by another verbatim match,
664 // don't hide the top verbatim match.
665 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
666 arraysize(kVerbatimMatches),
667 &matches);
668 result.AppendMatches(matches);
669 EXPECT_FALSE(result.ShouldHideTopMatch());
670 matches.clear();
671 result.Reset();
673 // Case 3: Top match is not a verbatim match. Do not hide the top match.
674 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches, 1, &matches);
675 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
676 arraysize(kVerbatimMatches),
677 &matches);
678 result.AppendMatches(matches);
679 EXPECT_FALSE(result.ShouldHideTopMatch());
682 TEST_F(AutocompleteResultTest, ShouldHideTopMatchAfterCopy) {
683 base::FieldTrialList::CreateFieldTrial("InstantExtended",
684 "Group1 hide_verbatim:1");
685 ACMatches matches;
687 // Case 1: Top match is a verbatim match followed by only copied matches.
688 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
689 arraysize(kVerbatimMatches),
690 &matches);
691 for (size_t i = 1; i < arraysize(kVerbatimMatches); ++i)
692 matches[i].from_previous = true;
693 AutocompleteResult result;
694 result.AppendMatches(matches);
695 EXPECT_TRUE(result.ShouldHideTopMatch());
696 result.Reset();
698 // Case 2: The copied matches are then followed by a non-verbatim match.
699 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches, 1, &matches);
700 result.AppendMatches(matches);
701 EXPECT_TRUE(result.ShouldHideTopMatch());
702 result.Reset();
704 // Case 3: The copied matches are instead followed by a verbatim match.
705 matches.back().from_previous = true;
706 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
707 result.AppendMatches(matches);
708 EXPECT_FALSE(result.ShouldHideTopMatch());
711 TEST_F(AutocompleteResultTest, DoNotHideTopMatch_FieldTrialFlagDisabled) {
712 // This test config is identical to ShouldHideTopMatch test ("Case 1") except
713 // that the "hide_verbatim" flag is disabled in the field trials.
714 base::FieldTrialList::CreateFieldTrial("InstantExtended",
715 "Group1 hide_verbatim:0");
716 ACMatches matches;
717 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
718 AutocompleteResult result;
719 result.AppendMatches(matches);
720 // Field trial flag "hide_verbatim" is disabled. Do not hide top match.
721 EXPECT_FALSE(result.ShouldHideTopMatch());
724 TEST_F(AutocompleteResultTest, TopMatchIsStandaloneVerbatimMatch) {
725 ACMatches matches;
726 AutocompleteResult result;
727 result.AppendMatches(matches);
729 // Case 1: Result set is empty.
730 EXPECT_FALSE(result.TopMatchIsStandaloneVerbatimMatch());
732 // Case 2: Top match is not a verbatim match.
733 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches, 1, &matches);
734 result.AppendMatches(matches);
735 EXPECT_FALSE(result.TopMatchIsStandaloneVerbatimMatch());
736 result.Reset();
737 matches.clear();
739 // Case 3: Top match is a verbatim match.
740 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
741 result.AppendMatches(matches);
742 EXPECT_TRUE(result.TopMatchIsStandaloneVerbatimMatch());
743 result.Reset();
744 matches.clear();
746 // Case 4: Standalone verbatim match found in AutocompleteResult.
747 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
748 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches, 1, &matches);
749 result.AppendMatches(matches);
750 EXPECT_TRUE(result.TopMatchIsStandaloneVerbatimMatch());
751 result.Reset();
752 matches.clear();
754 // Case 5: Multiple verbatim matches found in AutocompleteResult.
755 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
756 arraysize(kVerbatimMatches),
757 &matches);
758 result.AppendMatches(matches);
759 EXPECT_FALSE(result.ShouldHideTopMatch());