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"
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
;
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
,
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
);
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
);
65 class AutocompleteResultTest
: public testing::Test
{
68 // Used to build a url for the AutocompleteMatch. The URL becomes
69 // "http://" + ('a' + |url_id|) (e.g. an ID of 2 yields "http://b").
72 // ID of the provider.
79 std::vector
<AutocompleteMatch
> duplicate_matches
;
82 AutocompleteResultTest() {
83 // Destroy the existing FieldTrialList before creating a new one to avoid
85 field_trial_list_
.reset();
86 field_trial_list_
.reset(new base::FieldTrialList(
87 new metrics::SHA1EntropyProvider("foo")));
88 variations::testing::ClearAllVariationParams();
91 void SetUp() override
{
92 template_url_service_
.reset(new TemplateURLService(NULL
, 0));
93 template_url_service_
->Load();
96 // Configures |match| from |data|.
97 static void PopulateAutocompleteMatch(const TestData
& data
,
98 AutocompleteMatch
* match
);
100 // Adds |count| AutocompleteMatches to |matches|.
101 static void PopulateAutocompleteMatches(const TestData
* data
,
105 // Asserts that |result| has |expected_count| matches matching |expected|.
106 void AssertResultMatches(const AutocompleteResult
& result
,
107 const TestData
* expected
,
108 size_t expected_count
);
110 // Creates an AutocompleteResult from |last| and |current|. The two are
111 // merged by |CopyOldMatches| and compared by |AssertResultMatches|.
112 void RunCopyOldMatchesTest(const TestData
* last
, size_t last_size
,
113 const TestData
* current
, size_t current_size
,
114 const TestData
* expected
, size_t expected_size
);
117 scoped_ptr
<TemplateURLService
> template_url_service_
;
120 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
122 DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest
);
126 void AutocompleteResultTest::PopulateAutocompleteMatch(
127 const TestData
& data
,
128 AutocompleteMatch
* match
) {
129 match
->provider
= reinterpret_cast<AutocompleteProvider
*>(data
.provider_id
);
130 match
->fill_into_edit
= base::IntToString16(data
.url_id
);
131 std::string
url_id(1, data
.url_id
+ 'a');
132 match
->destination_url
= GURL("http://" + url_id
);
133 match
->relevance
= data
.relevance
;
134 match
->allowed_to_be_default_match
= true;
135 match
->duplicate_matches
= data
.duplicate_matches
;
139 void AutocompleteResultTest::PopulateAutocompleteMatches(
140 const TestData
* data
,
142 ACMatches
* matches
) {
143 for (size_t i
= 0; i
< count
; ++i
) {
144 AutocompleteMatch match
;
145 PopulateAutocompleteMatch(data
[i
], &match
);
146 matches
->push_back(match
);
150 void AutocompleteResultTest::AssertResultMatches(
151 const AutocompleteResult
& result
,
152 const TestData
* expected
,
153 size_t expected_count
) {
154 ASSERT_EQ(expected_count
, result
.size());
155 for (size_t i
= 0; i
< expected_count
; ++i
) {
156 AutocompleteMatch expected_match
;
157 PopulateAutocompleteMatch(expected
[i
], &expected_match
);
158 const AutocompleteMatch
& match
= *(result
.begin() + i
);
159 EXPECT_EQ(expected_match
.provider
, match
.provider
) << i
;
160 EXPECT_EQ(expected_match
.relevance
, match
.relevance
) << i
;
161 EXPECT_EQ(expected_match
.destination_url
.spec(),
162 match
.destination_url
.spec()) << i
;
166 void AutocompleteResultTest::RunCopyOldMatchesTest(
167 const TestData
* last
, size_t last_size
,
168 const TestData
* current
, size_t current_size
,
169 const TestData
* expected
, size_t expected_size
) {
170 AutocompleteInput
input(base::ASCIIToUTF16("a"), base::string16::npos
,
171 std::string(), GURL(),
172 OmniboxEventProto::INVALID_SPEC
, false, false, false,
174 TestSchemeClassifier());
176 ACMatches last_matches
;
177 PopulateAutocompleteMatches(last
, last_size
, &last_matches
);
178 AutocompleteResult last_result
;
179 last_result
.AppendMatches(last_matches
);
180 last_result
.SortAndCull(input
, template_url_service_
.get());
182 ACMatches current_matches
;
183 PopulateAutocompleteMatches(current
, current_size
, ¤t_matches
);
184 AutocompleteResult current_result
;
185 current_result
.AppendMatches(current_matches
);
186 current_result
.SortAndCull(input
, template_url_service_
.get());
187 current_result
.CopyOldMatches(
188 input
, last_result
, template_url_service_
.get());
190 AssertResultMatches(current_result
, expected
, expected_size
);
193 // Assertion testing for AutocompleteResult::Swap.
194 TEST_F(AutocompleteResultTest
, Swap
) {
195 AutocompleteResult r1
;
196 AutocompleteResult r2
;
198 // Swap with empty shouldn't do anything interesting.
200 EXPECT_EQ(r1
.end(), r1
.default_match());
201 EXPECT_EQ(r2
.end(), r2
.default_match());
203 // Swap with a single match.
205 AutocompleteMatch match
;
207 match
.allowed_to_be_default_match
= true;
208 AutocompleteInput
input(base::ASCIIToUTF16("a"), base::string16::npos
,
209 std::string(), GURL(),
210 OmniboxEventProto::INVALID_SPEC
, false, false, false,
211 true, TestSchemeClassifier());
212 matches
.push_back(match
);
213 r1
.AppendMatches(matches
);
214 r1
.SortAndCull(input
, template_url_service_
.get());
215 EXPECT_EQ(r1
.begin(), r1
.default_match());
216 EXPECT_EQ("http://a/", r1
.alternate_nav_url().spec());
218 EXPECT_TRUE(r1
.empty());
219 EXPECT_EQ(r1
.end(), r1
.default_match());
220 EXPECT_TRUE(r1
.alternate_nav_url().is_empty());
221 ASSERT_FALSE(r2
.empty());
222 EXPECT_EQ(r2
.begin(), r2
.default_match());
223 EXPECT_EQ("http://a/", r2
.alternate_nav_url().spec());
226 // Tests that if the new results have a lower max relevance score than last,
227 // any copied results have their relevance shifted down.
228 TEST_F(AutocompleteResultTest
, CopyOldMatches
) {
233 TestData current
[] = {
236 TestData result
[] = {
241 ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last
, arraysize(last
),
242 current
, arraysize(current
),
243 result
, arraysize(result
)));
246 // Tests that matches are copied correctly from two distinct providers.
247 TEST_F(AutocompleteResultTest
, CopyOldMatches2
) {
254 TestData current
[] = {
258 TestData result
[] = {
265 ASSERT_NO_FATAL_FAILURE(RunCopyOldMatchesTest(last
, arraysize(last
),
266 current
, arraysize(current
),
267 result
, arraysize(result
)));
270 // Tests that matches with empty destination URLs aren't treated as duplicates
272 TEST_F(AutocompleteResultTest
, SortAndCullEmptyDestinationURLs
) {
282 PopulateAutocompleteMatches(data
, arraysize(data
), &matches
);
283 matches
[1].destination_url
= GURL();
284 matches
[3].destination_url
= GURL();
285 matches
[4].destination_url
= GURL();
287 AutocompleteResult result
;
288 result
.AppendMatches(matches
);
289 AutocompleteInput
input(base::string16(), base::string16::npos
,
290 std::string(), GURL(),
291 OmniboxEventProto::INVALID_SPEC
, false, false, false,
293 TestSchemeClassifier());
294 result
.SortAndCull(input
, template_url_service_
.get());
296 // Of the two results with the same non-empty destination URL, the
297 // lower-relevance one should be dropped. All of the results with empty URLs
299 ASSERT_EQ(4U, result
.size());
300 EXPECT_TRUE(result
.match_at(0)->destination_url
.is_empty());
301 EXPECT_EQ(1300, result
.match_at(0)->relevance
);
302 EXPECT_TRUE(result
.match_at(1)->destination_url
.is_empty());
303 EXPECT_EQ(1200, result
.match_at(1)->relevance
);
304 EXPECT_TRUE(result
.match_at(2)->destination_url
.is_empty());
305 EXPECT_EQ(1100, result
.match_at(2)->relevance
);
306 EXPECT_EQ("http://b/", result
.match_at(3)->destination_url
.spec());
307 EXPECT_EQ(1000, result
.match_at(3)->relevance
);
310 TEST_F(AutocompleteResultTest
, SortAndCullDuplicateSearchURLs
) {
311 // Register a template URL that corresponds to 'foo' search engine.
312 TemplateURLData url_data
;
313 url_data
.short_name
= base::ASCIIToUTF16("unittest");
314 url_data
.SetKeyword(base::ASCIIToUTF16("foo"));
315 url_data
.SetURL("http://www.foo.com/s?q={searchTerms}");
316 template_url_service_
.get()->Add(new TemplateURL(url_data
));
327 PopulateAutocompleteMatches(data
, arraysize(data
), &matches
);
328 matches
[0].destination_url
= GURL("http://www.foo.com/s?q=foo");
329 matches
[1].destination_url
= GURL("http://www.foo.com/s?q=foo2");
330 matches
[2].destination_url
= GURL("http://www.foo.com/s?q=foo&oq=f");
331 matches
[3].destination_url
= GURL("http://www.foo.com/s?q=foo&aqs=0");
332 matches
[4].destination_url
= GURL("http://www.foo.com/");
334 AutocompleteResult result
;
335 result
.AppendMatches(matches
);
336 AutocompleteInput
input(base::string16(), base::string16::npos
,
337 std::string(), GURL(),
338 OmniboxEventProto::INVALID_SPEC
, false, false, false,
340 TestSchemeClassifier());
341 result
.SortAndCull(input
, template_url_service_
.get());
343 // We expect the 3rd and 4th results to be removed.
344 ASSERT_EQ(3U, result
.size());
345 EXPECT_EQ("http://www.foo.com/s?q=foo",
346 result
.match_at(0)->destination_url
.spec());
347 EXPECT_EQ(1300, result
.match_at(0)->relevance
);
348 EXPECT_EQ("http://www.foo.com/s?q=foo2",
349 result
.match_at(1)->destination_url
.spec());
350 EXPECT_EQ(1200, result
.match_at(1)->relevance
);
351 EXPECT_EQ("http://www.foo.com/",
352 result
.match_at(2)->destination_url
.spec());
353 EXPECT_EQ(900, result
.match_at(2)->relevance
);
356 TEST_F(AutocompleteResultTest
, SortAndCullWithMatchDups
) {
357 // Register a template URL that corresponds to 'foo' search engine.
358 TemplateURLData url_data
;
359 url_data
.short_name
= base::ASCIIToUTF16("unittest");
360 url_data
.SetKeyword(base::ASCIIToUTF16("foo"));
361 url_data
.SetURL("http://www.foo.com/s?q={searchTerms}");
362 template_url_service_
.get()->Add(new TemplateURL(url_data
));
364 AutocompleteMatch dup_match
;
365 dup_match
.destination_url
= GURL("http://www.foo.com/s?q=foo&oq=dup");
366 std::vector
<AutocompleteMatch
> dups
;
367 dups
.push_back(dup_match
);
370 { 0, 0, 1300, dups
},
373 { 3, 0, 1000, dups
},
379 PopulateAutocompleteMatches(data
, arraysize(data
), &matches
);
380 matches
[0].destination_url
= GURL("http://www.foo.com/s?q=foo");
381 matches
[1].destination_url
= GURL("http://www.foo.com/s?q=foo2");
382 matches
[2].destination_url
= GURL("http://www.foo.com/s?q=foo&oq=f");
383 matches
[3].destination_url
= GURL("http://www.foo.com/s?q=foo&aqs=0");
384 matches
[4].destination_url
= GURL("http://www.foo.com/");
385 matches
[5].destination_url
= GURL("http://www.foo.com/s?q=foo2&oq=f");
387 AutocompleteResult result
;
388 result
.AppendMatches(matches
);
389 AutocompleteInput
input(base::string16(), base::string16::npos
,
390 std::string(), GURL(),
391 OmniboxEventProto::INVALID_SPEC
, false, false, false,
393 TestSchemeClassifier());
394 result
.SortAndCull(input
, template_url_service_
.get());
396 // Expect 3 unique results after SortAndCull().
397 ASSERT_EQ(3U, result
.size());
399 // Check that 3rd and 4th result got added to the first result as dups
400 // and also duplicates of the 4th match got copied.
401 ASSERT_EQ(4U, result
.match_at(0)->duplicate_matches
.size());
402 const AutocompleteMatch
* first_match
= result
.match_at(0);
403 EXPECT_EQ(matches
[2].destination_url
,
404 first_match
->duplicate_matches
.at(1).destination_url
);
405 EXPECT_EQ(dup_match
.destination_url
,
406 first_match
->duplicate_matches
.at(2).destination_url
);
407 EXPECT_EQ(matches
[3].destination_url
,
408 first_match
->duplicate_matches
.at(3).destination_url
);
410 // Check that 6th result started a new list of dups for the second result.
411 ASSERT_EQ(1U, result
.match_at(1)->duplicate_matches
.size());
412 EXPECT_EQ(matches
[5].destination_url
,
413 result
.match_at(1)->duplicate_matches
.at(0).destination_url
);
416 TEST_F(AutocompleteResultTest
, SortAndCullWithDemotionsByType
) {
419 const AutocompleteMatchTestData data
[] = {
420 { "http://history-url/", AutocompleteMatchType::HISTORY_URL
},
421 { "http://search-what-you-typed/",
422 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED
},
423 { "http://history-title/", AutocompleteMatchType::HISTORY_TITLE
},
424 { "http://search-history/", AutocompleteMatchType::SEARCH_HISTORY
},
426 PopulateAutocompleteMatchesFromTestData(data
, arraysize(data
), &matches
);
428 // Demote the search history match relevance score.
429 matches
.back().relevance
= 500;
431 // Add a rule demoting history-url and killing history-title.
433 std::map
<std::string
, std::string
> params
;
434 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":3:*"] =
435 "1:50,7:100,2:0"; // 3 == HOME_PAGE
436 ASSERT_TRUE(variations::AssociateVariationParams(
437 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
439 base::FieldTrialList::CreateFieldTrial(
440 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
442 AutocompleteResult result
;
443 result
.AppendMatches(matches
);
444 AutocompleteInput
input(base::string16(), base::string16::npos
,
445 std::string(), GURL(),
446 OmniboxEventProto::HOME_PAGE
, false, false, false,
448 TestSchemeClassifier());
449 result
.SortAndCull(input
, template_url_service_
.get());
451 // Check the new ordering. The history-title results should be omitted.
452 // We cannot check relevance scores because the matches are sorted by
453 // demoted relevance but the actual relevance scores are not modified.
454 ASSERT_EQ(3u, result
.size());
455 EXPECT_EQ("http://search-what-you-typed/",
456 result
.match_at(0)->destination_url
.spec());
457 EXPECT_EQ("http://history-url/",
458 result
.match_at(1)->destination_url
.spec());
459 EXPECT_EQ("http://search-history/",
460 result
.match_at(2)->destination_url
.spec());
463 TEST_F(AutocompleteResultTest
, SortAndCullWithMatchDupsAndDemotionsByType
) {
466 const AutocompleteMatchTestData data
[] = {
467 { "http://search-what-you-typed/",
468 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED
},
469 { "http://dup-url/", AutocompleteMatchType::HISTORY_URL
},
470 { "http://dup-url/", AutocompleteMatchType::NAVSUGGEST
},
471 { "http://search-url/", AutocompleteMatchType::SEARCH_SUGGEST
},
472 { "http://history-url/", AutocompleteMatchType::HISTORY_URL
},
474 PopulateAutocompleteMatchesFromTestData(data
, arraysize(data
), &matches
);
476 // Add a rule demoting HISTORY_URL.
478 std::map
<std::string
, std::string
> params
;
479 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":8:*"] =
480 "1:50"; // 8 == INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS
481 ASSERT_TRUE(variations::AssociateVariationParams(
482 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "C", params
));
484 base::FieldTrialList::CreateFieldTrial(
485 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "C");
488 AutocompleteResult result
;
489 result
.AppendMatches(matches
);
490 AutocompleteInput
input(
491 base::string16(), base::string16::npos
, std::string(), GURL(),
492 OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS
, false,
494 TestSchemeClassifier());
495 result
.SortAndCull(input
, template_url_service_
.get());
497 // The NAVSUGGEST dup-url stay above search-url since the navsuggest
498 // variant should not be demoted.
499 ASSERT_EQ(4u, result
.size());
500 EXPECT_EQ("http://search-what-you-typed/",
501 result
.match_at(0)->destination_url
.spec());
502 EXPECT_EQ("http://dup-url/",
503 result
.match_at(1)->destination_url
.spec());
504 EXPECT_EQ(AutocompleteMatchType::NAVSUGGEST
,
505 result
.match_at(1)->type
);
506 EXPECT_EQ("http://search-url/",
507 result
.match_at(2)->destination_url
.spec());
508 EXPECT_EQ("http://history-url/",
509 result
.match_at(3)->destination_url
.spec());
513 TEST_F(AutocompleteResultTest
, SortAndCullReorderForDefaultMatch
) {
522 // Check that reorder doesn't do anything if the top result
523 // is already a legal default match (which is the default from
524 // PopulateAutocompleteMatches()).
526 PopulateAutocompleteMatches(data
, arraysize(data
), &matches
);
527 AutocompleteResult result
;
528 result
.AppendMatches(matches
);
529 AutocompleteInput
input(base::string16(), base::string16::npos
,
530 std::string(), GURL(),
531 OmniboxEventProto::HOME_PAGE
, false, false, false,
533 TestSchemeClassifier());
534 result
.SortAndCull(input
, template_url_service_
.get());
535 AssertResultMatches(result
, data
, 4);
539 // Check that reorder swaps up a result appropriately.
541 PopulateAutocompleteMatches(data
, arraysize(data
), &matches
);
542 matches
[0].allowed_to_be_default_match
= false;
543 matches
[1].allowed_to_be_default_match
= false;
544 AutocompleteResult result
;
545 result
.AppendMatches(matches
);
546 AutocompleteInput
input(base::string16(), base::string16::npos
,
547 std::string(), GURL(),
548 OmniboxEventProto::HOME_PAGE
, false, false, false,
550 TestSchemeClassifier());
551 result
.SortAndCull(input
, template_url_service_
.get());
552 ASSERT_EQ(4U, result
.size());
553 EXPECT_EQ("http://c/", result
.match_at(0)->destination_url
.spec());
554 EXPECT_EQ("http://a/", result
.match_at(1)->destination_url
.spec());
555 EXPECT_EQ("http://b/", result
.match_at(2)->destination_url
.spec());
556 EXPECT_EQ("http://d/", result
.match_at(3)->destination_url
.spec());
560 TEST_F(AutocompleteResultTest
, ShouldHideTopMatch
) {
561 base::FieldTrialList::CreateFieldTrial("InstantExtended",
562 "Group1 hide_verbatim:1");
565 // Case 1: Top match is a verbatim match.
566 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
, 1, &matches
);
567 AutocompleteResult result
;
568 result
.AppendMatches(matches
);
569 EXPECT_TRUE(result
.ShouldHideTopMatch());
573 // Case 2: If the verbatim first match is followed by another verbatim match,
574 // don't hide the top verbatim match.
575 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
,
576 arraysize(kVerbatimMatches
),
578 result
.AppendMatches(matches
);
579 EXPECT_FALSE(result
.ShouldHideTopMatch());
583 // Case 3: Top match is not a verbatim match. Do not hide the top match.
584 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches
, 1, &matches
);
585 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
,
586 arraysize(kVerbatimMatches
),
588 result
.AppendMatches(matches
);
589 EXPECT_FALSE(result
.ShouldHideTopMatch());
592 TEST_F(AutocompleteResultTest
, ShouldHideTopMatchAfterCopy
) {
593 base::FieldTrialList::CreateFieldTrial("InstantExtended",
594 "Group1 hide_verbatim:1");
597 // Case 1: Top match is a verbatim match followed by only copied matches.
598 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
,
599 arraysize(kVerbatimMatches
),
601 for (size_t i
= 1; i
< arraysize(kVerbatimMatches
); ++i
)
602 matches
[i
].from_previous
= true;
603 AutocompleteResult result
;
604 result
.AppendMatches(matches
);
605 EXPECT_TRUE(result
.ShouldHideTopMatch());
608 // Case 2: The copied matches are then followed by a non-verbatim match.
609 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches
, 1, &matches
);
610 result
.AppendMatches(matches
);
611 EXPECT_TRUE(result
.ShouldHideTopMatch());
614 // Case 3: The copied matches are instead followed by a verbatim match.
615 matches
.back().from_previous
= true;
616 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
, 1, &matches
);
617 result
.AppendMatches(matches
);
618 EXPECT_FALSE(result
.ShouldHideTopMatch());
621 TEST_F(AutocompleteResultTest
, DoNotHideTopMatch_FieldTrialFlagDisabled
) {
622 // This test config is identical to ShouldHideTopMatch test ("Case 1") except
623 // that the "hide_verbatim" flag is disabled in the field trials.
624 base::FieldTrialList::CreateFieldTrial("InstantExtended",
625 "Group1 hide_verbatim:0");
627 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
, 1, &matches
);
628 AutocompleteResult result
;
629 result
.AppendMatches(matches
);
630 // Field trial flag "hide_verbatim" is disabled. Do not hide top match.
631 EXPECT_FALSE(result
.ShouldHideTopMatch());
634 TEST_F(AutocompleteResultTest
, TopMatchIsStandaloneVerbatimMatch
) {
636 AutocompleteResult result
;
637 result
.AppendMatches(matches
);
639 // Case 1: Result set is empty.
640 EXPECT_FALSE(result
.TopMatchIsStandaloneVerbatimMatch());
642 // Case 2: Top match is not a verbatim match.
643 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches
, 1, &matches
);
644 result
.AppendMatches(matches
);
645 EXPECT_FALSE(result
.TopMatchIsStandaloneVerbatimMatch());
649 // Case 3: Top match is a verbatim match.
650 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
, 1, &matches
);
651 result
.AppendMatches(matches
);
652 EXPECT_TRUE(result
.TopMatchIsStandaloneVerbatimMatch());
656 // Case 4: Standalone verbatim match found in AutocompleteResult.
657 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
, 1, &matches
);
658 PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches
, 1, &matches
);
659 result
.AppendMatches(matches
);
660 EXPECT_TRUE(result
.TopMatchIsStandaloneVerbatimMatch());
664 // Case 5: Multiple verbatim matches found in AutocompleteResult.
665 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches
,
666 arraysize(kVerbatimMatches
),
668 result
.AppendMatches(matches
);
669 EXPECT_FALSE(result
.ShouldHideTopMatch());