| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/autofill/core/browser/autofill_profile_validator.h" |
| |
| #include <stddef.h> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/guid.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "components/autofill/core/browser/autofill_profile.h" |
| #include "components/autofill/core/browser/autofill_test_utils.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h" |
| #include "third_party/libaddressinput/src/cpp/test/testdata_source.h" |
| |
| namespace autofill { |
| |
| using ::i18n::addressinput::NullStorage; |
| using ::i18n::addressinput::Source; |
| using ::i18n::addressinput::Storage; |
| using ::i18n::addressinput::TestdataSource; |
| |
| using ::i18n::addressinput::COUNTRY; |
| using ::i18n::addressinput::ADMIN_AREA; |
| using ::i18n::addressinput::LOCALITY; |
| using ::i18n::addressinput::DEPENDENT_LOCALITY; |
| using ::i18n::addressinput::SORTING_CODE; |
| using ::i18n::addressinput::POSTAL_CODE; |
| using ::i18n::addressinput::STREET_ADDRESS; |
| using ::i18n::addressinput::RECIPIENT; |
| |
| // Used to load region rules for this test. |
| class ValidationTestDataSource : public TestdataSource { |
| public: |
| ValidationTestDataSource() : TestdataSource(true) {} |
| |
| ~ValidationTestDataSource() override {} |
| |
| void Get(const std::string& key, const Callback& data_ready) const override { |
| data_ready( |
| true, key, |
| new std::string( |
| "{" |
| "\"data/CA\": " |
| "{\"lang\": \"en\", \"upper\": \"ACNOSZ\", " |
| "\"zipex\": \"H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0\", " |
| "\"name\": \"CANADA\", " |
| "\"fmt\": \"%N%n%O%n%A%n%C %S %Z\", \"id\": \"data/CA\", " |
| "\"languages\": \"en\", \"sub_keys\": \"QC\", \"key\": " |
| "\"CA\", " |
| "\"require\": \"ACSZ\", \"sub_names\": \"Quebec\", " |
| "\"sub_zips\": \"G|H|J\"}, " |
| "\"data/CA/QC\": " |
| "{\"lang\": \"en\", \"key\": \"QC\", " |
| "\"id\": \"data/CA/QC\", \"zip\": \"G|H|J\", \"name\": \"Quebec\"}" |
| "}")); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ValidationTestDataSource); |
| }; |
| |
| class AutofillProfileValidatorTest : public testing::Test { |
| public: |
| AutofillProfileValidatorTest() |
| : validator_(new AutofillProfileValidator( |
| std::unique_ptr<Source>(new ValidationTestDataSource()), |
| std::unique_ptr<Storage>(new NullStorage))), |
| onvalidated_cb_( |
| base::BindOnce(&AutofillProfileValidatorTest::OnValidated, |
| base::Unretained(this))) {} |
| |
| protected: |
| const std::unique_ptr<AutofillProfileValidator> validator_; |
| |
| ~AutofillProfileValidatorTest() override {} |
| |
| void OnValidated(AutofillProfile* profile) { |
| // Make sure the profile has the expected validity state. |
| for (auto expectation : expected_validity_) { |
| EXPECT_EQ(expectation.second, |
| profile->GetValidityState(expectation.first)); |
| } |
| } |
| |
| bool AreRulesLoadedForRegion(std::string region_code) { |
| return validator_->AreRulesLoadedForRegion(region_code); |
| } |
| |
| void LoadRulesForRegion(std::string region_code) { |
| validator_->LoadRulesForRegion(region_code); |
| } |
| |
| AutofillProfileValidatorCallback onvalidated_cb_; |
| |
| std::vector<std::pair<ServerFieldType, AutofillProfile::ValidityState>> |
| expected_validity_; |
| |
| private: |
| base::test::ScopedTaskEnvironment scoped_task_scheduler; |
| |
| DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidatorTest); |
| }; |
| |
| // Validate a valid profile, for which the rules are not loaded, yet. |
| TEST_F(AutofillProfileValidatorTest, ValidateFullValidProfile_RulesNotLoaded) { |
| // This is a valid profile, and the rules are loaded in the constructors |
| // Province: "QC", Country: "CA" |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| |
| // Make sure that the rules are not pre-loaded. |
| std::string country_code = |
| base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); |
| EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a Full Profile, for which the rules are already loaded. |
| TEST_F(AutofillProfileValidatorTest, ValidateAddress_RulesLoaded) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| |
| // Pre-load the rules. |
| std::string country_code = |
| base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); |
| LoadRulesForRegion(country_code); |
| EXPECT_EQ(true, AreRulesLoadedForRegion(country_code)); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // When country code is invalid, the coutry code is invalid and the rest of the |
| // address and the phone are unvalidated. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_CountryCodeNotExists) { |
| const std::string country_code = "PP"; |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); |
| |
| EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::UNVALIDATED}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::UNVALIDATED}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // When country code is valid, but the rule is not in the source, the state and |
| // zip are unvalidated. |
| TEST_F(AutofillProfileValidatorTest, ValidateAddress_RuleNotExists) { |
| const std::string country_code = "US"; |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); |
| |
| EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::UNVALIDATED}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // When country code is empty, the profile is unvalidated. |
| TEST_F(AutofillProfileValidatorTest, ValidateAddress_EmptyCountryCode) { |
| ; |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::string16()); |
| |
| EXPECT_EQ(false, AreRulesLoadedForRegion("")); |
| |
| // Set up the test expectations. |
| // The phone is validated for the US. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY}, |
| {ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::UNVALIDATED}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::UNVALIDATED}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an invalid phone. |
| TEST_F(AutofillProfileValidatorTest, StartProfileValidation_InvalidPhone) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, |
| base::UTF8ToUTF16("Invalid Phone")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with a valid phone, valid email and invalid address. |
| TEST_F(AutofillProfileValidatorTest, StartProfileValidation_InvalidAddress) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an empty phone and invalid address. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_EmptyPhone_InvalidAddress) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16()); |
| profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY}, |
| {EMAIL_ADDRESS, AutofillProfile::VALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an invalid email and invalid address. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_InvalidEmail_InvalidAddress) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email")); |
| profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::INVALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::INVALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an empty email and invalid zip. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_EmptyEmail_InvalidZip) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(EMAIL_ADDRESS, base::string16()); |
| profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::INVALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::EMPTY}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an empty email and empty zip. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_InvalidEmail_EmptyZip) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("Invalid Email")); |
| profile.SetRawInfo(ADDRESS_HOME_ZIP, base::string16()); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::EMPTY}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::INVALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an invalid phone and invalid email. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_InvalidEmail_InvalidPhone) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email")); |
| profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, |
| base::UTF8ToUTF16("Invalid Phone")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID}, |
| {EMAIL_ADDRESS, AutofillProfile::INVALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an invalid email. |
| TEST_F(AutofillProfileValidatorTest, StartProfileValidation_InvalidEmail) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::VALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, |
| {EMAIL_ADDRESS, AutofillProfile::INVALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| // Validate a profile with an invalid email, invalid phone and invalid state. |
| TEST_F(AutofillProfileValidatorTest, |
| StartProfileValidation_InvalidEmail_InvalidPhone_InvalidAddress) { |
| AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); |
| profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email.")); |
| profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, |
| base::UTF8ToUTF16("Invalid Phone")); |
| profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); |
| |
| // Set up the test expectations. |
| expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, |
| {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, |
| {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, |
| {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID}, |
| {EMAIL_ADDRESS, AutofillProfile::INVALID}}; |
| |
| // Start the validator. |
| validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); |
| } |
| |
| } // namespace autofill |