OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/string16.h" | 8 #include "base/string16.h" |
9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "content/public/browser/notification_registrar.h" | 23 #include "content/public/browser/notification_registrar.h" |
24 #include "content/public/browser/notification_source.h" | 24 #include "content/public/browser/notification_source.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
26 | 26 |
27 static std::ostream& operator<<(std::ostream& os, | 27 static std::ostream& operator<<(std::ostream& os, |
28 const AutocompleteResult::const_iterator& it) { | 28 const AutocompleteResult::const_iterator& it) { |
29 return os << static_cast<const AutocompleteMatch*>(&(*it)); | 29 return os << static_cast<const AutocompleteMatch*>(&(*it)); |
30 } | 30 } |
31 | 31 |
32 namespace { | 32 namespace { |
33 const size_t kResultsPerProvider = 3; | 33 |
34 } | 34 const size_t num_results_per_provider = 3; |
35 | 35 |
36 // Autocomplete provider that provides known results. Note that this is | 36 // Autocomplete provider that provides known results. Note that this is |
37 // refcounted so that it can also be a task on the message loop. | 37 // refcounted so that it can also be a task on the message loop. |
38 class TestProvider : public AutocompleteProvider { | 38 class TestProvider : public AutocompleteProvider { |
39 public: | 39 public: |
40 TestProvider(int relevance, const string16& prefix) | 40 TestProvider(int relevance, const string16& prefix) |
41 : AutocompleteProvider(NULL, NULL, ""), | 41 : AutocompleteProvider(NULL, NULL, ""), |
42 relevance_(relevance), | 42 relevance_(relevance), |
43 prefix_(prefix) { | 43 prefix_(prefix) { |
44 } | 44 } |
(...skipping 27 matching lines...) Expand all Loading... |
72 AddResults(0, 1); | 72 AddResults(0, 1); |
73 | 73 |
74 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { | 74 if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) { |
75 done_ = false; | 75 done_ = false; |
76 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&TestProvider::Run, | 76 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&TestProvider::Run, |
77 this)); | 77 this)); |
78 } | 78 } |
79 } | 79 } |
80 | 80 |
81 void TestProvider::Run() { | 81 void TestProvider::Run() { |
82 DCHECK_GT(kResultsPerProvider, 0U); | 82 DCHECK_GT(num_results_per_provider, 0U); |
83 AddResults(1, kResultsPerProvider); | 83 AddResults(1, num_results_per_provider); |
84 done_ = true; | 84 done_ = true; |
85 DCHECK(listener_); | 85 DCHECK(listener_); |
86 listener_->OnProviderUpdate(true); | 86 listener_->OnProviderUpdate(true); |
87 } | 87 } |
88 | 88 |
89 void TestProvider::AddResults(int start_at, int num) { | 89 void TestProvider::AddResults(int start_at, int num) { |
90 for (int i = start_at; i < num; i++) { | 90 for (int i = start_at; i < num; i++) { |
91 AutocompleteMatch match(this, relevance_ - i, false, | 91 AutocompleteMatch match(this, relevance_ - i, false, |
92 AutocompleteMatch::URL_WHAT_YOU_TYPED); | 92 AutocompleteMatch::URL_WHAT_YOU_TYPED); |
93 | 93 |
94 match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); | 94 match.fill_into_edit = prefix_ + UTF8ToUTF16(base::IntToString(i)); |
95 match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit)); | 95 match.destination_url = GURL(UTF16ToUTF8(match.fill_into_edit)); |
96 | 96 |
97 match.contents = match.fill_into_edit; | 97 match.contents = match.fill_into_edit; |
98 match.contents_class.push_back( | 98 match.contents_class.push_back( |
99 ACMatchClassification(0, ACMatchClassification::NONE)); | 99 ACMatchClassification(0, ACMatchClassification::NONE)); |
100 match.description = match.fill_into_edit; | 100 match.description = match.fill_into_edit; |
101 match.description_class.push_back( | 101 match.description_class.push_back( |
102 ACMatchClassification(0, ACMatchClassification::NONE)); | 102 ACMatchClassification(0, ACMatchClassification::NONE)); |
103 | 103 |
104 matches_.push_back(match); | 104 matches_.push_back(match); |
105 } | 105 } |
106 } | 106 } |
107 | 107 |
108 class AutocompleteProviderTest : public testing::Test, | 108 class AutocompleteProviderTest : public testing::Test, |
109 public content::NotificationObserver { | 109 public content::NotificationObserver { |
110 protected: | 110 protected: |
111 struct KeywordTestData { | |
112 const string16 fill_into_edit; | |
113 const string16 keyword; | |
114 const bool expected_keyword_result; | |
115 }; | |
116 | |
117 protected: | |
118 void ResetControllerWithTestProviders(bool same_destinations); | 111 void ResetControllerWithTestProviders(bool same_destinations); |
119 | 112 |
120 // Runs a query on the input "a", and makes sure both providers' input is | 113 // Runs a query on the input "a", and makes sure both providers' input is |
121 // properly collected. | 114 // properly collected. |
122 void RunTest(); | 115 void RunTest(); |
123 | 116 |
124 void RunRedundantKeywordTest(const KeywordTestData* match_data, size_t size); | |
125 | |
126 void RunQuery(const string16 query); | |
127 | |
128 void ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); | 117 void ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); |
129 void ResetControllerWithKeywordProvider(); | |
130 void RunExactKeymatchTest(bool allow_exact_keyword_match); | 118 void RunExactKeymatchTest(bool allow_exact_keyword_match); |
131 | 119 |
132 // These providers are owned by the controller once it's created. | 120 // These providers are owned by the controller once it's created. |
133 ACProviders providers_; | 121 ACProviders providers_; |
134 | 122 |
135 AutocompleteResult result_; | 123 AutocompleteResult result_; |
136 scoped_ptr<AutocompleteController> controller_; | |
137 | 124 |
138 private: | 125 private: |
139 // content::NotificationObserver | 126 // content::NotificationObserver |
140 virtual void Observe(int type, | 127 virtual void Observe(int type, |
141 const content::NotificationSource& source, | 128 const content::NotificationSource& source, |
142 const content::NotificationDetails& details); | 129 const content::NotificationDetails& details); |
143 | 130 |
144 MessageLoopForUI message_loop_; | 131 MessageLoopForUI message_loop_; |
| 132 scoped_ptr<AutocompleteController> controller_; |
145 content::NotificationRegistrar registrar_; | 133 content::NotificationRegistrar registrar_; |
146 TestingProfile profile_; | 134 TestingProfile profile_; |
147 }; | 135 }; |
148 | 136 |
149 void AutocompleteProviderTest::ResetControllerWithTestProviders( | 137 void AutocompleteProviderTest::ResetControllerWithTestProviders( |
150 bool same_destinations) { | 138 bool same_destinations) { |
151 // Forget about any existing providers. The controller owns them and will | 139 // Forget about any existing providers. The controller owns them and will |
152 // Release() them below, when we delete it during the call to reset(). | 140 // Release() them below, when we delete it during the call to reset(). |
153 providers_.clear(); | 141 providers_.clear(); |
154 | 142 |
155 // Construct two new providers, with either the same or different prefixes. | 143 // Construct two new providers, with either the same or different prefixes. |
156 TestProvider* providerA = new TestProvider(kResultsPerProvider, | 144 TestProvider* providerA = new TestProvider(num_results_per_provider, |
157 ASCIIToUTF16("http://a")); | 145 ASCIIToUTF16("http://a")); |
158 providerA->AddRef(); | 146 providerA->AddRef(); |
159 providers_.push_back(providerA); | 147 providers_.push_back(providerA); |
160 | 148 |
161 TestProvider* providerB = new TestProvider(kResultsPerProvider * 2, | 149 TestProvider* providerB = new TestProvider(num_results_per_provider * 2, |
162 same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b")); | 150 same_destinations ? ASCIIToUTF16("http://a") : ASCIIToUTF16("http://b")); |
163 providerB->AddRef(); | 151 providerB->AddRef(); |
164 providers_.push_back(providerB); | 152 providers_.push_back(providerB); |
165 | 153 |
166 // Reset the controller to contain our new providers. | 154 // Reset the controller to contain our new providers. |
167 AutocompleteController* controller = | 155 AutocompleteController* controller = |
168 new AutocompleteController(providers_, &profile_); | 156 new AutocompleteController(providers_, &profile_); |
169 controller_.reset(controller); | 157 controller_.reset(controller); |
170 providerA->set_listener(controller); | 158 providerA->set_listener(controller); |
171 providerB->set_listener(controller); | 159 providerB->set_listener(controller); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 // Create both a keyword and search provider, and add them in that order. | 194 // Create both a keyword and search provider, and add them in that order. |
207 // (Order is important; see comments in RunExactKeymatchTest().) | 195 // (Order is important; see comments in RunExactKeymatchTest().) |
208 AutocompleteProvider* keyword_provider = new KeywordProvider(NULL, | 196 AutocompleteProvider* keyword_provider = new KeywordProvider(NULL, |
209 &profile_); | 197 &profile_); |
210 keyword_provider->AddRef(); | 198 keyword_provider->AddRef(); |
211 providers_.push_back(keyword_provider); | 199 providers_.push_back(keyword_provider); |
212 AutocompleteProvider* search_provider = new SearchProvider(NULL, &profile_); | 200 AutocompleteProvider* search_provider = new SearchProvider(NULL, &profile_); |
213 search_provider->AddRef(); | 201 search_provider->AddRef(); |
214 providers_.push_back(search_provider); | 202 providers_.push_back(search_provider); |
215 | 203 |
216 controller_.reset(new AutocompleteController(providers_, &profile_)); | |
217 } | |
218 | |
219 void AutocompleteProviderTest:: | |
220 ResetControllerWithKeywordProvider() { | |
221 profile_.CreateTemplateURLService(); | |
222 | |
223 TemplateURLService* turl_model = | |
224 TemplateURLServiceFactory::GetForProfile(&profile_); | |
225 | |
226 // Create a TemplateURL for KeywordProvider. | |
227 TemplateURL* keyword_t_url = new TemplateURL(); | |
228 keyword_t_url->set_short_name(ASCIIToUTF16("foo.com")); | |
229 keyword_t_url->set_keyword(ASCIIToUTF16("foo.com")); | |
230 keyword_t_url->SetURL("http://foo.com/{searchTerms}", 0, 0); | |
231 turl_model->Add(keyword_t_url); | |
232 ASSERT_NE(0, keyword_t_url->id()); | |
233 | |
234 // Create another TemplateURL for KeywordProvider. | |
235 keyword_t_url = new TemplateURL(); | |
236 keyword_t_url->set_short_name(ASCIIToUTF16("bar.com")); | |
237 keyword_t_url->set_keyword(ASCIIToUTF16("bar.com")); | |
238 keyword_t_url->SetURL("http://bar.com/{searchTerms}", 0, 0); | |
239 turl_model->Add(keyword_t_url); | |
240 ASSERT_NE(0, keyword_t_url->id()); | |
241 | |
242 // Forget about any existing providers. The controller owns them and will | |
243 // Release() them below, when we delete it during the call to reset(). | |
244 providers_.clear(); | |
245 | |
246 // Create both a keyword and search provider, and add them in that order. | |
247 // (Order is important; see comments in RunExactKeymatchTest().) | |
248 KeywordProvider* keyword_provider = new KeywordProvider(NULL, | |
249 &profile_); | |
250 keyword_provider->AddRef(); | |
251 providers_.push_back(keyword_provider); | |
252 | |
253 AutocompleteController* controller = | 204 AutocompleteController* controller = |
254 new AutocompleteController(providers_, &profile_); | 205 new AutocompleteController(providers_, &profile_); |
255 controller->set_keyword_provider(keyword_provider); | |
256 controller_.reset(controller); | 206 controller_.reset(controller); |
257 } | 207 } |
258 | 208 |
259 void AutocompleteProviderTest::RunTest() { | 209 void AutocompleteProviderTest::RunTest() { |
260 RunQuery(ASCIIToUTF16("a")); | 210 result_.Reset(); |
261 } | 211 controller_->Start(ASCIIToUTF16("a"), string16(), true, false, true, |
| 212 AutocompleteInput::ALL_MATCHES); |
262 | 213 |
263 void AutocompleteProviderTest::RunRedundantKeywordTest( | 214 // The message loop will terminate when all autocomplete input has been |
264 const KeywordTestData* match_data, | 215 // collected. |
265 size_t size) { | 216 MessageLoop::current()->Run(); |
266 ACMatches matches; | |
267 for (size_t i = 0; i < size; ++i) { | |
268 AutocompleteMatch match; | |
269 match.fill_into_edit = match_data[i].fill_into_edit; | |
270 match.keyword = match_data[i].keyword; | |
271 matches.push_back(match); | |
272 } | |
273 | |
274 AutocompleteResult result; | |
275 result.AppendMatches(matches); | |
276 controller_->UpdateAssociatedKeywords(&result); | |
277 | |
278 for (size_t j = 0; j < result.size(); ++j) { | |
279 EXPECT_EQ(match_data[j].expected_keyword_result, | |
280 result.match_at(j).associated_keyword.get() != NULL); | |
281 } | |
282 } | |
283 | |
284 | |
285 void AutocompleteProviderTest::RunQuery(const string16 query) { | |
286 result_.Reset(); | |
287 controller_->Start(query, string16(), true, false, true, | |
288 AutocompleteInput::ALL_MATCHES); | |
289 | |
290 if (!controller_->done()) | |
291 // The message loop will terminate when all autocomplete input has been | |
292 // collected. | |
293 MessageLoop::current()->Run(); | |
294 } | 217 } |
295 | 218 |
296 void AutocompleteProviderTest::RunExactKeymatchTest( | 219 void AutocompleteProviderTest::RunExactKeymatchTest( |
297 bool allow_exact_keyword_match) { | 220 bool allow_exact_keyword_match) { |
298 // Send the controller input which exactly matches the keyword provider we | 221 // Send the controller input which exactly matches the keyword provider we |
299 // created in ResetControllerWithKeywordAndSearchProviders(). The default | 222 // created in ResetControllerWithKeywordAndSearchProviders(). The default |
300 // match should thus be a keyword match iff |allow_exact_keyword_match| is | 223 // match should thus be a keyword match iff |allow_exact_keyword_match| is |
301 // true. | 224 // true. |
302 controller_->Start(ASCIIToUTF16("k test"), string16(), true, false, | 225 controller_->Start(ASCIIToUTF16("k test"), string16(), true, false, |
303 allow_exact_keyword_match, | 226 allow_exact_keyword_match, |
(...skipping 16 matching lines...) Expand all Loading... |
320 } | 243 } |
321 } | 244 } |
322 | 245 |
323 // Tests that the default selection is set properly when updating results. | 246 // Tests that the default selection is set properly when updating results. |
324 TEST_F(AutocompleteProviderTest, Query) { | 247 TEST_F(AutocompleteProviderTest, Query) { |
325 ResetControllerWithTestProviders(false); | 248 ResetControllerWithTestProviders(false); |
326 RunTest(); | 249 RunTest(); |
327 | 250 |
328 // Make sure the default match gets set to the highest relevance match. The | 251 // Make sure the default match gets set to the highest relevance match. The |
329 // highest relevance matches should come from the second provider. | 252 // highest relevance matches should come from the second provider. |
330 EXPECT_EQ(kResultsPerProvider * 2, result_.size()); // two providers | 253 EXPECT_EQ(num_results_per_provider * 2, result_.size()); // two providers |
331 ASSERT_NE(result_.end(), result_.default_match()); | 254 ASSERT_NE(result_.end(), result_.default_match()); |
332 EXPECT_EQ(providers_[1], result_.default_match()->provider); | 255 EXPECT_EQ(providers_[1], result_.default_match()->provider); |
333 } | 256 } |
334 | 257 |
335 TEST_F(AutocompleteProviderTest, RemoveDuplicates) { | 258 TEST_F(AutocompleteProviderTest, RemoveDuplicates) { |
336 ResetControllerWithTestProviders(true); | 259 ResetControllerWithTestProviders(true); |
337 RunTest(); | 260 RunTest(); |
338 | 261 |
339 // Make sure all the first provider's results were eliminated by the second | 262 // Make sure all the first provider's results were eliminated by the second |
340 // provider's. | 263 // provider's. |
341 EXPECT_EQ(kResultsPerProvider, result_.size()); | 264 EXPECT_EQ(num_results_per_provider, result_.size()); |
342 for (AutocompleteResult::const_iterator i(result_.begin()); | 265 for (AutocompleteResult::const_iterator i(result_.begin()); |
343 i != result_.end(); ++i) | 266 i != result_.end(); ++i) |
344 EXPECT_EQ(providers_[1], i->provider); | 267 EXPECT_EQ(providers_[1], i->provider); |
345 } | 268 } |
346 | 269 |
347 TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { | 270 TEST_F(AutocompleteProviderTest, AllowExactKeywordMatch) { |
348 ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); | 271 ResetControllerWithTestProvidersWithKeywordAndSearchProviders(); |
349 RunExactKeymatchTest(true); | 272 RunExactKeymatchTest(true); |
350 RunExactKeymatchTest(false); | 273 RunExactKeymatchTest(false); |
351 } | 274 } |
352 | 275 |
353 // Test that redundant associated keywords are removed. | |
354 TEST_F(AutocompleteProviderTest, RedundantKeywordsIgnoredInResult) { | |
355 ResetControllerWithKeywordProvider(); | |
356 | |
357 // Get the controller's internal members in the correct state. | |
358 RunQuery(ASCIIToUTF16("fo")); | |
359 | |
360 { | |
361 KeywordTestData duplicate_url[] = { | |
362 { ASCIIToUTF16("fo"), string16(), false }, | |
363 { ASCIIToUTF16("foo.com"), string16(), true }, | |
364 { ASCIIToUTF16("foo.com"), string16(), false } | |
365 }; | |
366 | |
367 SCOPED_TRACE("Duplicate url"); | |
368 RunRedundantKeywordTest(duplicate_url, ARRAYSIZE_UNSAFE(duplicate_url)); | |
369 } | |
370 | |
371 { | |
372 KeywordTestData keyword_match[] = { | |
373 { ASCIIToUTF16("foo.com"), ASCIIToUTF16("foo.com"), false }, | |
374 { ASCIIToUTF16("foo.com"), string16(), false } | |
375 }; | |
376 | |
377 SCOPED_TRACE("Duplicate url with keyword match"); | |
378 RunRedundantKeywordTest(keyword_match, ARRAYSIZE_UNSAFE(keyword_match)); | |
379 } | |
380 | |
381 { | |
382 KeywordTestData multiple_keyword[] = { | |
383 { ASCIIToUTF16("fo"), string16(), false }, | |
384 { ASCIIToUTF16("foo.com"), string16(), true }, | |
385 { ASCIIToUTF16("foo.com"), string16(), false }, | |
386 { ASCIIToUTF16("bar.com"), string16(), true }, | |
387 }; | |
388 | |
389 SCOPED_TRACE("Duplicate url with multiple keywords"); | |
390 RunRedundantKeywordTest(multiple_keyword, | |
391 ARRAYSIZE_UNSAFE(multiple_keyword)); | |
392 } | |
393 } | |
394 | |
395 typedef testing::Test AutocompleteTest; | 276 typedef testing::Test AutocompleteTest; |
396 | 277 |
397 TEST_F(AutocompleteTest, InputType) { | 278 TEST_F(AutocompleteTest, InputType) { |
398 struct test_data { | 279 struct test_data { |
399 const string16 input; | 280 const string16 input; |
400 const AutocompleteInput::Type type; | 281 const AutocompleteInput::Type type; |
401 } input_cases[] = { | 282 } input_cases[] = { |
402 { string16(), AutocompleteInput::INVALID }, | 283 { string16(), AutocompleteInput::INVALID }, |
403 { ASCIIToUTF16("?"), AutocompleteInput::FORCED_QUERY }, | 284 { ASCIIToUTF16("?"), AutocompleteInput::FORCED_QUERY }, |
404 { ASCIIToUTF16("?foo"), AutocompleteInput::FORCED_QUERY }, | 285 { ASCIIToUTF16("?foo"), AutocompleteInput::FORCED_QUERY }, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 &scheme, | 477 &scheme, |
597 &host); | 478 &host); |
598 AutocompleteInput input(input_cases[i].input, string16(), true, false, | 479 AutocompleteInput input(input_cases[i].input, string16(), true, false, |
599 true, AutocompleteInput::ALL_MATCHES); | 480 true, AutocompleteInput::ALL_MATCHES); |
600 EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin); | 481 EXPECT_EQ(input_cases[i].scheme.begin, scheme.begin); |
601 EXPECT_EQ(input_cases[i].scheme.len, scheme.len); | 482 EXPECT_EQ(input_cases[i].scheme.len, scheme.len); |
602 EXPECT_EQ(input_cases[i].host.begin, host.begin); | 483 EXPECT_EQ(input_cases[i].host.begin, host.begin); |
603 EXPECT_EQ(input_cases[i].host.len, host.len); | 484 EXPECT_EQ(input_cases[i].host.len, host.len); |
604 } | 485 } |
605 } | 486 } |
| 487 |
| 488 } // namespace |
OLD | NEW |