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/base_search_provider.h"
7 #include "base/strings/string16.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/omnibox/autocomplete_match.h"
10 #include "components/omnibox/autocomplete_match_type.h"
11 #include "components/omnibox/autocomplete_provider_client.h"
12 #include "components/omnibox/autocomplete_scheme_classifier.h"
13 #include "components/omnibox/search_suggestion_parser.h"
14 #include "components/omnibox/suggestion_answer.h"
15 #include "components/search_engines/search_terms_data.h"
16 #include "components/search_engines/template_url_service.h"
17 #include "components/search_engines/template_url_service_client.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using testing::NiceMock
;
22 using testing::Return
;
25 class MockAutocompleteProviderClient
: public AutocompleteProviderClient
{
27 MockAutocompleteProviderClient() {}
28 MOCK_METHOD0(RequestContext
, net::URLRequestContextGetter
*());
29 MOCK_METHOD0(IsOffTheRecord
, bool());
30 MOCK_METHOD0(AcceptLanguages
, std::string());
31 MOCK_METHOD0(SearchSuggestEnabled
, bool());
32 MOCK_METHOD0(ShowBookmarkBar
, bool());
33 MOCK_METHOD0(SchemeClassifier
, const AutocompleteSchemeClassifier
&());
36 void(const base::string16
& text
,
38 bool allow_exact_keyword_match
,
39 metrics::OmniboxEventProto::PageClassification page_classification
,
40 AutocompleteMatch
* match
,
41 GURL
* alternate_nav_url
));
42 MOCK_METHOD0(InMemoryDatabase
, history::URLDatabase
*());
43 MOCK_METHOD2(DeleteMatchingURLsForKeywordFromHistory
,
44 void(history::KeywordID keyword_id
, const base::string16
& term
));
45 MOCK_METHOD0(TabSyncEnabledAndUnencrypted
, bool());
46 MOCK_METHOD1(PrefetchImage
, void(const GURL
& url
));
49 DISALLOW_COPY_AND_ASSIGN(MockAutocompleteProviderClient
);
52 class TestBaseSearchProvider
: public BaseSearchProvider
{
54 typedef BaseSearchProvider::MatchMap MatchMap
;
56 // Note: Takes ownership of client. scoped_ptr<> would be the right way to
57 // express that, but NiceMock<> can't forward a scoped_ptr.
58 TestBaseSearchProvider(TemplateURLService
* template_url_service
,
59 AutocompleteProviderClient
* client
,
60 AutocompleteProvider::Type type
)
61 : BaseSearchProvider(template_url_service
,
62 scoped_ptr
<AutocompleteProviderClient
>(client
),
64 MOCK_METHOD1(DeleteMatch
, void(const AutocompleteMatch
& match
));
65 MOCK_CONST_METHOD1(AddProviderInfo
, void(ProvidersInfo
* provider_info
));
66 MOCK_CONST_METHOD1(GetTemplateURL
, const TemplateURL
*(bool is_keyword
));
67 MOCK_CONST_METHOD1(GetInput
, const AutocompleteInput(bool is_keyword
));
68 MOCK_CONST_METHOD1(ShouldAppendExtraParams
,
69 bool(const SearchSuggestionParser::SuggestResult
& result
));
70 MOCK_METHOD1(RecordDeletionResult
, void(bool success
));
73 void(const AutocompleteInput
& input
, bool minimal_changes
,
74 bool called_due_to_focus
));
75 void AddMatchToMap(const SearchSuggestionParser::SuggestResult
& result
,
76 const std::string
& metadata
,
77 int accepted_suggestion
,
78 bool mark_as_deletable
,
81 BaseSearchProvider::AddMatchToMap(result
,
90 virtual ~TestBaseSearchProvider() {}
93 DISALLOW_COPY_AND_ASSIGN(TestBaseSearchProvider
);
96 class BaseSearchProviderTest
: public testing::Test
{
98 ~BaseSearchProviderTest() override
{}
101 void SetUp() override
{
103 new TemplateURLService(NULL
,
104 scoped_ptr
<SearchTermsData
>(new SearchTermsData
),
106 scoped_ptr
<TemplateURLServiceClient
>(),
110 provider_
= new NiceMock
<TestBaseSearchProvider
>(
112 new NiceMock
<MockAutocompleteProviderClient
>,
113 AutocompleteProvider::TYPE_SEARCH
);
116 scoped_refptr
<NiceMock
<TestBaseSearchProvider
> > provider_
;
117 scoped_ptr
<TemplateURLService
> service_
;
120 TEST_F(BaseSearchProviderTest
, PreserveAnswersWhenDeduplicating
) {
121 TemplateURLData data
;
122 data
.SetURL("http://foo.com/url?bar={searchTerms}");
123 scoped_ptr
<TemplateURL
> template_url(new TemplateURL(data
));
125 TestBaseSearchProvider::MatchMap map
;
126 base::string16 query
= base::ASCIIToUTF16("weather los angeles");
127 base::string16 answer_contents
= base::ASCIIToUTF16("some answer content");
128 base::string16 answer_type
= base::ASCIIToUTF16("2334");
129 scoped_ptr
<SuggestionAnswer
> answer(new SuggestionAnswer());
130 answer
->set_type(2334);
132 EXPECT_CALL(*provider_
, GetInput(_
))
133 .WillRepeatedly(Return(AutocompleteInput()));
134 EXPECT_CALL(*provider_
, GetTemplateURL(_
))
135 .WillRepeatedly(Return(template_url
.get()));
137 SearchSuggestionParser::SuggestResult
more_relevant(
138 query
, AutocompleteMatchType::SEARCH_HISTORY
, query
, base::string16(),
139 base::string16(), base::string16(), base::string16(), nullptr,
140 std::string(), std::string(), false, 1300, true, false, query
);
141 provider_
->AddMatchToMap(
142 more_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
145 SearchSuggestionParser::SuggestResult
less_relevant(
146 query
, AutocompleteMatchType::SEARCH_SUGGEST
, query
, base::string16(),
147 base::string16(), answer_contents
, answer_type
,
148 SuggestionAnswer::copy(answer
.get()), std::string(), std::string(),
149 false, 850, true, false, query
);
150 provider_
->AddMatchToMap(
151 less_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
154 ASSERT_EQ(1U, map
.size());
155 AutocompleteMatch match
= map
.begin()->second
;
156 ASSERT_EQ(1U, match
.duplicate_matches
.size());
157 AutocompleteMatch duplicate
= match
.duplicate_matches
[0];
159 EXPECT_EQ(answer_contents
, match
.answer_contents
);
160 EXPECT_EQ(answer_type
, match
.answer_type
);
161 EXPECT_TRUE(answer
->Equals(*match
.answer
));
162 EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY
, match
.type
);
163 EXPECT_EQ(1300, match
.relevance
);
165 EXPECT_EQ(answer_contents
, duplicate
.answer_contents
);
166 EXPECT_EQ(answer_type
, duplicate
.answer_type
);
167 EXPECT_TRUE(answer
->Equals(*duplicate
.answer
));
168 EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST
, duplicate
.type
);
169 EXPECT_EQ(850, duplicate
.relevance
);
171 // Ensure answers are not copied over existing answers.
173 base::string16 answer_contents2
= base::ASCIIToUTF16("different answer");
174 base::string16 answer_type2
= base::ASCIIToUTF16("8242");
175 scoped_ptr
<SuggestionAnswer
> answer2(new SuggestionAnswer());
176 answer2
->set_type(8242);
177 more_relevant
= SearchSuggestionParser::SuggestResult(
178 query
, AutocompleteMatchType::SEARCH_HISTORY
, query
, base::string16(),
179 base::string16(), answer_contents2
, answer_type2
,
180 SuggestionAnswer::copy(answer2
.get()), std::string(), std::string(),
181 false, 1300, true, false, query
);
182 provider_
->AddMatchToMap(
183 more_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
185 provider_
->AddMatchToMap(
186 less_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
188 ASSERT_EQ(1U, map
.size());
189 match
= map
.begin()->second
;
190 ASSERT_EQ(1U, match
.duplicate_matches
.size());
191 duplicate
= match
.duplicate_matches
[0];
193 EXPECT_EQ(answer_contents2
, match
.answer_contents
);
194 EXPECT_EQ(answer_type2
, match
.answer_type
);
195 EXPECT_TRUE(answer2
->Equals(*match
.answer
));
196 EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY
, match
.type
);
197 EXPECT_EQ(1300, match
.relevance
);
199 EXPECT_EQ(answer_contents
, duplicate
.answer_contents
);
200 EXPECT_EQ(answer_type
, duplicate
.answer_type
);
201 EXPECT_TRUE(answer
->Equals(*duplicate
.answer
));
202 EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST
, duplicate
.type
);
203 EXPECT_EQ(850, duplicate
.relevance
);