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 <libaddressinput/address_ui.h>
     16 
     17 #include <libaddressinput/address_field.h>
     18 #include <libaddressinput/address_ui_component.h>
     19 #include <libaddressinput/localization.h>
     20 
     21 #include <set>
     22 #include <string>
     23 #include <vector>
     24 
     25 #include <gtest/gtest.h>
     26 
     27 namespace {
     28 
     29 using i18n::addressinput::ADMIN_AREA;
     30 using i18n::addressinput::AddressField;
     31 using i18n::addressinput::AddressUiComponent;
     32 using i18n::addressinput::BuildComponents;
     33 using i18n::addressinput::COUNTRY;
     34 using i18n::addressinput::GetRegionCodes;
     35 using i18n::addressinput::Localization;
     36 using i18n::addressinput::POSTAL_CODE;
     37 using i18n::addressinput::RECIPIENT;
     38 using i18n::addressinput::STREET_ADDRESS;
     39 
     40 static const char kUiLanguageTag[] = "en";
     41 
     42 // Returns testing::AssertionSuccess if the |components| are valid. Uses
     43 // |region_code| in test failure messages.
     44 testing::AssertionResult ComponentsAreValid(
     45     const std::vector<AddressUiComponent>& components) {
     46   if (components.empty()) {
     47     return testing::AssertionFailure() << "no components";
     48   }
     49 
     50   for (std::vector<AddressUiComponent>::const_iterator
     51        component_it = components.begin();
     52        component_it != components.end(); ++component_it) {
     53     static const AddressField kMinAddressField = COUNTRY;
     54     static const AddressField kMaxAddressField = RECIPIENT;
     55     if (component_it->field < kMinAddressField ||
     56         component_it->field > kMaxAddressField) {
     57       return testing::AssertionFailure() << "unexpected field "
     58                                          << component_it->field;
     59     }
     60 
     61     if (component_it->name.empty()) {
     62       return testing::AssertionFailure() << "empty field name for field "
     63                                          << component_it->field;
     64     }
     65   }
     66 
     67   return testing::AssertionSuccess();
     68 }
     69 
     70 // Tests for address UI functions.
     71 class AddressUiTest : public testing::TestWithParam<std::string> {
     72  protected:
     73   Localization localization_;
     74   std::string best_address_language_tag_;
     75 };
     76 
     77 // Verifies that a region code consists of two characters, for example "TW".
     78 TEST_P(AddressUiTest, RegionCodeHasTwoCharacters) {
     79   EXPECT_EQ(2, GetParam().size());
     80 }
     81 
     82 // Verifies that BuildComponents() returns valid UI components for a region
     83 // code.
     84 TEST_P(AddressUiTest, ComponentsAreValid) {
     85   EXPECT_TRUE(ComponentsAreValid(BuildComponents(
     86       GetParam(), localization_, kUiLanguageTag, &best_address_language_tag_)));
     87 }
     88 
     89 // Verifies that BuildComponents() returns at most one input field of each type.
     90 TEST_P(AddressUiTest, UniqueFieldTypes) {
     91   std::set<AddressField> fields;
     92   const std::vector<AddressUiComponent>& components =
     93       BuildComponents(GetParam(), localization_, kUiLanguageTag,
     94                       &best_address_language_tag_);
     95   for (std::vector<AddressUiComponent>::const_iterator it = components.begin();
     96        it != components.end(); ++it) {
     97     EXPECT_TRUE(fields.insert(it->field).second);
     98   }
     99 }
    100 
    101 // Test all regions codes.
    102 INSTANTIATE_TEST_CASE_P(
    103     AllRegions, AddressUiTest,
    104     testing::ValuesIn(GetRegionCodes()));
    105 
    106 // Verifies that BuildComponents() returns an empty vector for an invalid region
    107 // code.
    108 TEST_F(AddressUiTest, InvalidRegionCodeReturnsEmptyVector) {
    109   EXPECT_TRUE(BuildComponents(
    110       "INVALID-REGION-CODE", localization_, kUiLanguageTag,
    111       &best_address_language_tag_).empty());
    112 }
    113 
    114 // Test data for determining the best language tag and whether the right format
    115 // pattern was used (fmt vs lfmt).
    116 struct LanguageTestCase {
    117   LanguageTestCase(const std::string& region_code,
    118                    const std::string& ui_language_tag,
    119                    const std::string& expected_best_address_language_tag,
    120                    AddressField expected_first_field)
    121       : region_code(region_code),
    122         ui_language_tag(ui_language_tag),
    123         expected_best_address_language_tag(expected_best_address_language_tag),
    124         expected_first_field(expected_first_field) {}
    125 
    126   ~LanguageTestCase() {}
    127 
    128   // The CLDR region code to test.
    129   const std::string region_code;
    130 
    131   // The BCP 47 language tag to test.
    132   const std::string ui_language_tag;
    133 
    134   // The expected value for the best language tag returned by BuildComponents().
    135   const std::string expected_best_address_language_tag;
    136 
    137   // The first field expected to be returned from BuildComponents(). Useful for
    138   // determining whether the returned format is in Latin or default order.
    139   const AddressField expected_first_field;
    140 };
    141 
    142 class BestAddressLanguageTagTest
    143     : public testing::TestWithParam<LanguageTestCase> {
    144  protected:
    145   Localization localization_;
    146   std::string best_address_language_tag_;
    147 };
    148 
    149 std::string GetterStub(int) { return std::string(); }
    150 
    151 TEST_P(BestAddressLanguageTagTest, CorrectBestAddressLanguageTag) {
    152   localization_.SetGetter(&GetterStub);
    153   const std::vector<AddressUiComponent>& components = BuildComponents(
    154       GetParam().region_code, localization_, GetParam().ui_language_tag,
    155       &best_address_language_tag_);
    156   EXPECT_EQ(GetParam().expected_best_address_language_tag,
    157             best_address_language_tag_);
    158   ASSERT_FALSE(components.empty());
    159   EXPECT_EQ(GetParam().expected_first_field, components.front().field);
    160 }
    161 
    162 INSTANTIATE_TEST_CASE_P(
    163     LanguageTestCases, BestAddressLanguageTagTest,
    164     testing::Values(
    165         // Armenia supports hy and has a Latin format.
    166         LanguageTestCase("AM", "", "hy", RECIPIENT),
    167         LanguageTestCase("AM", "hy", "hy", RECIPIENT),
    168         LanguageTestCase("AM", "en", "hy-Latn", RECIPIENT),
    169 
    170         // P.R. China supports zh-Hans and has a Latin format.
    171         LanguageTestCase("CN", "zh-hans", "zh-Hans", POSTAL_CODE),
    172         LanguageTestCase("CN", "zh-hant", "zh-Hans", POSTAL_CODE),
    173         LanguageTestCase("CN", "zh-hans-CN", "zh-Hans", POSTAL_CODE),
    174         LanguageTestCase("CN", "zh", "zh-Hans", POSTAL_CODE),
    175         LanguageTestCase("CN", "ZH_HANS", "zh-Hans", POSTAL_CODE),
    176         LanguageTestCase("CN", "zh-cmn-Hans-CN", "zh-Hans", POSTAL_CODE),
    177         LanguageTestCase("CN", "zh-Latn", "zh-Latn", RECIPIENT),
    178         LanguageTestCase("CN", "zh-latn-CN", "zh-Latn", RECIPIENT),
    179         LanguageTestCase("CN", "en", "zh-Latn", RECIPIENT),
    180         LanguageTestCase("CN", "ja", "zh-Latn", RECIPIENT),
    181         LanguageTestCase("CN", "ko", "zh-Latn", RECIPIENT),
    182         LanguageTestCase("CN", "ZH_LATN", "zh-Latn", RECIPIENT),
    183         // Libaddressinput does not have information about extended language
    184         // subtags, so it uses the zh-Latn language tag for all base languages
    185         // that are not zh, even if it's effectively the same language.
    186         // Mandarin Chinese, Simplified script, as used in China:
    187         LanguageTestCase("CN", "cmn-Hans-CN", "zh-Latn", RECIPIENT),
    188 
    189         // Hong Kong supports zh-Hant and en. It has a Latin format.
    190         LanguageTestCase("HK", "zh", "zh-Hant", ADMIN_AREA),
    191         LanguageTestCase("HK", "zh-hans", "zh-Hant", ADMIN_AREA),
    192         LanguageTestCase("HK", "zh-hant", "zh-Hant", ADMIN_AREA),
    193         LanguageTestCase("HK", "zh-yue-HK", "zh-Hant", ADMIN_AREA),
    194         LanguageTestCase("HK", "en", "en", ADMIN_AREA),
    195         LanguageTestCase("HK", "zh-latn", "zh-Latn", RECIPIENT),
    196         LanguageTestCase("HK", "fr", "zh-Latn", RECIPIENT),
    197         LanguageTestCase("HK", "ja", "zh-Latn", RECIPIENT),
    198         LanguageTestCase("HK", "ko", "zh-Latn", RECIPIENT),
    199         // Libaddressinput does not have information about extended language
    200         // subtags, so it uses the zh-Latn language tag for all base languages
    201         // that are not zh or en, even if it's effectively the same language.
    202         // Cantonese Chinese, as used in Hong Kong:
    203         LanguageTestCase("HK", "yue-HK", "zh-Latn", RECIPIENT),
    204 
    205         // Macao supports zh-Hant and pt. It has a Latin format.
    206         LanguageTestCase("MO", "zh", "zh-Hant", STREET_ADDRESS),
    207         LanguageTestCase("MO", "zh-Hant", "zh-Hant", STREET_ADDRESS),
    208         LanguageTestCase("MO", "pt", "pt", STREET_ADDRESS),
    209         LanguageTestCase("MO", "zh-Latn", "zh-Latn", RECIPIENT),
    210         LanguageTestCase("MO", "en", "zh-Latn", RECIPIENT),
    211 
    212         // Switzerland supports de, fr, and it.
    213         LanguageTestCase("CH", "de", "de", RECIPIENT),
    214         LanguageTestCase("CH", "de-DE", "de", RECIPIENT),
    215         LanguageTestCase("CH", "de-Latn-DE", "de", RECIPIENT),
    216         LanguageTestCase("CH", "fr", "fr", RECIPIENT),
    217         LanguageTestCase("CH", "it", "it", RECIPIENT),
    218         LanguageTestCase("CH", "en", "de", RECIPIENT),
    219 
    220         // Antarctica does not have language information.
    221         LanguageTestCase("AQ", "en", "en", RECIPIENT),
    222         LanguageTestCase("AQ", "fr", "fr", RECIPIENT),
    223         LanguageTestCase("AQ", "es", "es", RECIPIENT),
    224         LanguageTestCase("AQ", "zh-Hans", "zh-Hans", RECIPIENT),
    225 
    226         // Egypt supports ar and has a Latin format.
    227         LanguageTestCase("EG", "ar", "ar", RECIPIENT),
    228         LanguageTestCase("EG", "ar-Arab", "ar", RECIPIENT),
    229         LanguageTestCase("EG", "ar-Latn", "ar-Latn", RECIPIENT),
    230         LanguageTestCase("EG", "fr", "ar-Latn", RECIPIENT),
    231         LanguageTestCase("EG", "fa", "ar-Latn", RECIPIENT),
    232         // Libaddressinput does not have language-to-script mapping, so it uses
    233         // the ar-Latn language tag for all base languages that are not ar, even
    234         // if the script is the same.
    235         LanguageTestCase("EG", "fa-Arab", "ar-Latn", RECIPIENT)));
    236 
    237 }  // namespace
    238