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: 17 explicit TestSearchTermsData(const char* google_base_url) 18 : google_base_url_(google_base_url) { 19 } 20 21 virtual std::string GoogleBaseURLValue() const { 22 return google_base_url_; 23 } 24 25 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. 31 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: 44 virtual void TearDown() { 45 TemplateURLRef::SetGoogleBaseURL(NULL); 46 } 47 48 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 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 63 TEST_F(TemplateURLTest, TestValidWithComplete) { 64 TemplateURLRef ref("{searchTerms}", 0, 0); 65 ASSERT_TRUE(ref.IsValid()); 66 } 67 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 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 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 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 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 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 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 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 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 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 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 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 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. 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 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) 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 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 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 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 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 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 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 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 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 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 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