blob: 0cbe236e873bcf50178c8ea615b976a951e743c0 [file] [log] [blame]
// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "validation_task.h"
#include <libaddressinput/address_data.h>
#include <libaddressinput/address_field.h>
#include <libaddressinput/address_problem.h>
#include <libaddressinput/address_validator.h>
#include <libaddressinput/callback.h>
#include <libaddressinput/supplier.h>
#include <cstddef>
#include <memory>
#include <gtest/gtest.h>
#include "lookup_key.h"
#include "rule.h"
#include "util/size.h"
namespace i18n {
namespace addressinput {
class ValidationTaskTest : public testing::Test {
public:
ValidationTaskTest(const ValidationTaskTest&) = delete;
ValidationTaskTest& operator=(const ValidationTaskTest&) = delete;
protected:
ValidationTaskTest()
: json_(),
success_(true),
address_(),
allow_postal_(false),
require_name_(false),
filter_(),
problems_(),
expected_(),
called_(false),
validated_(BuildCallback(this, &ValidationTaskTest::Validated)) {
// Add all problems to the filter except those affected by the metadata
// in region_data_constants.cc.
static const AddressField kFields[] = {
COUNTRY,
ADMIN_AREA,
LOCALITY,
DEPENDENT_LOCALITY,
SORTING_CODE,
POSTAL_CODE,
STREET_ADDRESS,
ORGANIZATION,
RECIPIENT,
};
static const AddressProblem kProblems[] = {
// UNEXPECTED_FIELD is validated using IsFieldUsed().
// MISSING_REQUIRED_FIELD is validated using IsFieldRequired().
UNKNOWN_VALUE,
INVALID_FORMAT,
MISMATCHING_VALUE,
USES_P_O_BOX,
};
for (AddressField field : kFields) {
for (AddressProblem problem : kProblems) {
filter_.emplace(field, problem);
}
}
filter_.emplace(COUNTRY, UNEXPECTED_FIELD);
filter_.emplace(COUNTRY, MISSING_REQUIRED_FIELD);
filter_.emplace(RECIPIENT, UNEXPECTED_FIELD);
filter_.emplace(RECIPIENT, MISSING_REQUIRED_FIELD);
}
void Validate() {
Rule rule[size(LookupKey::kHierarchy)];
auto* task = new ValidationTask(
address_,
allow_postal_,
require_name_,
&filter_,
&problems_,
*validated_);
Supplier::RuleHierarchy hierarchy;
for (size_t i = 0;
i < size(LookupKey::kHierarchy) && json_[i] != nullptr; ++i) {
ASSERT_TRUE(rule[i].ParseSerializedRule(json_[i]));
hierarchy.rule[i] = &rule[i];
}
(*task->supplied_)(success_, *task->lookup_key_, hierarchy);
}
const char* json_[size(LookupKey::kHierarchy)];
bool success_;
AddressData address_;
bool allow_postal_;
bool require_name_;
FieldProblemMap filter_;
FieldProblemMap problems_;
FieldProblemMap expected_;
bool called_;
private:
void Validated(bool success,
const AddressData& address,
const FieldProblemMap& problems) {
ASSERT_EQ(success_, success);
ASSERT_EQ(&address_, &address);
ASSERT_EQ(&problems_, &problems);
called_ = true;
}
const std::unique_ptr<const AddressValidator::Callback> validated_;
};
namespace {
TEST_F(ValidationTaskTest, FailureCountryRuleNull) {
success_ = false;
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, FailureCountryRuleEmpty) {
json_[0] = "{}";
success_ = false;
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, SuccessCountryRuleNullNameEmpty) {
expected_.emplace(COUNTRY, MISSING_REQUIRED_FIELD);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, SuccessCountryRuleNullNameNotEmpty) {
address_.region_code = "rrr";
expected_.emplace(COUNTRY, UNKNOWN_VALUE);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, SuccessCountryRuleEmptyNameEmpty) {
json_[0] = "{}";
expected_.emplace(COUNTRY, MISSING_REQUIRED_FIELD);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, SuccessCountryRuleEmptyNameNotEmpty) {
json_[0] = "{}";
address_.region_code = "rrr";
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, MissingRequiredFieldsUS) {
json_[0] = "{}";
address_.region_code = "US";
filter_.emplace(ADMIN_AREA, MISSING_REQUIRED_FIELD);
filter_.emplace(LOCALITY, MISSING_REQUIRED_FIELD);
filter_.emplace(POSTAL_CODE, MISSING_REQUIRED_FIELD);
filter_.emplace(STREET_ADDRESS, MISSING_REQUIRED_FIELD);
expected_.emplace(ADMIN_AREA, MISSING_REQUIRED_FIELD);
expected_.emplace(LOCALITY, MISSING_REQUIRED_FIELD);
expected_.emplace(POSTAL_CODE, MISSING_REQUIRED_FIELD);
expected_.emplace(STREET_ADDRESS, MISSING_REQUIRED_FIELD);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, MissingNoRequiredFieldsUS) {
json_[0] = "{}";
address_.region_code = "US";
address_.administrative_area = "sss";
address_.locality = "ccc";
address_.postal_code = "zzz";
address_.address_line.emplace_back("aaa");
address_.organization = "ooo";
address_.recipient = "nnn";
filter_.emplace(ADMIN_AREA, MISSING_REQUIRED_FIELD);
filter_.emplace(LOCALITY, MISSING_REQUIRED_FIELD);
filter_.emplace(POSTAL_CODE, MISSING_REQUIRED_FIELD);
filter_.emplace(STREET_ADDRESS, MISSING_REQUIRED_FIELD);
filter_.emplace(ORGANIZATION, MISSING_REQUIRED_FIELD);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, UnexpectedFieldUS) {
json_[0] = "{}";
address_.region_code = "US";
address_.dependent_locality = "ddd";
filter_.emplace(DEPENDENT_LOCALITY, UNEXPECTED_FIELD);
expected_.emplace(DEPENDENT_LOCALITY, UNEXPECTED_FIELD);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, MissingRequiredFieldRequireName) {
json_[0] = "{}";
address_.region_code = "rrr";
require_name_ = true;
expected_.emplace(RECIPIENT, MISSING_REQUIRED_FIELD);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, UnknownValueRuleNull) {
json_[0] = R"({"fmt":"%R%S","require":"RS","sub_keys":"aa~bb"})";
address_.region_code = "rrr";
address_.administrative_area = "sss";
expected_.emplace(ADMIN_AREA, UNKNOWN_VALUE);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, NoUnknownValueRuleNotNull) {
json_[0] = R"({"fmt":"%R%S","require":"RS","sub_keys":"aa~bb"})";
json_[1] = "{}";
address_.region_code = "rrr";
address_.administrative_area = "sss";
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeUnrecognizedFormatTooShort) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
address_.region_code = "rrr";
address_.postal_code = "12";
expected_.emplace(POSTAL_CODE, INVALID_FORMAT);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeUnrecognizedFormatTooLong) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
address_.region_code = "rrr";
address_.postal_code = "1234";
expected_.emplace(POSTAL_CODE, INVALID_FORMAT);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeRecognizedFormat) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
address_.region_code = "rrr";
address_.postal_code = "123";
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeMismatchingValue1) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
json_[1] = R"({"zip":"1"})";
address_.region_code = "rrr";
address_.postal_code = "000";
expected_.emplace(POSTAL_CODE, MISMATCHING_VALUE);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeMismatchingValue2) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
json_[1] = R"({"zip":"1"})";
json_[2] = R"({"zip":"12"})";
address_.region_code = "rrr";
address_.postal_code = "100";
expected_.emplace(POSTAL_CODE, MISMATCHING_VALUE);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeMismatchingValue3) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
json_[1] = R"({"zip":"1"})";
json_[2] = R"({"zip":"12"})";
json_[3] = R"({"zip":"123"})";
address_.region_code = "rrr";
address_.postal_code = "120";
expected_.emplace(POSTAL_CODE, MISMATCHING_VALUE);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeMatchingValue) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{3}"})";
json_[1] = R"({"zip":"1"})";
json_[2] = R"({"zip":"12"})";
json_[3] = R"({"zip":"123"})";
address_.region_code = "rrr";
address_.postal_code = "123";
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodePrefixMismatchingValue) {
json_[0] = R"({"fmt":"%Z","zip":"\\d{5}"})";
json_[1] = R"({"zip":"9[0-5]|96[01]"})";
address_.region_code = "rrr";
address_.postal_code = "10960";
expected_.emplace(POSTAL_CODE, MISMATCHING_VALUE);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, PostalCodeFilterIgnoresMismatching) {
json_[0] = R"({"zip":"\\d{3}"})";
json_[1] = R"({"zip":"1"})";
address_.region_code = "rrr";
address_.postal_code = "000";
filter_.erase(POSTAL_CODE);
filter_.emplace(POSTAL_CODE, INVALID_FORMAT);
// (POSTAL_CODE, MISMATCHING_VALUE) should not be reported.
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, UsesPoBoxLanguageUnd) {
json_[0] = R"({"fmt":"%A"})";
address_.region_code = "rrr";
address_.address_line.emplace_back("aaa");
address_.address_line.emplace_back("P.O. Box");
address_.address_line.emplace_back("aaa");
expected_.emplace(STREET_ADDRESS, USES_P_O_BOX);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, UsesPoBoxLanguageDa) {
json_[0] = R"({"fmt":"%A","languages":"da"})";
address_.region_code = "rrr";
address_.address_line.emplace_back("aaa");
address_.address_line.emplace_back("Postboks");
address_.address_line.emplace_back("aaa");
expected_.emplace(STREET_ADDRESS, USES_P_O_BOX);
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, UsesPoBoxLanguageDaNotMatchDe) {
json_[0] = R"({"fmt":"%A","languages":"da"})";
address_.region_code = "rrr";
address_.address_line.emplace_back("aaa");
address_.address_line.emplace_back("Postfach");
address_.address_line.emplace_back("aaa");
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
TEST_F(ValidationTaskTest, UsesPoBoxAllowPostal) {
json_[0] = R"({"fmt":"%A"})";
address_.region_code = "rrr";
address_.address_line.emplace_back("aaa");
address_.address_line.emplace_back("P.O. Box");
address_.address_line.emplace_back("aaa");
allow_postal_ = true;
ASSERT_NO_FATAL_FAILURE(Validate());
ASSERT_TRUE(called_);
EXPECT_EQ(expected_, problems_);
}
} // namespace
} // namespace addressinput
} // namespace i18n