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
3 // found in the LICENSE file.
4
5 #include "base/base_paths.h"
6 #include "base/string_util.h"
7 #include "base/utf_string_conversions.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/rlz/rlz.h"
10 #include "chrome/browser/search_engines/search_terms_data.h"
11 #include "chrome/browser/search_engines/template_url.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 // Simple implementation of SearchTermsData.
15 class TestSearchTermsData : public SearchTermsData {
16 public:
TestSearchTermsData(const char * google_base_url)17 explicit TestSearchTermsData(const char* google_base_url)
18 : google_base_url_(google_base_url) {
19 }
20
GoogleBaseURLValue() const21 virtual std::string GoogleBaseURLValue() const {
22 return google_base_url_;
23 }
24
GetApplicationLocale() const25 virtual std::string GetApplicationLocale() const {
26 return "yy";
27 }
28
29 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
30 // Returns the value for the Chrome Omnibox rlz.
GetRlzParameterValue() const31 virtual string16 GetRlzParameterValue() const {
32 return string16();
33 }
34 #endif
35
36 private:
37 std::string google_base_url_;
38
39 DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData);
40 };
41
42 class TemplateURLTest : public testing::Test {
43 public:
TearDown()44 virtual void TearDown() {
45 TemplateURLRef::SetGoogleBaseURL(NULL);
46 }
47
CheckSuggestBaseURL(const char * base_url,const char * base_suggest_url) const48 void CheckSuggestBaseURL(const char* base_url,
49 const char* base_suggest_url) const {
50 TestSearchTermsData search_terms_data(base_url);
51 EXPECT_STREQ(base_suggest_url,
52 search_terms_data.GoogleBaseSuggestURLValue().c_str());
53 }
54 };
55
TEST_F(TemplateURLTest,Defaults)56 TEST_F(TemplateURLTest, Defaults) {
57 TemplateURL url;
58 ASSERT_FALSE(url.show_in_default_list());
59 ASSERT_FALSE(url.safe_for_autoreplace());
60 ASSERT_EQ(0, url.prepopulate_id());
61 }
62
TEST_F(TemplateURLTest,TestValidWithComplete)63 TEST_F(TemplateURLTest, TestValidWithComplete) {
64 TemplateURLRef ref("{searchTerms}", 0, 0);
65 ASSERT_TRUE(ref.IsValid());
66 }
67
TEST_F(TemplateURLTest,URLRefTestSearchTerms)68 TEST_F(TemplateURLTest, URLRefTestSearchTerms) {
69 struct SearchTermsCase {
70 const char* url;
71 const string16 terms;
72 const char* output;
73 } search_term_cases[] = {
74 { "http://foo{searchTerms}", ASCIIToUTF16("sea rch/bar"),
75 "http://foosea%20rch/bar" },
76 { "http://foo{searchTerms}?boo=abc", ASCIIToUTF16("sea rch/bar"),
77 "http://foosea%20rch/bar?boo=abc" },
78 { "http://foo/?boo={searchTerms}", ASCIIToUTF16("sea rch/bar"),
79 "http://foo/?boo=sea+rch%2Fbar" },
80 { "http://en.wikipedia.org/{searchTerms}", ASCIIToUTF16("wiki/?"),
81 "http://en.wikipedia.org/wiki/%3F" }
82 };
83 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) {
84 const SearchTermsCase& value = search_term_cases[i];
85 TemplateURL t_url;
86 TemplateURLRef ref(value.url, 0, 0);
87 ASSERT_TRUE(ref.IsValid());
88
89 ASSERT_TRUE(ref.SupportsReplacement());
90 GURL result = GURL(ref.ReplaceSearchTerms(t_url, value.terms,
91 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
92 ASSERT_TRUE(result.is_valid());
93 ASSERT_EQ(value.output, result.spec());
94 }
95 }
96
TEST_F(TemplateURLTest,URLRefTestCount)97 TEST_F(TemplateURLTest, URLRefTestCount) {
98 TemplateURL t_url;
99 TemplateURLRef ref("http://foo{searchTerms}{count?}", 0, 0);
100 ASSERT_TRUE(ref.IsValid());
101 ASSERT_TRUE(ref.SupportsReplacement());
102 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
103 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
104 ASSERT_TRUE(result.is_valid());
105 ASSERT_EQ("http://foox/", result.spec());
106 }
107
TEST_F(TemplateURLTest,URLRefTestCount2)108 TEST_F(TemplateURLTest, URLRefTestCount2) {
109 TemplateURL t_url;
110 TemplateURLRef ref("http://foo{searchTerms}{count}", 0, 0);
111 ASSERT_TRUE(ref.IsValid());
112 ASSERT_TRUE(ref.SupportsReplacement());
113 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
114 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
115 ASSERT_TRUE(result.is_valid());
116 ASSERT_EQ("http://foox10/", result.spec());
117 }
118
TEST_F(TemplateURLTest,URLRefTestIndices)119 TEST_F(TemplateURLTest, URLRefTestIndices) {
120 TemplateURL t_url;
121 TemplateURLRef ref("http://foo{searchTerms}x{startIndex?}y{startPage?}",
122 1, 2);
123 ASSERT_TRUE(ref.IsValid());
124 ASSERT_TRUE(ref.SupportsReplacement());
125 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
126 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
127 ASSERT_TRUE(result.is_valid());
128 ASSERT_EQ("http://fooxxy/", result.spec());
129 }
130
TEST_F(TemplateURLTest,URLRefTestIndices2)131 TEST_F(TemplateURLTest, URLRefTestIndices2) {
132 TemplateURL t_url;
133 TemplateURLRef ref("http://foo{searchTerms}x{startIndex}y{startPage}", 1, 2);
134 ASSERT_TRUE(ref.IsValid());
135 ASSERT_TRUE(ref.SupportsReplacement());
136 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
137 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
138 ASSERT_TRUE(result.is_valid());
139 ASSERT_EQ("http://fooxx1y2/", result.spec());
140 }
141
TEST_F(TemplateURLTest,URLRefTestEncoding)142 TEST_F(TemplateURLTest, URLRefTestEncoding) {
143 TemplateURL t_url;
144 TemplateURLRef ref(
145 "http://foo{searchTerms}x{inputEncoding?}y{outputEncoding?}a", 1, 2);
146 ASSERT_TRUE(ref.IsValid());
147 ASSERT_TRUE(ref.SupportsReplacement());
148 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
149 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
150 ASSERT_TRUE(result.is_valid());
151 ASSERT_EQ("http://fooxxutf-8ya/", result.spec());
152 }
153
TEST_F(TemplateURLTest,InputEncodingBeforeSearchTerm)154 TEST_F(TemplateURLTest, InputEncodingBeforeSearchTerm) {
155 TemplateURL t_url;
156 TemplateURLRef ref(
157 "http://foox{inputEncoding?}a{searchTerms}y{outputEncoding?}b", 1, 2);
158 ASSERT_TRUE(ref.IsValid());
159 ASSERT_TRUE(ref.SupportsReplacement());
160 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
161 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
162 ASSERT_TRUE(result.is_valid());
163 ASSERT_EQ("http://fooxutf-8axyb/", result.spec());
164 }
165
TEST_F(TemplateURLTest,URLRefTestEncoding2)166 TEST_F(TemplateURLTest, URLRefTestEncoding2) {
167 TemplateURL t_url;
168 TemplateURLRef ref(
169 "http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a", 1, 2);
170 ASSERT_TRUE(ref.IsValid());
171 ASSERT_TRUE(ref.SupportsReplacement());
172 GURL result = GURL(ref.ReplaceSearchTerms(t_url, ASCIIToUTF16("X"),
173 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
174 ASSERT_TRUE(result.is_valid());
175 ASSERT_EQ("http://fooxxutf-8yutf-8a/", result.spec());
176 }
177
TEST_F(TemplateURLTest,URLRefTestSearchTermsUsingTermsData)178 TEST_F(TemplateURLTest, URLRefTestSearchTermsUsingTermsData) {
179 struct SearchTermsCase {
180 const char* url;
181 const string16 terms;
182 const char* output;
183 } search_term_cases[] = {
184 { "{google:baseURL}{language}{searchTerms}", string16(),
185 "http://example.com/e/yy" },
186 { "{google:baseSuggestURL}{searchTerms}", string16(),
187 "http://clients1.example.com/complete/" }
188 };
189
190 TestSearchTermsData search_terms_data("http://example.com/e/");
191 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(search_term_cases); ++i) {
192 const SearchTermsCase& value = search_term_cases[i];
193 TemplateURL t_url;
194 TemplateURLRef ref(value.url, 0, 0);
195 ASSERT_TRUE(ref.IsValid());
196
197 ASSERT_TRUE(ref.SupportsReplacement());
198 GURL result = GURL(ref.ReplaceSearchTermsUsingTermsData(
199 t_url, value.terms,
200 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16(),
201 search_terms_data));
202 ASSERT_TRUE(result.is_valid());
203 ASSERT_EQ(value.output, result.spec());
204 }
205 }
206
TEST_F(TemplateURLTest,URLRefTermToWide)207 TEST_F(TemplateURLTest, URLRefTermToWide) {
208 struct ToWideCase {
209 const char* encoded_search_term;
210 const string16 expected_decoded_term;
211 } to_wide_cases[] = {
212 {"hello+world", ASCIIToUTF16("hello world")},
213 // Test some big-5 input.
214 {"%a7A%A6%6e+to+you", WideToUTF16(L"\x4f60\x597d to you")},
215 // Test some UTF-8 input. We should fall back to this when the encoding
216 // doesn't look like big-5. We have a '5' in the middle, which is an invalid
217 // Big-5 trailing byte.
218 {"%e4%bd%a05%e5%a5%bd+to+you", WideToUTF16(L"\x4f60\x35\x597d to you")},
219 // Undecodable input should stay escaped.
220 {"%91%01+abcd", WideToUTF16(L"%91%01 abcd")},
221 // Make sure we convert %2B to +.
222 {"C%2B%2B", ASCIIToUTF16("C++")},
223 // C%2B is escaped as C%252B, make sure we unescape it properly.
224 {"C%252B", ASCIIToUTF16("C%2B")},
225 };
226
227 TemplateURL t_url;
228
229 // Set one input encoding: big-5. This is so we can test fallback to UTF-8.
230 std::vector<std::string> encodings;
231 encodings.push_back("big-5");
232 t_url.set_input_encodings(encodings);
233
234 TemplateURLRef ref("http://foo?q={searchTerms}", 1, 2);
235 ASSERT_TRUE(ref.IsValid());
236 ASSERT_TRUE(ref.SupportsReplacement());
237
238 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(to_wide_cases); i++) {
239 string16 result = ref.SearchTermToString16(t_url,
240 to_wide_cases[i].encoded_search_term);
241
242 EXPECT_EQ(to_wide_cases[i].expected_decoded_term, result);
243 }
244 }
245
TEST_F(TemplateURLTest,SetFavicon)246 TEST_F(TemplateURLTest, SetFavicon) {
247 TemplateURL url;
248 GURL favicon_url("http://favicon.url");
249 url.SetFaviconURL(favicon_url);
250 ASSERT_EQ(1U, url.image_refs().size());
251 ASSERT_TRUE(favicon_url == url.GetFaviconURL());
252
253 GURL favicon_url2("http://favicon2.url");
254 url.SetFaviconURL(favicon_url2);
255 ASSERT_EQ(1U, url.image_refs().size());
256 ASSERT_TRUE(favicon_url2 == url.GetFaviconURL());
257 }
258
TEST_F(TemplateURLTest,DisplayURLToURLRef)259 TEST_F(TemplateURLTest, DisplayURLToURLRef) {
260 struct TestData {
261 const std::string url;
262 const string16 expected_result;
263 } data[] = {
264 { "http://foo{searchTerms}x{inputEncoding}y{outputEncoding}a",
265 ASCIIToUTF16("http://foo%sx{inputEncoding}y{outputEncoding}a") },
266 { "http://X",
267 ASCIIToUTF16("http://X") },
268 { "http://foo{searchTerms",
269 ASCIIToUTF16("http://foo{searchTerms") },
270 { "http://foo{searchTerms}{language}",
271 ASCIIToUTF16("http://foo%s{language}") },
272 };
273 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
274 TemplateURLRef ref(data[i].url, 1, 2);
275 EXPECT_EQ(data[i].expected_result, ref.DisplayURL());
276 EXPECT_EQ(data[i].url,
277 TemplateURLRef::DisplayURLToURLRef(ref.DisplayURL()));
278 }
279 }
280
TEST_F(TemplateURLTest,ReplaceSearchTerms)281 TEST_F(TemplateURLTest, ReplaceSearchTerms) {
282 struct TestData {
283 const std::string url;
284 const std::string expected_result;
285 } data[] = {
286 { "http://foo/{language}{searchTerms}{inputEncoding}",
287 "http://foo/{language}XUTF-8" },
288 { "http://foo/{language}{inputEncoding}{searchTerms}",
289 "http://foo/{language}UTF-8X" },
290 { "http://foo/{searchTerms}{language}{inputEncoding}",
291 "http://foo/X{language}UTF-8" },
292 { "http://foo/{searchTerms}{inputEncoding}{language}",
293 "http://foo/XUTF-8{language}" },
294 { "http://foo/{inputEncoding}{searchTerms}{language}",
295 "http://foo/UTF-8X{language}" },
296 { "http://foo/{inputEncoding}{language}{searchTerms}",
297 "http://foo/UTF-8{language}X" },
298 { "http://foo/{language}a{searchTerms}a{inputEncoding}a",
299 "http://foo/{language}aXaUTF-8a" },
300 { "http://foo/{language}a{inputEncoding}a{searchTerms}a",
301 "http://foo/{language}aUTF-8aXa" },
302 { "http://foo/{searchTerms}a{language}a{inputEncoding}a",
303 "http://foo/Xa{language}aUTF-8a" },
304 { "http://foo/{searchTerms}a{inputEncoding}a{language}a",
305 "http://foo/XaUTF-8a{language}a" },
306 { "http://foo/{inputEncoding}a{searchTerms}a{language}a",
307 "http://foo/UTF-8aXa{language}a" },
308 { "http://foo/{inputEncoding}a{language}a{searchTerms}a",
309 "http://foo/UTF-8a{language}aXa" },
310 };
311 TemplateURL turl;
312 turl.add_input_encoding("UTF-8");
313 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
314 TemplateURLRef ref(data[i].url, 1, 2);
315 EXPECT_TRUE(ref.IsValid());
316 EXPECT_TRUE(ref.SupportsReplacement());
317 std::string expected_result = data[i].expected_result;
318 ReplaceSubstringsAfterOffset(&expected_result, 0, "{language}",
319 g_browser_process->GetApplicationLocale());
320 GURL result = GURL(ref.ReplaceSearchTerms(turl, ASCIIToUTF16("X"),
321 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
322 EXPECT_TRUE(result.is_valid());
323 EXPECT_EQ(expected_result, result.spec());
324 }
325 }
326
327
328 // Tests replacing search terms in various encodings and making sure the
329 // generated URL matches the expected value.
TEST_F(TemplateURLTest,ReplaceArbitrarySearchTerms)330 TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
331 struct TestData {
332 const std::string encoding;
333 const string16 search_term;
334 const std::string url;
335 const std::string expected_result;
336 } data[] = {
337 { "BIG5", WideToUTF16(L"\x60BD"),
338 "http://foo/?{searchTerms}{inputEncoding}",
339 "http://foo/?%B1~BIG5" },
340 { "UTF-8", ASCIIToUTF16("blah"),
341 "http://foo/?{searchTerms}{inputEncoding}",
342 "http://foo/?blahUTF-8" },
343 };
344 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
345 TemplateURL turl;
346 turl.add_input_encoding(data[i].encoding);
347 TemplateURLRef ref(data[i].url, 1, 2);
348 GURL result = GURL(ref.ReplaceSearchTerms(turl,
349 data[i].search_term, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
350 string16()));
351 EXPECT_TRUE(result.is_valid());
352 EXPECT_EQ(data[i].expected_result, result.spec());
353 }
354 }
355
TEST_F(TemplateURLTest,Suggestions)356 TEST_F(TemplateURLTest, Suggestions) {
357 struct TestData {
358 const int accepted_suggestion;
359 const string16 original_query_for_suggestion;
360 const std::string expected_result;
361 } data[] = {
362 { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16(),
363 "http://bar/foo?q=foobar" },
364 { TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, ASCIIToUTF16("foo"),
365 "http://bar/foo?q=foobar" },
366 { TemplateURLRef::NO_SUGGESTION_CHOSEN, string16(),
367 "http://bar/foo?aq=f&q=foobar" },
368 { TemplateURLRef::NO_SUGGESTION_CHOSEN, ASCIIToUTF16("foo"),
369 "http://bar/foo?aq=f&q=foobar" },
370 { 0, string16(), "http://bar/foo?aq=0&oq=&q=foobar" },
371 { 1, ASCIIToUTF16("foo"), "http://bar/foo?aq=1&oq=foo&q=foobar" },
372 };
373 TemplateURL turl;
374 turl.add_input_encoding("UTF-8");
375 TemplateURLRef ref("http://bar/foo?{google:acceptedSuggestion}"
376 "{google:originalQueryForSuggestion}q={searchTerms}", 1, 2);
377 ASSERT_TRUE(ref.IsValid());
378 ASSERT_TRUE(ref.SupportsReplacement());
379 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
380 GURL result = GURL(ref.ReplaceSearchTerms(turl, ASCIIToUTF16("foobar"),
381 data[i].accepted_suggestion, data[i].original_query_for_suggestion));
382 EXPECT_TRUE(result.is_valid());
383 EXPECT_EQ(data[i].expected_result, result.spec());
384 }
385 }
386
387 #if defined(OS_WIN)
TEST_F(TemplateURLTest,RLZ)388 TEST_F(TemplateURLTest, RLZ) {
389 string16 rlz_string;
390 #if defined(GOOGLE_CHROME_BUILD)
391 RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz_string);
392 #endif
393
394 TemplateURL t_url;
395 TemplateURLRef ref("http://bar/?{google:RLZ}{searchTerms}", 1, 2);
396 ASSERT_TRUE(ref.IsValid());
397 ASSERT_TRUE(ref.SupportsReplacement());
398 GURL result(ref.ReplaceSearchTerms(t_url, L"x",
399 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
400 ASSERT_TRUE(result.is_valid());
401 std::string expected_url = "http://bar/?";
402 if (!rlz_string.empty()) {
403 expected_url += "rlz=" + WideToUTF8(rlz_string) + "&";
404 }
405 expected_url += "x";
406 ASSERT_EQ(expected_url, result.spec());
407 }
408 #endif
409
TEST_F(TemplateURLTest,HostAndSearchTermKey)410 TEST_F(TemplateURLTest, HostAndSearchTermKey) {
411 struct TestData {
412 const std::string url;
413 const std::string host;
414 const std::string path;
415 const std::string search_term_key;
416 } data[] = {
417 { "http://blah/?foo=bar&q={searchTerms}&b=x", "blah", "/", "q"},
418
419 // No query key should result in empty values.
420 { "http://blah/{searchTerms}", "", "", ""},
421
422 // No term should result in empty values.
423 { "http://blah/", "", "", ""},
424
425 // Multiple terms should result in empty values.
426 { "http://blah/?q={searchTerms}&x={searchTerms}", "", "", ""},
427
428 // Term in the host shouldn't match.
429 { "http://{searchTerms}", "", "", ""},
430
431 { "http://blah/?q={searchTerms}", "blah", "/", "q"},
432
433 // Single term with extra chars in value should match.
434 { "http://blah/?q=stock:{searchTerms}", "blah", "/", "q"},
435 };
436
437 TemplateURL t_url;
438 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
439 t_url.SetURL(data[i].url, 0, 0);
440 EXPECT_EQ(data[i].host, t_url.url()->GetHost());
441 EXPECT_EQ(data[i].path, t_url.url()->GetPath());
442 EXPECT_EQ(data[i].search_term_key, t_url.url()->GetSearchTermKey());
443 }
444 }
445
TEST_F(TemplateURLTest,GoogleBaseSuggestURL)446 TEST_F(TemplateURLTest, GoogleBaseSuggestURL) {
447 static const struct {
448 const char* const base_url;
449 const char* const base_suggest_url;
450 } data[] = {
451 { "http://google.com/", "http://clients1.google.com/complete/", },
452 { "http://www.google.com/", "http://clients1.google.com/complete/", },
453 { "http://www.google.co.uk/", "http://clients1.google.co.uk/complete/", },
454 { "http://www.google.com.by/",
455 "http://clients1.google.com.by/complete/", },
456 { "http://google.com/intl/xx/", "http://clients1.google.com/complete/", },
457 };
458
459 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i)
460 CheckSuggestBaseURL(data[i].base_url, data[i].base_suggest_url);
461 }
462
TEST_F(TemplateURLTest,Keyword)463 TEST_F(TemplateURLTest, Keyword) {
464 TemplateURL t_url;
465 t_url.SetURL("http://www.google.com/search", 0, 0);
466 EXPECT_FALSE(t_url.autogenerate_keyword());
467 t_url.set_keyword(ASCIIToUTF16("foo"));
468 EXPECT_EQ(ASCIIToUTF16("foo"), t_url.keyword());
469 t_url.set_autogenerate_keyword(true);
470 EXPECT_TRUE(t_url.autogenerate_keyword());
471 EXPECT_EQ(ASCIIToUTF16("google.com"), t_url.keyword());
472 t_url.set_keyword(ASCIIToUTF16("foo"));
473 EXPECT_FALSE(t_url.autogenerate_keyword());
474 EXPECT_EQ(ASCIIToUTF16("foo"), t_url.keyword());
475 }
476
TEST_F(TemplateURLTest,ParseParameterKnown)477 TEST_F(TemplateURLTest, ParseParameterKnown) {
478 std::string parsed_url("{searchTerms}");
479 TemplateURLRef url_ref(parsed_url, 0, 0);
480 TemplateURLRef::Replacements replacements;
481 EXPECT_TRUE(url_ref.ParseParameter(0, 12, &parsed_url, &replacements));
482 EXPECT_EQ(std::string(), parsed_url);
483 ASSERT_EQ(1U, replacements.size());
484 EXPECT_EQ(static_cast<size_t>(0), replacements[0].index);
485 EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
486 }
487
TEST_F(TemplateURLTest,ParseParameterUnknown)488 TEST_F(TemplateURLTest, ParseParameterUnknown) {
489 std::string parsed_url("{}");
490 TemplateURLRef url_ref(parsed_url, 0, 0);
491 TemplateURLRef::Replacements replacements;
492 EXPECT_FALSE(url_ref.ParseParameter(0, 1, &parsed_url, &replacements));
493 EXPECT_EQ("{}", parsed_url);
494 EXPECT_TRUE(replacements.empty());
495 }
496
TEST_F(TemplateURLTest,ParseURLEmpty)497 TEST_F(TemplateURLTest, ParseURLEmpty) {
498 TemplateURLRef url_ref("", 0, 0);
499 TemplateURLRef::Replacements replacements;
500 bool valid = false;
501 EXPECT_EQ(std::string(), url_ref.ParseURL("", &replacements, &valid));
502 EXPECT_TRUE(replacements.empty());
503 EXPECT_TRUE(valid);
504 }
505
TEST_F(TemplateURLTest,ParseURLNoTemplateEnd)506 TEST_F(TemplateURLTest, ParseURLNoTemplateEnd) {
507 TemplateURLRef url_ref("{", 0, 0);
508 TemplateURLRef::Replacements replacements;
509 bool valid = false;
510 EXPECT_EQ(std::string(), url_ref.ParseURL("{", &replacements, &valid));
511 EXPECT_TRUE(replacements.empty());
512 EXPECT_FALSE(valid);
513 }
514
TEST_F(TemplateURLTest,ParseURLNoKnownParameters)515 TEST_F(TemplateURLTest, ParseURLNoKnownParameters) {
516 TemplateURLRef url_ref("{}", 0, 0);
517 TemplateURLRef::Replacements replacements;
518 bool valid = false;
519 EXPECT_EQ("{}", url_ref.ParseURL("{}", &replacements, &valid));
520 EXPECT_TRUE(replacements.empty());
521 EXPECT_TRUE(valid);
522 }
523
TEST_F(TemplateURLTest,ParseURLTwoParameters)524 TEST_F(TemplateURLTest, ParseURLTwoParameters) {
525 TemplateURLRef url_ref("{}{{%s}}", 0, 0);
526 TemplateURLRef::Replacements replacements;
527 bool valid = false;
528 EXPECT_EQ("{}{}",
529 url_ref.ParseURL("{}{{searchTerms}}", &replacements, &valid));
530 ASSERT_EQ(1U, replacements.size());
531 EXPECT_EQ(static_cast<size_t>(3), replacements[0].index);
532 EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
533 EXPECT_TRUE(valid);
534 }
535
TEST_F(TemplateURLTest,ParseURLNestedParameter)536 TEST_F(TemplateURLTest, ParseURLNestedParameter) {
537 TemplateURLRef url_ref("{%s", 0, 0);
538 TemplateURLRef::Replacements replacements;
539 bool valid = false;
540 EXPECT_EQ("{", url_ref.ParseURL("{{searchTerms}", &replacements, &valid));
541 ASSERT_EQ(1U, replacements.size());
542 EXPECT_EQ(static_cast<size_t>(1), replacements[0].index);
543 EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
544 EXPECT_TRUE(valid);
545 }
546