1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/autocomplete/autocomplete_result.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/metrics/field_trial.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_util.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "chrome/browser/autocomplete/autocomplete_input.h" 13 #include "chrome/browser/autocomplete/autocomplete_match.h" 14 #include "chrome/browser/autocomplete/autocomplete_provider.h" 15 #include "chrome/browser/omnibox/omnibox_field_trial.h" 16 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" 17 #include "chrome/browser/search_engines/template_url_service.h" 18 #include "chrome/browser/search_engines/template_url_service_test_util.h" 19 #include "chrome/common/autocomplete_match_type.h" 20 #include "chrome/common/metrics/variations/variations_util.h" 21 #include "chrome/test/base/testing_profile.h" 22 #include "components/variations/entropy_provider.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 namespace { 26 27 // Creates an AutocompleteMatch using |destination_url| and |type| and appends 28 // it to |matches|. 29 void AddMatch(const std::string& destination_url, AutocompleteMatch::Type type, 30 ACMatches* matches) { 31 ASSERT_TRUE(matches != NULL); 32 AutocompleteMatch* last_match = 33 !matches->empty() ? &((*matches)[matches->size() - 1]) : NULL; 34 AutocompleteMatch match; 35 match.destination_url = GURL(destination_url); 36 match.relevance = last_match ? last_match->relevance - 100 : 1300; 37 match.allowed_to_be_default_match = true; 38 match.type = type; 39 matches->push_back(match); 40 } 41 42 } // namespace 43 44 class AutocompleteResultTest : public testing::Test { 45 public: 46 struct TestData { 47 // Used to build a url for the AutocompleteMatch. The URL becomes 48 // "http://" + ('a' + |url_id|) (e.g. an ID of 2 yields "http://b"). 49 int url_id; 50 51 // ID of the provider. 52 int provider_id; 53 54 // Relevance score. 55 int relevance; 56 }; 57 58 AutocompleteResultTest() { 59 // Destroy the existing FieldTrialList before creating a new one to avoid 60 // a DCHECK. 61 field_trial_list_.reset(); 62 field_trial_list_.reset(new base::FieldTrialList( 63 new metrics::SHA1EntropyProvider("foo"))); 64 chrome_variations::testing::ClearAllVariationParams(); 65 } 66 67 virtual void SetUp() OVERRIDE { 68 #if defined(OS_ANDROID) 69 TemplateURLPrepopulateData::InitCountryCode( 70 std::string() /* unknown country code */); 71 #endif 72 test_util_.SetUp(); 73 test_util_.VerifyLoad(); 74 } 75 76 virtual void TearDown() OVERRIDE { 77 test_util_.TearDown(); 78 } 79 80 // Configures |match| from |data|. 81 static void PopulateAutocompleteMatch(const TestData& data, 82 AutocompleteMatch* match); 83 84 // Adds |count| AutocompleteMatches to |matches|. 85 static void PopulateAutocompleteMatches(const TestData* data, 86 size_t count, 87 ACMatches* matches); 88 89 // Asserts that |result| has |expected_count| matches matching |expected|. 90 void AssertResultMatches(const AutocompleteResult& result, 91 const TestData* expected, 92 size_t expected_count); 93 94 // Creates an AutocompleteResult from |last| and |current|. The two are 95 // merged by |CopyOldMatches| and compared by |AssertResultMatches|. 96 void RunCopyOldMatchesTest(const TestData* last, size_t last_size, 97 const TestData* current, size_t current_size, 98 const TestData* expected, size_t expected_size); 99 100 protected: 101 TemplateURLServiceTestUtil test_util_; 102 103 private: 104 scoped_ptr<base::FieldTrialList> field_trial_list_; 105 106 DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest); 107 }; 108 109 // static 110 void AutocompleteResultTest::PopulateAutocompleteMatch( 111 const TestData& data, 112 AutocompleteMatch* match) { 113 match->provider = reinterpret_cast<AutocompleteProvider*>(data.provider_id); 114 match->fill_into_edit = base::IntToString16(data.url_id); 115 std::string url_id(1, data.url_id + 'a'); 116 match->destination_url = GURL("http://" + url_id); 117 match->relevance = data.relevance; 118 match->allowed_to_be_default_match = true; 119 } 120 121 // static 122 void AutocompleteResultTest::PopulateAutocompleteMatches( 123 const TestData* data, 124 size_t count, 125 ACMatches* matches) { 126 for (size_t i = 0; i < count; ++i) { 127 AutocompleteMatch match; 128 PopulateAutocompleteMatch(data[i], &match); 129 matches->push_back(match); 130 } 131 } 132 133 void AutocompleteResultTest::AssertResultMatches( 134 const AutocompleteResult& result, 135 const TestData* expected, 136 size_t expected_count) { 137 ASSERT_EQ(expected_count, result.size()); 138 for (size_t i = 0; i < expected_count; ++i) { 139 AutocompleteMatch expected_match; 140 PopulateAutocompleteMatch(expected[i], &expected_match); 141 const AutocompleteMatch& match = *(result.begin() + i); 142 EXPECT_EQ(expected_match.provider, match.provider) << i; 143 EXPECT_EQ(expected_match.relevance, match.relevance) << i; 144 EXPECT_EQ(expected_match.destination_url.spec(), 145 match.destination_url.spec()) << i; 146 } 147 } 148 149 void AutocompleteResultTest::RunCopyOldMatchesTest( 150 const TestData* last, size_t last_size, 151 const TestData* current, size_t current_size, 152 const TestData* expected, size_t expected_size) { 153 AutocompleteInput input(ASCIIToUTF16("a"), base::string16::npos, 154 base::string16(), GURL(), 155 AutocompleteInput::INVALID_SPEC, false, false, false, 156 AutocompleteInput::ALL_MATCHES); 157 158 ACMatches last_matches; 159 PopulateAutocompleteMatches(last, last_size, &last_matches); 160 AutocompleteResult last_result; 161 last_result.AppendMatches(last_matches); 162 last_result.SortAndCull(input, test_util_.profile()); 163 164 ACMatches current_matches; 165 PopulateAutocompleteMatches(current, current_size, ¤t_matches); 166 AutocompleteResult current_result; 167 current_result.AppendMatches(current_matches); 168 current_result.SortAndCull(input, test_util_.profile()); 169 current_result.CopyOldMatches(input, last_result, test_util_.profile()); 170 171 AssertResultMatches(current_result, expected, expected_size); 172 } 173 174 // Assertion testing for AutocompleteResult::Swap. 175 TEST_F(AutocompleteResultTest, Swap) { 176 AutocompleteResult r1; 177 AutocompleteResult r2; 178 179 // Swap with empty shouldn't do anything interesting. 180 r1.Swap(&r2); 181 EXPECT_EQ(r1.end(), r1.default_match()); 182 EXPECT_EQ(r2.end(), r2.default_match()); 183 184 // Swap with a single match. 185 ACMatches matches; 186 AutocompleteMatch match; 187 match.relevance = 1; 188 match.allowed_to_be_default_match = true; 189 AutocompleteInput input(ASCIIToUTF16("a"), base::string16::npos, 190 base::string16(), GURL(), 191 AutocompleteInput::INVALID_SPEC, false, false, false, 192 AutocompleteInput::ALL_MATCHES); 193 matches.push_back(match); 194 r1.AppendMatches(matches); 195 r1.SortAndCull(input, test_util_.profile()); 196 EXPECT_EQ(r1.begin(), r1.default_match()); 197 EXPECT_EQ("http://a/", r1.alternate_nav_url().spec()); 198 r1.Swap(&r2); 199 EXPECT_TRUE(r1.empty()); 200 EXPECT_EQ(r1.end(), r1.default_match()); 201 EXPECT_TRUE(r1.alternate_nav_url().is_empty()); 202 ASSERT_FALSE(r2.empty()); 203 EXPECT_EQ(r2.begin(), r2.default_match()); 204 EXPECT_EQ("http://a/", r2.alternate_nav_url().spec()); 205 } 206 207 // Tests that if the new results have a lower max relevance score than last, 208 // any copied results have their relevance shifted down. 209 TEST_F(AutocompleteResultTest, CopyOldMatches) { 210 TestData last[] = { 211 { 0, 0, 1000 }, 212 { 1, 0, 500 }, 213 }; 214 TestData current[] = { 215 { 2, 0, 400 }, 216 }; 217 TestData result[] = { 218 { 2, 0, 400 }, 219 { 1, 0, 399 }, 220 }; 221 222 ASSERT_NO_FATAL_FAILURE( 223 RunCopyOldMatchesTest(last, ARRAYSIZE_UNSAFE(last), 224 current, ARRAYSIZE_UNSAFE(current), 225 result, ARRAYSIZE_UNSAFE(result))); 226 } 227 228 // Tests that matches are copied correctly from two distinct providers. 229 TEST_F(AutocompleteResultTest, CopyOldMatches2) { 230 TestData last[] = { 231 { 0, 0, 1000 }, 232 { 1, 1, 500 }, 233 { 2, 0, 400 }, 234 { 3, 1, 300 }, 235 }; 236 TestData current[] = { 237 { 4, 0, 1100 }, 238 { 5, 1, 550 }, 239 }; 240 TestData result[] = { 241 { 4, 0, 1100 }, 242 { 5, 1, 550 }, 243 { 2, 0, 400 }, 244 { 3, 1, 300 }, 245 }; 246 247 ASSERT_NO_FATAL_FAILURE( 248 RunCopyOldMatchesTest(last, ARRAYSIZE_UNSAFE(last), 249 current, ARRAYSIZE_UNSAFE(current), 250 result, ARRAYSIZE_UNSAFE(result))); 251 } 252 253 // Tests that matches with empty destination URLs aren't treated as duplicates 254 // and culled. 255 TEST_F(AutocompleteResultTest, SortAndCullEmptyDestinationURLs) { 256 TestData data[] = { 257 { 1, 0, 500 }, 258 { 0, 0, 1100 }, 259 { 1, 0, 1000 }, 260 { 0, 0, 1300 }, 261 { 0, 0, 1200 }, 262 }; 263 264 ACMatches matches; 265 PopulateAutocompleteMatches(data, arraysize(data), &matches); 266 matches[1].destination_url = GURL(); 267 matches[3].destination_url = GURL(); 268 matches[4].destination_url = GURL(); 269 270 AutocompleteResult result; 271 result.AppendMatches(matches); 272 AutocompleteInput input(base::string16(), base::string16::npos, 273 base::string16(), GURL(), 274 AutocompleteInput::INVALID_SPEC, false, false, false, 275 AutocompleteInput::ALL_MATCHES); 276 result.SortAndCull(input, test_util_.profile()); 277 278 // Of the two results with the same non-empty destination URL, the 279 // lower-relevance one should be dropped. All of the results with empty URLs 280 // should be kept. 281 ASSERT_EQ(4U, result.size()); 282 EXPECT_TRUE(result.match_at(0)->destination_url.is_empty()); 283 EXPECT_EQ(1300, result.match_at(0)->relevance); 284 EXPECT_TRUE(result.match_at(1)->destination_url.is_empty()); 285 EXPECT_EQ(1200, result.match_at(1)->relevance); 286 EXPECT_TRUE(result.match_at(2)->destination_url.is_empty()); 287 EXPECT_EQ(1100, result.match_at(2)->relevance); 288 EXPECT_EQ("http://b/", result.match_at(3)->destination_url.spec()); 289 EXPECT_EQ(1000, result.match_at(3)->relevance); 290 } 291 292 TEST_F(AutocompleteResultTest, SortAndCullDuplicateSearchURLs) { 293 // Register a template URL that corresponds to 'foo' search engine. 294 TemplateURLData url_data; 295 url_data.short_name = ASCIIToUTF16("unittest"); 296 url_data.SetKeyword(ASCIIToUTF16("foo")); 297 url_data.SetURL("http://www.foo.com/s?q={searchTerms}"); 298 test_util_.model()->Add(new TemplateURL(test_util_.profile(), url_data)); 299 300 TestData data[] = { 301 { 0, 0, 1300 }, 302 { 1, 0, 1200 }, 303 { 2, 0, 1100 }, 304 { 3, 0, 1000 }, 305 { 4, 1, 900 }, 306 }; 307 308 ACMatches matches; 309 PopulateAutocompleteMatches(data, arraysize(data), &matches); 310 matches[0].destination_url = GURL("http://www.foo.com/s?q=foo"); 311 matches[1].destination_url = GURL("http://www.foo.com/s?q=foo2"); 312 matches[2].destination_url = GURL("http://www.foo.com/s?q=foo&oq=f"); 313 matches[3].destination_url = GURL("http://www.foo.com/s?q=foo&aqs=0"); 314 matches[4].destination_url = GURL("http://www.foo.com/"); 315 316 AutocompleteResult result; 317 result.AppendMatches(matches); 318 AutocompleteInput input(base::string16(), base::string16::npos, 319 base::string16(), GURL(), 320 AutocompleteInput::INVALID_SPEC, false, false, false, 321 AutocompleteInput::ALL_MATCHES); 322 result.SortAndCull(input, test_util_.profile()); 323 324 // We expect the 3rd and 4th results to be removed. 325 ASSERT_EQ(3U, result.size()); 326 EXPECT_EQ("http://www.foo.com/s?q=foo", 327 result.match_at(0)->destination_url.spec()); 328 EXPECT_EQ(1300, result.match_at(0)->relevance); 329 EXPECT_EQ("http://www.foo.com/s?q=foo2", 330 result.match_at(1)->destination_url.spec()); 331 EXPECT_EQ(1200, result.match_at(1)->relevance); 332 EXPECT_EQ("http://www.foo.com/", 333 result.match_at(2)->destination_url.spec()); 334 EXPECT_EQ(900, result.match_at(2)->relevance); 335 } 336 337 TEST_F(AutocompleteResultTest, SortAndCullWithDemotionsByType) { 338 // Add some matches. 339 ACMatches matches; 340 AddMatch("http://history-url/", AutocompleteMatchType::HISTORY_URL, &matches); 341 AddMatch("http://search-what-you-typed/", 342 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, &matches); 343 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 344 &matches); 345 346 // Add a search history type match and demote its relevance score. 347 AddMatch("http://search-history/", AutocompleteMatchType::SEARCH_HISTORY, 348 &matches); 349 matches[matches.size() - 1].relevance = 500; 350 351 // Add a rule demoting history-url and killing history-title. 352 { 353 std::map<std::string, std::string> params; 354 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":3:*"] = 355 "1:50,7:100,2:0"; // 3 == HOME_PAGE 356 ASSERT_TRUE(chrome_variations::AssociateVariationParams( 357 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); 358 } 359 base::FieldTrialList::CreateFieldTrial( 360 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); 361 362 AutocompleteResult result; 363 result.AppendMatches(matches); 364 AutocompleteInput input(base::string16(), base::string16::npos, 365 base::string16(), GURL(), 366 AutocompleteInput::HOME_PAGE, false, false, false, 367 AutocompleteInput::ALL_MATCHES); 368 result.SortAndCull(input, test_util_.profile()); 369 370 // Check the new ordering. The history-title results should be omitted. 371 // We cannot check relevance scores because the matches are sorted by 372 // demoted relevance but the actual relevance scores are not modified. 373 ASSERT_EQ(3u, result.size()); 374 EXPECT_EQ("http://search-what-you-typed/", 375 result.match_at(0)->destination_url.spec()); 376 EXPECT_EQ("http://history-url/", 377 result.match_at(1)->destination_url.spec()); 378 EXPECT_EQ("http://search-history/", 379 result.match_at(2)->destination_url.spec()); 380 } 381 382 TEST_F(AutocompleteResultTest, SortAndCullWithUndemotableTypes) { 383 // Add some matches. 384 ACMatches matches(3); 385 matches[0].destination_url = GURL("http://top-history-url/"); 386 matches[0].relevance = 1400; 387 matches[0].allowed_to_be_default_match = true; 388 matches[0].type = AutocompleteMatchType::HISTORY_URL; 389 matches[1].destination_url = GURL("http://history-url2/"); 390 matches[1].relevance = 1300; 391 matches[1].allowed_to_be_default_match = true; 392 matches[1].type = AutocompleteMatchType::HISTORY_URL; 393 matches[2].destination_url = GURL("http://search-what-you-typed/"); 394 matches[2].relevance = 1200; 395 matches[2].allowed_to_be_default_match = true; 396 matches[2].type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED; 397 398 // Add a rule demoting history-url, but don't demote the top match. 399 { 400 std::map<std::string, std::string> params; 401 // 3 == HOME_PAGE 402 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":3:*"] = 403 "1:50"; 404 params[std::string(OmniboxFieldTrial::kUndemotableTopTypeRule) + ":3:*"] = 405 "1,5"; 406 ASSERT_TRUE(chrome_variations::AssociateVariationParams( 407 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "B", params)); 408 } 409 base::FieldTrialList::CreateFieldTrial( 410 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "B"); 411 412 AutocompleteResult result; 413 result.AppendMatches(matches); 414 AutocompleteInput input(base::string16(), base::string16::npos, 415 base::string16(), GURL(), 416 AutocompleteInput::HOME_PAGE, false, false, false, 417 AutocompleteInput::ALL_MATCHES); 418 result.SortAndCull(input, test_util_.profile()); 419 420 // Check the new ordering. The first history-url result should not be 421 // demoted, but the second result should be. 422 // We cannot check relevance scores because the matches are sorted by 423 // demoted relevance but the actual relevance scores are not modified. 424 ASSERT_EQ(3u, result.size()); 425 EXPECT_EQ("http://top-history-url/", 426 result.match_at(0)->destination_url.spec()); 427 EXPECT_EQ("http://search-what-you-typed/", 428 result.match_at(1)->destination_url.spec()); 429 EXPECT_EQ("http://history-url2/", 430 result.match_at(2)->destination_url.spec()); 431 } 432 433 TEST_F(AutocompleteResultTest, SortAndCullReorderForDefaultMatch) { 434 TestData data[] = { 435 { 0, 0, 1300 }, 436 { 1, 0, 1200 }, 437 { 2, 0, 1100 }, 438 { 3, 0, 1000 } 439 }; 440 441 { 442 // Check that reorder doesn't do anything if the top result 443 // is already a legal default match (which is the default from 444 // PopulateAutocompleteMatches()). 445 ACMatches matches; 446 PopulateAutocompleteMatches(data, arraysize(data), &matches); 447 AutocompleteResult result; 448 result.AppendMatches(matches); 449 AutocompleteInput input(base::string16(), base::string16::npos, 450 base::string16(), GURL(), 451 AutocompleteInput::HOME_PAGE, false, false, false, 452 AutocompleteInput::ALL_MATCHES); 453 result.SortAndCull(input, test_util_.profile()); 454 AssertResultMatches(result, data, 4); 455 } 456 457 { 458 // Check that reorder swaps up a result appropriately. 459 ACMatches matches; 460 PopulateAutocompleteMatches(data, arraysize(data), &matches); 461 matches[0].allowed_to_be_default_match = false; 462 matches[1].allowed_to_be_default_match = false; 463 AutocompleteResult result; 464 result.AppendMatches(matches); 465 AutocompleteInput input(base::string16(), base::string16::npos, 466 base::string16(), GURL(), 467 AutocompleteInput::HOME_PAGE, false, false, false, 468 AutocompleteInput::ALL_MATCHES); 469 result.SortAndCull(input, test_util_.profile()); 470 ASSERT_EQ(4U, result.size()); 471 EXPECT_EQ("http://c/", result.match_at(0)->destination_url.spec()); 472 EXPECT_EQ("http://a/", result.match_at(1)->destination_url.spec()); 473 EXPECT_EQ("http://b/", result.match_at(2)->destination_url.spec()); 474 EXPECT_EQ("http://d/", result.match_at(3)->destination_url.spec()); 475 } 476 } 477 478 TEST_F(AutocompleteResultTest, ShouldHideTopMatch) { 479 // Add some matches. 480 ACMatches matches; 481 AddMatch("http://search-what-you-typed/", 482 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, &matches); 483 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 484 &matches); 485 AddMatch("http://search-history/", AutocompleteMatchType::SEARCH_HISTORY, 486 &matches); 487 488 base::FieldTrialList::CreateFieldTrial("InstantExtended", 489 "Group1 hide_verbatim:1"); 490 AutocompleteResult result; 491 result.AppendMatches(matches); 492 EXPECT_TRUE(result.ShouldHideTopMatch()); 493 } 494 495 TEST_F(AutocompleteResultTest, DoNotHideTopMatch) { 496 ACMatches matches; 497 AddMatch("http://search-what-you-typed/", 498 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, &matches); 499 AddMatch("http://url-what-you-typed/", 500 AutocompleteMatchType::URL_WHAT_YOU_TYPED, &matches); 501 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 502 &matches); 503 AddMatch("http://search-history/", AutocompleteMatchType::SEARCH_HISTORY, 504 &matches); 505 506 base::FieldTrialList::CreateFieldTrial("InstantExtended", 507 "Group1 hide_verbatim:1"); 508 AutocompleteResult result; 509 result.AppendMatches(matches); 510 // If the verbatim first match is followed by another verbatim match, don't 511 // hide the top verbatim match. 512 EXPECT_FALSE(result.ShouldHideTopMatch()); 513 } 514 515 TEST_F(AutocompleteResultTest, DoNotHideTopMatch_TopMatchIsNotVerbatim) { 516 ACMatches matches; 517 AddMatch("http://search-history/", AutocompleteMatchType::SEARCH_HISTORY, 518 &matches); 519 AddMatch("http://search-what-you-typed/", 520 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, &matches); 521 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 522 &matches); 523 524 base::FieldTrialList::CreateFieldTrial("InstantExtended", 525 "Group1 hide_verbatim:1"); 526 AutocompleteResult result; 527 result.AppendMatches(matches); 528 // Top match is not a verbatim type match. Do not hide the top match. 529 EXPECT_FALSE(result.ShouldHideTopMatch()); 530 } 531 532 TEST_F(AutocompleteResultTest, DoNotHideTopMatch_FieldTrialFlagDisabled) { 533 // Add some matches. This test config is identical to ShouldHideTopMatch test 534 // except that the "hide_verbatim" flag is disabled in the field trials. 535 ACMatches matches; 536 AddMatch("http://search-what-you-typed/", 537 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, &matches); 538 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 539 &matches); 540 AddMatch("http://search-history/", AutocompleteMatchType::SEARCH_HISTORY, 541 &matches); 542 543 base::FieldTrialList::CreateFieldTrial("InstantExtended", 544 "Group1 hide_verbatim:0"); 545 AutocompleteResult result; 546 result.AppendMatches(matches); 547 // Field trial flag "hide_verbatim" is disabled. Do not hide top match. 548 EXPECT_FALSE(result.ShouldHideTopMatch()); 549 } 550 551 TEST_F(AutocompleteResultTest, 552 TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches) { 553 ACMatches matches; 554 AddMatch("http://url-what-you-typed/", 555 AutocompleteMatchType::URL_WHAT_YOU_TYPED, &matches); 556 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 557 &matches); 558 559 AutocompleteResult result; 560 result.AppendMatches(matches); 561 EXPECT_TRUE(result.TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches()); 562 } 563 564 TEST_F(AutocompleteResultTest, 565 TopMatchIsVerbatimAndHasConsecutiveVerbatimMatches) { 566 ACMatches matches; 567 AddMatch("http://search-what-you-typed/", 568 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, &matches); 569 AddMatch("http://url-what-you-typed/", 570 AutocompleteMatchType::URL_WHAT_YOU_TYPED, &matches); 571 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 572 &matches); 573 574 AutocompleteResult result; 575 result.AppendMatches(matches); 576 EXPECT_FALSE(result.TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches()); 577 } 578 579 TEST_F(AutocompleteResultTest, TopMatchIsNotVerbatim) { 580 ACMatches matches; 581 AutocompleteResult result; 582 result.AppendMatches(matches); 583 584 // Result set is empty. 585 EXPECT_FALSE(result.TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches()); 586 587 // Add a non-verbatim match to the result. 588 AddMatch("http://history-title/", AutocompleteMatchType::HISTORY_TITLE, 589 &matches); 590 591 result.AppendMatches(matches); 592 EXPECT_FALSE(result.TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches()); 593 } 594 595 TEST_F(AutocompleteResultTest, 596 TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches_SingleMatchFound) { 597 ACMatches matches; 598 AddMatch("http://url-what-you-typed/", 599 AutocompleteMatchType::URL_WHAT_YOU_TYPED, &matches); 600 601 AutocompleteResult result; 602 result.AppendMatches(matches); 603 EXPECT_TRUE(result.TopMatchIsVerbatimAndHasNoConsecutiveVerbatimMatches()); 604 } 605