1 // Copyright (C) 2014 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "address_validator_test.h" 16 17 #include <libaddressinput/address_data.h> 18 #include <libaddressinput/address_field.h> 19 #include <libaddressinput/address_problem.h> 20 #include <libaddressinput/address_validator.h> 21 #include <libaddressinput/downloader.h> 22 #include <libaddressinput/load_rules_delegate.h> 23 #include <libaddressinput/storage.h> 24 #include <libaddressinput/util/scoped_ptr.h> 25 26 #include <cstddef> 27 #include <set> 28 #include <string> 29 #include <vector> 30 31 #include <gtest/gtest.h> 32 33 #include "fake_downloader.h" 34 #include "fake_storage.h" 35 #include "region_data_constants.h" 36 37 namespace i18n { 38 namespace addressinput { 39 40 class AddressValidatorTest : public testing::Test, public LoadRulesDelegate { 41 public: 42 AddressValidatorTest() 43 : validator_(BuildAddressValidatorForTesting( 44 FakeDownloader::kFakeDataUrl, 45 scoped_ptr<Downloader>(new FakeDownloader), 46 scoped_ptr<Storage>(new FakeStorage), 47 this)) { 48 validator_->LoadRules("US"); 49 } 50 51 virtual ~AddressValidatorTest() {} 52 53 protected: 54 scoped_ptr<AddressValidator> validator_; 55 56 private: 57 // LoadRulesDelegate implementation. 58 virtual void OnAddressValidationRulesLoaded(const std::string& country_code, 59 bool success) { 60 AddressData address_data; 61 address_data.country_code = country_code; 62 AddressValidator::Status status = 63 validator_->ValidateAddress(address_data, AddressProblemFilter(), NULL); 64 EXPECT_EQ(success, status == AddressValidator::SUCCESS); 65 } 66 }; 67 68 TEST_F(AddressValidatorTest, RegionHasRules) { 69 const std::vector<std::string>& region_codes = 70 RegionDataConstants::GetRegionCodes(); 71 AddressData address; 72 for (size_t i = 0; i < region_codes.size(); ++i) { 73 SCOPED_TRACE("For region: " + region_codes[i]); 74 validator_->LoadRules(region_codes[i]); 75 address.country_code = region_codes[i]; 76 EXPECT_EQ( 77 AddressValidator::SUCCESS, 78 validator_->ValidateAddress(address, AddressProblemFilter(), NULL)); 79 } 80 } 81 82 TEST_F(AddressValidatorTest, EmptyAddressNoFatalFailure) { 83 AddressData address; 84 address.country_code = "US"; 85 86 AddressProblems problems; 87 EXPECT_EQ( 88 AddressValidator::SUCCESS, 89 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 90 } 91 92 TEST_F(AddressValidatorTest, USZipCode) { 93 AddressData address; 94 address.address_lines.push_back("340 Main St."); 95 address.locality = "Venice"; 96 address.administrative_area = "CA"; 97 address.country_code = "US"; 98 99 // Valid Californian zip code. 100 address.postal_code = "90291"; 101 AddressProblems problems; 102 EXPECT_EQ( 103 AddressValidator::SUCCESS, 104 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 105 EXPECT_TRUE(problems.empty()); 106 107 problems.clear(); 108 109 // An extended, valid Californian zip code. 110 address.postal_code = "90210-1234"; 111 EXPECT_EQ( 112 AddressValidator::SUCCESS, 113 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 114 EXPECT_TRUE(problems.empty()); 115 116 problems.clear(); 117 118 // New York zip code (which is invalid for California). 119 address.postal_code = "12345"; 120 EXPECT_EQ( 121 AddressValidator::SUCCESS, 122 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 123 EXPECT_EQ(1U, problems.size()); 124 EXPECT_EQ(problems[0].field, POSTAL_CODE); 125 EXPECT_EQ(problems[0].type, AddressProblem::MISMATCHING_VALUE); 126 127 problems.clear(); 128 129 // A zip code with a "90" in the middle. 130 address.postal_code = "12903"; 131 EXPECT_EQ( 132 AddressValidator::SUCCESS, 133 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 134 EXPECT_EQ(1U, problems.size()); 135 EXPECT_EQ(problems[0].field, POSTAL_CODE); 136 EXPECT_EQ(problems[0].type, AddressProblem::MISMATCHING_VALUE); 137 138 problems.clear(); 139 140 // Invalid zip code (too many digits). 141 address.postal_code = "902911"; 142 EXPECT_EQ( 143 AddressValidator::SUCCESS, 144 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 145 EXPECT_EQ(1U, problems.size()); 146 EXPECT_EQ(problems[0].field, POSTAL_CODE); 147 EXPECT_EQ(problems[0].type, AddressProblem::UNRECOGNIZED_FORMAT); 148 149 problems.clear(); 150 151 // Invalid zip code (too few digits). 152 address.postal_code = "9029"; 153 EXPECT_EQ( 154 AddressValidator::SUCCESS, 155 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 156 EXPECT_EQ(1U, problems.size()); 157 EXPECT_EQ(problems[0].field, POSTAL_CODE); 158 EXPECT_EQ(problems[0].type, AddressProblem::UNRECOGNIZED_FORMAT); 159 } 160 161 TEST_F(AddressValidatorTest, BasicValidation) { 162 // US rules should always be available, even though this load call fails. 163 validator_->LoadRules("US"); 164 AddressData address; 165 address.country_code = "US"; 166 address.language_code = "en"; 167 address.administrative_area = "TX"; 168 address.locality = "Paris"; 169 address.postal_code = "75461"; 170 address.address_lines.push_back("123 Main St"); 171 AddressProblems problems; 172 EXPECT_EQ( 173 AddressValidator::SUCCESS, 174 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 175 EXPECT_TRUE(problems.empty()); 176 177 // The display name works as well as the key. 178 address.administrative_area = "Texas"; 179 problems.clear(); 180 EXPECT_EQ( 181 AddressValidator::SUCCESS, 182 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 183 EXPECT_TRUE(problems.empty()); 184 185 // Ignore capitalization. 186 address.administrative_area = "tx"; 187 problems.clear(); 188 EXPECT_EQ( 189 AddressValidator::SUCCESS, 190 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 191 EXPECT_TRUE(problems.empty()); 192 193 // Ignore capitalization. 194 address.administrative_area = "teXas"; 195 problems.clear(); 196 EXPECT_EQ( 197 AddressValidator::SUCCESS, 198 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 199 EXPECT_TRUE(problems.empty()); 200 201 // Ignore diacriticals. 202 address.administrative_area = "T\u00E9xas"; 203 problems.clear(); 204 EXPECT_EQ( 205 AddressValidator::SUCCESS, 206 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 207 EXPECT_TRUE(problems.empty()); 208 } 209 210 TEST_F(AddressValidatorTest, BasicValidationFailure) { 211 // US rules should always be available, even though this load call fails. 212 validator_->LoadRules("US"); 213 AddressData address; 214 address.country_code = "US"; 215 address.language_code = "en"; 216 address.administrative_area = "XT"; 217 address.locality = "Paris"; 218 address.postal_code = "75461"; 219 address.address_lines.push_back("123 Main St"); 220 AddressProblems problems; 221 EXPECT_EQ( 222 AddressValidator::SUCCESS, 223 validator_->ValidateAddress(address, AddressProblemFilter(), &problems)); 224 225 ASSERT_EQ(1U, problems.size()); 226 EXPECT_EQ(AddressProblem::UNKNOWN_VALUE, problems[0].type); 227 EXPECT_EQ(ADMIN_AREA, problems[0].field); 228 } 229 230 TEST_F(AddressValidatorTest, NoNullSuggestionsCrash) { 231 AddressData address; 232 address.country_code = "US"; 233 EXPECT_EQ(AddressValidator::SUCCESS, 234 validator_->GetSuggestions(address, COUNTRY, 1, NULL)); 235 } 236 237 TEST_F(AddressValidatorTest, SuggestAdminAreaForPostalCode) { 238 AddressData address; 239 address.country_code = "US"; 240 address.postal_code = "90291"; 241 242 std::vector<AddressData> suggestions; 243 EXPECT_EQ(AddressValidator::SUCCESS, 244 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 245 ASSERT_EQ(1U, suggestions.size()); 246 EXPECT_EQ("CA", suggestions[0].administrative_area); 247 EXPECT_EQ("90291", suggestions[0].postal_code); 248 } 249 250 TEST_F(AddressValidatorTest, SuggestLocalityForPostalCodeWithAdminArea) { 251 validator_->LoadRules("TW"); 252 AddressData address; 253 address.country_code = "TW"; 254 address.postal_code = "515"; 255 address.administrative_area = "Changhua"; 256 257 std::vector<AddressData> suggestions; 258 EXPECT_EQ(AddressValidator::SUCCESS, 259 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 260 ASSERT_EQ(1U, suggestions.size()); 261 EXPECT_EQ("Dacun Township", suggestions[0].locality); 262 EXPECT_EQ("Changhua County", suggestions[0].administrative_area); 263 EXPECT_EQ("515", suggestions[0].postal_code); 264 } 265 266 TEST_F(AddressValidatorTest, SuggestAdminAreaForPostalCodeWithLocality) { 267 validator_->LoadRules("TW"); 268 AddressData address; 269 address.country_code = "TW"; 270 address.postal_code = "515"; 271 address.locality = "Dacun"; 272 273 std::vector<AddressData> suggestions; 274 EXPECT_EQ(AddressValidator::SUCCESS, 275 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 276 ASSERT_EQ(1U, suggestions.size()); 277 EXPECT_EQ("Dacun Township", suggestions[0].locality); 278 EXPECT_EQ("Changhua County", suggestions[0].administrative_area); 279 EXPECT_EQ("515", suggestions[0].postal_code); 280 } 281 282 TEST_F(AddressValidatorTest, NoSuggestForPostalCodeWithWrongAdminArea) { 283 AddressData address; 284 address.country_code = "US"; 285 address.postal_code = "90066"; 286 address.postal_code = "TX"; 287 288 std::vector<AddressData> suggestions; 289 EXPECT_EQ(AddressValidator::SUCCESS, 290 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 291 EXPECT_TRUE(suggestions.empty()); 292 } 293 294 TEST_F(AddressValidatorTest, SuggestForLocality) { 295 validator_->LoadRules("CN"); 296 AddressData address; 297 address.country_code = "CN"; 298 address.locality = "Anqin"; 299 300 std::vector<AddressData> suggestions; 301 EXPECT_EQ(AddressValidator::SUCCESS, 302 validator_->GetSuggestions(address, LOCALITY, 10, &suggestions)); 303 ASSERT_EQ(1U, suggestions.size()); 304 EXPECT_EQ("Anqing Shi", suggestions[0].locality); 305 EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area); 306 } 307 308 TEST_F(AddressValidatorTest, SuggestForLocalityAndAdminArea) { 309 validator_->LoadRules("CN"); 310 AddressData address; 311 address.country_code = "CN"; 312 address.locality = "Anqing"; 313 address.administrative_area = "Anhui"; 314 315 std::vector<AddressData> suggestions; 316 EXPECT_EQ(AddressValidator::SUCCESS, 317 validator_->GetSuggestions(address, LOCALITY, 10, &suggestions)); 318 ASSERT_EQ(1U, suggestions.size()); 319 EXPECT_TRUE(suggestions[0].dependent_locality.empty()); 320 EXPECT_EQ("Anqing Shi", suggestions[0].locality); 321 EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area); 322 } 323 324 TEST_F(AddressValidatorTest, SuggestForAdminAreaAndLocality) { 325 validator_->LoadRules("CN"); 326 AddressData address; 327 address.country_code = "CN"; 328 address.locality = "Anqing"; 329 address.administrative_area = "Anhui"; 330 331 std::vector<AddressData> suggestions; 332 EXPECT_EQ(AddressValidator::SUCCESS, 333 validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions)); 334 ASSERT_EQ(1U, suggestions.size()); 335 EXPECT_TRUE(suggestions[0].dependent_locality.empty()); 336 EXPECT_TRUE(suggestions[0].locality.empty()); 337 EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area); 338 } 339 340 TEST_F(AddressValidatorTest, SuggestForDependentLocality) { 341 validator_->LoadRules("CN"); 342 AddressData address; 343 address.country_code = "CN"; 344 address.dependent_locality = "Zongyang"; 345 346 std::vector<AddressData> suggestions; 347 EXPECT_EQ(AddressValidator::SUCCESS, 348 validator_->GetSuggestions( 349 address, DEPENDENT_LOCALITY, 10, &suggestions)); 350 ASSERT_EQ(1U, suggestions.size()); 351 EXPECT_EQ("Zongyang Xian", suggestions[0].dependent_locality); 352 EXPECT_EQ("Anqing Shi", suggestions[0].locality); 353 EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area); 354 } 355 356 TEST_F(AddressValidatorTest, 357 NoSuggestForDependentLocalityWithWrongAdminArea) { 358 validator_->LoadRules("CN"); 359 AddressData address; 360 address.country_code = "CN"; 361 address.dependent_locality = "Zongyang"; 362 address.administrative_area = "Sichuan Sheng"; 363 364 std::vector<AddressData> suggestions; 365 EXPECT_EQ(AddressValidator::SUCCESS, 366 validator_->GetSuggestions( 367 address, DEPENDENT_LOCALITY, 10, &suggestions)); 368 EXPECT_TRUE(suggestions.empty()); 369 } 370 371 TEST_F(AddressValidatorTest, EmptySuggestionsOverLimit) { 372 AddressData address; 373 address.country_code = "US"; 374 address.administrative_area = "A"; 375 376 std::vector<AddressData> suggestions; 377 EXPECT_EQ(AddressValidator::SUCCESS, 378 validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions)); 379 EXPECT_TRUE(suggestions.empty()); 380 } 381 382 TEST_F(AddressValidatorTest, PreferShortSuggestions) { 383 AddressData address; 384 address.country_code = "US"; 385 address.administrative_area = "CA"; 386 387 std::vector<AddressData> suggestions; 388 EXPECT_EQ(AddressValidator::SUCCESS, 389 validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions)); 390 ASSERT_EQ(1U, suggestions.size()); 391 EXPECT_EQ("CA", suggestions[0].administrative_area); 392 } 393 394 TEST_F(AddressValidatorTest, SuggestTheSingleMatchForFullMatchName) { 395 AddressData address; 396 address.country_code = "US"; 397 address.administrative_area = "Texas"; 398 399 std::vector<AddressData> suggestions; 400 EXPECT_EQ(AddressValidator::SUCCESS, 401 validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions)); 402 ASSERT_EQ(1U, suggestions.size()); 403 EXPECT_EQ("Texas", suggestions[0].administrative_area); 404 } 405 406 TEST_F(AddressValidatorTest, SuggestAdminArea) { 407 AddressData address; 408 address.country_code = "US"; 409 address.administrative_area = "Cali"; 410 411 std::vector<AddressData> suggestions; 412 EXPECT_EQ(AddressValidator::SUCCESS, 413 validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions)); 414 ASSERT_EQ(1U, suggestions.size()); 415 EXPECT_EQ("California", suggestions[0].administrative_area); 416 } 417 418 TEST_F(AddressValidatorTest, MultipleSuggestions) { 419 AddressData address; 420 address.country_code = "US"; 421 address.administrative_area = "MA"; 422 423 std::vector<AddressData> suggestions; 424 EXPECT_EQ(AddressValidator::SUCCESS, 425 validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions)); 426 EXPECT_LT(1U, suggestions.size()); 427 428 // Massachusetts should not be a suggestion, because it's already covered 429 // under MA. 430 std::set<std::string> expected_suggestions; 431 expected_suggestions.insert("MA"); 432 expected_suggestions.insert("Maine"); 433 expected_suggestions.insert("Marshall Islands"); 434 expected_suggestions.insert("Maryland"); 435 for (std::vector<AddressData>::const_iterator it = suggestions.begin(); 436 it != suggestions.end(); ++it) { 437 expected_suggestions.erase(it->administrative_area); 438 } 439 EXPECT_TRUE(expected_suggestions.empty()); 440 } 441 442 TEST_F(AddressValidatorTest, SuggestNonLatinKeyWhenLanguageMatches) { 443 validator_->LoadRules("KR"); 444 AddressData address; 445 address.language_code = "ko"; 446 address.country_code = "KR"; 447 address.postal_code = "210-210"; 448 449 std::vector<AddressData> suggestions; 450 EXPECT_EQ(AddressValidator::SUCCESS, 451 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 452 ASSERT_EQ(1U, suggestions.size()); 453 EXPECT_EQ("", suggestions[0].administrative_area); 454 EXPECT_EQ("210-210", suggestions[0].postal_code); 455 } 456 457 TEST_F(AddressValidatorTest, SuggestNonLatinKeyWhenUserInputIsNotLatin) { 458 validator_->LoadRules("KR"); 459 AddressData address; 460 address.language_code = "en"; 461 address.country_code = "KR"; 462 address.administrative_area = ""; 463 464 std::vector<AddressData> suggestions; 465 EXPECT_EQ(AddressValidator::SUCCESS, 466 validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions)); 467 ASSERT_EQ(1U, suggestions.size()); 468 EXPECT_EQ("", suggestions[0].administrative_area); 469 } 470 471 TEST_F(AddressValidatorTest, 472 SuggestLatinNameWhenLanguageDiffersAndLatinNameAvailable) { 473 validator_->LoadRules("KR"); 474 AddressData address; 475 address.language_code = "en"; 476 address.country_code = "KR"; 477 address.postal_code = "210-210"; 478 479 std::vector<AddressData> suggestions; 480 EXPECT_EQ(AddressValidator::SUCCESS, 481 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 482 ASSERT_EQ(1U, suggestions.size()); 483 EXPECT_EQ("Gangwon", suggestions[0].administrative_area); 484 EXPECT_EQ("210-210", suggestions[0].postal_code); 485 } 486 487 TEST_F(AddressValidatorTest, SuggestLatinNameWhenUserInputIsLatin) { 488 validator_->LoadRules("KR"); 489 AddressData address; 490 address.language_code = "ko"; 491 address.country_code = "KR"; 492 address.administrative_area = "Gang"; 493 494 std::vector<AddressData> suggestions; 495 EXPECT_EQ(AddressValidator::SUCCESS, 496 validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions)); 497 ASSERT_EQ(1U, suggestions.size()); 498 EXPECT_EQ("Gangwon", suggestions[0].administrative_area); 499 } 500 501 TEST_F(AddressValidatorTest, NoSuggestionsForEmptyAddress) { 502 AddressData address; 503 address.country_code = "US"; 504 505 std::vector<AddressData> suggestions; 506 EXPECT_EQ( 507 AddressValidator::SUCCESS, 508 validator_->GetSuggestions(address, POSTAL_CODE, 999, &suggestions)); 509 EXPECT_TRUE(suggestions.empty()); 510 } 511 512 TEST_F(AddressValidatorTest, SuggestionIncludesCountry) { 513 AddressData address; 514 address.country_code = "US"; 515 address.postal_code = "90291"; 516 517 std::vector<AddressData> suggestions; 518 EXPECT_EQ(AddressValidator::SUCCESS, 519 validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions)); 520 ASSERT_EQ(1U, suggestions.size()); 521 EXPECT_EQ("US", suggestions[0].country_code); 522 } 523 524 TEST_F(AddressValidatorTest, SuggestOnlyForAdministrativeAreasAndPostalCode) { 525 AddressData address; 526 address.country_code = "US"; 527 address.administrative_area = "CA"; 528 address.locality = "Los Angeles"; 529 address.dependent_locality = "Venice"; 530 address.postal_code = "90291"; 531 address.sorting_code = "123"; 532 address.address_lines.push_back("123 Main St"); 533 address.organization = "Google"; 534 address.recipient = "Jon Smith"; 535 536 // Fields that should not have suggestions in US. 537 static const AddressField kNoSugestFields[] = { 538 COUNTRY, 539 LOCALITY, 540 DEPENDENT_LOCALITY, 541 SORTING_CODE, 542 STREET_ADDRESS, 543 ORGANIZATION, 544 RECIPIENT 545 }; 546 547 static const size_t kNumNoSuggestFields = 548 sizeof kNoSugestFields / sizeof (AddressField); 549 550 for (size_t i = 0; i < kNumNoSuggestFields; ++i) { 551 std::vector<AddressData> suggestions; 552 EXPECT_EQ(AddressValidator::SUCCESS, 553 validator_->GetSuggestions( 554 address, kNoSugestFields[i], 999, &suggestions)); 555 EXPECT_TRUE(suggestions.empty()); 556 } 557 } 558 559 TEST_F(AddressValidatorTest, CanonicalizeUsAdminAreaName) { 560 AddressData address; 561 address.country_code = "US"; 562 address.administrative_area = "cALIFORNIa"; 563 EXPECT_TRUE(validator_->CanonicalizeAdministrativeArea(&address)); 564 EXPECT_EQ("CA", address.administrative_area); 565 } 566 567 TEST_F(AddressValidatorTest, CanonicalizeUsAdminAreaKey) { 568 AddressData address; 569 address.country_code = "US"; 570 address.administrative_area = "CA"; 571 EXPECT_TRUE(validator_->CanonicalizeAdministrativeArea(&address)); 572 EXPECT_EQ("CA", address.administrative_area); 573 } 574 575 TEST_F(AddressValidatorTest, CanonicalizeJpAdminAreaKey) { 576 validator_->LoadRules("JP"); 577 AddressData address; 578 address.country_code = "JP"; 579 address.administrative_area = ""; 580 EXPECT_TRUE(validator_->CanonicalizeAdministrativeArea(&address)); 581 EXPECT_EQ("", address.administrative_area); 582 } 583 584 TEST_F(AddressValidatorTest, CanonicalizeJpAdminAreaLatinName) { 585 validator_->LoadRules("JP"); 586 AddressData address; 587 address.country_code = "JP"; 588 address.administrative_area = "tOKYo"; 589 EXPECT_TRUE(validator_->CanonicalizeAdministrativeArea(&address)); 590 EXPECT_EQ("TOKYO", address.administrative_area); 591 } 592 593 } // namespace addressinput 594 } // namespace i18n 595