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(GetRequestContext
, net::URLRequestContextGetter
*());
29 MOCK_METHOD0(GetSchemeClassifier
, const AutocompleteSchemeClassifier
&());
30 MOCK_METHOD0(GetHistoryService
, history::HistoryService
*());
31 MOCK_METHOD0(GetBookmarkModel
, bookmarks::BookmarkModel
*());
32 MOCK_METHOD0(GetInMemoryDatabase
, history::URLDatabase
*());
33 MOCK_METHOD0(GetTemplateURLService
, TemplateURLService
*());
34 MOCK_METHOD0(GetSearchTermsData
, const SearchTermsData
&());
36 // Can't mock scoped_refptr :\.
37 scoped_refptr
<ShortcutsBackend
> GetShortcutsBackend() override
{
40 scoped_refptr
<ShortcutsBackend
> GetShortcutsBackendIfExists() override
{
44 MOCK_METHOD0(GetAcceptLanguages
, std::string());
45 MOCK_METHOD0(IsOffTheRecord
, bool());
46 MOCK_METHOD0(SearchSuggestEnabled
, bool());
47 MOCK_METHOD0(ShowBookmarkBar
, bool());
48 MOCK_METHOD0(TabSyncEnabledAndUnencrypted
, bool());
51 void(const base::string16
& text
,
53 bool allow_exact_keyword_match
,
54 metrics::OmniboxEventProto::PageClassification page_classification
,
55 AutocompleteMatch
* match
,
56 GURL
* alternate_nav_url
));
57 MOCK_METHOD2(DeleteMatchingURLsForKeywordFromHistory
,
58 void(history::KeywordID keyword_id
, const base::string16
& term
));
59 MOCK_METHOD1(PrefetchImage
, void(const GURL
& url
));
62 DISALLOW_COPY_AND_ASSIGN(MockAutocompleteProviderClient
);
65 class TestBaseSearchProvider
: public BaseSearchProvider
{
67 typedef BaseSearchProvider::MatchMap MatchMap
;
69 TestBaseSearchProvider(AutocompleteProvider::Type type
,
70 AutocompleteProviderClient
* client
,
71 TemplateURLService
* template_url_service
)
72 : BaseSearchProvider(type
, client
, template_url_service
) {}
73 MOCK_METHOD1(DeleteMatch
, void(const AutocompleteMatch
& match
));
74 MOCK_CONST_METHOD1(AddProviderInfo
, void(ProvidersInfo
* provider_info
));
75 MOCK_CONST_METHOD1(GetTemplateURL
, const TemplateURL
*(bool is_keyword
));
76 MOCK_CONST_METHOD1(GetInput
, const AutocompleteInput(bool is_keyword
));
77 MOCK_CONST_METHOD1(ShouldAppendExtraParams
,
78 bool(const SearchSuggestionParser::SuggestResult
& result
));
79 MOCK_METHOD1(RecordDeletionResult
, void(bool success
));
82 void(const AutocompleteInput
& input
, bool minimal_changes
));
83 void AddMatchToMap(const SearchSuggestionParser::SuggestResult
& result
,
84 const std::string
& metadata
,
85 int accepted_suggestion
,
86 bool mark_as_deletable
,
89 BaseSearchProvider::AddMatchToMap(result
,
98 virtual ~TestBaseSearchProvider() {}
101 DISALLOW_COPY_AND_ASSIGN(TestBaseSearchProvider
);
104 class BaseSearchProviderTest
: public testing::Test
{
106 ~BaseSearchProviderTest() override
{}
109 void SetUp() override
{
111 new TemplateURLService(NULL
,
112 scoped_ptr
<SearchTermsData
>(new SearchTermsData
),
114 scoped_ptr
<TemplateURLServiceClient
>(),
118 client_
.reset(new NiceMock
<MockAutocompleteProviderClient
>());
119 provider_
= new NiceMock
<TestBaseSearchProvider
>(
120 AutocompleteProvider::TYPE_SEARCH
, client_
.get(), service_
.get());
123 scoped_refptr
<NiceMock
<TestBaseSearchProvider
> > provider_
;
124 scoped_ptr
<TemplateURLService
> service_
;
125 scoped_ptr
<NiceMock
<MockAutocompleteProviderClient
>> client_
;
128 TEST_F(BaseSearchProviderTest
, PreserveAnswersWhenDeduplicating
) {
129 TemplateURLData data
;
130 data
.SetURL("http://foo.com/url?bar={searchTerms}");
131 scoped_ptr
<TemplateURL
> template_url(new TemplateURL(data
));
133 TestBaseSearchProvider::MatchMap map
;
134 base::string16 query
= base::ASCIIToUTF16("weather los angeles");
135 base::string16 answer_contents
= base::ASCIIToUTF16("some answer content");
136 base::string16 answer_type
= base::ASCIIToUTF16("2334");
137 scoped_ptr
<SuggestionAnswer
> answer(new SuggestionAnswer());
138 answer
->set_type(2334);
140 EXPECT_CALL(*provider_
, GetInput(_
))
141 .WillRepeatedly(Return(AutocompleteInput()));
142 EXPECT_CALL(*provider_
, GetTemplateURL(_
))
143 .WillRepeatedly(Return(template_url
.get()));
145 SearchSuggestionParser::SuggestResult
more_relevant(
146 query
, AutocompleteMatchType::SEARCH_HISTORY
, query
, base::string16(),
147 base::string16(), base::string16(), base::string16(), nullptr,
148 std::string(), std::string(), false, 1300, true, false, query
);
149 provider_
->AddMatchToMap(
150 more_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
153 SearchSuggestionParser::SuggestResult
less_relevant(
154 query
, AutocompleteMatchType::SEARCH_SUGGEST
, query
, base::string16(),
155 base::string16(), answer_contents
, answer_type
,
156 SuggestionAnswer::copy(answer
.get()), std::string(), std::string(),
157 false, 850, true, false, query
);
158 provider_
->AddMatchToMap(
159 less_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
162 ASSERT_EQ(1U, map
.size());
163 AutocompleteMatch match
= map
.begin()->second
;
164 ASSERT_EQ(1U, match
.duplicate_matches
.size());
165 AutocompleteMatch duplicate
= match
.duplicate_matches
[0];
167 EXPECT_EQ(answer_contents
, match
.answer_contents
);
168 EXPECT_EQ(answer_type
, match
.answer_type
);
169 EXPECT_TRUE(answer
->Equals(*match
.answer
));
170 EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY
, match
.type
);
171 EXPECT_EQ(1300, match
.relevance
);
173 EXPECT_EQ(answer_contents
, duplicate
.answer_contents
);
174 EXPECT_EQ(answer_type
, duplicate
.answer_type
);
175 EXPECT_TRUE(answer
->Equals(*duplicate
.answer
));
176 EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST
, duplicate
.type
);
177 EXPECT_EQ(850, duplicate
.relevance
);
179 // Ensure answers are not copied over existing answers.
181 base::string16 answer_contents2
= base::ASCIIToUTF16("different answer");
182 base::string16 answer_type2
= base::ASCIIToUTF16("8242");
183 scoped_ptr
<SuggestionAnswer
> answer2(new SuggestionAnswer());
184 answer2
->set_type(8242);
185 more_relevant
= SearchSuggestionParser::SuggestResult(
186 query
, AutocompleteMatchType::SEARCH_HISTORY
, query
, base::string16(),
187 base::string16(), answer_contents2
, answer_type2
,
188 SuggestionAnswer::copy(answer2
.get()), std::string(), std::string(),
189 false, 1300, true, false, query
);
190 provider_
->AddMatchToMap(
191 more_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
193 provider_
->AddMatchToMap(
194 less_relevant
, std::string(), TemplateURLRef::NO_SUGGESTION_CHOSEN
,
196 ASSERT_EQ(1U, map
.size());
197 match
= map
.begin()->second
;
198 ASSERT_EQ(1U, match
.duplicate_matches
.size());
199 duplicate
= match
.duplicate_matches
[0];
201 EXPECT_EQ(answer_contents2
, match
.answer_contents
);
202 EXPECT_EQ(answer_type2
, match
.answer_type
);
203 EXPECT_TRUE(answer2
->Equals(*match
.answer
));
204 EXPECT_EQ(AutocompleteMatchType::SEARCH_HISTORY
, match
.type
);
205 EXPECT_EQ(1300, match
.relevance
);
207 EXPECT_EQ(answer_contents
, duplicate
.answer_contents
);
208 EXPECT_EQ(answer_type
, duplicate
.answer_type
);
209 EXPECT_TRUE(answer
->Equals(*duplicate
.answer
));
210 EXPECT_EQ(AutocompleteMatchType::SEARCH_SUGGEST
, duplicate
.type
);
211 EXPECT_EQ(850, duplicate
.relevance
);