summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-26 18:48:40 +0000
committerrouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-26 18:48:40 +0000
commita0dfb78cf6ad6d6bb8144c640e1090eedd552096 (patch)
tree1f9c5885c30d05c04dc4d399d760907bf5a01287
parent21f45399766cbdf6e262efbdb66556e4981d09fa (diff)
downloadchromium_src-a0dfb78cf6ad6d6bb8144c640e1090eedd552096.zip
chromium_src-a0dfb78cf6ad6d6bb8144c640e1090eedd552096.tar.gz
chromium_src-a0dfb78cf6ad6d6bb8144c640e1090eedd552096.tar.bz2
[rac] libaddressinput suggestions for partial addresses
This patch adds a method AddressValidator::GetSuggestions() to libaddressinput. The method takes an incomplete address and suggests a list of more complete address. This method can be used for autocompleting addresses while the user is typing. For example, if the user types "Cali", then the method will suggest "California". The method uses the downloaded validation rules for suggestions. BUG=333401 Review URL: https://codereview.chromium.org/146583009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@253524 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/autofill/mock_address_validator.cc1
-rw-r--r--chrome/browser/ui/autofill/mock_address_validator.h7
-rw-r--r--third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h6
-rw-r--r--third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_validator.h30
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/address_data.cc58
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/address_validator.cc239
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc60
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.h17
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/rule.cc29
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/rule.h13
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/ruleset.cc5
-rw-r--r--third_party/libaddressinput/chromium/cpp/src/ruleset.h20
-rw-r--r--third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc316
-rw-r--r--third_party/libaddressinput/chromium/cpp/test/country_rules_aggregator_test.cc15
-rw-r--r--third_party/libaddressinput/chromium/cpp/test/retriever_test.cc16
15 files changed, 756 insertions, 76 deletions
diff --git a/chrome/browser/ui/autofill/mock_address_validator.cc b/chrome/browser/ui/autofill/mock_address_validator.cc
index 8ef38f7..3361bea 100644
--- a/chrome/browser/ui/autofill/mock_address_validator.cc
+++ b/chrome/browser/ui/autofill/mock_address_validator.cc
@@ -10,6 +10,7 @@ MockAddressValidator::MockAddressValidator() {
using testing::_;
using testing::Return;
ON_CALL(*this, ValidateAddress(_, _, _)).WillByDefault(Return(SUCCESS));
+ ON_CALL(*this, GetSuggestions(_, _, _, _)).WillByDefault(Return(SUCCESS));
ON_CALL(*this, CanonicalizeAdministrativeArea(_)).WillByDefault(Return(true));
}
diff --git a/chrome/browser/ui/autofill/mock_address_validator.h b/chrome/browser/ui/autofill/mock_address_validator.h
index 239be6c..d958561 100644
--- a/chrome/browser/ui/autofill/mock_address_validator.h
+++ b/chrome/browser/ui/autofill/mock_address_validator.h
@@ -30,6 +30,13 @@ class MockAddressValidator : public ::i18n::addressinput::AddressValidator {
const ::i18n::addressinput::AddressProblemFilter& filter,
::i18n::addressinput::AddressProblems* problems));
+ MOCK_CONST_METHOD4(GetSuggestions,
+ ::i18n::addressinput::AddressValidator::Status(
+ const ::i18n::addressinput::AddressData& user_input,
+ ::i18n::addressinput::AddressField focused_field,
+ size_t suggestions_limit,
+ std::vector< ::i18n::addressinput::AddressData>* suggestions));
+
MOCK_CONST_METHOD1(CanonicalizeAdministrativeArea,
bool(::i18n::addressinput::AddressData* address_data));
diff --git a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h
index 46c26db..e9ca7a4 100644
--- a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h
+++ b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h
@@ -52,7 +52,11 @@ struct AddressData {
// STREET_ADDRESS, which comprises multiple fields.
const std::string& GetFieldValue(AddressField field) const;
- // Guesses the BCP 47 languge code to be used for formatting the address for
+ // Sets the |field| to |value|. The parameter should not be STREET_ADDRESS,
+ // which comprises multiple fields.
+ void SetFieldValue(AddressField field, const std::string& value);
+
+ // Guesses the BCP 47 language code to be used for formatting the address for
// display. For example, guesses "en" if the |country_code| is "US". Can
// return an empty string.
const std::string& GuessLanguageCode() const;
diff --git a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_validator.h b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_validator.h
index 50f7726..a9285f2 100644
--- a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_validator.h
+++ b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_validator.h
@@ -120,6 +120,36 @@ class AddressValidator {
const AddressProblemFilter& filter,
AddressProblems* problems) const = 0;
+ // Fills in |suggestions| for the partially typed in |user_input|, assuming
+ // the user is typing in the |focused_field|. If the number of |suggestions|
+ // is over the |suggestion_limit|, then returns no |suggestions| at all.
+ //
+ // If the |solutions| parameter is NULL, the checks whether the validation
+ // rules are available, but does not fill in suggestions.
+ //
+ // Sample user input 1:
+ // country code = "US"
+ // postal code = "90066"
+ // focused field = POSTAL_CODE
+ // suggestions limit = 1
+ // Suggestion:
+ // [{administrative_area: "CA"}]
+ //
+ // Sample user input 2:
+ // country code = "CN"
+ // dependent locality = "Zongyang"
+ // focused field = DEPENDENT_LOCALITY
+ // suggestions limit = 10
+ // Suggestion:
+ // [{dependent_locality: "Zongyang Xian",
+ // locality: "Anqing Shi",
+ // administrative_area: "Anhui Sheng"}]
+ virtual Status GetSuggestions(
+ const AddressData& user_input,
+ AddressField focused_field,
+ size_t suggestion_limit,
+ std::vector<AddressData>* suggestions) const = 0;
+
// Canonicalizes the administrative area in |address_data|. For example,
// "texas" changes to "TX". Returns true on success, otherwise leaves
// |address_data| alone and returns false.
diff --git a/third_party/libaddressinput/chromium/cpp/src/address_data.cc b/third_party/libaddressinput/chromium/cpp/src/address_data.cc
index e3bc3ed..51d36c6 100644
--- a/third_party/libaddressinput/chromium/cpp/src/address_data.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/address_data.cc
@@ -28,6 +28,35 @@
namespace i18n {
namespace addressinput {
+namespace {
+
+const std::string* GetMemberForField(const AddressData& address,
+ AddressField field) {
+ switch (field) {
+ case COUNTRY:
+ return &address.country_code;
+ case ADMIN_AREA:
+ return &address.administrative_area;
+ case LOCALITY:
+ return &address.locality;
+ case DEPENDENT_LOCALITY:
+ return &address.dependent_locality;
+ case SORTING_CODE:
+ return &address.sorting_code;
+ case POSTAL_CODE:
+ return &address.postal_code;
+ case ORGANIZATION:
+ return &address.organization;
+ case RECIPIENT:
+ return &address.recipient;
+ default:
+ assert(false);
+ return NULL;
+ }
+}
+
+} // namespace
+
void AddressData::FormatForDisplay(std::vector<std::string>* lines) const {
assert(lines != NULL);
lines->clear();
@@ -66,26 +95,15 @@ void AddressData::FormatForDisplay(std::vector<std::string>* lines) const {
}
const std::string& AddressData::GetFieldValue(AddressField field) const {
- switch (field) {
- case COUNTRY:
- return country_code;
- case ADMIN_AREA:
- return administrative_area;
- case LOCALITY:
- return locality;
- case DEPENDENT_LOCALITY:
- return dependent_locality;
- case SORTING_CODE:
- return sorting_code;
- case POSTAL_CODE:
- return postal_code;
- case ORGANIZATION:
- return organization;
- case RECIPIENT:
- return recipient;
- default:
- assert(false);
- return recipient;
+ const std::string* field_value = GetMemberForField(*this, field);
+ return field_value != NULL ? *field_value : country_code;
+}
+
+void AddressData::SetFieldValue(AddressField field, const std::string& value) {
+ std::string* field_value =
+ const_cast<std::string*>(GetMemberForField(*this, field));
+ if (field_value != NULL) {
+ *field_value = value;
}
}
diff --git a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc
index fe36bd8..5ca32b1 100644
--- a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc
@@ -27,6 +27,8 @@
#include <map>
#include <set>
#include <string>
+#include <utility>
+#include <vector>
#include <re2/re2.h>
@@ -37,12 +39,196 @@
#include "rule.h"
#include "ruleset.h"
#include "util/stl_util.h"
+#include "util/string_compare.h"
namespace i18n {
namespace addressinput {
namespace {
+// A bit map of MatchingRuleField values.
+typedef int MatchingRuleFields;
+
+// The field in the rule that matches a user input. Can be used in a bitmask.
+enum MatchingRuleField {
+ NONE = 0,
+ KEY = 1,
+ NAME = 2,
+ LATIN_NAME = 4
+};
+
+// Returns true if |prefix_regex| matches a prefix of |value|. For example,
+// "(90|81)" matches a prefix of "90291".
+bool ValueMatchesPrefixRegex(const std::string& value,
+ const std::string& prefix_regex) {
+ return RE2::FullMatch(value, "^(" + prefix_regex + ").*");
+}
+
+// Returns true if the first |length| characters of |a| are loosely equal to the
+// first |length| characters of |b|.
+bool LoosePrefixCompare(const std::string& a,
+ const std::string& b,
+ size_t length) {
+ return LooseStringCompare(a.substr(0, length), b.substr(0, length));
+}
+
+// Returns true if the fields of |address| are empty strings between the |begin|
+// field exclusively and the |end| field inclusively.
+bool AddressFieldsEmpty(const AddressData& address,
+ AddressField begin,
+ AddressField end) {
+ for (int field = begin + 1; field <= end; ++field) {
+ if (!address.GetFieldValue(static_cast<AddressField>(field)).empty()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Finds the most accurate rulesets that match |user_input| and adds them to
+// |suggestions| as address data structures.
+//
+// Converts the rulesets into data structures by copying either the ruleset key,
+// name, or latinized name into the field of the data structure. Traverses the
+// tree of rulesets up to its root to capture the most complete suggestion. For
+// example, converts the ruleset for "data/CN/北京市/昌平区" into (latinized)
+// "Changping Qu, Beijing Shi, CN" address.
+//
+// Note that both "data/US" and "data/US/CA" rulesets match a "California, US,
+// 90291" user input, but only "data/US/CA" ends up in |suggestions|, because
+// it's more accurate than "data/US".
+//
+// Considers only |parent_matching_rule_fields| when comparing rules to user
+// input values. For example, if |parent_matching_rule_fields| is KEY | NAME,
+// then the function ignores the latinized name for the ruleset.
+//
+// If the number of |suggestions| is over the |suggestions_limit|, then clears
+// |suggestions| and returns false.
+//
+// The |suggestions| parameter should not be NULL.
+bool FindSuggestions(const AddressData& user_input,
+ AddressField focused_field,
+ size_t suggestions_limit,
+ const Ruleset& ruleset,
+ MatchingRuleFields parent_matching_rule_fields,
+ std::vector<AddressData>* suggestions) {
+ assert(suggestions != NULL);
+
+ // Compare the postal code of |user_input| with the |ruleset|.
+ const Rule& rule = ruleset.GetLanguageCodeRule(user_input.language_code);
+ if (!rule.GetPostalCodeFormat().empty() &&
+ !user_input.postal_code.empty() &&
+ !ValueMatchesPrefixRegex(
+ user_input.postal_code, rule.GetPostalCodeFormat())) {
+ return true;
+ }
+
+ // Compare the value of |ruleset->field()| in |user input| with the key,
+ // name, and latinized name for |ruleset|.
+ const std::string& input = user_input.GetFieldValue(ruleset.field());
+ MatchingRuleFields matching_rule_fields = NONE;
+ if (input.empty() || ruleset.field() == COUNTRY) {
+ matching_rule_fields = parent_matching_rule_fields;
+ } else {
+ if ((parent_matching_rule_fields & KEY) &&
+ LoosePrefixCompare(input, rule.GetKey(), input.length())) {
+ matching_rule_fields |= KEY;
+ }
+ if ((parent_matching_rule_fields & NAME) &&
+ LoosePrefixCompare(input, rule.GetName(), input.length())) {
+ matching_rule_fields |= NAME;
+ }
+ if ((parent_matching_rule_fields & LATIN_NAME) &&
+ LoosePrefixCompare(input, rule.GetLatinName(), input.length())) {
+ matching_rule_fields |= LATIN_NAME;
+ }
+ }
+
+ if (matching_rule_fields == NONE) {
+ return true;
+ }
+
+ // Add a suggestion based on |ruleset|.
+ if (ruleset.field() == DEPENDENT_LOCALITY ||
+ ruleset.field() == focused_field ||
+ (ruleset.GetSubRegionRulesets().empty() &&
+ AddressFieldsEmpty(user_input, ruleset.field(), DEPENDENT_LOCALITY))) {
+ if (suggestions->size() >= suggestions_limit) {
+ suggestions->clear();
+ return false;
+ }
+
+ // If the user's language is not one of the supported languages of a country
+ // that has latinized names for its regions, then prefer to suggest the
+ // latinized region names. If the user types in local script instead, then
+ // the local script names will be suggested.
+ bool prefer_latin_name =
+ !rule.GetLanguage().empty() &&
+ rule.GetLanguage() != user_input.language_code &&
+ !rule.GetLatinName().empty();
+
+ MatchingRuleField rule_field = NONE;
+ if (prefer_latin_name && (matching_rule_fields & LATIN_NAME)) {
+ rule_field = LATIN_NAME;
+ } else if (matching_rule_fields & KEY) {
+ rule_field = KEY;
+ } else if (matching_rule_fields & NAME) {
+ rule_field = NAME;
+ } else if (matching_rule_fields & LATIN_NAME) {
+ rule_field = LATIN_NAME;
+ } else {
+ assert(false);
+ }
+
+ AddressData suggestion;
+ suggestion.postal_code = user_input.postal_code;
+
+ // Traverse the tree of rulesets from the most specific |ruleset| to the
+ // country-wide "root" of the tree. Use the region names found at each of
+ // the levels of the ruleset tree to build the |suggestion|.
+ for (const Ruleset* suggestion_ruleset = &ruleset;
+ suggestion_ruleset->parent() != NULL;
+ suggestion_ruleset = suggestion_ruleset->parent()) {
+ const Rule& suggestion_rule =
+ suggestion_ruleset->GetLanguageCodeRule(user_input.language_code);
+ switch (rule_field) {
+ case KEY:
+ suggestion.SetFieldValue(
+ suggestion_ruleset->field(), suggestion_rule.GetKey());
+ break;
+ case NAME:
+ suggestion.SetFieldValue(
+ suggestion_ruleset->field(), suggestion_rule.GetName());
+ break;
+ case LATIN_NAME:
+ suggestion.SetFieldValue(
+ suggestion_ruleset->field(), suggestion_rule.GetLatinName());
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ }
+
+ suggestions->push_back(suggestion);
+ return true;
+ }
+
+ for (std::map<std::string, Ruleset*>::const_iterator
+ subregion_ruleset_it = ruleset.GetSubRegionRulesets().begin();
+ subregion_ruleset_it != ruleset.GetSubRegionRulesets().end();
+ ++subregion_ruleset_it) {
+ assert(subregion_ruleset_it->second != NULL);
+ if (!FindSuggestions(user_input, focused_field, suggestions_limit,
+ *subregion_ruleset_it->second, matching_rule_fields,
+ suggestions)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
// Returns true if the filter is empty (all problems allowed) or contains the
// |field|->|problem| mapping (explicitly allowed).
bool FilterAllows(const AddressProblemFilter& filter,
@@ -79,11 +265,12 @@ class AddressValidatorImpl : public AddressValidator {
public:
// Takes ownership of |downloader| and |storage|. Does not take ownership of
// |load_rules_delegate|.
- AddressValidatorImpl(scoped_ptr<Downloader> downloader,
+ AddressValidatorImpl(const std::string& validation_data_url,
+ scoped_ptr<Downloader> downloader,
scoped_ptr<Storage> storage,
LoadRulesDelegate* load_rules_delegate)
: aggregator_(scoped_ptr<Retriever>(new Retriever(
- VALIDATION_DATA_URL,
+ validation_data_url,
downloader.Pass(),
storage.Pass()))),
load_rules_delegate_(load_rules_delegate),
@@ -130,8 +317,9 @@ class AddressValidatorImpl : public AddressValidator {
: RULES_UNAVAILABLE;
}
- if (problems == NULL)
+ if (problems == NULL) {
return SUCCESS;
+ }
const Ruleset* ruleset = ruleset_it->second;
assert(ruleset != NULL);
@@ -179,8 +367,8 @@ class AddressValidatorImpl : public AddressValidator {
FilterAllows(filter,
POSTAL_CODE,
AddressProblem::MISMATCHING_VALUE) &&
- !RE2::FullMatch(address.postal_code,
- "^(" + rule.GetPostalCodeFormat() + ").*")) {
+ !ValueMatchesPrefixRegex(
+ address.postal_code, rule.GetPostalCodeFormat())) {
problems->push_back(AddressProblem(
POSTAL_CODE,
AddressProblem::MISMATCHING_VALUE,
@@ -193,6 +381,34 @@ class AddressValidatorImpl : public AddressValidator {
return SUCCESS;
}
+ // AddressValidator implementation.
+ virtual Status GetSuggestions(const AddressData& user_input,
+ AddressField focused_field,
+ size_t suggestions_limit,
+ std::vector<AddressData>* suggestions) const {
+ std::map<std::string, const Ruleset*>::const_iterator ruleset_it =
+ rules_.find(user_input.country_code);
+
+ if (ruleset_it == rules_.end()) {
+ return
+ loading_rules_.find(user_input.country_code) != loading_rules_.end()
+ ? RULES_NOT_READY
+ : RULES_UNAVAILABLE;
+ }
+
+ if (suggestions == NULL) {
+ return SUCCESS;
+ }
+ suggestions->clear();
+
+ const Ruleset* country_ruleset = ruleset_it->second;
+ assert(country_ruleset != NULL);
+
+ FindSuggestions(user_input, focused_field, suggestions_limit,
+ *country_ruleset, KEY | NAME | LATIN_NAME, suggestions);
+ return SUCCESS;
+ }
+
virtual bool CanonicalizeAdministrativeArea(AddressData* address_data) const {
std::map<std::string, const Ruleset*>::const_iterator ruleset_it =
rules_.find(address_data->country_code);
@@ -274,7 +490,18 @@ scoped_ptr<AddressValidator> AddressValidator::Build(
scoped_ptr<Storage> storage,
LoadRulesDelegate* load_rules_delegate) {
return scoped_ptr<AddressValidator>(new AddressValidatorImpl(
- downloader.Pass(), storage.Pass(), load_rules_delegate));
+ VALIDATION_DATA_URL, downloader.Pass(), storage.Pass(),
+ load_rules_delegate));
+}
+
+scoped_ptr<AddressValidator> BuildAddressValidatorForTesting(
+ const std::string& validation_data_url,
+ scoped_ptr<Downloader> downloader,
+ scoped_ptr<Storage> storage,
+ LoadRulesDelegate* load_rules_delegate) {
+ return scoped_ptr<AddressValidator>(new AddressValidatorImpl(
+ validation_data_url, downloader.Pass(), storage.Pass(),
+ load_rules_delegate));
}
} // namespace addressinput
diff --git a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
index dbb913b..7a114e0 100644
--- a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.cc
@@ -21,6 +21,7 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
+#include <map>
#include <string>
#include <vector>
@@ -72,14 +73,17 @@ void CountryRulesAggregator::OnDataReady(bool success,
return;
}
- scoped_ptr<Ruleset> ruleset = Build(key_, COUNTRY);
+ std::map<std::string, std::string> language_keys;
+ scoped_ptr<Ruleset> ruleset = Build(key_, COUNTRY, language_keys);
const bool parse_success = ruleset != NULL;
(*rules_ready_)(parse_success, country_code_, ruleset.Pass());
Reset();
}
-scoped_ptr<Ruleset> CountryRulesAggregator::Build(const std::string& key,
- AddressField field) {
+scoped_ptr<Ruleset> CountryRulesAggregator::Build(
+ const std::string& key,
+ AddressField field,
+ const std::map<std::string, std::string>& language_specific_keys) {
scoped_ptr<Rule> rule = ParseRule(key, field);
if (rule == NULL) {
return scoped_ptr<Ruleset>();
@@ -100,29 +104,63 @@ scoped_ptr<Ruleset> CountryRulesAggregator::Build(const std::string& key,
}
scoped_ptr<Ruleset> ruleset(new Ruleset(field, rule.Pass()));
+ std::map<std::string, std::map<std::string, std::string> >
+ language_specific_subkeys;
// Parse the language-specific rules. For example, parse the rules for "fr"
// and "it" languages in Switzerland.
for (std::vector<std::string>::const_iterator
- lang_it = non_default_languages_.begin();
- lang_it != non_default_languages_.end(); ++lang_it) {
- scoped_ptr<Rule> lang_rule = ParseRule(key + "--" + *lang_it, field);
- if (lang_rule == NULL) {
+ non_default_language_it = non_default_languages_.begin();
+ non_default_language_it != non_default_languages_.end();
+ ++non_default_language_it) {
+ std::map<std::string, std::string>::const_iterator
+ language_specific_key_it =
+ language_specific_keys.find(*non_default_language_it);
+ std::string language_specific_key =
+ language_specific_key_it != language_specific_keys.end()
+ ? language_specific_key_it->second
+ : key;
+ scoped_ptr<Rule> language_specific_rule =
+ ParseRule(language_specific_key + "--" + *non_default_language_it,
+ field);
+
+ if (language_specific_rule == NULL ||
+ language_specific_rule->GetSubKeys().size() !=
+ ruleset->rule().GetSubKeys().size()) {
return scoped_ptr<Ruleset>();
}
- ruleset->AddLanguageCodeRule(*lang_it, lang_rule.Pass());
+
+ // Build the language specific subkeys for the next level of
+ // rules. Examples:
+ // ["data/CA/AB"]["fr"] <- "data/CA/AB"
+ // ["data/HK/香港島"]["en"] <- "data/HK/Kowloon"
+ for (size_t i = 0; i < ruleset->rule().GetSubKeys().size(); ++i) {
+ const std::string& subkey = key + "/" + ruleset->rule().GetSubKeys()[i];
+ const std::string& language_specific_subkey =
+ key + "/" + language_specific_rule->GetSubKeys()[i];
+ language_specific_subkeys[subkey][*non_default_language_it] =
+ language_specific_subkey;
+ }
+
+ ruleset->AddLanguageCodeRule(
+ *non_default_language_it, language_specific_rule.Pass());
}
- // Parse the sub-keys. For example, parse the rules for all of the states in
- // US: "CA", "TX", "NY", etc.
+ // Parse the sub-keys recursively. For example, parse the rules for all of the
+ // states in US: "CA", "TX", "NY", etc.
for (std::vector<std::string>::const_iterator
subkey_it = ruleset->rule().GetSubKeys().begin();
subkey_it != ruleset->rule().GetSubKeys().end(); ++subkey_it) {
+ std::string subkey = key + "/" + *subkey_it;
scoped_ptr<Ruleset> sub_ruleset =
- Build(key + "/" + *subkey_it, static_cast<AddressField>(field + 1));
+ Build(subkey,
+ static_cast<AddressField>(field + 1),
+ language_specific_subkeys[subkey]);
+
if (sub_ruleset == NULL) {
return scoped_ptr<Ruleset>();
}
+
ruleset->AddSubRegionRuleset(*subkey_it, sub_ruleset.Pass());
}
diff --git a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.h b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.h
index db23e52..a092ffb 100644
--- a/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.h
+++ b/third_party/libaddressinput/chromium/cpp/src/country_rules_aggregator.h
@@ -20,6 +20,7 @@
#include <libaddressinput/util/basictypes.h>
#include <libaddressinput/util/scoped_ptr.h>
+#include <map>
#include <string>
#include <vector>
@@ -75,9 +76,19 @@ class CountryRulesAggregator {
const std::string& key,
const std::string& data);
- // Builds and returns the ruleset for |key| at |field| level. Returns NULL on
- // failure, e.g. missing sub-region data in JSON.
- scoped_ptr<Ruleset> Build(const std::string& key, AddressField field);
+ // Builds and returns the ruleset for |key| at |field| level. Language
+ // specific rules are retrieved using |language_specific_keys|, which is a
+ // mapping of language to key.
+ //
+ // Most regions use the same keys for all language variations. For example,
+ // "CA/AB--fr" is a French variant of "CA/AB". The notable exception is Hong
+ // Kong, where "data/HK/Kowloon--en" is the English variant of "HK/香港島".
+ //
+ // Returns NULL on failure, e.g. missing sub-region data in JSON.
+ scoped_ptr<Ruleset> Build(
+ const std::string& key,
+ AddressField field,
+ const std::map<std::string, std::string>& language_specific_keys);
// Builds and returns the rule for |key| at |field| level. Returns NULL if
// |key| is not in JSON.
diff --git a/third_party/libaddressinput/chromium/cpp/src/rule.cc b/third_party/libaddressinput/chromium/cpp/src/rule.cc
index b3f9feb..1604390 100644
--- a/third_party/libaddressinput/chromium/cpp/src/rule.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/rule.cc
@@ -215,14 +215,21 @@ bool FormatElement::operator==(const FormatElement& other) const {
}
Rule::Rule()
- : format_(),
+ : key_(),
+ name_(),
+ latin_name_(),
+ format_(),
required_(),
sub_keys_(),
+ sub_names_(),
+ sub_lnames_(),
languages_(),
language_(),
postal_code_format_(),
admin_area_name_message_id_(INVALID_MESSAGE_ID),
- postal_code_name_message_id_(INVALID_MESSAGE_ID) {}
+ invalid_admin_area_message_id_(INVALID_MESSAGE_ID),
+ postal_code_name_message_id_(INVALID_MESSAGE_ID),
+ invalid_postal_code_message_id_(INVALID_MESSAGE_ID) {}
Rule::~Rule() {}
@@ -239,11 +246,17 @@ const Rule& Rule::GetDefault() {
}
void Rule::CopyFrom(const Rule& rule) {
+ key_ = rule.key_;
+ name_ = rule.name_;
+ latin_name_ = rule.latin_name_;
format_ = rule.format_;
required_ = rule.required_;
sub_keys_ = rule.sub_keys_;
languages_ = rule.languages_;
language_ = rule.language_;
+ sub_keys_ = rule.sub_keys_;
+ sub_names_ = rule.sub_names_;
+ sub_lnames_ = rule.sub_lnames_;
postal_code_format_ = rule.postal_code_format_;
admin_area_name_message_id_ = rule.admin_area_name_message_id_;
invalid_admin_area_message_id_ = rule.invalid_admin_area_message_id_;
@@ -262,6 +275,18 @@ bool Rule::ParseSerializedRule(const std::string& serialized_rule) {
void Rule::ParseJsonRule(const Json& json_rule) {
std::string value;
+ if (json_rule.GetStringValueForKey("key", &value)) {
+ key_.swap(value);
+ }
+
+ if (json_rule.GetStringValueForKey("name", &value)) {
+ name_.swap(value);
+ }
+
+ if (json_rule.GetStringValueForKey("lname", &value)) {
+ latin_name_.swap(value);
+ }
+
if (json_rule.GetStringValueForKey("fmt", &value)) {
ParseAddressFieldsFormat(value, &format_);
}
diff --git a/third_party/libaddressinput/chromium/cpp/src/rule.h b/third_party/libaddressinput/chromium/cpp/src/rule.h
index 5671330..407455b 100644
--- a/third_party/libaddressinput/chromium/cpp/src/rule.h
+++ b/third_party/libaddressinput/chromium/cpp/src/rule.h
@@ -80,6 +80,16 @@ class Rule {
// Parses |json_rule|, which must contain parsed serialized rule.
void ParseJsonRule(const Json& json_rule);
+ // Returns the key for this rule. For example, can return "TX".
+ const std::string& GetKey() const { return key_; }
+
+ // Returns the name for this rule. For example, the name for "TX" is "Texas".
+ const std::string& GetName() const { return name_; }
+
+ // Returns the latinized version of the name. For example, the latinized
+ // version of "北京市" is "Beijing Shi".
+ const std::string& GetLatinName() const { return latin_name_; }
+
// Returns the format of the address as it should appear on an envelope.
const std::vector<std::vector<FormatElement> >& GetFormat() const {
return format_;
@@ -141,6 +151,9 @@ class Rule {
const std::vector<std::string>& values,
std::string* sub_key) const;
+ std::string key_;
+ std::string name_;
+ std::string latin_name_;
std::vector<std::vector<FormatElement> > format_;
std::vector<AddressField> required_;
std::vector<std::string> sub_keys_;
diff --git a/third_party/libaddressinput/chromium/cpp/src/ruleset.cc b/third_party/libaddressinput/chromium/cpp/src/ruleset.cc
index a3eca96..43823b4 100644
--- a/third_party/libaddressinput/chromium/cpp/src/ruleset.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/ruleset.cc
@@ -29,7 +29,8 @@ namespace i18n {
namespace addressinput {
Ruleset::Ruleset(AddressField field, scoped_ptr<Rule> rule)
- : field_(field),
+ : parent_(NULL),
+ field_(field),
rule_(rule.Pass()),
sub_regions_(),
language_codes_() {
@@ -48,6 +49,8 @@ void Ruleset::AddSubRegionRuleset(const std::string& sub_region,
assert(sub_regions_.find(sub_region) == sub_regions_.end());
assert(ruleset != NULL);
assert(ruleset->field() == static_cast<AddressField>(field() + 1));
+
+ ruleset->parent_ = this;
sub_regions_[sub_region] = ruleset.release();
}
diff --git a/third_party/libaddressinput/chromium/cpp/src/ruleset.h b/third_party/libaddressinput/chromium/cpp/src/ruleset.h
index 2e5dbbe..350a675 100644
--- a/third_party/libaddressinput/chromium/cpp/src/ruleset.h
+++ b/third_party/libaddressinput/chromium/cpp/src/ruleset.h
@@ -21,6 +21,7 @@
#include <map>
#include <string>
+#include <vector>
namespace i18n {
namespace addressinput {
@@ -50,6 +51,11 @@ class Ruleset {
~Ruleset();
+ // Returns the parent ruleset. This is NULL until this ruleset has been passed
+ // into a AddSubRegionRuleset() method. Consequently, this is always NULL for
+ // a country-level ruleset.
+ Ruleset* parent() const { return parent_; }
+
// Returns the field type for this ruleset.
AddressField field() const { return field_; }
@@ -57,8 +63,9 @@ class Ruleset {
// the country.
const Rule& rule() const { return *rule_; }
- // Adds the |ruleset| for |sub_region|. A |sub_region| should be added at most
- // once. The |ruleset| should not be NULL.
+ // Adds the |ruleset| for |sub_region| and sets this to be its parent. A
+ // |sub_region| should be added at most once. The |ruleset| should not be
+ // NULL.
//
// The field of the |ruleset| parameter must be exactly one smaller than the
// field of this ruleset. For example, a COUNTRY ruleset can contain
@@ -80,7 +87,16 @@ class Ruleset {
// rule. Otherwise returns the rule in the default language of the country.
const Rule& GetLanguageCodeRule(const std::string& language_code) const;
+ // Returns a mapping of sub-region keys to rulesets. The caller does now own
+ // the result. The values are not NULL.
+ const std::map<std::string, Ruleset*>& GetSubRegionRulesets() const {
+ return sub_regions_;
+ }
+
private:
+ // The parent ruleset of this object. The parent ruleset owns this object.
+ Ruleset* parent_;
+
// The field of this ruleset.
const AddressField field_;
diff --git a/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc b/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc
index 0007312..59c8eab 100644
--- a/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc
@@ -22,20 +22,32 @@
#include <libaddressinput/storage.h>
#include <libaddressinput/util/scoped_ptr.h>
+#include <cstddef>
+#include <set>
#include <string>
+#include <vector>
#include <gtest/gtest.h>
#include "fake_downloader.h"
#include "fake_storage.h"
+#include "region_data_constants.h"
namespace i18n {
namespace addressinput {
-class AddressValidatorTest : public testing::Test, public LoadRulesDelegate {
+scoped_ptr<AddressValidator> BuildAddressValidatorForTesting(
+ const std::string& validation_data_url,
+ scoped_ptr<Downloader> downloader,
+ scoped_ptr<Storage> storage,
+ LoadRulesDelegate* load_rules_delegate);
+
+class AddressValidatorTest : public testing::TestWithParam<std::string>,
+ public LoadRulesDelegate {
public:
AddressValidatorTest()
- : validator_(AddressValidator::Build(
+ : validator_(BuildAddressValidatorForTesting(
+ FakeDownloader::kFakeDataUrl,
scoped_ptr<Downloader>(new FakeDownloader),
scoped_ptr<Storage>(new FakeStorage),
this)) {
@@ -59,6 +71,19 @@ class AddressValidatorTest : public testing::Test, public LoadRulesDelegate {
}
};
+TEST_P(AddressValidatorTest, RegionHasRules) {
+ validator_->LoadRules(GetParam());
+ AddressData address;
+ address.country_code = GetParam();
+ EXPECT_EQ(
+ AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, AddressProblemFilter(), NULL));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ AllRegions, AddressValidatorTest,
+ testing::ValuesIn(RegionDataConstants::GetRegionCodes()));
+
TEST_F(AddressValidatorTest, EmptyAddressNoFatalFailure) {
AddressData address;
address.country_code = "US";
@@ -207,30 +232,275 @@ TEST_F(AddressValidatorTest, BasicValidationFailure) {
EXPECT_EQ(ADMIN_AREA, problems[0].field);
}
-TEST_F(AddressValidatorTest, ValidationFailureWithNoRulesPresent) {
- // The fake downloader/fake storage will fail to get these rules.
- validator_->LoadRules("CA");
+TEST_F(AddressValidatorTest, NoNullSuggestionsCrash) {
+ AddressData address;
+ address.country_code = "US";
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, COUNTRY, 1, NULL));
+}
+
+TEST_F(AddressValidatorTest, SuggestAdminAreaForPostalCode) {
+ AddressData address;
+ address.country_code = "US";
+ address.postal_code = "90291";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("CA", suggestions[0].administrative_area);
+ EXPECT_EQ("90291", suggestions[0].postal_code);
+}
+
+TEST_F(AddressValidatorTest, SuggestLocalityForPostalCodeWithAdminArea) {
+ validator_->LoadRules("TW");
+ AddressData address;
+ address.country_code = "TW";
+ address.postal_code = "515";
+ address.administrative_area = "Changhua";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Dacun Township", suggestions[0].locality);
+ EXPECT_EQ("Changhua County", suggestions[0].administrative_area);
+ EXPECT_EQ("515", suggestions[0].postal_code);
+}
+
+TEST_F(AddressValidatorTest, SuggestAdminAreaForPostalCodeWithLocality) {
+ validator_->LoadRules("TW");
+ AddressData address;
+ address.country_code = "TW";
+ address.postal_code = "515";
+ address.locality = "Dacun";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Dacun Township", suggestions[0].locality);
+ EXPECT_EQ("Changhua County", suggestions[0].administrative_area);
+ EXPECT_EQ("515", suggestions[0].postal_code);
+}
+
+TEST_F(AddressValidatorTest, NoSuggestForPostalCodeWithWrongAdminArea) {
+ AddressData address;
+ address.country_code = "US";
+ address.postal_code = "90066";
+ address.postal_code = "TX";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ EXPECT_TRUE(suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, SuggestForLocality) {
+ validator_->LoadRules("CN");
+ AddressData address;
+ address.country_code = "CN";
+ address.locality = "Anqin";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, LOCALITY, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Anqing Shi", suggestions[0].locality);
+ EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, SuggestForLocalityAndAdminArea) {
+ validator_->LoadRules("CN");
+ AddressData address;
+ address.country_code = "CN";
+ address.locality = "Anqing";
+ address.administrative_area = "Anhui";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, LOCALITY, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_TRUE(suggestions[0].dependent_locality.empty());
+ EXPECT_EQ("Anqing Shi", suggestions[0].locality);
+ EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, SuggestForAdminAreaAndLocality) {
+ validator_->LoadRules("CN");
+ AddressData address;
+ address.country_code = "CN";
+ address.locality = "Anqing";
+ address.administrative_area = "Anhui";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_TRUE(suggestions[0].dependent_locality.empty());
+ EXPECT_TRUE(suggestions[0].locality.empty());
+ EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, SuggestForDependentLocality) {
+ validator_->LoadRules("CN");
+ AddressData address;
+ address.country_code = "CN";
+ address.dependent_locality = "Zongyang";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(
+ address, DEPENDENT_LOCALITY, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Zongyang Xian", suggestions[0].dependent_locality);
+ EXPECT_EQ("Anqing Shi", suggestions[0].locality);
+ EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest,
+ NoSuggestForDependentLocalityWithWrongAdminArea) {
+ validator_->LoadRules("CN");
+ AddressData address;
+ address.country_code = "CN";
+ address.dependent_locality = "Zongyang";
+ address.administrative_area = "Sichuan Sheng";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(
+ address, DEPENDENT_LOCALITY, 10, &suggestions));
+ EXPECT_TRUE(suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, EmptySuggestionsOverLimit) {
+ AddressData address;
+ address.country_code = "US";
+ address.administrative_area = "A";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
+ EXPECT_TRUE(suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, PreferShortSuggestions) {
+ AddressData address;
+ address.country_code = "US";
+ address.administrative_area = "CA";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("CA", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, SuggestTheSingleMatchForFullMatchName) {
+ AddressData address;
+ address.country_code = "US";
+ address.administrative_area = "Texas";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Texas", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, SuggestAdminArea) {
+ AddressData address;
+ address.country_code = "US";
+ address.administrative_area = "Cali";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("California", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, MultipleSuggestions) {
+ AddressData address;
+ address.country_code = "US";
+ address.administrative_area = "MA";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
+ EXPECT_LT(1U, suggestions.size());
+
+ // Massachusetts should not be a suggestion, because it's already covered
+ // under MA.
+ std::set<std::string> expected_suggestions;
+ expected_suggestions.insert("MA");
+ expected_suggestions.insert("Maine");
+ expected_suggestions.insert("Marshall Islands");
+ expected_suggestions.insert("Maryland");
+ for (std::vector<AddressData>::const_iterator it = suggestions.begin();
+ it != suggestions.end(); ++it) {
+ expected_suggestions.erase(it->administrative_area);
+ }
+ EXPECT_TRUE(expected_suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, SuggestNonLatinKeyWhenLanguageMatches) {
+ validator_->LoadRules("KR");
+ AddressData address;
+ address.language_code = "ko";
+ address.country_code = "KR";
+ address.postal_code = "210-210";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("강원도", suggestions[0].administrative_area);
+ EXPECT_EQ("210-210", suggestions[0].postal_code);
+}
+
+TEST_F(AddressValidatorTest, SuggestNonLatinKeyWhenUserInputIsNotLatin) {
+ validator_->LoadRules("KR");
AddressData address;
- address.country_code = "CA";
address.language_code = "en";
- address.administrative_area = "Never never land";
- address.locality = "grassy knoll";
- address.postal_code = "1234";
- address.address_lines.push_back("123 Main St");
- AddressProblems problems;
- EXPECT_EQ(
- AddressValidator::RULES_UNAVAILABLE,
- validator_->ValidateAddress(address, AddressProblemFilter(), &problems));
- EXPECT_TRUE(problems.empty());
+ address.country_code = "KR";
+ address.administrative_area = "강원";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("강원도", suggestions[0].administrative_area);
+}
- // Field requirements are still enforced even if the rules aren't downloaded.
- address.administrative_area = "";
- problems.clear();
- EXPECT_EQ(
- AddressValidator::RULES_UNAVAILABLE,
- validator_->ValidateAddress(address, AddressProblemFilter(), &problems));
- ASSERT_EQ(1U, problems.size());
- EXPECT_EQ(AddressProblem::MISSING_REQUIRED_FIELD, problems[0].type);
+TEST_F(AddressValidatorTest,
+ SuggestLatinNameWhenLanguageDiffersAndLatinNameAvailable) {
+ validator_->LoadRules("KR");
+ AddressData address;
+ address.language_code = "en";
+ address.country_code = "KR";
+ address.postal_code = "210-210";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Gangwon", suggestions[0].administrative_area);
+ EXPECT_EQ("210-210", suggestions[0].postal_code);
+}
+
+TEST_F(AddressValidatorTest, SuggestLatinNameWhenUserInputIsLatin) {
+ validator_->LoadRules("KR");
+ AddressData address;
+ address.language_code = "ko";
+ address.country_code = "KR";
+ address.administrative_area = "Gang";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
+ ASSERT_EQ(1, suggestions.size());
+ EXPECT_EQ("Gangwon", suggestions[0].administrative_area);
}
} // namespace addressinput
diff --git a/third_party/libaddressinput/chromium/cpp/test/country_rules_aggregator_test.cc b/third_party/libaddressinput/chromium/cpp/test/country_rules_aggregator_test.cc
index b82675b..07fe410 100644
--- a/third_party/libaddressinput/chromium/cpp/test/country_rules_aggregator_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/country_rules_aggregator_test.cc
@@ -29,6 +29,7 @@
#include "fake_downloader.h"
#include "fake_storage.h"
+#include "region_data_constants.h"
#include "retriever.h"
#include "rule.h"
#include "ruleset.h"
@@ -36,7 +37,7 @@
namespace i18n {
namespace addressinput {
-class CountryRulesAggregatorTest : public testing::Test {
+class CountryRulesAggregatorTest : public testing::TestWithParam<std::string> {
public:
CountryRulesAggregatorTest()
: aggregator_(scoped_ptr<Retriever>(new Retriever(
@@ -72,14 +73,13 @@ class CountryRulesAggregatorTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(CountryRulesAggregatorTest);
};
-TEST_F(CountryRulesAggregatorTest, ValidRuleset) {
- aggregator_.AggregateRules("CH", BuildCallback());
+TEST_P(CountryRulesAggregatorTest, ValidRuleset) {
+ aggregator_.AggregateRules(GetParam(), BuildCallback());
EXPECT_TRUE(success_);
- EXPECT_EQ("CH", country_code_);
+ EXPECT_EQ(GetParam(), country_code_);
ASSERT_TRUE(ruleset_ != NULL);
const std::vector<std::string>& sub_keys = ruleset_->rule().GetSubKeys();
- EXPECT_TRUE(sub_keys.size() > 0);
for (std::vector<std::string>::const_iterator sub_key_it = sub_keys.begin();
sub_key_it != sub_keys.end(); ++sub_key_it) {
EXPECT_TRUE(ruleset_->GetSubRegionRuleset(*sub_key_it) != NULL);
@@ -95,7 +95,6 @@ TEST_F(CountryRulesAggregatorTest, ValidRuleset) {
non_default_languages.erase(default_lang_it);
}
- EXPECT_TRUE(non_default_languages.size() > 0);
for (std::vector<std::string>::const_iterator
lang_it = non_default_languages.begin();
lang_it != non_default_languages.end();
@@ -105,5 +104,9 @@ TEST_F(CountryRulesAggregatorTest, ValidRuleset) {
}
}
+INSTANTIATE_TEST_CASE_P(
+ AllRegions, CountryRulesAggregatorTest,
+ testing::ValuesIn(RegionDataConstants::GetRegionCodes()));
+
} // namespace addressinput
} // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc b/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc
index 95a8d5f..2eb201d 100644
--- a/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc
@@ -54,7 +54,7 @@ scoped_ptr<std::string> Wrap(const std::string& data,
} // namespace
// Tests for Retriever object.
-class RetrieverTest : public testing::Test {
+class RetrieverTest : public testing::TestWithParam<std::string> {
protected:
RetrieverTest()
: storage_(NULL),
@@ -104,6 +104,20 @@ class RetrieverTest : public testing::Test {
}
};
+TEST_P(RetrieverTest, RegionHasData) {
+ std::string key = "data/" + GetParam();
+ retriever_->Retrieve(key, BuildCallback());
+
+ EXPECT_TRUE(success_);
+ EXPECT_EQ(key, key_);
+ EXPECT_FALSE(data_.empty());
+ EXPECT_NE(kEmptyData, data_);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ AllRegions, RetrieverTest,
+ testing::ValuesIn(RegionDataConstants::GetRegionCodes()));
+
TEST_F(RetrieverTest, RetrieveData) {
retriever_->Retrieve(kKey, BuildCallback());