Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(456)

Side by Side Diff: chrome/browser/autocomplete/history_url_provider_unittest.cc

Issue 1610283002: Componentizes history_url_provider_unittest.cc. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/chrome_tests_unit.gypi » ('j') | components/omnibox/browser/DEPS » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "components/omnibox/browser/history_url_provider.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10
11 #include "base/macros.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/time/time.h"
18 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
19 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
20 #include "chrome/browser/history/history_service_factory.h"
21 #include "chrome/browser/search_engines/chrome_template_url_service_client.h"
22 #include "chrome/browser/search_engines/template_url_service_factory.h"
23 #include "chrome/common/pref_names.h"
24 #include "chrome/test/base/testing_browser_process.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "components/history/core/browser/history_service.h"
27 #include "components/history/core/browser/url_database.h"
28 #include "components/metrics/proto/omnibox_event.pb.h"
29 #include "components/metrics/proto/omnibox_input_type.pb.h"
30 #include "components/omnibox/browser/autocomplete_match.h"
31 #include "components/omnibox/browser/autocomplete_provider.h"
32 #include "components/omnibox/browser/autocomplete_provider_listener.h"
33 #include "components/omnibox/browser/autocomplete_result.h"
34 #include "components/omnibox/browser/history_quick_provider.h"
35 #include "components/search_engines/default_search_manager.h"
36 #include "components/search_engines/search_terms_data.h"
37 #include "components/search_engines/template_url.h"
38 #include "components/search_engines/template_url_service.h"
39 #include "components/url_formatter/url_fixer.h"
40 #include "content/public/test/test_browser_thread_bundle.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42
43 using base::ASCIIToUTF16;
44 using base::Time;
45 using base::TimeDelta;
46
47 using content::TestBrowserThreadBundle;
48
49 struct TestURLInfo {
50 const char* url;
51 const char* title;
52 int visit_count;
53 int typed_count;
54 int age_in_days;
55 } test_db[] = {
56 {"http://www.google.com/", "Google", 3, 3, 80},
57
58 // High-quality pages should get a host synthesized as a lower-quality match.
59 {"http://slashdot.org/favorite_page.html", "Favorite page", 200, 100, 80},
60
61 // Less popular pages should have hosts synthesized as higher-quality
62 // matches.
63 {"http://kerneltrap.org/not_very_popular.html", "Less popular", 4, 0, 80},
64
65 // Unpopular pages should not appear in the results at all.
66 {"http://freshmeat.net/unpopular.html", "Unpopular", 1, 0, 80},
67
68 // If a host has a match, we should pick it up during host synthesis.
69 {"http://news.google.com/?ned=us&topic=n", "Google News - U.S.", 2, 2, 80},
70 {"http://news.google.com/", "Google News", 1, 1, 80},
71
72 // Matches that are normally not inline-autocompletable should be
73 // autocompleted if they are shorter substitutes for longer matches that would
74 // have been inline autocompleted.
75 {"http://synthesisatest.com/foo/", "Test A", 1, 1, 80},
76 {"http://synthesisbtest.com/foo/", "Test B", 1, 1, 80},
77 {"http://synthesisbtest.com/foo/bar.html", "Test B Bar", 2, 2, 80},
78
79 // Suggested short URLs must be "good enough" and must match user input.
80 {"http://foo.com/", "Dir", 5, 5, 80},
81 {"http://foo.com/dir/", "Dir", 2, 2, 80},
82 {"http://foo.com/dir/another/", "Dir", 5, 1, 80},
83 {"http://foo.com/dir/another/again/", "Dir", 10, 0, 80},
84 {"http://foo.com/dir/another/again/myfile.html", "File", 10, 2, 80},
85
86 // We throw in a lot of extra URLs here to make sure we're testing the
87 // history database's query, not just the autocomplete provider.
88 {"http://startest.com/y/a", "A", 2, 2, 80},
89 {"http://startest.com/y/b", "B", 5, 2, 80},
90 {"http://startest.com/x/c", "C", 5, 2, 80},
91 {"http://startest.com/x/d", "D", 5, 5, 80},
92 {"http://startest.com/y/e", "E", 4, 2, 80},
93 {"http://startest.com/y/f", "F", 3, 2, 80},
94 {"http://startest.com/y/g", "G", 3, 2, 80},
95 {"http://startest.com/y/h", "H", 3, 2, 80},
96 {"http://startest.com/y/i", "I", 3, 2, 80},
97 {"http://startest.com/y/j", "J", 3, 2, 80},
98 {"http://startest.com/y/k", "K", 3, 2, 80},
99 {"http://startest.com/y/l", "L", 3, 2, 80},
100 {"http://startest.com/y/m", "M", 3, 2, 80},
101
102 // A file: URL is useful for testing that fixup does the right thing w.r.t.
103 // the number of trailing slashes on the user's input.
104 {"file:///C:/foo.txt", "", 2, 2, 80},
105
106 // Results with absurdly high typed_counts so that very generic queries like
107 // "http" will give consistent results even if more data is added above.
108 {"http://bogussite.com/a", "Bogus A", 10002, 10000, 80},
109 {"http://bogussite.com/b", "Bogus B", 10001, 10000, 80},
110 {"http://bogussite.com/c", "Bogus C", 10000, 10000, 80},
111
112 // Domain name with number.
113 {"http://www.17173.com/", "Domain with number", 3, 3, 80},
114
115 // URLs to test exact-matching behavior.
116 {"http://go/", "Intranet URL", 1, 1, 80},
117 {"http://gooey/", "Intranet URL 2", 5, 5, 80},
118
119 // URLs for testing offset adjustment.
120 {"http://www.\xEA\xB5\x90\xEC\x9C\xA1.kr/", "Korean", 2, 2, 80},
121 {"http://spaces.com/path%20with%20spaces/foo.html", "Spaces", 2, 2, 80},
122 {"http://ms/c++%20style%20guide", "Style guide", 2, 2, 80},
123
124 // URLs for testing ctrl-enter behavior.
125 {"http://binky/", "Intranet binky", 2, 2, 80},
126 {"http://winky/", "Intranet winky", 2, 2, 80},
127 {"http://www.winky.com/", "Internet winky", 5, 0, 80},
128
129 // URLs used by EmptyVisits.
130 {"http://pandora.com/", "Pandora", 2, 2, 80},
131 // This entry is explicitly added more recently than
132 // history::kLowQualityMatchAgeLimitInDays.
133 // {"http://pa/", "pa", 0, 0, 80},
134
135 // For intranet based tests.
136 {"http://intra/one", "Intranet", 2, 2, 80},
137 {"http://intra/two", "Intranet two", 1, 1, 80},
138 {"http://intra/three", "Intranet three", 2, 2, 80},
139 {"http://moo/bar", "Intranet moo", 1, 1, 80},
140 {"http://typedhost/typedpath", "Intranet typed", 1, 1, 80},
141 {"http://typedhost/untypedpath", "Intranet untyped", 1, 0, 80},
142
143 {"http://x.com/one", "Internet", 2, 2, 80},
144 {"http://x.com/two", "Internet two", 1, 1, 80},
145 {"http://x.com/three", "Internet three", 2, 2, 80},
146
147 // For punycode tests.
148 {"http://puny.xn--1lq90ic7f1rc.cn/", "Punycode", 2, 2, 5 },
149
150 // For experimental HUP scoring test.
151 {"http://7.com/1a", "One", 8, 4, 4},
152 {"http://7.com/2a", "Two A", 4, 2, 8},
153 {"http://7.com/2b", "Two B", 4, 1, 8},
154 {"http://7.com/3a", "Three", 2, 1, 16},
155 {"http://7.com/4a", "Four A", 1, 1, 32},
156 {"http://7.com/4b", "Four B", 1, 1, 64},
157 {"http://7.com/5a", "Five A", 8, 0, 64}, // never typed.
158 };
159
160 class HistoryURLProviderTest : public testing::Test,
161 public AutocompleteProviderListener {
162 public:
163 struct UrlAndLegalDefault {
164 std::string url;
165 bool allowed_to_be_default_match;
166 };
167
168 HistoryURLProviderTest()
169 : sort_matches_(false) {
170 HistoryQuickProvider::set_disabled(true);
171 }
172
173 ~HistoryURLProviderTest() override {
174 HistoryQuickProvider::set_disabled(false);
175 }
176
177 // AutocompleteProviderListener:
178 void OnProviderUpdate(bool updated_matches) override;
179
180 protected:
181 static scoped_ptr<KeyedService> CreateTemplateURLService(
182 content::BrowserContext* context) {
183 Profile* profile = static_cast<Profile*>(context);
184 return make_scoped_ptr(new TemplateURLService(
185 profile->GetPrefs(), make_scoped_ptr(new SearchTermsData), NULL,
186 scoped_ptr<TemplateURLServiceClient>(new ChromeTemplateURLServiceClient(
187 HistoryServiceFactory::GetForProfile(
188 profile, ServiceAccessType::EXPLICIT_ACCESS))),
189 NULL, NULL, base::Closure()));
190 }
191
192 // testing::Test
193 void SetUp() override {
194 ASSERT_TRUE(SetUpImpl(false));
195 }
196 void TearDown() override;
197
198 // Does the real setup.
199 bool SetUpImpl(bool no_db) WARN_UNUSED_RESULT;
200
201 // Fills test data into the history system.
202 void FillData();
203
204 // Runs an autocomplete query on |text| and checks to see that the returned
205 // results' destination URLs match those provided. Also allows checking
206 // that the input type was identified correctly.
207 void RunTest(const base::string16& text,
208 const std::string& desired_tld,
209 bool prevent_inline_autocomplete,
210 const UrlAndLegalDefault* expected_urls,
211 size_t num_results,
212 metrics::OmniboxInputType::Type* identified_input_type);
213
214 // A version of the above without the final |type| output parameter.
215 void RunTest(const base::string16& text,
216 const std::string& desired_tld,
217 bool prevent_inline_autocomplete,
218 const UrlAndLegalDefault* expected_urls,
219 size_t num_results) {
220 metrics::OmniboxInputType::Type type;
221 return RunTest(text, desired_tld, prevent_inline_autocomplete,
222 expected_urls, num_results, &type);
223 }
224
225 content::TestBrowserThreadBundle thread_bundle_;
226 ACMatches matches_;
227 scoped_ptr<TestingProfile> profile_;
228 scoped_ptr<ChromeAutocompleteProviderClient> client_;
229 history::HistoryService* history_service_;
230 scoped_refptr<HistoryURLProvider> autocomplete_;
231 // Should the matches be sorted and duplicates removed?
232 bool sort_matches_;
233 };
234
235 class HistoryURLProviderTestNoDB : public HistoryURLProviderTest {
236 protected:
237 void SetUp() override {
238 ASSERT_TRUE(SetUpImpl(true));
239 }
240 };
241
242 class HistoryURLProviderTestNoSearchProvider : public HistoryURLProviderTest {
243 protected:
244 void SetUp() override {
245 DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(true);
246 HistoryURLProviderTest::SetUp();
247 }
248
249 void TearDown() override {
250 HistoryURLProviderTest::TearDown();
251 DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(false);
252 }
253 };
254
255 void HistoryURLProviderTest::OnProviderUpdate(bool updated_matches) {
256 if (autocomplete_->done())
257 base::MessageLoop::current()->QuitWhenIdle();
258 }
259
260 bool HistoryURLProviderTest::SetUpImpl(bool no_db) {
261 profile_.reset(new TestingProfile());
262 client_.reset(new ChromeAutocompleteProviderClient(profile_.get()));
263 if (!(profile_->CreateHistoryService(true, no_db)))
264 return false;
265 if (!no_db) {
266 profile_->BlockUntilHistoryProcessesPendingRequests();
267 profile_->BlockUntilHistoryIndexIsRefreshed();
268 }
269 profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "en-US,en,ko");
270 history_service_ = HistoryServiceFactory::GetForProfile(
271 profile_.get(), ServiceAccessType::EXPLICIT_ACCESS);
272
273 autocomplete_ = new HistoryURLProvider(client_.get(), this);
274 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
275 profile_.get(), &HistoryURLProviderTest::CreateTemplateURLService);
276 FillData();
277 return true;
278 }
279
280 void HistoryURLProviderTest::TearDown() {
281 autocomplete_ = NULL;
282 }
283
284 void HistoryURLProviderTest::FillData() {
285 // Most visits are a long time ago (some tests require this since we do some
286 // special logic for things visited very recently). Note that this time must
287 // be more recent than the "expire history" threshold for the data to be kept
288 // in the main database.
289 //
290 // TODO(brettw) It would be nice if we could test this behavior, in which
291 // case the time would be specifed in the test_db structure.
292 const Time now = Time::Now();
293
294 for (size_t i = 0; i < arraysize(test_db); ++i) {
295 const TestURLInfo& cur = test_db[i];
296 const GURL current_url(cur.url);
297 history_service_->AddPageWithDetails(
298 current_url, base::UTF8ToUTF16(cur.title), cur.visit_count,
299 cur.typed_count, now - TimeDelta::FromDays(cur.age_in_days), false,
300 history::SOURCE_BROWSED);
301 }
302
303 history_service_->AddPageWithDetails(
304 GURL("http://pa/"), base::UTF8ToUTF16("pa"), 0, 0,
305 Time::Now() -
306 TimeDelta::FromDays(history::kLowQualityMatchAgeLimitInDays - 1),
307 false, history::SOURCE_BROWSED);
308 }
309
310 void HistoryURLProviderTest::RunTest(
311 const base::string16& text,
312 const std::string& desired_tld,
313 bool prevent_inline_autocomplete,
314 const UrlAndLegalDefault* expected_urls,
315 size_t num_results,
316 metrics::OmniboxInputType::Type* identified_input_type) {
317 AutocompleteInput input(text, base::string16::npos, desired_tld, GURL(),
318 metrics::OmniboxEventProto::INVALID_SPEC,
319 prevent_inline_autocomplete, false, true, true, false,
320 ChromeAutocompleteSchemeClassifier(profile_.get()));
321 *identified_input_type = input.type();
322 autocomplete_->Start(input, false);
323 if (!autocomplete_->done())
324 base::MessageLoop::current()->Run();
325
326 matches_ = autocomplete_->matches();
327 if (sort_matches_) {
328 TemplateURLService* service =
329 TemplateURLServiceFactory::GetForProfile(profile_.get());
330 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) {
331 i->ComputeStrippedDestinationURL(
332 input, client_->GetAcceptLanguages(), service);
333 }
334 AutocompleteResult::DedupMatchesByDestination(
335 input.current_page_classification(), false, &matches_);
336 std::sort(matches_.begin(), matches_.end(),
337 &AutocompleteMatch::MoreRelevant);
338 }
339 ASSERT_EQ(num_results, matches_.size()) << "Input text: " << text
340 << "\nTLD: \"" << desired_tld << "\"";
341 for (size_t i = 0; i < num_results; ++i) {
342 EXPECT_EQ(expected_urls[i].url, matches_[i].destination_url.spec());
343 EXPECT_EQ(expected_urls[i].allowed_to_be_default_match,
344 matches_[i].allowed_to_be_default_match);
345 }
346 }
347
348 TEST_F(HistoryURLProviderTest, PromoteShorterURLs) {
349 // Test that hosts get synthesized below popular pages.
350 const UrlAndLegalDefault expected_nonsynth[] = {
351 { "http://slashdot.org/favorite_page.html", false },
352 { "http://slashdot.org/", false }
353 };
354 RunTest(ASCIIToUTF16("slash"), std::string(), true, expected_nonsynth,
355 arraysize(expected_nonsynth));
356
357 // Test that hosts get synthesized above less popular pages.
358 const UrlAndLegalDefault expected_synth[] = {
359 { "http://kerneltrap.org/", false },
360 { "http://kerneltrap.org/not_very_popular.html", false }
361 };
362 RunTest(ASCIIToUTF16("kernel"), std::string(), true, expected_synth,
363 arraysize(expected_synth));
364
365 // Test that unpopular pages are ignored completely.
366 RunTest(ASCIIToUTF16("fresh"), std::string(), true, NULL, 0);
367
368 // Test that if we create or promote shorter suggestions that would not
369 // normally be inline autocompletable, we make them inline autocompletable if
370 // the original suggestion (that we replaced as "top") was inline
371 // autocompletable.
372 const UrlAndLegalDefault expected_synthesisa[] = {
373 { "http://synthesisatest.com/", true },
374 { "http://synthesisatest.com/foo/", true }
375 };
376 RunTest(ASCIIToUTF16("synthesisa"), std::string(), false, expected_synthesisa,
377 arraysize(expected_synthesisa));
378 EXPECT_LT(matches_.front().relevance, 1200);
379 const UrlAndLegalDefault expected_synthesisb[] = {
380 { "http://synthesisbtest.com/foo/", true },
381 { "http://synthesisbtest.com/foo/bar.html", true }
382 };
383 RunTest(ASCIIToUTF16("synthesisb"), std::string(), false, expected_synthesisb,
384 arraysize(expected_synthesisb));
385 EXPECT_GE(matches_.front().relevance, 1410);
386
387 // Test that if we have a synthesized host that matches a suggestion, they
388 // get combined into one.
389 const UrlAndLegalDefault expected_combine[] = {
390 { "http://news.google.com/", false },
391 { "http://news.google.com/?ned=us&topic=n", false },
392 };
393 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("news"), std::string(), true,
394 expected_combine,
395 arraysize(expected_combine)));
396 // The title should also have gotten set properly on the host for the
397 // synthesized one, since it was also in the results.
398 EXPECT_EQ(ASCIIToUTF16("Google News"), matches_.front().description);
399
400 // Test that short URL matching works correctly as the user types more
401 // (several tests):
402 // The entry for foo.com is the best of all five foo.com* entries.
403 const UrlAndLegalDefault short_1[] = {
404 { "http://foo.com/", false },
405 { "http://foo.com/dir/another/again/myfile.html", false },
406 { "http://foo.com/dir/", false }
407 };
408 RunTest(ASCIIToUTF16("foo"), std::string(), true, short_1,
409 arraysize(short_1));
410
411 // When the user types the whole host, make sure we don't get two results for
412 // it.
413 const UrlAndLegalDefault short_2[] = {
414 { "http://foo.com/", true },
415 { "http://foo.com/dir/another/again/myfile.html", false },
416 { "http://foo.com/dir/", false },
417 { "http://foo.com/dir/another/", false }
418 };
419 RunTest(ASCIIToUTF16("foo.com"), std::string(), true, short_2,
420 arraysize(short_2));
421 RunTest(ASCIIToUTF16("foo.com/"), std::string(), true, short_2,
422 arraysize(short_2));
423
424 // The filename is the second best of the foo.com* entries, but there is a
425 // shorter URL that's "good enough". The host doesn't match the user input
426 // and so should not appear.
427 const UrlAndLegalDefault short_3[] = {
428 { "http://foo.com/dir/another/", false },
429 { "http://foo.com/d", true },
430 { "http://foo.com/dir/another/again/myfile.html", false },
431 { "http://foo.com/dir/", false }
432 };
433 RunTest(ASCIIToUTF16("foo.com/d"), std::string(), true, short_3,
434 arraysize(short_3));
435 // If prevent_inline_autocomplete is false, we won't bother creating the
436 // URL-what-you-typed match because we have promoted inline autocompletions.
437 const UrlAndLegalDefault short_3_allow_inline[] = {
438 { "http://foo.com/dir/another/", true },
439 { "http://foo.com/dir/another/again/myfile.html", true },
440 { "http://foo.com/dir/", true }
441 };
442 RunTest(ASCIIToUTF16("foo.com/d"), std::string(), false, short_3_allow_inline,
443 arraysize(short_3_allow_inline));
444
445 // We shouldn't promote shorter URLs than the best if they're not good
446 // enough.
447 const UrlAndLegalDefault short_4[] = {
448 { "http://foo.com/dir/another/again/myfile.html", false },
449 { "http://foo.com/dir/another/a", true },
450 { "http://foo.com/dir/another/again/", false }
451 };
452 RunTest(ASCIIToUTF16("foo.com/dir/another/a"), std::string(), true, short_4,
453 arraysize(short_4));
454 // If prevent_inline_autocomplete is false, we won't bother creating the
455 // URL-what-you-typed match because we have promoted inline autocompletions.
456 const UrlAndLegalDefault short_4_allow_inline[] = {
457 { "http://foo.com/dir/another/again/myfile.html", true },
458 { "http://foo.com/dir/another/again/", true }
459 };
460 RunTest(ASCIIToUTF16("foo.com/dir/another/a"), std::string(), false,
461 short_4_allow_inline, arraysize(short_4_allow_inline));
462
463 // Exact matches should always be best no matter how much more another match
464 // has been typed.
465 const UrlAndLegalDefault short_5a[] = {
466 { "http://gooey/", true },
467 { "http://www.google.com/", true },
468 { "http://go/", true }
469 };
470 const UrlAndLegalDefault short_5b[] = {
471 { "http://go/", true },
472 { "http://gooey/", true },
473 { "http://www.google.com/", true }
474 };
475 RunTest(ASCIIToUTF16("g"), std::string(), false, short_5a,
476 arraysize(short_5a));
477 RunTest(ASCIIToUTF16("go"), std::string(), false, short_5b,
478 arraysize(short_5b));
479 }
480
481 TEST_F(HistoryURLProviderTest, CullRedirects) {
482 // URLs we will be using, plus the visit counts they will initially get
483 // (the redirect set below will also increment the visit counts). We want
484 // the results to be in A,B,C order. Note also that our visit counts are
485 // all high enough so that domain synthesizing won't get triggered.
486 struct TestCase {
487 const char* url;
488 int count;
489 } test_cases[] = {
490 {"http://redirects/A", 30},
491 {"http://redirects/B", 20},
492 {"http://redirects/C", 10}
493 };
494 for (size_t i = 0; i < arraysize(test_cases); ++i) {
495 history_service_->AddPageWithDetails(GURL(test_cases[i].url),
496 ASCIIToUTF16("Title"), test_cases[i].count, test_cases[i].count,
497 Time::Now(), false, history::SOURCE_BROWSED);
498 }
499
500 // Create a B->C->A redirect chain, but set the visit counts such that they
501 // will appear in A,B,C order in the results. The autocomplete query will
502 // search for the most recent visit when looking for redirects, so this will
503 // be found even though the previous visits had no redirects.
504 history::RedirectList redirects_to_a;
505 redirects_to_a.push_back(GURL(test_cases[1].url));
506 redirects_to_a.push_back(GURL(test_cases[2].url));
507 redirects_to_a.push_back(GURL(test_cases[0].url));
508 history_service_->AddPage(GURL(test_cases[0].url), base::Time::Now(),
509 NULL, 0, GURL(), redirects_to_a, ui::PAGE_TRANSITION_TYPED,
510 history::SOURCE_BROWSED, true);
511
512 // Because all the results are part of a redirect chain with other results,
513 // all but the first one (A) should be culled. We should get the default
514 // "what you typed" result, plus this one.
515 const base::string16 typing(ASCIIToUTF16("http://redirects/"));
516 const UrlAndLegalDefault expected_results[] = {
517 { test_cases[0].url, false },
518 { base::UTF16ToUTF8(typing), true }
519 };
520 RunTest(typing, std::string(), true, expected_results,
521 arraysize(expected_results));
522
523 // If prevent_inline_autocomplete is false, we won't bother creating the
524 // URL-what-you-typed match because we have promoted inline autocompletions.
525 // The result set should instead consist of a single URL representing the
526 // whole set of redirects.
527 const UrlAndLegalDefault expected_results_allow_inlining[] = {
528 { test_cases[0].url, true }
529 };
530 RunTest(typing, std::string(), false, expected_results_allow_inlining,
531 arraysize(expected_results_allow_inlining));
532 }
533
534 TEST_F(HistoryURLProviderTestNoSearchProvider, WhatYouTypedNoSearchProvider) {
535 // When no search provider is available, make sure we provide WYT matches
536 // for text that could be a URL.
537
538 const UrlAndLegalDefault results_1[] = {
539 { "http://wytmatch/", true }
540 };
541 RunTest(ASCIIToUTF16("wytmatch"), std::string(), false, results_1,
542 arraysize(results_1));
543
544 RunTest(ASCIIToUTF16("wytmatch foo bar"), std::string(), false, NULL, 0);
545 RunTest(ASCIIToUTF16("wytmatch+foo+bar"), std::string(), false, NULL, 0);
546
547 const UrlAndLegalDefault results_2[] = {
548 { "http://wytmatch+foo+bar.com/", true }
549 };
550 RunTest(ASCIIToUTF16("wytmatch+foo+bar.com"), std::string(), false,
551 results_2, arraysize(results_2));
552 }
553
554 TEST_F(HistoryURLProviderTest, WhatYouTyped) {
555 // Make sure we suggest a What You Typed match at the right times.
556 RunTest(ASCIIToUTF16("wytmatch"), std::string(), false, NULL, 0);
557 RunTest(ASCIIToUTF16("wytmatch foo bar"), std::string(), false, NULL, 0);
558 RunTest(ASCIIToUTF16("wytmatch+foo+bar"), std::string(), false, NULL, 0);
559 RunTest(ASCIIToUTF16("wytmatch+foo+bar.com"), std::string(), false, NULL, 0);
560
561 const UrlAndLegalDefault results_1[] = {
562 { "http://www.wytmatch.com/", true }
563 };
564 RunTest(ASCIIToUTF16("wytmatch"), "com", false, results_1,
565 arraysize(results_1));
566
567 const UrlAndLegalDefault results_2[] = {
568 { "http://wytmatch%20foo%20bar/", true }
569 };
570 RunTest(ASCIIToUTF16("http://wytmatch foo bar"), std::string(), false,
571 results_2, arraysize(results_2));
572
573 const UrlAndLegalDefault results_3[] = {
574 { "https://wytmatch%20foo%20bar/", true }
575 };
576 RunTest(ASCIIToUTF16("https://wytmatch foo bar"), std::string(), false,
577 results_3, arraysize(results_3));
578 }
579
580 TEST_F(HistoryURLProviderTest, Fixup) {
581 // Test for various past crashes we've had.
582 RunTest(ASCIIToUTF16("\\"), std::string(), false, NULL, 0);
583 RunTest(ASCIIToUTF16("#"), std::string(), false, NULL, 0);
584 RunTest(ASCIIToUTF16("%20"), std::string(), false, NULL, 0);
585 const UrlAndLegalDefault fixup_crash[] = {
586 { "http://%EF%BD%A5@s/", true }
587 };
588 RunTest(base::WideToUTF16(L"\uff65@s"), std::string(), false, fixup_crash,
589 arraysize(fixup_crash));
590 RunTest(base::WideToUTF16(L"\u2015\u2015@ \uff7c"), std::string(), false,
591 NULL, 0);
592
593 // Fixing up "file:" should result in an inline autocomplete offset of just
594 // after "file:", not just after "file://".
595 const base::string16 input_1(ASCIIToUTF16("file:"));
596 const UrlAndLegalDefault fixup_1[] = {
597 { "file:///C:/foo.txt", true }
598 };
599 ASSERT_NO_FATAL_FAILURE(RunTest(input_1, std::string(), false, fixup_1,
600 arraysize(fixup_1)));
601 EXPECT_EQ(ASCIIToUTF16("///C:/foo.txt"),
602 matches_.front().inline_autocompletion);
603
604 // Fixing up "http:/" should result in an inline autocomplete offset of just
605 // after "http:/", not just after "http:".
606 const base::string16 input_2(ASCIIToUTF16("http:/"));
607 const UrlAndLegalDefault fixup_2[] = {
608 { "http://bogussite.com/a", true },
609 { "http://bogussite.com/b", true },
610 { "http://bogussite.com/c", true }
611 };
612 ASSERT_NO_FATAL_FAILURE(RunTest(input_2, std::string(), false, fixup_2,
613 arraysize(fixup_2)));
614 EXPECT_EQ(ASCIIToUTF16("/bogussite.com/a"),
615 matches_.front().inline_autocompletion);
616
617 // Adding a TLD to a small number like "56" should result in "www.56.com"
618 // rather than "0.0.0.56.com".
619 const UrlAndLegalDefault fixup_3[] = {
620 { "http://www.56.com/", true }
621 };
622 RunTest(ASCIIToUTF16("56"), "com", true, fixup_3, arraysize(fixup_3));
623
624 // An input looks like a IP address like "127.0.0.1" should result in
625 // "http://127.0.0.1/".
626 const UrlAndLegalDefault fixup_4[] = {
627 { "http://127.0.0.1/", true }
628 };
629 RunTest(ASCIIToUTF16("127.0.0.1"), std::string(), false, fixup_4,
630 arraysize(fixup_4));
631
632 // An number "17173" should result in "http://www.17173.com/" in db.
633 const UrlAndLegalDefault fixup_5[] = {
634 { "http://www.17173.com/", true }
635 };
636 RunTest(ASCIIToUTF16("17173"), std::string(), false, fixup_5,
637 arraysize(fixup_5));
638 }
639
640 // Make sure the results for the input 'p' don't change between the first and
641 // second passes.
642 TEST_F(HistoryURLProviderTest, EmptyVisits) {
643 // Wait for history to create the in memory DB.
644 profile_->BlockUntilHistoryProcessesPendingRequests();
645
646 AutocompleteInput input(
647 ASCIIToUTF16("pa"), base::string16::npos, std::string(), GURL(),
648 metrics::OmniboxEventProto::INVALID_SPEC, false, false, true, true, false,
649 ChromeAutocompleteSchemeClassifier(profile_.get()));
650 autocomplete_->Start(input, false);
651 // HistoryURLProvider shouldn't be done (waiting on async results).
652 EXPECT_FALSE(autocomplete_->done());
653
654 // We should get back an entry for pandora.
655 matches_ = autocomplete_->matches();
656 ASSERT_GT(matches_.size(), 0u);
657 EXPECT_EQ(GURL("http://pandora.com/"), matches_[0].destination_url);
658 int pandora_relevance = matches_[0].relevance;
659
660 // Run the message loop. When |autocomplete_| finishes the loop is quit.
661 base::MessageLoop::current()->Run();
662 EXPECT_TRUE(autocomplete_->done());
663 matches_ = autocomplete_->matches();
664 ASSERT_GT(matches_.size(), 0u);
665 EXPECT_EQ(GURL("http://pandora.com/"), matches_[0].destination_url);
666 EXPECT_EQ(pandora_relevance, matches_[0].relevance);
667 }
668
669 TEST_F(HistoryURLProviderTestNoDB, NavigateWithoutDB) {
670 // Ensure that we will still produce matches for navigation when there is no
671 // database.
672 UrlAndLegalDefault navigation_1[] = {
673 { "http://test.com/", true }
674 };
675 RunTest(ASCIIToUTF16("test.com"), std::string(), false, navigation_1,
676 arraysize(navigation_1));
677
678 UrlAndLegalDefault navigation_2[] = {
679 { "http://slash/", true }
680 };
681 RunTest(ASCIIToUTF16("slash"), std::string(), false, navigation_2,
682 arraysize(navigation_2));
683
684 RunTest(ASCIIToUTF16("this is a query"), std::string(), false, NULL, 0);
685 }
686
687 TEST_F(HistoryURLProviderTest, DontAutocompleteOnTrailingWhitespace) {
688 AutocompleteInput input(
689 ASCIIToUTF16("slash "), base::string16::npos, std::string(), GURL(),
690 metrics::OmniboxEventProto::INVALID_SPEC, false, false, true, true, false,
691 ChromeAutocompleteSchemeClassifier(profile_.get()));
692 autocomplete_->Start(input, false);
693 if (!autocomplete_->done())
694 base::MessageLoop::current()->Run();
695
696 // None of the matches should attempt to autocomplete.
697 matches_ = autocomplete_->matches();
698 for (size_t i = 0; i < matches_.size(); ++i) {
699 EXPECT_TRUE(matches_[i].inline_autocompletion.empty());
700 EXPECT_FALSE(matches_[i].allowed_to_be_default_match);
701 }
702 }
703
704 TEST_F(HistoryURLProviderTest, TreatEmailsAsSearches) {
705 // Visiting foo.com should not make this string be treated as a navigation.
706 // That means the result should be scored around 1200 ("what you typed")
707 // and not 1400+.
708 const UrlAndLegalDefault expected[] = {
709 { "http://user@foo.com/", true }
710 };
711 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("user@foo.com"), std::string(),
712 false, expected, arraysize(expected)));
713 EXPECT_LE(1200, matches_[0].relevance);
714 EXPECT_LT(matches_[0].relevance, 1210);
715 }
716
717 TEST_F(HistoryURLProviderTest, IntranetURLsWithPaths) {
718 struct TestCase {
719 const char* input;
720 int relevance;
721 } test_cases[] = {
722 { "fooey", 0 },
723 { "fooey/", 1200 }, // 1200 for URL would still navigate by default.
724 { "fooey/a", 1200 }, // 1200 for UNKNOWN would not.
725 { "fooey/a b", 1200 }, // Also UNKNOWN.
726 { "gooey", 1410 },
727 { "gooey/", 1410 },
728 { "gooey/a", 1400 },
729 { "gooey/a b", 1400 },
730 };
731 for (size_t i = 0; i < arraysize(test_cases); ++i) {
732 SCOPED_TRACE(test_cases[i].input);
733 if (test_cases[i].relevance == 0) {
734 RunTest(ASCIIToUTF16(test_cases[i].input), std::string(), false, NULL, 0);
735 } else {
736 const UrlAndLegalDefault output[] = {
737 {url_formatter::FixupURL(test_cases[i].input, std::string()).spec(),
738 true}};
739 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16(test_cases[i].input),
740 std::string(), false, output, arraysize(output)));
741 // Actual relevance should be at least what test_cases expects and
742 // and no more than 10 more.
743 EXPECT_LE(test_cases[i].relevance, matches_[0].relevance);
744 EXPECT_LT(matches_[0].relevance, test_cases[i].relevance + 10);
745 }
746 }
747 }
748
749 // Makes sure autocompletion happens for intranet sites that have been
750 // previoulsy visited.
751 TEST_F(HistoryURLProviderTest, IntranetURLCompletion) {
752 sort_matches_ = true;
753
754 const UrlAndLegalDefault expected1[] = {
755 { "http://intra/three", true },
756 { "http://intra/two", true }
757 };
758 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("intra/t"), std::string(), false,
759 expected1, arraysize(expected1)));
760 EXPECT_LE(1410, matches_[0].relevance);
761 EXPECT_LT(matches_[0].relevance, 1420);
762 // It uses the default scoring.
763 EXPECT_EQ(matches_[1].relevance, 1203);
764
765 const UrlAndLegalDefault expected2[] = {
766 { "http://moo/b", true },
767 { "http://moo/bar", true }
768 };
769 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("moo/b"), std::string(), false,
770 expected2, arraysize(expected2)));
771 // The url what you typed match should be around 1400, otherwise the
772 // search what you typed match is going to be first.
773 EXPECT_LE(1400, matches_[0].relevance);
774 EXPECT_LT(matches_[0].relevance, 1410);
775
776 const UrlAndLegalDefault expected3[] = {
777 { "http://intra/one", true },
778 { "http://intra/three", true },
779 { "http://intra/two", true }
780 };
781 RunTest(ASCIIToUTF16("intra"), std::string(), false, expected3,
782 arraysize(expected3));
783
784 const UrlAndLegalDefault expected4[] = {
785 { "http://intra/one", true },
786 { "http://intra/three", true },
787 { "http://intra/two", true }
788 };
789 RunTest(ASCIIToUTF16("intra/"), std::string(), false, expected4,
790 arraysize(expected4));
791
792 const UrlAndLegalDefault expected5[] = {
793 { "http://intra/one", true }
794 };
795 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("intra/o"), std::string(), false,
796 expected5, arraysize(expected5)));
797 EXPECT_LE(1410, matches_[0].relevance);
798 EXPECT_LT(matches_[0].relevance, 1420);
799
800 const UrlAndLegalDefault expected6[] = {
801 { "http://intra/x", true }
802 };
803 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("intra/x"), std::string(), false,
804 expected6, arraysize(expected6)));
805 EXPECT_LE(1400, matches_[0].relevance);
806 EXPECT_LT(matches_[0].relevance, 1410);
807
808 const UrlAndLegalDefault expected7[] = {
809 { "http://typedhost/untypedpath", true }
810 };
811 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16("typedhost/untypedpath"),
812 std::string(), false, expected7,
813 arraysize(expected7)));
814 EXPECT_LE(1400, matches_[0].relevance);
815 EXPECT_LT(matches_[0].relevance, 1410);
816 }
817
818 TEST_F(HistoryURLProviderTest, CrashDueToFixup) {
819 // This test passes if we don't crash. The results don't matter.
820 const char* const test_cases[] = {
821 "//c",
822 "\\@st",
823 "view-source:x",
824 };
825 for (size_t i = 0; i < arraysize(test_cases); ++i) {
826 AutocompleteInput input(
827 ASCIIToUTF16(test_cases[i]), base::string16::npos, std::string(),
828 GURL(), metrics::OmniboxEventProto::INVALID_SPEC, false, false, true,
829 true, false, ChromeAutocompleteSchemeClassifier(profile_.get()));
830 autocomplete_->Start(input, false);
831 if (!autocomplete_->done())
832 base::MessageLoop::current()->Run();
833 }
834 }
835
836 TEST_F(HistoryURLProviderTest, DoesNotProvideMatchesOnFocus) {
837 AutocompleteInput input(
838 ASCIIToUTF16("foo"), base::string16::npos, std::string(), GURL(),
839 metrics::OmniboxEventProto::INVALID_SPEC, false, false, true, true, true,
840 ChromeAutocompleteSchemeClassifier(profile_.get()));
841 autocomplete_->Start(input, false);
842 EXPECT_TRUE(autocomplete_->matches().empty());
843 }
844
845 TEST_F(HistoryURLProviderTest, DoesNotInlinePunycodeMatches) {
846 // A URL that matches due to a match in the punycode URL are allowed to be the
847 // default match if the URL doesn't get rendered as international characters
848 // in the given locale.
849 const UrlAndLegalDefault expected_true[] = {
850 { "http://puny.xn--1lq90ic7f1rc.cn/", true },
851 };
852 UrlAndLegalDefault expected_false[] = {
853 { "http://puny.xn--1lq90ic7f1rc.cn/", false },
854 };
855 RunTest(ASCIIToUTF16("pun"), std::string(), false, expected_true,
856 arraysize(expected_true));
857 RunTest(ASCIIToUTF16("puny."), std::string(), false, expected_true,
858 arraysize(expected_true));
859 RunTest(ASCIIToUTF16("puny.x"), std::string(), false, expected_true,
860 arraysize(expected_true));
861 RunTest(ASCIIToUTF16("puny.xn"), std::string(), false, expected_true,
862 arraysize(expected_true));
863 RunTest(ASCIIToUTF16("puny.xn--"), std::string(), false, expected_true,
864 arraysize(expected_true));
865 RunTest(ASCIIToUTF16("puny.xn--1l"), std::string(), false, expected_true,
866 arraysize(expected_true));
867 RunTest(ASCIIToUTF16("puny.xn--1lq90ic7f1rc"), std::string(), false,
868 expected_true, arraysize(expected_true));
869 RunTest(ASCIIToUTF16("puny.xn--1lq90ic7f1rc."), std::string(), false,
870 expected_true, arraysize(expected_true));
871 // Set the language so the punycode part of the URL is rendered as
872 // international characters. Then this match should not be allowed to be
873 // the default match if the inline autocomplete text starts in the middle
874 // of the international characters.
875 profile_->GetPrefs()->SetString(prefs::kAcceptLanguages, "zh-CN");
876 RunTest(ASCIIToUTF16("pun"), std::string(), false, expected_true,
877 arraysize(expected_true));
878 RunTest(ASCIIToUTF16("puny."), std::string(), false, expected_true,
879 arraysize(expected_true));
880 RunTest(ASCIIToUTF16("puny.x"), std::string(), false, expected_false,
881 arraysize(expected_false));
882 RunTest(ASCIIToUTF16("puny.xn"), std::string(), false, expected_false,
883 arraysize(expected_false));
884 RunTest(ASCIIToUTF16("puny.xn--"), std::string(), false, expected_false,
885 arraysize(expected_false));
886 RunTest(ASCIIToUTF16("puny.xn--1l"), std::string(), false, expected_false,
887 arraysize(expected_false));
888 RunTest(ASCIIToUTF16("puny.xn--1lq90ic7f1rc"), std::string(), false,
889 expected_true, arraysize(expected_true));
890 RunTest(ASCIIToUTF16("puny.xn--1lq90ic7f1rc."), std::string(), false,
891 expected_true, arraysize(expected_true));
892 }
893
894 TEST_F(HistoryURLProviderTest, CullSearchResults) {
895 // Set up a default search engine.
896 TemplateURLData data;
897 data.SetShortName(ASCIIToUTF16("TestEngine"));
898 data.SetKeyword(ASCIIToUTF16("TestEngine"));
899 data.SetURL("http://testsearch.com/?q={searchTerms}");
900 TemplateURLService* template_url_service =
901 TemplateURLServiceFactory::GetForProfile(profile_.get());
902 TemplateURL* template_url = new TemplateURL(data);
903 template_url_service->Add(template_url);
904 template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
905 template_url_service->Load();
906
907 // URLs we will be using, plus the visit counts they will initially get
908 // (the redirect set below will also increment the visit counts). We want
909 // the results to be in A,B,C order. Note also that our visit counts are
910 // all high enough so that domain synthesizing won't get triggered.
911 struct TestCase {
912 const char* url;
913 int count;
914 } test_cases[] = {
915 {"https://testsearch.com/", 30},
916 {"https://testsearch.com/?q=foobar", 20},
917 {"http://foobar.com/", 10}
918 };
919 for (size_t i = 0; i < arraysize(test_cases); ++i) {
920 history_service_->AddPageWithDetails(GURL(test_cases[i].url),
921 base::UTF8ToUTF16("Title"), test_cases[i].count, test_cases[i].count,
922 Time::Now(), false, history::SOURCE_BROWSED);
923 }
924
925 // We should not see search URLs when typing a previously used query.
926 const UrlAndLegalDefault expected_when_searching_query[] = {
927 { test_cases[2].url, false }
928 };
929 RunTest(ASCIIToUTF16("foobar"), std::string(), true,
930 expected_when_searching_query, arraysize(expected_when_searching_query));
931
932 // We should not see search URLs when typing the search engine name.
933 const UrlAndLegalDefault expected_when_searching_site[] = {
934 { test_cases[0].url, false }
935 };
936 RunTest(ASCIIToUTF16("testsearch"), std::string(), true,
937 expected_when_searching_site, arraysize(expected_when_searching_site));
938 }
939
940 TEST_F(HistoryURLProviderTest, SuggestExactInput) {
941 const size_t npos = std::string::npos;
942 struct TestCase {
943 // Inputs:
944 const char* input;
945 bool trim_http;
946 // Expected Outputs:
947 const char* contents;
948 // Offsets of the ACMatchClassifications, terminated by npos.
949 size_t offsets[3];
950 // The index of the ACMatchClassification that should have the MATCH bit
951 // set, npos if no ACMatchClassification should have the MATCH bit set.
952 size_t match_classification_index;
953 } test_cases[] = {
954 { "http://www.somesite.com", false,
955 "http://www.somesite.com", {0, npos, npos}, 0 },
956 { "www.somesite.com", true,
957 "www.somesite.com", {0, npos, npos}, 0 },
958 { "www.somesite.com", false,
959 "http://www.somesite.com", {0, 7, npos}, 1 },
960 { "somesite.com", true,
961 "somesite.com", {0, npos, npos}, 0 },
962 { "somesite.com", false,
963 "http://somesite.com", {0, 7, npos}, 1 },
964 { "w", true,
965 "w", {0, npos, npos}, 0 },
966 { "w", false,
967 "http://w", {0, 7, npos}, 1 },
968 { "w.com", true,
969 "w.com", {0, npos, npos}, 0 },
970 { "w.com", false,
971 "http://w.com", {0, 7, npos}, 1 },
972 { "www.w.com", true,
973 "www.w.com", {0, npos, npos}, 0 },
974 { "www.w.com", false,
975 "http://www.w.com", {0, 7, npos}, 1 },
976 { "view-source:w", true,
977 "view-source:w", {0, npos, npos}, 0 },
978 { "view-source:www.w.com/", true,
979 "view-source:www.w.com", {0, npos, npos}, npos },
980 { "view-source:www.w.com/", false,
981 "view-source:http://www.w.com", {0, npos, npos}, npos },
982 { "view-source:http://www.w.com/", false,
983 "view-source:http://www.w.com", {0, npos, npos}, 0 },
984 { " view-source:", true,
985 "view-source:", {0, npos, npos}, 0 },
986 { "http:////////w.com", false,
987 "http://w.com", {0, npos, npos}, npos },
988 { " http:////////www.w.com", false,
989 "http://www.w.com", {0, npos, npos}, npos },
990 { "http:a///www.w.com", false,
991 "http://a///www.w.com", {0, npos, npos}, npos },
992 { "mailto://a@b.com", true,
993 "mailto://a@b.com", {0, npos, npos}, 0 },
994 { "mailto://a@b.com", false,
995 "mailto://a@b.com", {0, npos, npos}, 0 },
996 };
997 for (size_t i = 0; i < arraysize(test_cases); ++i) {
998 SCOPED_TRACE(testing::Message() << "Index " << i << " input: "
999 << test_cases[i].input << ", trim_http: "
1000 << test_cases[i].trim_http);
1001
1002 AutocompleteInput input(
1003 ASCIIToUTF16(test_cases[i].input), base::string16::npos, std::string(),
1004 GURL("about:blank"), metrics::OmniboxEventProto::INVALID_SPEC, false,
1005 false, true, true, false,
1006 ChromeAutocompleteSchemeClassifier(profile_.get()));
1007 AutocompleteMatch match(autocomplete_->SuggestExactInput(
1008 input, input.canonicalized_url(), test_cases[i].trim_http));
1009 EXPECT_EQ(ASCIIToUTF16(test_cases[i].contents), match.contents);
1010 for (size_t match_index = 0; match_index < match.contents_class.size();
1011 ++match_index) {
1012 EXPECT_EQ(test_cases[i].offsets[match_index],
1013 match.contents_class[match_index].offset);
1014 EXPECT_EQ(ACMatchClassification::URL |
1015 (match_index == test_cases[i].match_classification_index ?
1016 ACMatchClassification::MATCH : 0),
1017 match.contents_class[match_index].style);
1018 }
1019 EXPECT_EQ(npos, test_cases[i].offsets[match.contents_class.size()]);
1020 }
1021 }
1022
1023 TEST_F(HistoryURLProviderTest, HUPScoringExperiment) {
1024 HUPScoringParams max_2000_no_time_decay;
1025 max_2000_no_time_decay.typed_count_buckets.buckets().push_back(
1026 std::make_pair(0.0, 2000));
1027 HUPScoringParams max_1250_no_time_decay;
1028 max_1250_no_time_decay.typed_count_buckets.buckets().push_back(
1029 std::make_pair(0.0, 1250));
1030 HUPScoringParams max_1000_no_time_decay;
1031 max_1000_no_time_decay.typed_count_buckets.buckets().push_back(
1032 std::make_pair(0.0, 1000));
1033
1034 HUPScoringParams max_1100_with_time_decay_and_max_cap;
1035 max_1100_with_time_decay_and_max_cap.typed_count_buckets.
1036 set_relevance_cap(1400);
1037 max_1100_with_time_decay_and_max_cap.typed_count_buckets.
1038 set_half_life_days(16);
1039 max_1100_with_time_decay_and_max_cap.typed_count_buckets.buckets().push_back(
1040 std::make_pair(0.5, 1100));
1041 max_1100_with_time_decay_and_max_cap.typed_count_buckets.buckets().push_back(
1042 std::make_pair(0.24, 200));
1043 max_1100_with_time_decay_and_max_cap.typed_count_buckets.buckets().push_back(
1044 std::make_pair(0.0, 100));
1045
1046 HUPScoringParams max_1100_visit_typed_decays;
1047 max_1100_visit_typed_decays.typed_count_buckets.set_half_life_days(16);
1048 max_1100_visit_typed_decays.typed_count_buckets.buckets().push_back(
1049 std::make_pair(0.5, 1100));
1050 max_1100_visit_typed_decays.typed_count_buckets.buckets().push_back(
1051 std::make_pair(0.0, 100));
1052 max_1100_visit_typed_decays.visited_count_buckets.set_half_life_days(16);
1053 max_1100_visit_typed_decays.visited_count_buckets.buckets().push_back(
1054 std::make_pair(0.5, 550));
1055 max_1100_visit_typed_decays.visited_count_buckets.buckets().push_back(
1056 std::make_pair(0.0, 50));
1057
1058 const int kMaxMatches = 3;
1059 struct TestCase {
1060 const char* input;
1061 HUPScoringParams scoring_params;
1062 struct ExpectedMatch {
1063 const char* url;
1064 int control_relevance;
1065 int experiment_relevance;
1066 };
1067 ExpectedMatch matches[kMaxMatches];
1068 } test_cases[] = {
1069 // Max score 2000 -> no demotion.
1070 { "7.com/1", max_2000_no_time_decay,
1071 {{"7.com/1a", 1413, 1413}, {NULL, 0, 0}, {NULL, 0, 0}} },
1072
1073 // Limit score to 1250/1000 and make sure that the top match is unchanged.
1074 { "7.com/1", max_1250_no_time_decay,
1075 {{"7.com/1a", 1413, 1413}, {NULL, 0, 0}, {NULL, 0, 0}} },
1076 { "7.com/2", max_1250_no_time_decay,
1077 {{"7.com/2a", 1413, 1413}, {"7.com/2b", 1412, 1250}, {NULL, 0, 0}} },
1078 { "7.com/4", max_1000_no_time_decay,
1079 {{"7.com/4", 1203, 1203}, {"7.com/4a", 1202, 1000},
1080 {"7.com/4b", 1201, 999}} },
1081
1082 // Max relevance cap is 1400 and half-life is 16 days.
1083 { "7.com/1", max_1100_with_time_decay_and_max_cap,
1084 {{"7.com/1a", 1413, 1413}, {NULL, 0, 0}, {NULL, 0, 0}} },
1085 { "7.com/4", max_1100_with_time_decay_and_max_cap,
1086 {{"7.com/4", 1203, 1203}, {"7.com/4a", 1202, 200},
1087 {"7.com/4b", 1201, 100}} },
1088
1089 // Max relevance cap is 1400 and half-life is 16 days for both visit/typed.
1090 { "7.com/5", max_1100_visit_typed_decays,
1091 {{"7.com/5", 1203, 1203}, {"7.com/5a", 1202, 50}, {NULL, 0, 0}} },
1092 };
1093 for (size_t i = 0; i < arraysize(test_cases); ++i) {
1094 SCOPED_TRACE(test_cases[i].input);
1095 UrlAndLegalDefault output[kMaxMatches];
1096 int max_matches;
1097 for (max_matches = 0; max_matches < kMaxMatches; ++max_matches) {
1098 if (test_cases[i].matches[max_matches].url == NULL)
1099 break;
1100 output[max_matches].url =
1101 url_formatter::FixupURL(test_cases[i].matches[max_matches].url,
1102 std::string())
1103 .spec();
1104 output[max_matches].allowed_to_be_default_match = true;
1105 }
1106 autocomplete_->scoring_params_ = test_cases[i].scoring_params;
1107
1108 // Test the experiment (scoring enabled). When scoring is disabled, it uses
1109 // the default experimental scoring.
1110 autocomplete_->scoring_params_.experimental_scoring_enabled = true;
1111 ASSERT_NO_FATAL_FAILURE(RunTest(ASCIIToUTF16(test_cases[i].input),
1112 std::string(), false, output, max_matches));
1113 for (int j = 0; j < max_matches; ++j) {
1114 EXPECT_EQ(test_cases[i].matches[j].experiment_relevance,
1115 matches_[j].relevance);
1116 }
1117 }
1118 }
OLDNEW
« no previous file with comments | « no previous file | chrome/chrome_tests_unit.gypi » ('j') | components/omnibox/browser/DEPS » ('J')

Powered by Google App Engine
This is Rietveld 408576698