| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/autocomplete/search_provider.h" | 5 #include "chrome/browser/autocomplete/search_provider.h" |
| 6 | 6 |
| 7 #include "base/metrics/field_trial.h" | 7 #include "base/metrics/field_trial.h" |
| 8 #include "base/prefs/pref_service.h" | 8 #include "base/prefs/pref_service.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" | 14 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" |
| 15 #include "chrome/browser/autocomplete/autocomplete_controller.h" | 15 #include "chrome/browser/autocomplete/autocomplete_controller.h" |
| 16 #include "chrome/browser/autocomplete/autocomplete_input.h" | 16 #include "chrome/browser/autocomplete/autocomplete_input.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete_match.h" | 17 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 18 #include "chrome/browser/autocomplete/autocomplete_provider.h" | 18 #include "chrome/browser/autocomplete/autocomplete_provider.h" |
| 19 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" | 19 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" |
| 20 #include "chrome/browser/autocomplete/history_url_provider.h" | 20 #include "chrome/browser/autocomplete/history_url_provider.h" |
| 21 #include "chrome/browser/history/history_service.h" | 21 #include "chrome/browser/history/history_service.h" |
| 22 #include "chrome/browser/history/history_service_factory.h" | 22 #include "chrome/browser/history/history_service_factory.h" |
| 23 #include "chrome/browser/omnibox/omnibox_field_trial.h" | 23 #include "chrome/browser/omnibox/omnibox_field_trial.h" |
| 24 #include "chrome/browser/search/search.h" | 24 #include "chrome/browser/search/search.h" |
| 25 #include "chrome/browser/search_engines/template_url.h" | 25 #include "chrome/browser/search_engines/template_url.h" |
| 26 #include "chrome/browser/search_engines/template_url_service.h" | 26 #include "chrome/browser/search_engines/template_url_service.h" |
| 27 #include "chrome/browser/search_engines/template_url_service_factory.h" | 27 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 28 #include "chrome/common/instant_types.h" | |
| 29 #include "chrome/common/metrics/entropy_provider.h" | 28 #include "chrome/common/metrics/entropy_provider.h" |
| 30 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
| 31 #include "chrome/test/base/testing_browser_process.h" | 30 #include "chrome/test/base/testing_browser_process.h" |
| 32 #include "chrome/test/base/testing_profile.h" | 31 #include "chrome/test/base/testing_profile.h" |
| 33 #include "content/public/test/test_browser_thread.h" | 32 #include "content/public/test/test_browser_thread.h" |
| 34 #include "net/url_request/test_url_fetcher_factory.h" | 33 #include "net/url_request/test_url_fetcher_factory.h" |
| 35 #include "net/url_request/url_request_status.h" | 34 #include "net/url_request/url_request_status.h" |
| 36 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
| 37 | 36 |
| 38 using content::BrowserThread; | 37 using content::BrowserThread; |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 // URLFetchers runs. | 278 // URLFetchers runs. |
| 280 message_loop_.RunUntilIdle(); | 279 message_loop_.RunUntilIdle(); |
| 281 } | 280 } |
| 282 | 281 |
| 283 void SearchProviderTest::QueryForInputAndSetWYTMatch( | 282 void SearchProviderTest::QueryForInputAndSetWYTMatch( |
| 284 const string16& text, | 283 const string16& text, |
| 285 AutocompleteMatch* wyt_match) { | 284 AutocompleteMatch* wyt_match) { |
| 286 QueryForInput(text, false, false); | 285 QueryForInput(text, false, false); |
| 287 profile_.BlockUntilHistoryProcessesPendingRequests(); | 286 profile_.BlockUntilHistoryProcessesPendingRequests(); |
| 288 ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery()); | 287 ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery()); |
| 289 EXPECT_NE(chrome::IsInstantExtendedAPIEnabled(), provider_->done()); | |
| 290 if (!wyt_match) | 288 if (!wyt_match) |
| 291 return; | 289 return; |
| 292 ASSERT_GE(provider_->matches().size(), 1u); | 290 ASSERT_GE(provider_->matches().size(), 1u); |
| 293 EXPECT_TRUE(FindMatchWithDestination(GURL( | 291 EXPECT_TRUE(FindMatchWithDestination(GURL( |
| 294 default_t_url_->url_ref().ReplaceSearchTerms( | 292 default_t_url_->url_ref().ReplaceSearchTerms( |
| 295 TemplateURLRef::SearchTermsArgs(text))), | 293 TemplateURLRef::SearchTermsArgs(text))), |
| 296 wyt_match)); | 294 wyt_match)); |
| 297 } | 295 } |
| 298 | 296 |
| 299 void SearchProviderTest::TearDown() { | 297 void SearchProviderTest::TearDown() { |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 for (size_t i = 0; i < arraysize(inputs); ++i) { | 501 for (size_t i = 0; i < arraysize(inputs); ++i) { |
| 504 QueryForInput(ASCIIToUTF16(inputs[i]), false, false); | 502 QueryForInput(ASCIIToUTF16(inputs[i]), false, false); |
| 505 // Make sure the default providers suggest service was not queried. | 503 // Make sure the default providers suggest service was not queried. |
| 506 ASSERT_TRUE(test_factory_.GetFetcherByID( | 504 ASSERT_TRUE(test_factory_.GetFetcherByID( |
| 507 SearchProvider::kDefaultProviderURLFetcherID) == NULL); | 505 SearchProvider::kDefaultProviderURLFetcherID) == NULL); |
| 508 // Run till the history results complete. | 506 // Run till the history results complete. |
| 509 RunTillProviderDone(); | 507 RunTillProviderDone(); |
| 510 } | 508 } |
| 511 } | 509 } |
| 512 | 510 |
| 513 // Make sure FinalizeInstantQuery works. | |
| 514 TEST_F(SearchProviderTest, FinalizeInstantQuery) { | |
| 515 chrome::EnableInstantExtendedAPIForTesting(); | |
| 516 | |
| 517 ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("foo"), | |
| 518 NULL)); | |
| 519 | |
| 520 // Tell the provider Instant is done. | |
| 521 provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"), | |
| 522 InstantSuggestion(ASCIIToUTF16("bar"), | |
| 523 INSTANT_COMPLETE_NOW, | |
| 524 INSTANT_SUGGESTION_SEARCH, | |
| 525 string16(), | |
| 526 kNoMatchIndex)); | |
| 527 | |
| 528 // The provider should now be done. | |
| 529 EXPECT_TRUE(provider_->done()); | |
| 530 | |
| 531 // There should be two matches, one for what you typed, the other for | |
| 532 // 'foobar'. | |
| 533 EXPECT_EQ(2u, provider_->matches().size()); | |
| 534 GURL instant_url(default_t_url_->url_ref().ReplaceSearchTerms( | |
| 535 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("foobar")))); | |
| 536 AutocompleteMatch instant_match; | |
| 537 EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match)); | |
| 538 | |
| 539 // And the 'foobar' match should not have a description, it'll be set later. | |
| 540 EXPECT_TRUE(instant_match.description.empty()); | |
| 541 | |
| 542 // Make sure the what you typed match has no description. | |
| 543 AutocompleteMatch wyt_match; | |
| 544 EXPECT_TRUE(FindMatchWithDestination( | |
| 545 GURL(default_t_url_->url_ref().ReplaceSearchTerms( | |
| 546 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("foo")))), | |
| 547 &wyt_match)); | |
| 548 EXPECT_TRUE(wyt_match.description.empty()); | |
| 549 | |
| 550 // Instant search suggestions should be ranked above verbatim matches. | |
| 551 EXPECT_GT(instant_match.relevance, wyt_match.relevance); | |
| 552 } | |
| 553 | |
| 554 // Make sure FinalizeInstantQuery works with URL suggestions. | |
| 555 TEST_F(SearchProviderTest, FinalizeInstantURL) { | |
| 556 chrome::EnableInstantExtendedAPIForTesting(); | |
| 557 | |
| 558 ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("ex"), | |
| 559 NULL)); | |
| 560 | |
| 561 // Tell the provider Instant is done. | |
| 562 provider_->FinalizeInstantQuery(ASCIIToUTF16("ex"), | |
| 563 InstantSuggestion( | |
| 564 ASCIIToUTF16("http://example.com/"), | |
| 565 INSTANT_COMPLETE_NOW, | |
| 566 INSTANT_SUGGESTION_URL, | |
| 567 string16(), | |
| 568 kNoMatchIndex)); | |
| 569 | |
| 570 // The provider should now be done. | |
| 571 EXPECT_TRUE(provider_->done()); | |
| 572 | |
| 573 // There should be two matches, one for what you typed, the other for | |
| 574 // "http://example.com/". | |
| 575 EXPECT_EQ(2u, provider_->matches().size()); | |
| 576 GURL instant_url("http://example.com"); | |
| 577 AutocompleteMatch instant_match; | |
| 578 EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match)); | |
| 579 | |
| 580 // The Instant match should not have a description, it'll be set later. | |
| 581 EXPECT_TRUE(instant_match.description.empty()); | |
| 582 | |
| 583 // Make sure the what you typed match has no description. | |
| 584 AutocompleteMatch wyt_match; | |
| 585 EXPECT_TRUE(FindMatchWithDestination( | |
| 586 GURL(default_t_url_->url_ref().ReplaceSearchTerms( | |
| 587 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("ex")))), | |
| 588 &wyt_match)); | |
| 589 EXPECT_TRUE(wyt_match.description.empty()); | |
| 590 | |
| 591 // The Instant URL should be more relevant. | |
| 592 EXPECT_GT(instant_match.relevance, wyt_match.relevance); | |
| 593 } | |
| 594 | |
| 595 // An Instant URL suggestion should behave the same way whether the input text | |
| 596 // is classified as UNKNOWN or as an URL. Otherwise if the user types | |
| 597 // "example.co" url-what-you-typed will displace the Instant suggestion for | |
| 598 // "example.com". | |
| 599 TEST_F(SearchProviderTest, FinalizeInstantURLWithURLText) { | |
| 600 chrome::EnableInstantExtendedAPIForTesting(); | |
| 601 | |
| 602 ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch( | |
| 603 ASCIIToUTF16("example.co"), NULL)); | |
| 604 | |
| 605 // Tell the provider Instant is done. | |
| 606 provider_->FinalizeInstantQuery(ASCIIToUTF16("example.co"), | |
| 607 InstantSuggestion( | |
| 608 ASCIIToUTF16("http://example.com/"), | |
| 609 INSTANT_COMPLETE_NOW, | |
| 610 INSTANT_SUGGESTION_URL, | |
| 611 string16(), | |
| 612 kNoMatchIndex)); | |
| 613 | |
| 614 // The provider should now be done. | |
| 615 EXPECT_TRUE(provider_->done()); | |
| 616 | |
| 617 // There should be two matches, one for what you typed, the other for | |
| 618 // "http://example.com/". | |
| 619 EXPECT_EQ(2u, provider_->matches().size()); | |
| 620 GURL instant_url("http://example.com"); | |
| 621 AutocompleteMatch instant_match; | |
| 622 EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match)); | |
| 623 | |
| 624 // The Instant match should not have a description, it'll be set later. | |
| 625 EXPECT_TRUE(instant_match.description.empty()); | |
| 626 | |
| 627 // The Instant URL should be more relevant than a URL_WHAT_YOU_TYPED match. | |
| 628 EXPECT_GT(instant_match.relevance, | |
| 629 HistoryURLProvider::kScoreForWhatYouTypedResult); | |
| 630 } | |
| 631 | |
| 632 // Make sure that if FinalizeInstantQuery is invoked before suggest results | |
| 633 // return, the suggest text from FinalizeInstantQuery is remembered. | |
| 634 TEST_F(SearchProviderTest, RememberInstantQuery) { | |
| 635 chrome::EnableInstantExtendedAPIForTesting(); | |
| 636 | |
| 637 QueryForInput(ASCIIToUTF16("foo"), false, false); | |
| 638 | |
| 639 // Finalize the Instant query immediately. | |
| 640 provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"), | |
| 641 InstantSuggestion(ASCIIToUTF16("bar"), | |
| 642 INSTANT_COMPLETE_NOW, | |
| 643 INSTANT_SUGGESTION_SEARCH, | |
| 644 string16(), | |
| 645 kNoMatchIndex)); | |
| 646 | |
| 647 // There should be two matches, one for what you typed, the other for | |
| 648 // 'foobar'. | |
| 649 EXPECT_EQ(2u, provider_->matches().size()); | |
| 650 GURL instant_url(default_t_url_->url_ref().ReplaceSearchTerms( | |
| 651 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("foobar")))); | |
| 652 AutocompleteMatch instant_match; | |
| 653 EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match)); | |
| 654 | |
| 655 // Wait until history and the suggest query complete. | |
| 656 profile_.BlockUntilHistoryProcessesPendingRequests(); | |
| 657 ASSERT_NO_FATAL_FAILURE(FinishDefaultSuggestQuery()); | |
| 658 | |
| 659 // Provider should be done. | |
| 660 EXPECT_TRUE(provider_->done()); | |
| 661 | |
| 662 // There should be two matches, one for what you typed, the other for | |
| 663 // 'foobar'. | |
| 664 EXPECT_EQ(2u, provider_->matches().size()); | |
| 665 EXPECT_TRUE(FindMatchWithDestination(instant_url, &instant_match)); | |
| 666 | |
| 667 // And the 'foobar' match should not have a description, it'll be set later. | |
| 668 EXPECT_TRUE(instant_match.description.empty()); | |
| 669 } | |
| 670 | |
| 671 // Make sure that if trailing whitespace is added to the text supplied to | |
| 672 // AutocompleteInput the default suggest text is cleared. | |
| 673 TEST_F(SearchProviderTest, DifferingText) { | |
| 674 chrome::EnableInstantExtendedAPIForTesting(); | |
| 675 | |
| 676 ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("foo"), | |
| 677 NULL)); | |
| 678 | |
| 679 // Finalize the Instant query immediately. | |
| 680 provider_->FinalizeInstantQuery(ASCIIToUTF16("foo"), | |
| 681 InstantSuggestion(ASCIIToUTF16("bar"), | |
| 682 INSTANT_COMPLETE_NOW, | |
| 683 INSTANT_SUGGESTION_SEARCH, | |
| 684 string16(), | |
| 685 kNoMatchIndex)); | |
| 686 | |
| 687 // Query with the same input text, but trailing whitespace. | |
| 688 AutocompleteMatch instant_match; | |
| 689 ASSERT_NO_FATAL_FAILURE(QueryForInputAndSetWYTMatch(ASCIIToUTF16("foo "), | |
| 690 &instant_match)); | |
| 691 | |
| 692 // There should only one match, for what you typed. | |
| 693 EXPECT_EQ(1u, provider_->matches().size()); | |
| 694 EXPECT_FALSE(instant_match.destination_url.is_empty()); | |
| 695 } | |
| 696 | |
| 697 TEST_F(SearchProviderTest, DontAutocompleteURLLikeTerms) { | 511 TEST_F(SearchProviderTest, DontAutocompleteURLLikeTerms) { |
| 698 AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse( | 512 AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse( |
| 699 &profile_, &AutocompleteClassifierFactory::BuildInstanceFor); | 513 &profile_, &AutocompleteClassifierFactory::BuildInstanceFor); |
| 700 GURL url = AddSearchToHistory(default_t_url_, | 514 GURL url = AddSearchToHistory(default_t_url_, |
| 701 ASCIIToUTF16("docs.google.com"), 1); | 515 ASCIIToUTF16("docs.google.com"), 1); |
| 702 | 516 |
| 703 // Add the term as a url. | 517 // Add the term as a url. |
| 704 HistoryServiceFactory::GetForProfile(&profile_, Profile::EXPLICIT_ACCESS)-> | 518 HistoryServiceFactory::GetForProfile(&profile_, Profile::EXPLICIT_ACCESS)-> |
| 705 AddPageWithDetails(GURL("http://docs.google.com"), string16(), 1, 1, | 519 AddPageWithDetails(GURL("http://docs.google.com"), string16(), 1, 1, |
| 706 base::Time::Now(), false, history::SOURCE_BROWSED); | 520 base::Time::Now(), false, history::SOURCE_BROWSED); |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 } | 1465 } |
| 1652 // Ensure that no expected matches are missing. | 1466 // Ensure that no expected matches are missing. |
| 1653 for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j) | 1467 for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j) |
| 1654 EXPECT_EQ(kNotApplicable, cases[i].matches[j].contents) << | 1468 EXPECT_EQ(kNotApplicable, cases[i].matches[j].contents) << |
| 1655 "Case # " << i << " " << description; | 1469 "Case # " << i << " " << description; |
| 1656 } | 1470 } |
| 1657 } | 1471 } |
| 1658 | 1472 |
| 1659 TEST_F(SearchProviderTest, LocalAndRemoteRelevances) { | 1473 TEST_F(SearchProviderTest, LocalAndRemoteRelevances) { |
| 1660 // Enable Instant Extended in order to allow an increased number of | 1474 // Enable Instant Extended in order to allow an increased number of |
| 1661 // suggestions. Unfortunately this requires us to call FinalizeInstantQuery() | 1475 // suggestions. |
| 1662 // every time. | |
| 1663 chrome::EnableInstantExtendedAPIForTesting(); | 1476 chrome::EnableInstantExtendedAPIForTesting(); |
| 1664 | 1477 |
| 1665 // We hardcode the string "term1" below, so ensure that the search term that | 1478 // We hardcode the string "term1" below, so ensure that the search term that |
| 1666 // got added to history already is that string. | 1479 // got added to history already is that string. |
| 1667 ASSERT_EQ(ASCIIToUTF16("term1"), term1_); | 1480 ASSERT_EQ(ASCIIToUTF16("term1"), term1_); |
| 1668 string16 term = term1_.substr(0, term1_.length() - 1); | 1481 string16 term = term1_.substr(0, term1_.length() - 1); |
| 1669 | 1482 |
| 1670 AddSearchToHistory(default_t_url_, term + ASCIIToUTF16("2"), 2); | 1483 AddSearchToHistory(default_t_url_, term + ASCIIToUTF16("2"), 2); |
| 1671 profile_.BlockUntilHistoryProcessesPendingRequests(); | 1484 profile_.BlockUntilHistoryProcessesPendingRequests(); |
| 1672 | 1485 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"NAVIGATION\"," | 1543 "{\"google:suggesttype\":[\"QUERY\", \"QUERY\", \"NAVIGATION\"," |
| 1731 "\"NAVIGATION\"]," | 1544 "\"NAVIGATION\"]," |
| 1732 // A verbatim query for URL-like input scores 850, so the navigation | 1545 // A verbatim query for URL-like input scores 850, so the navigation |
| 1733 // scores here should bracket it. | 1546 // scores here should bracket it. |
| 1734 "\"google:suggestrelevance\":[9999, 9998, 900, 800]}]", | 1547 "\"google:suggestrelevance\":[9999, 9998, 900, 800]}]", |
| 1735 { "a.com/1", "a.com", "a.com/2", "a1", kNotApplicable, kNotApplicable } }, | 1548 { "a.com/1", "a.com", "a.com/2", "a1", kNotApplicable, kNotApplicable } }, |
| 1736 }; | 1549 }; |
| 1737 | 1550 |
| 1738 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) { | 1551 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) { |
| 1739 QueryForInput(cases[i].input, false, false); | 1552 QueryForInput(cases[i].input, false, false); |
| 1740 provider_->FinalizeInstantQuery(string16(), InstantSuggestion()); | |
| 1741 net::TestURLFetcher* fetcher = WaitUntilURLFetcherIsReady( | 1553 net::TestURLFetcher* fetcher = WaitUntilURLFetcherIsReady( |
| 1742 SearchProvider::kDefaultProviderURLFetcherID); | 1554 SearchProvider::kDefaultProviderURLFetcherID); |
| 1743 ASSERT_TRUE(fetcher); | 1555 ASSERT_TRUE(fetcher); |
| 1744 fetcher->set_response_code(200); | 1556 fetcher->set_response_code(200); |
| 1745 fetcher->SetResponseString(cases[i].json); | 1557 fetcher->SetResponseString(cases[i].json); |
| 1746 fetcher->delegate()->OnURLFetchComplete(fetcher); | 1558 fetcher->delegate()->OnURLFetchComplete(fetcher); |
| 1747 RunTillProviderDone(); | 1559 RunTillProviderDone(); |
| 1748 | 1560 |
| 1749 const std::string description = "for input with json=" + cases[i].json; | 1561 const std::string description = "for input with json=" + cases[i].json; |
| 1750 const ACMatches& matches = provider_->matches(); | 1562 const ACMatches& matches = provider_->matches(); |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2271 } else { | 2083 } else { |
| 2272 ASSERT_NE(sug_end, sug_it) << "Failed to find " << suggestion; | 2084 ASSERT_NE(sug_end, sug_it) << "Failed to find " << suggestion; |
| 2273 EXPECT_EQ(ASCIIToUTF16(suggestion), sug_it->suggestion()); | 2085 EXPECT_EQ(ASCIIToUTF16(suggestion), sug_it->suggestion()); |
| 2274 ++sug_it; | 2086 ++sug_it; |
| 2275 } | 2087 } |
| 2276 } | 2088 } |
| 2277 EXPECT_EQ(sug_end, sug_it); | 2089 EXPECT_EQ(sug_end, sug_it); |
| 2278 EXPECT_EQ(nav_end, nav_it); | 2090 EXPECT_EQ(nav_end, nav_it); |
| 2279 } | 2091 } |
| 2280 } | 2092 } |
| OLD | NEW |