OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "chrome/browser/autocomplete/autocomplete_match.h" | 8 #include "chrome/browser/autocomplete/autocomplete_match.h" |
9 #include "chrome/browser/autocomplete/keyword_provider.h" | 9 #include "chrome/browser/autocomplete/keyword_provider.h" |
10 #include "chrome/browser/search_engines/template_url.h" | 10 #include "chrome/browser/search_engines/template_url.h" |
11 #include "chrome/browser/search_engines/template_url_service.h" | 11 #include "chrome/browser/search_engines/template_url_service.h" |
12 #include "chrome/common/chrome_switches.h" | 12 #include "chrome/common/chrome_switches.h" |
13 #include "chrome/test/base/testing_browser_process.h" | 13 #include "chrome/test/base/testing_browser_process.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
15 #include "url/gurl.h" | 15 #include "url/gurl.h" |
16 | 16 |
17 class KeywordProviderTest : public testing::Test { | 17 class KeywordProviderTest : public testing::Test { |
18 protected: | 18 protected: |
19 template<class ResultType> | 19 template<class ResultType> |
20 struct test_data { | 20 struct MatchType { |
21 const ResultType member; | |
22 bool allowed_to_be_default_match; | |
23 }; | |
24 | |
25 template<class ResultType> | |
26 struct TestData { | |
21 const string16 input; | 27 const string16 input; |
22 const size_t num_results; | 28 const size_t num_results; |
23 const ResultType output[3]; | 29 const MatchType<ResultType> output[3]; |
24 }; | 30 }; |
25 | 31 |
26 KeywordProviderTest() : kw_provider_(NULL) { } | 32 KeywordProviderTest() : kw_provider_(NULL) { } |
27 virtual ~KeywordProviderTest() { } | 33 virtual ~KeywordProviderTest() { } |
28 | 34 |
29 virtual void SetUp(); | 35 virtual void SetUp(); |
30 virtual void TearDown(); | 36 virtual void TearDown(); |
31 | 37 |
32 template<class ResultType> | 38 template<class ResultType> |
33 void RunTest(test_data<ResultType>* keyword_cases, | 39 void RunTest(TestData<ResultType>* keyword_cases, |
34 int num_cases, | 40 int num_cases, |
35 ResultType AutocompleteMatch::* member); | 41 ResultType AutocompleteMatch::* member); |
36 | 42 |
37 protected: | 43 protected: |
38 static const TemplateURLService::Initializer kTestData[]; | 44 static const TemplateURLService::Initializer kTestData[]; |
39 | 45 |
40 scoped_refptr<KeywordProvider> kw_provider_; | 46 scoped_refptr<KeywordProvider> kw_provider_; |
41 scoped_ptr<TemplateURLService> model_; | 47 scoped_ptr<TemplateURLService> model_; |
42 }; | 48 }; |
43 | 49 |
(...skipping 13 matching lines...) Expand all Loading... | |
57 kw_provider_ = new KeywordProvider(NULL, model_.get()); | 63 kw_provider_ = new KeywordProvider(NULL, model_.get()); |
58 } | 64 } |
59 | 65 |
60 void KeywordProviderTest::TearDown() { | 66 void KeywordProviderTest::TearDown() { |
61 model_.reset(); | 67 model_.reset(); |
62 kw_provider_ = NULL; | 68 kw_provider_ = NULL; |
63 } | 69 } |
64 | 70 |
65 template<class ResultType> | 71 template<class ResultType> |
66 void KeywordProviderTest::RunTest( | 72 void KeywordProviderTest::RunTest( |
67 test_data<ResultType>* keyword_cases, | 73 TestData<ResultType>* keyword_cases, |
68 int num_cases, | 74 int num_cases, |
69 ResultType AutocompleteMatch::* member) { | 75 ResultType AutocompleteMatch::* member) { |
70 ACMatches matches; | 76 ACMatches matches; |
71 for (int i = 0; i < num_cases; ++i) { | 77 for (int i = 0; i < num_cases; ++i) { |
78 SCOPED_TRACE(keyword_cases[i].input); | |
72 AutocompleteInput input(keyword_cases[i].input, string16::npos, string16(), | 79 AutocompleteInput input(keyword_cases[i].input, string16::npos, string16(), |
73 GURL(), AutocompleteInput::INVALID_SPEC, true, | 80 GURL(), AutocompleteInput::INVALID_SPEC, true, |
74 false, true, AutocompleteInput::ALL_MATCHES); | 81 false, true, AutocompleteInput::ALL_MATCHES); |
75 kw_provider_->Start(input, false); | 82 kw_provider_->Start(input, false); |
76 EXPECT_TRUE(kw_provider_->done()); | 83 EXPECT_TRUE(kw_provider_->done()); |
77 matches = kw_provider_->matches(); | 84 matches = kw_provider_->matches(); |
78 EXPECT_EQ(keyword_cases[i].num_results, matches.size()) << | 85 EXPECT_EQ(keyword_cases[i].num_results, matches.size()); |
msw
2013/08/07 20:09:21
nit: you could make this ASSERT_EQ, then remove th
Mark P
2013/08/07 22:13:05
Done.
| |
79 ASCIIToUTF16("Input was: ") + keyword_cases[i].input; | |
80 if (matches.size() == keyword_cases[i].num_results) { | 86 if (matches.size() == keyword_cases[i].num_results) { |
81 for (size_t j = 0; j < keyword_cases[i].num_results; ++j) { | 87 for (size_t j = 0; j < matches.size(); ++j) { |
82 EXPECT_EQ(keyword_cases[i].output[j], matches[j].*member); | 88 EXPECT_EQ(keyword_cases[i].output[j].member, matches[j].*member); |
89 EXPECT_EQ(keyword_cases[i].output[j].allowed_to_be_default_match, | |
90 matches[j].allowed_to_be_default_match); | |
83 } | 91 } |
84 } | 92 } |
85 } | 93 } |
86 } | 94 } |
87 | 95 |
88 TEST_F(KeywordProviderTest, Edit) { | 96 TEST_F(KeywordProviderTest, Edit) { |
89 test_data<string16> edit_cases[] = { | 97 const MatchType<string16> kEmptyMatch = { string16(), false }; |
98 TestData<string16> edit_cases[] = { | |
90 // Searching for a nonexistent prefix should give nothing. | 99 // Searching for a nonexistent prefix should give nothing. |
91 {ASCIIToUTF16("Not Found"), 0, {}}, | 100 { ASCIIToUTF16("Not Found"), 0, |
92 {ASCIIToUTF16("aaaaaNot Found"), 0, {}}, | 101 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, |
102 { ASCIIToUTF16("aaaaaNot Found"), 0, | |
103 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
93 | 104 |
94 // Check that tokenization only collapses whitespace between first tokens, | 105 // Check that tokenization only collapses whitespace between first tokens, |
95 // no-query-input cases have a space appended, and action is not escaped. | 106 // no-query-input cases have a space appended, and action is not escaped. |
96 {ASCIIToUTF16("z"), 1, {ASCIIToUTF16("z ")}}, | 107 { ASCIIToUTF16("z"), 1, |
97 {ASCIIToUTF16("z \t"), 1, {ASCIIToUTF16("z ")}}, | 108 { { ASCIIToUTF16("z "), true }, kEmptyMatch, kEmptyMatch } }, |
109 { ASCIIToUTF16("z \t"), 1, | |
110 { { ASCIIToUTF16("z "), true }, kEmptyMatch, kEmptyMatch } }, | |
98 | 111 |
99 // Check that exact, substituting keywords with a verbatim search term | 112 // Check that exact, substituting keywords with a verbatim search term |
100 // don't generate a result. (These are handled by SearchProvider.) | 113 // don't generate a result. (These are handled by SearchProvider.) |
101 {ASCIIToUTF16("z foo"), 0, {}}, | 114 { ASCIIToUTF16("z foo"), 0, |
102 {ASCIIToUTF16("z a b c++"), 0, {}}, | 115 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, |
116 { ASCIIToUTF16("z a b c++"), 0, | |
117 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
103 | 118 |
104 // Matches should be limited to three, and sorted in quality order, not | 119 // Matches should be limited to three, and sorted in quality order, not |
105 // alphabetical. | 120 // alphabetical. |
106 {ASCIIToUTF16("aaa"), 2, {ASCIIToUTF16("aaaa "), | 121 { ASCIIToUTF16("aaa"), 2, |
107 ASCIIToUTF16("aaaaa ")}}, | 122 { { ASCIIToUTF16("aaaa "), false }, |
108 {ASCIIToUTF16("a 1 2 3"), 3, {ASCIIToUTF16("aa 1 2 3"), | 123 { ASCIIToUTF16("aaaaa "), false }, |
109 ASCIIToUTF16("ab 1 2 3"), | 124 kEmptyMatch } }, |
110 ASCIIToUTF16("aaaa 1 2 3")}}, | 125 { ASCIIToUTF16("a 1 2 3"), 3, |
111 {ASCIIToUTF16("www.a"), 3, {ASCIIToUTF16("aa "), | 126 { { ASCIIToUTF16("aa 1 2 3"), false }, |
112 ASCIIToUTF16("ab "), | 127 { ASCIIToUTF16("ab 1 2 3"), false }, |
113 ASCIIToUTF16("aaaa ")}}, | 128 { ASCIIToUTF16("aaaa 1 2 3"), false } } }, |
129 { ASCIIToUTF16("www.a"), 3, | |
130 { { ASCIIToUTF16("aa "), false }, | |
131 { ASCIIToUTF16("ab "), false }, | |
132 { ASCIIToUTF16("aaaa "), false } } }, | |
114 // Exact matches should prevent returning inexact matches. Also, the | 133 // Exact matches should prevent returning inexact matches. Also, the |
115 // verbatim query for this keyword match should not be returned. (It's | 134 // verbatim query for this keyword match should not be returned. (It's |
116 // returned by SearchProvider.) | 135 // returned by SearchProvider.) |
117 {ASCIIToUTF16("aaaa foo"), 0, {}}, | 136 { ASCIIToUTF16("aaaa foo"), 0, |
118 {ASCIIToUTF16("www.aaaa foo"), 0, {}}, | 137 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, |
138 { ASCIIToUTF16("www.aaaa foo"), 0, | |
139 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
119 | 140 |
120 // Clean up keyword input properly. "http" and "https" are the only | 141 // Clean up keyword input properly. "http" and "https" are the only |
121 // allowed schemes. | 142 // allowed schemes. |
122 {ASCIIToUTF16("www"), 1, {ASCIIToUTF16("www ")}}, | 143 { ASCIIToUTF16("www"), 1, |
123 {ASCIIToUTF16("www."), 0, {}}, | 144 { { ASCIIToUTF16("www "), true }, kEmptyMatch, kEmptyMatch }}, |
124 {ASCIIToUTF16("www.w w"), 2, {ASCIIToUTF16("www w"), | 145 { ASCIIToUTF16("www."), 0, |
125 ASCIIToUTF16("weasel w")}}, | 146 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, |
126 {ASCIIToUTF16("http://www"), 1, {ASCIIToUTF16("www ")}}, | 147 { ASCIIToUTF16("www.w w"), 2, |
127 {ASCIIToUTF16("http://www."), 0, {}}, | 148 { { ASCIIToUTF16("www w"), false }, |
128 {ASCIIToUTF16("ftp: blah"), 0, {}}, | 149 { ASCIIToUTF16("weasel w"), false }, |
129 {ASCIIToUTF16("mailto:z"), 0, {}}, | 150 kEmptyMatch } }, |
130 {ASCIIToUTF16("ftp://z"), 0, {}}, | 151 { ASCIIToUTF16("http://www"), 1, |
131 {ASCIIToUTF16("https://z"), 1, {ASCIIToUTF16("z ")}}, | 152 { { ASCIIToUTF16("www "), true }, kEmptyMatch, kEmptyMatch } }, |
153 { ASCIIToUTF16("http://www."), 0, | |
154 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
155 { ASCIIToUTF16("ftp: blah"), 0, | |
156 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
157 { ASCIIToUTF16("mailto:z"), 0, | |
158 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
159 { ASCIIToUTF16("ftp://z"), 0, | |
160 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
161 { ASCIIToUTF16("https://z"), 1, | |
162 { { ASCIIToUTF16("z "), true }, kEmptyMatch, kEmptyMatch } }, | |
132 }; | 163 }; |
133 | 164 |
134 RunTest<string16>(edit_cases, arraysize(edit_cases), | 165 RunTest<string16>(edit_cases, arraysize(edit_cases), |
135 &AutocompleteMatch::fill_into_edit); | 166 &AutocompleteMatch::fill_into_edit); |
136 } | 167 } |
137 | 168 |
138 TEST_F(KeywordProviderTest, URL) { | 169 TEST_F(KeywordProviderTest, URL) { |
139 test_data<GURL> url_cases[] = { | 170 const MatchType<GURL> kEmptyMatch = { GURL(), false }; |
171 TestData<GURL> url_cases[] = { | |
140 // No query input -> empty destination URL. | 172 // No query input -> empty destination URL. |
141 {ASCIIToUTF16("z"), 1, {GURL()}}, | 173 { ASCIIToUTF16("z"), 1, |
142 {ASCIIToUTF16("z \t"), 1, {GURL()}}, | 174 { { GURL(), true }, kEmptyMatch, kEmptyMatch } }, |
175 { ASCIIToUTF16("z \t"), 1, | |
176 { { GURL(), true }, kEmptyMatch, kEmptyMatch } }, | |
143 | 177 |
144 // Check that tokenization only collapses whitespace between first tokens | 178 // Check that tokenization only collapses whitespace between first tokens |
145 // and query input, but not rest of URL, is escaped. | 179 // and query input, but not rest of URL, is escaped. |
146 {ASCIIToUTF16("w bar +baz"), 2, {GURL(" +%2B?=bar+%2Bbazfoo "), | 180 { ASCIIToUTF16("w bar +baz"), 2, |
147 GURL("bar+%2Bbaz=z")}}, | 181 { { GURL(" +%2B?=bar+%2Bbazfoo "), false }, |
182 { GURL("bar+%2Bbaz=z"), false }, | |
183 kEmptyMatch } }, | |
148 | 184 |
149 // Substitution should work with various locations of the "%s". | 185 // Substitution should work with various locations of the "%s". |
150 {ASCIIToUTF16("aaa 1a2b"), 2, {GURL("http://aaaa/?aaaa=1&b=1a2b&c"), | 186 { ASCIIToUTF16("aaa 1a2b"), 2, |
151 GURL("1a2b")}}, | 187 { { GURL("http://aaaa/?aaaa=1&b=1a2b&c"), false }, |
152 {ASCIIToUTF16("a 1 2 3"), 3, {GURL("aa.com?foo=1+2+3"), | 188 { GURL("1a2b"), false }, |
153 GURL("bogus URL 1+2+3"), | 189 kEmptyMatch } }, |
154 GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}}, | 190 { ASCIIToUTF16("a 1 2 3"), 3, |
155 {ASCIIToUTF16("www.w w"), 2, {GURL(" +%2B?=wfoo "), | 191 { { GURL("aa.com?foo=1+2+3"), false }, |
156 GURL("weaselwweasel")}}, | 192 { GURL("bogus URL 1+2+3"), false }, |
193 { GURL("http://aaaa/?aaaa=1&b=1+2+3&c"), false } } }, | |
194 { ASCIIToUTF16("www.w w"), 2, | |
195 { { GURL(" +%2B?=wfoo "), false }, | |
196 { GURL("weaselwweasel"), false }, | |
197 kEmptyMatch } }, | |
157 }; | 198 }; |
158 | 199 |
159 RunTest<GURL>(url_cases, arraysize(url_cases), | 200 RunTest<GURL>(url_cases, arraysize(url_cases), |
160 &AutocompleteMatch::destination_url); | 201 &AutocompleteMatch::destination_url); |
161 } | 202 } |
162 | 203 |
163 TEST_F(KeywordProviderTest, Contents) { | 204 TEST_F(KeywordProviderTest, Contents) { |
164 test_data<string16> contents_cases[] = { | 205 const MatchType<string16> kEmptyMatch = { string16(), false }; |
206 TestData<string16> contents_cases[] = { | |
165 // No query input -> substitute "<enter query>" into contents. | 207 // No query input -> substitute "<enter query>" into contents. |
166 {ASCIIToUTF16("z"), 1, | 208 { ASCIIToUTF16("z"), 1, |
167 {ASCIIToUTF16("Search z for <enter query>")}}, | 209 { { ASCIIToUTF16("Search z for <enter query>"), true }, |
168 {ASCIIToUTF16("z \t"), 1, | 210 kEmptyMatch, |
169 {ASCIIToUTF16("Search z for <enter query>")}}, | 211 kEmptyMatch } }, |
212 { ASCIIToUTF16("z \t"), 1, | |
213 { { ASCIIToUTF16("Search z for <enter query>"), true }, | |
214 kEmptyMatch, | |
215 kEmptyMatch } }, | |
170 | 216 |
171 // Exact keyword matches with remaining text should return nothing. | 217 // Exact keyword matches with remaining text should return nothing. |
172 {ASCIIToUTF16("www.www www"), 0, {}}, | 218 { ASCIIToUTF16("www.www www"), 0, |
173 {ASCIIToUTF16("z a b c++"), 0, {}}, | 219 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, |
220 { ASCIIToUTF16("z a b c++"), 0, | |
221 { kEmptyMatch, kEmptyMatch, kEmptyMatch } }, | |
174 | 222 |
175 // Exact keyword matches with remaining text when the keyword is an | 223 // Exact keyword matches with remaining text when the keyword is an |
176 // extension keyword should return something. This is tested in | 224 // extension keyword should return something. This is tested in |
177 // chrome/browser/extensions/api/omnibox/omnibox_apitest.cc's | 225 // chrome/browser/extensions/api/omnibox/omnibox_apitest.cc's |
178 // in OmniboxApiTest's Basic test. | 226 // in OmniboxApiTest's Basic test. |
179 | 227 |
180 // Substitution should work with various locations of the "%s". | 228 // Substitution should work with various locations of the "%s". |
181 {ASCIIToUTF16("aaa"), 2, | 229 { ASCIIToUTF16("aaa"), 2, |
182 {ASCIIToUTF16("Search aaaa for <enter query>"), | 230 { { ASCIIToUTF16("Search aaaa for <enter query>"), false }, |
183 ASCIIToUTF16("Search aaaaa for <enter query>")}}, | 231 { ASCIIToUTF16("Search aaaaa for <enter query>"), false }, |
184 {ASCIIToUTF16("www.w w"), 2, | 232 kEmptyMatch} }, |
185 {ASCIIToUTF16("Search www for w"), | 233 { ASCIIToUTF16("www.w w"), 2, |
186 ASCIIToUTF16("Search weasel for w")}}, | 234 { { ASCIIToUTF16("Search www for w"), false }, |
235 { ASCIIToUTF16("Search weasel for w"), false }, | |
236 kEmptyMatch } }, | |
187 // Also, check that tokenization only collapses whitespace between first | 237 // Also, check that tokenization only collapses whitespace between first |
188 // tokens and contents are not escaped or unescaped. | 238 // tokens and contents are not escaped or unescaped. |
189 {ASCIIToUTF16("a 1 2+ 3"), 3, | 239 { ASCIIToUTF16("a 1 2+ 3"), 3, |
190 {ASCIIToUTF16("Search aa for 1 2+ 3"), | 240 { { ASCIIToUTF16("Search aa for 1 2+ 3"), false }, |
191 ASCIIToUTF16("Search ab for 1 2+ 3"), | 241 { ASCIIToUTF16("Search ab for 1 2+ 3"), false }, |
192 ASCIIToUTF16("Search aaaa for 1 2+ 3")}}, | 242 { ASCIIToUTF16("Search aaaa for 1 2+ 3"), false } } }, |
193 }; | 243 }; |
194 | 244 |
195 RunTest<string16>(contents_cases, arraysize(contents_cases), | 245 RunTest<string16>(contents_cases, arraysize(contents_cases), |
196 &AutocompleteMatch::contents); | 246 &AutocompleteMatch::contents); |
197 } | 247 } |
198 | 248 |
199 TEST_F(KeywordProviderTest, AddKeyword) { | 249 TEST_F(KeywordProviderTest, AddKeyword) { |
200 TemplateURLData data; | 250 TemplateURLData data; |
201 data.short_name = ASCIIToUTF16("Test"); | 251 data.short_name = ASCIIToUTF16("Test"); |
202 string16 keyword(ASCIIToUTF16("foo")); | 252 string16 keyword(ASCIIToUTF16("foo")); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 EXPECT_EQ(cases[i].updated_cursor_position, input.cursor_position()); | 329 EXPECT_EQ(cases[i].updated_cursor_position, input.cursor_position()); |
280 } | 330 } |
281 } | 331 } |
282 | 332 |
283 // If extra query params are specified on the command line, they should be | 333 // If extra query params are specified on the command line, they should be |
284 // reflected (only) in the default search provider's destination URL. | 334 // reflected (only) in the default search provider's destination URL. |
285 TEST_F(KeywordProviderTest, ExtraQueryParams) { | 335 TEST_F(KeywordProviderTest, ExtraQueryParams) { |
286 CommandLine::ForCurrentProcess()->AppendSwitchASCII( | 336 CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
287 switches::kExtraSearchQueryParams, "a=b"); | 337 switches::kExtraSearchQueryParams, "a=b"); |
288 | 338 |
289 test_data<GURL> url_cases[] = { | 339 TestData<GURL> url_cases[] = { |
290 {ASCIIToUTF16("a 1 2 3"), 3, {GURL("aa.com?a=b&foo=1+2+3"), | 340 { ASCIIToUTF16("a 1 2 3"), 3, |
291 GURL("bogus URL 1+2+3"), | 341 { { GURL("aa.com?a=b&foo=1+2+3"), false }, |
292 GURL("http://aaaa/?aaaa=1&b=1+2+3&c")}}, | 342 { GURL("bogus URL 1+2+3"), false }, |
343 { GURL("http://aaaa/?aaaa=1&b=1+2+3&c"), false } } }, | |
293 }; | 344 }; |
294 | 345 |
295 RunTest<GURL>(url_cases, arraysize(url_cases), | 346 RunTest<GURL>(url_cases, arraysize(url_cases), |
296 &AutocompleteMatch::destination_url); | 347 &AutocompleteMatch::destination_url); |
297 } | 348 } |
OLD | NEW |