Home | History | Annotate | Download | only in test
      1 // Copyright (C) 2013 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 "rule.h"
     16 
     17 #include <libaddressinput/address_field.h>
     18 
     19 #include <string>
     20 #include <utility>
     21 #include <vector>
     22 
     23 #include <gtest/gtest.h>
     24 
     25 #include "region_data_constants.h"
     26 
     27 namespace {
     28 
     29 using i18n::addressinput::AddressField;
     30 using i18n::addressinput::ADMIN_AREA;
     31 using i18n::addressinput::COUNTRY;
     32 using i18n::addressinput::FormatElement;
     33 using i18n::addressinput::LOCALITY;
     34 using i18n::addressinput::ORGANIZATION;
     35 using i18n::addressinput::POSTAL_CODE;
     36 using i18n::addressinput::RECIPIENT;
     37 using i18n::addressinput::RegionDataConstants;
     38 using i18n::addressinput::Rule;
     39 using i18n::addressinput::STREET_ADDRESS;
     40 
     41 bool IsFormatEmpty(const std::vector<std::vector<FormatElement> >& format) {
     42   for (std::vector<std::vector<FormatElement> >::const_iterator
     43            it = format.begin();
     44        it != format.end();
     45        ++it) {
     46     if (!it->empty()) {
     47       return false;
     48     }
     49   }
     50   return true;
     51 }
     52 
     53 TEST(RuleTest, CopyOverwritesRule) {
     54   Rule rule;
     55   ASSERT_TRUE(rule.ParseSerializedRule(
     56       "{"
     57       "\"fmt\":\"%S%Z\","
     58       "\"require\":\"SZ\","
     59       "\"state_name_type\":\"area\","
     60       "\"zip_name_type\":\"postal\","
     61       "\"sub_keys\":\"CA~NY~TX\","
     62       "\"lang\":\"en\","
     63       "\"languages\":\"en~fr\","
     64       "\"zip\":\"\\\\d{5}([ \\\\-]\\\\d{4})?\""
     65       "}"));
     66 
     67   Rule copy;
     68   EXPECT_NE(rule.GetFormat(), copy.GetFormat());
     69   EXPECT_NE(rule.GetRequired(), copy.GetRequired());
     70   EXPECT_NE(rule.GetSubKeys(), copy.GetSubKeys());
     71   EXPECT_NE(rule.GetLanguages(), copy.GetLanguages());
     72   EXPECT_NE(rule.GetLanguage(), copy.GetLanguage());
     73   EXPECT_NE(rule.GetPostalCodeFormat(), copy.GetPostalCodeFormat());
     74   EXPECT_NE(rule.GetAdminAreaNameType(),
     75             copy.GetAdminAreaNameType());
     76   EXPECT_NE(rule.GetPostalCodeNameType(),
     77             copy.GetPostalCodeNameType());
     78 
     79   copy.CopyFrom(rule);
     80   EXPECT_EQ(rule.GetFormat(), copy.GetFormat());
     81   EXPECT_EQ(rule.GetRequired(), copy.GetRequired());
     82   EXPECT_EQ(rule.GetSubKeys(), copy.GetSubKeys());
     83   EXPECT_EQ(rule.GetLanguages(), copy.GetLanguages());
     84   EXPECT_EQ(rule.GetLanguage(), copy.GetLanguage());
     85   EXPECT_EQ(rule.GetPostalCodeFormat(), copy.GetPostalCodeFormat());
     86   EXPECT_EQ(rule.GetAdminAreaNameType(),
     87             copy.GetAdminAreaNameType());
     88   EXPECT_EQ(rule.GetPostalCodeNameType(),
     89             copy.GetPostalCodeNameType());
     90 }
     91 
     92 TEST(RuleTest, ParseOverwritesRule) {
     93   Rule rule;
     94   ASSERT_TRUE(rule.ParseSerializedRule(
     95       "{"
     96       "\"fmt\":\"%S%Z\","
     97       "\"require\":\"SZ\","
     98       "\"state_name_type\":\"area\","
     99       "\"zip_name_type\":\"postal\","
    100       "\"sub_keys\":\"CA~NY~TX\","
    101       "\"lang\":\"en\","
    102       "\"languages\":\"en~fr\","
    103       "\"zip\":\"\\\\d{5}([ \\\\-]\\\\d{4})?\""
    104       "}"));
    105   EXPECT_FALSE(IsFormatEmpty(rule.GetFormat()));
    106   EXPECT_FALSE(rule.GetRequired().empty());
    107   EXPECT_FALSE(rule.GetSubKeys().empty());
    108   EXPECT_FALSE(rule.GetLanguages().empty());
    109   EXPECT_FALSE(rule.GetLanguage().empty());
    110   EXPECT_FALSE(rule.GetPostalCodeFormat().empty());
    111   EXPECT_EQ("area", rule.GetAdminAreaNameType());
    112   EXPECT_EQ("postal", rule.GetPostalCodeNameType());
    113 
    114   ASSERT_TRUE(rule.ParseSerializedRule(
    115       "{"
    116       "\"fmt\":\"\","
    117       "\"require\":\"\","
    118       "\"state_name_type\":\"do_si\","
    119       "\"zip_name_type\":\"zip\","
    120       "\"sub_keys\":\"\","
    121       "\"lang\":\"\","
    122       "\"languages\":\"\","
    123       "\"zip\":\"\""
    124       "}"));
    125   EXPECT_TRUE(IsFormatEmpty(rule.GetFormat()));
    126   EXPECT_TRUE(rule.GetRequired().empty());
    127   EXPECT_TRUE(rule.GetSubKeys().empty());
    128   EXPECT_TRUE(rule.GetLanguages().empty());
    129   EXPECT_TRUE(rule.GetLanguage().empty());
    130   EXPECT_TRUE(rule.GetPostalCodeFormat().empty());
    131   EXPECT_EQ("do_si", rule.GetAdminAreaNameType());
    132   EXPECT_EQ("zip", rule.GetPostalCodeNameType());
    133 }
    134 
    135 TEST(RuleTest, ParseEmptyDataDoesNotOverwriteRule) {
    136   Rule rule;
    137   ASSERT_TRUE(rule.ParseSerializedRule(
    138       "{"
    139       "\"fmt\":\"%S%Z\","
    140       "\"require\":\"SZ\","
    141       "\"state_name_type\":\"area\","
    142       "\"zip_name_type\":\"postal\","
    143       "\"sub_keys\":\"CA~NY~TX\","
    144       "\"lang\":\"en\","
    145       "\"languages\":\"en~fr\","
    146       "\"zip\":\"\\\\d{5}([ \\\\-]\\\\d{4})?\""
    147       "}"));
    148 
    149   Rule copy;
    150   copy.CopyFrom(rule);
    151   ASSERT_TRUE(copy.ParseSerializedRule("{}"));
    152 
    153   EXPECT_EQ(rule.GetFormat(), copy.GetFormat());
    154   EXPECT_EQ(rule.GetRequired(), copy.GetRequired());
    155   EXPECT_EQ(rule.GetSubKeys(), copy.GetSubKeys());
    156   EXPECT_EQ(rule.GetLanguages(), copy.GetLanguages());
    157   EXPECT_EQ(rule.GetLanguage(), copy.GetLanguage());
    158   EXPECT_EQ(rule.GetPostalCodeFormat(), copy.GetPostalCodeFormat());
    159   EXPECT_EQ(rule.GetAdminAreaNameType(),
    160             copy.GetAdminAreaNameType());
    161   EXPECT_EQ(rule.GetPostalCodeNameType(),
    162             copy.GetPostalCodeNameType());
    163 }
    164 
    165 TEST(RuleTest, ParseFormatWithNewLines) {
    166   Rule rule;
    167   ASSERT_TRUE(
    168       rule.ParseSerializedRule("{\"fmt\":\"%O%n%N%n%A%nAX-%Z %C%nLAND\"}"));
    169 
    170   std::vector<std::vector<FormatElement> > expected_format;
    171   expected_format.push_back(
    172       std::vector<FormatElement>(1, FormatElement(ORGANIZATION)));
    173   expected_format.push_back(
    174       std::vector<FormatElement>(1, FormatElement(RECIPIENT)));
    175   expected_format.push_back(
    176       std::vector<FormatElement>(1, FormatElement(STREET_ADDRESS)));
    177   expected_format.push_back(
    178       std::vector<FormatElement>(1, FormatElement("AX-")));
    179   expected_format.back().push_back(FormatElement(POSTAL_CODE));
    180   expected_format.back().push_back(FormatElement(" "));
    181   expected_format.back().push_back(FormatElement(LOCALITY));
    182   expected_format.push_back(
    183       std::vector<FormatElement>(1, FormatElement("LAND")));
    184 
    185   EXPECT_EQ(expected_format, rule.GetFormat());
    186 }
    187 
    188 TEST(RuleTest, DoubleTokenPrefixDoesNotCrash) {
    189   Rule rule;
    190   EXPECT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"%%R\"}"));
    191 }
    192 
    193 TEST(RuleTest, DoubleNewlineFormatDoesNotCrash) {
    194   Rule rule;
    195   EXPECT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"%n%n\"}"));
    196 }
    197 
    198 TEST(RuleTest, FormatTokenWithoutPrefixDoesNotCrash) {
    199   Rule rule;
    200   ASSERT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"R\"}"));
    201 }
    202 
    203 TEST(RuleTest, ParseDuplicateTokenInFormatDoesNotCrash) {
    204   Rule rule;
    205   EXPECT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"%R%R\"}"));
    206 }
    207 
    208 TEST(RuleTest, ParseInvalidFormatFieldsDoesNotCrash) {
    209   Rule rule;
    210   EXPECT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"%K%L\"}"));
    211 }
    212 
    213 TEST(RuleTest, PrefixWithoutTokenFormatDoesNotCrash) {
    214   Rule rule;
    215   EXPECT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"%\"}"));
    216 }
    217 
    218 TEST(RuleTest, EmptyStringFormatDoesNotCrash) {
    219   Rule rule;
    220   EXPECT_TRUE(rule.ParseSerializedRule("{\"fmt\":\"\"}"));
    221 }
    222 
    223 TEST(RuleTest, ParseRequiredFields) {
    224   Rule rule;
    225   ASSERT_TRUE(rule.ParseSerializedRule("{\"require\":\"ONAZC\"}"));
    226   std::vector<AddressField> expected;
    227   expected.push_back(ORGANIZATION);
    228   expected.push_back(RECIPIENT);
    229   expected.push_back(STREET_ADDRESS);
    230   expected.push_back(POSTAL_CODE);
    231   expected.push_back(LOCALITY);
    232   EXPECT_EQ(expected, rule.GetRequired());
    233 }
    234 
    235 TEST(RuleTest, ParseEmptyStringRequiredFields) {
    236   Rule rule;
    237   ASSERT_TRUE(rule.ParseSerializedRule("{\"require\":\"\"}"));
    238   EXPECT_TRUE(rule.GetRequired().empty());
    239 }
    240 
    241 TEST(RuleTest, ParseInvalidRequiredFields) {
    242   Rule rule;
    243   ASSERT_TRUE(rule.ParseSerializedRule("{\"require\":\"garbage\"}"));
    244   EXPECT_TRUE(rule.GetRequired().empty());
    245 }
    246 
    247 TEST(RuleTest, ParseDuplicateRequiredFields) {
    248   Rule rule;
    249   ASSERT_TRUE(rule.ParseSerializedRule("{\"require\":\"SSS\"}"));
    250   EXPECT_EQ(std::vector<AddressField>(3, ADMIN_AREA), rule.GetRequired());
    251 }
    252 
    253 TEST(RuleTest, ParsesSubKeysCorrectly) {
    254   Rule rule;
    255   ASSERT_TRUE(rule.ParseSerializedRule("{\"sub_keys\":\"CA~NY~TX\"}"));
    256   std::vector<std::string> expected;
    257   expected.push_back("CA");
    258   expected.push_back("NY");
    259   expected.push_back("TX");
    260   EXPECT_EQ(expected, rule.GetSubKeys());
    261 }
    262 
    263 TEST(RuleTest, ParsesLanguageCorrectly) {
    264   Rule rule;
    265   ASSERT_TRUE(rule.ParseSerializedRule("{\"lang\":\"en\"}"));
    266   EXPECT_EQ("en", rule.GetLanguage());
    267 }
    268 
    269 TEST(RuleTest, ParsesLanguagesCorrectly) {
    270   Rule rule;
    271   ASSERT_TRUE(rule.ParseSerializedRule("{\"languages\":\"de~fr~it\"}"));
    272   std::vector<std::string> expected;
    273   expected.push_back("de");
    274   expected.push_back("fr");
    275   expected.push_back("it");
    276   EXPECT_EQ(expected, rule.GetLanguages());
    277 }
    278 
    279 TEST(RuleTest, ParsesPostalCodeFormatCorrectly) {
    280   Rule rule;
    281   ASSERT_TRUE(rule.ParseSerializedRule(
    282       "{"
    283       "\"zip\":\"\\\\d{5}([ \\\\-]\\\\d{4})?\""
    284       "}"));
    285   EXPECT_EQ("\\d{5}([ \\-]\\d{4})?", rule.GetPostalCodeFormat());
    286 }
    287 
    288 TEST(RuleTest, EmptyStringIsNotValid) {
    289   Rule rule;
    290   EXPECT_FALSE(rule.ParseSerializedRule(std::string()));
    291 }
    292 
    293 TEST(RuleTest, EmptyDictionaryIsValid) {
    294   Rule rule;
    295   EXPECT_TRUE(rule.ParseSerializedRule("{}"));
    296 }
    297 
    298 TEST(RuleTest, ParseSubKeyTest) {
    299   i18n::addressinput::Rule rule;
    300   ASSERT_TRUE(rule.ParseSerializedRule(
    301       "{ \"sub_keys\": \"FOO~BAR~BAZ\","
    302       "  \"sub_names\": \"Foolandia~Bartopolis~Bazmonia\","
    303       "  \"sub_lnames\": \"Foolandia2~Bartopolis2~Bazmonia2\" }"));
    304   EXPECT_EQ(3U, rule.GetSubKeys().size());
    305 
    306   std::string sub_key;
    307   EXPECT_TRUE(rule.CanonicalizeSubKey("BAR", false, &sub_key));
    308   EXPECT_EQ("BAR", sub_key);
    309   sub_key.clear();
    310 
    311   EXPECT_TRUE(rule.CanonicalizeSubKey("Bartopolis", false, &sub_key));
    312   EXPECT_EQ("BAR", sub_key);
    313   sub_key.clear();
    314 
    315   // Unlatinize.
    316   EXPECT_TRUE(rule.CanonicalizeSubKey("Bartopolis2", false, &sub_key));
    317   EXPECT_EQ("BAR", sub_key);
    318   sub_key.clear();
    319 
    320   // Keep input latin.
    321   EXPECT_TRUE(rule.CanonicalizeSubKey("Bartopolis2", true, &sub_key));
    322   EXPECT_EQ("Bartopolis2", sub_key);
    323   sub_key.clear();
    324 
    325   EXPECT_FALSE(rule.CanonicalizeSubKey("Beertopia", false, &sub_key));
    326   EXPECT_EQ("", sub_key);
    327 }
    328 
    329 struct LabelData {
    330   LabelData(const std::string& data, const std::string& name_type)
    331       : data(data), name_type(name_type) {}
    332 
    333   ~LabelData() {}
    334 
    335   std::string data;
    336   std::string name_type;
    337 };
    338 
    339 // Tests for parsing the postal code name.
    340 class PostalCodeNameParseTest : public testing::TestWithParam<LabelData> {
    341  protected:
    342   Rule rule_;
    343 };
    344 
    345 // Verifies that a postal code name is parsed correctly.
    346 TEST_P(PostalCodeNameParseTest, ParsedCorrectly) {
    347   ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().data));
    348   EXPECT_EQ(GetParam().name_type, rule_.GetPostalCodeNameType());
    349 }
    350 
    351 // Test parsing all postal code names.
    352 INSTANTIATE_TEST_CASE_P(
    353     AllPostalCodeNames, PostalCodeNameParseTest,
    354     testing::Values(
    355         LabelData("{\"zip_name_type\":\"postal\"}", "postal"),
    356         LabelData("{\"zip_name_type\":\"zip\"}", "zip")));
    357 
    358 // Tests for parsing the administrative area name.
    359 class AdminAreaNameParseTest : public testing::TestWithParam<LabelData> {
    360  protected:
    361   Rule rule_;
    362 };
    363 
    364 // Verifies that an administrative area name is parsed correctly.
    365 TEST_P(AdminAreaNameParseTest, ParsedCorrectly) {
    366   ASSERT_TRUE(rule_.ParseSerializedRule(GetParam().data));
    367   EXPECT_EQ(GetParam().name_type, rule_.GetAdminAreaNameType());
    368 }
    369 
    370 // Test parsing all administrative area names.
    371 INSTANTIATE_TEST_CASE_P(
    372     AllAdminAreaNames, AdminAreaNameParseTest,
    373     testing::Values(
    374         LabelData("{\"state_name_type\":\"area\"}", "area"),
    375         LabelData("{\"state_name_type\":\"county\"}", "county"),
    376         LabelData("{\"state_name_type\":\"department\"}", "department"),
    377         LabelData("{\"state_name_type\":\"district\"}", "district"),
    378         LabelData("{\"state_name_type\":\"do_si\"}", "do_si"),
    379         LabelData("{\"state_name_type\":\"emirate\"}", "emirate"),
    380         LabelData("{\"state_name_type\":\"island\"}", "island"),
    381         LabelData("{\"state_name_type\":\"parish\"}", "parish"),
    382         LabelData("{\"state_name_type\":\"prefecture\"}", "prefecture"),
    383         LabelData("{\"state_name_type\":\"province\"}", "province"),
    384         LabelData("{\"state_name_type\":\"state\"}", "state")));
    385 
    386 // Verifies that an address format does not contain consecutive lines with
    387 // multiple fields each. Such address format (e.g. {{ELEMENT, ELEMENT},
    388 // {ELEMENT, ELEMENT}}) will result in incorrect behavior of BuildComponents()
    389 // public API.
    390 TEST(RuleParseTest, ConsecutiveLinesWithMultipleFields) {
    391   const std::vector<std::string>& region_codes =
    392       RegionDataConstants::GetRegionCodes();
    393   Rule rule;
    394   for (size_t i = 0; i < region_codes.size(); ++i) {
    395     const std::string& region_data =
    396         RegionDataConstants::GetRegionData(region_codes[i]);
    397     SCOPED_TRACE(region_codes[i] + ": " + region_data);
    398 
    399     ASSERT_TRUE(rule.ParseSerializedRule(region_data));
    400     bool previous_line_has_single_field = true;
    401     for (std::vector<std::vector<FormatElement> >::const_iterator
    402              line_it = rule.GetFormat().begin();
    403          line_it != rule.GetFormat().end();
    404          ++line_it) {
    405       int num_fields = 0;
    406       for (std::vector<FormatElement>::const_iterator
    407                element_it = line_it->begin();
    408            element_it != line_it->end();
    409            ++element_it) {
    410         if (element_it->IsField()) {
    411           ++num_fields;
    412         }
    413       }
    414       if (num_fields == 0) {
    415         continue;
    416       }
    417       ASSERT_TRUE(num_fields == 1 || previous_line_has_single_field);
    418       previous_line_has_single_field = num_fields == 1;
    419     }
    420   }
    421 }
    422 
    423 // Verifies that a street line is surrounded by either newlines or spaces. A
    424 // different format will result in incorrect behavior in
    425 // AddressData::BuildDisplayLines().
    426 TEST(RuleParseTest, StreetAddressSurroundingElements) {
    427   const std::vector<std::string>& region_codes =
    428       RegionDataConstants::GetRegionCodes();
    429   Rule rule;
    430   for (size_t i = 0; i < region_codes.size(); ++i) {
    431     const std::string& region_data =
    432         RegionDataConstants::GetRegionData(region_codes[i]);
    433     SCOPED_TRACE(region_codes[i] + ": " + region_data);
    434 
    435     ASSERT_TRUE(rule.ParseSerializedRule(region_data));
    436     for (std::vector<std::vector<FormatElement> >::const_iterator
    437              line_it = rule.GetFormat().begin();
    438          line_it != rule.GetFormat().end();
    439          ++line_it) {
    440       for (size_t i = 0; i < line_it->size(); ++i) {
    441         const FormatElement& element = line_it->at(i);
    442         if (element.IsField() && element.field == STREET_ADDRESS) {
    443           bool surrounded_by_newlines = line_it->size() == 1;
    444           bool surrounded_by_spaces =
    445               i > 0 &&
    446               i < line_it->size() - 1 &&
    447               !line_it->at(i - 1).IsField() &&
    448               line_it->at(i - 1).literal == " " &&
    449               !line_it->at(i + 1).IsField() &&
    450               line_it->at(i + 1).literal == " ";
    451           EXPECT_TRUE(surrounded_by_newlines || surrounded_by_spaces);
    452         }
    453       }
    454     }
    455   }
    456 }
    457 
    458 }  // namespace
    459