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 37namespace i18n { 38namespace addressinput { 39 40class 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 68TEST_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 82TEST_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 92TEST_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 161TEST_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 210TEST_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 230TEST_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 237TEST_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 250TEST_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 266TEST_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 282TEST_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 294TEST_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 308TEST_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 324TEST_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 340TEST_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 356TEST_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 371TEST_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 382TEST_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 394TEST_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 406TEST_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 418TEST_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 442TEST_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 457TEST_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 471TEST_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 487TEST_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 501TEST_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 512TEST_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 524TEST_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 559TEST_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 567TEST_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 575TEST_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 584TEST_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