Fix experimental app list search box disappearing on profile switch.
[chromium-blink-merge.git] / components / omnibox / autocomplete_result_unittest.cc
blobc7ce401b9a2fcfcb434501448bfc480c75281e0e
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 } // namespace
65 class AutocompleteResultTest : public testing::Test {
66 public:
67 struct TestData {
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").
70 int url_id;
72 // ID of the provider.
73 int provider_id;
75 // Relevance score.
76 int relevance;
78 // Duplicate matches.
79 std::vector<AutocompleteMatch> duplicate_matches;
82 AutocompleteResultTest() {
83 // Destroy the existing FieldTrialList before creating a new one to avoid
84 // a DCHECK.
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,
102 size_t count,
103 ACMatches* matches);
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);
116 protected:
117 scoped_ptr<TemplateURLService> template_url_service_;
119 private:
120 scoped_ptr<base::FieldTrialList> field_trial_list_;
122 DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest);
125 // static
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;
138 // static
139 void AutocompleteResultTest::PopulateAutocompleteMatches(
140 const TestData* data,
141 size_t count,
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,
173 true,
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, &current_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.
199 r1.Swap(&r2);
200 EXPECT_EQ(r1.end(), r1.default_match());
201 EXPECT_EQ(r2.end(), r2.default_match());
203 // Swap with a single match.
204 ACMatches matches;
205 AutocompleteMatch match;
206 match.relevance = 1;
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());
217 r1.Swap(&r2);
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) {
229 TestData last[] = {
230 { 0, 0, 1000 },
231 { 1, 0, 500 },
233 TestData current[] = {
234 { 2, 0, 400 },
236 TestData result[] = {
237 { 2, 0, 400 },
238 { 1, 0, 399 },
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) {
248 TestData last[] = {
249 { 0, 0, 1000 },
250 { 1, 1, 500 },
251 { 2, 0, 400 },
252 { 3, 1, 300 },
254 TestData current[] = {
255 { 4, 0, 1100 },
256 { 5, 1, 550 },
258 TestData result[] = {
259 { 4, 0, 1100 },
260 { 5, 1, 550 },
261 { 2, 0, 400 },
262 { 3, 1, 300 },
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
271 // and culled.
272 TEST_F(AutocompleteResultTest, SortAndCullEmptyDestinationURLs) {
273 TestData data[] = {
274 { 1, 0, 500 },
275 { 0, 0, 1100 },
276 { 1, 0, 1000 },
277 { 0, 0, 1300 },
278 { 0, 0, 1200 },
281 ACMatches matches;
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,
292 true,
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
298 // should be kept.
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));
318 TestData data[] = {
319 { 0, 0, 1300 },
320 { 1, 0, 1200 },
321 { 2, 0, 1100 },
322 { 3, 0, 1000 },
323 { 4, 1, 900 },
326 ACMatches matches;
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,
339 true,
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);
369 TestData data[] = {
370 { 0, 0, 1300, dups },
371 { 1, 0, 1200 },
372 { 2, 0, 1100 },
373 { 3, 0, 1000, dups },
374 { 4, 1, 900 },
375 { 5, 0, 800 },
378 ACMatches matches;
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,
392 true,
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) {
417 // Add some matches.
418 ACMatches matches;
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,
447 true,
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) {
464 // Add some matches.
465 ACMatches matches;
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,
493 false, false, true,
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) {
514 TestData data[] = {
515 { 0, 0, 1300 },
516 { 1, 0, 1200 },
517 { 2, 0, 1100 },
518 { 3, 0, 1000 }
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()).
525 ACMatches matches;
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,
532 true,
533 TestSchemeClassifier());
534 result.SortAndCull(input, template_url_service_.get());
535 AssertResultMatches(result, data, 4);
539 // Check that reorder swaps up a result appropriately.
540 ACMatches matches;
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,
549 true,
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");
563 ACMatches matches;
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());
570 matches.clear();
571 result.Reset();
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),
577 &matches);
578 result.AppendMatches(matches);
579 EXPECT_FALSE(result.ShouldHideTopMatch());
580 matches.clear();
581 result.Reset();
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),
587 &matches);
588 result.AppendMatches(matches);
589 EXPECT_FALSE(result.ShouldHideTopMatch());
592 TEST_F(AutocompleteResultTest, ShouldHideTopMatchAfterCopy) {
593 base::FieldTrialList::CreateFieldTrial("InstantExtended",
594 "Group1 hide_verbatim:1");
595 ACMatches matches;
597 // Case 1: Top match is a verbatim match followed by only copied matches.
598 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
599 arraysize(kVerbatimMatches),
600 &matches);
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());
606 result.Reset();
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());
612 result.Reset();
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");
626 ACMatches matches;
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) {
635 ACMatches matches;
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());
646 result.Reset();
647 matches.clear();
649 // Case 3: Top match is a verbatim match.
650 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
651 result.AppendMatches(matches);
652 EXPECT_TRUE(result.TopMatchIsStandaloneVerbatimMatch());
653 result.Reset();
654 matches.clear();
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());
661 result.Reset();
662 matches.clear();
664 // Case 5: Multiple verbatim matches found in AutocompleteResult.
665 PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
666 arraysize(kVerbatimMatches),
667 &matches);
668 result.AppendMatches(matches);
669 EXPECT_FALSE(result.ShouldHideTopMatch());