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_input_helper.h>
     16 
     17 #include <libaddressinput/address_data.h>
     18 #include <libaddressinput/callback.h>
     19 #include <libaddressinput/null_storage.h>
     20 #include <libaddressinput/preload_supplier.h>
     21 #include <libaddressinput/util/basictypes.h>
     22 #include <libaddressinput/util/scoped_ptr.h>
     23 
     24 #include <string>
     25 #include <utility>
     26 
     27 #include <gtest/gtest.h>
     28 
     29 #include "mock_source.h"
     30 #include "testdata_source.h"
     31 
     32 namespace {
     33 
     34 using i18n::addressinput::AddressData;
     35 using i18n::addressinput::AddressInputHelper;
     36 using i18n::addressinput::BuildCallback;
     37 using i18n::addressinput::Callback;
     38 using i18n::addressinput::MockSource;
     39 using i18n::addressinput::NullStorage;
     40 using i18n::addressinput::PreloadSupplier;
     41 using i18n::addressinput::scoped_ptr;
     42 using i18n::addressinput::TestdataSource;
     43 
     44 class AddressInputHelperTest : public testing::Test {
     45  protected:
     46   AddressInputHelperTest()
     47       // Our PreloadSupplier loads all data for a country at a time.
     48       : supplier_(new TestdataSource(true), new NullStorage),
     49         address_input_helper_(&supplier_),
     50         loaded_(BuildCallback(this, &AddressInputHelperTest::Loaded)) {}
     51 
     52   // Helper method to test FillAddress that ensures the PreloadSupplier has the
     53   // necessary data preloaded.
     54   void FillAddress(AddressData* address) {
     55     const std::string& region_code = address->region_code;
     56     if (!region_code.empty()) {
     57       supplier_.LoadRules(region_code, *loaded_);
     58     }
     59     address_input_helper_.FillAddress(address);
     60   }
     61 
     62  private:
     63   // Used to preload data that we need.
     64   void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
     65 
     66   PreloadSupplier supplier_;
     67   const AddressInputHelper address_input_helper_;
     68   const scoped_ptr<const PreloadSupplier::Callback> loaded_;
     69   DISALLOW_COPY_AND_ASSIGN(AddressInputHelperTest);
     70 };
     71 
     72 TEST_F(AddressInputHelperTest, AddressWithMissingPostalCode) {
     73   AddressData address;
     74   address.region_code = "CX";
     75   address.administrative_area = "WA";
     76 
     77   // There is only one postal code for Christmas Island
     78   AddressData expected = address;
     79   expected.postal_code = "6798";
     80   FillAddress(&address);
     81   EXPECT_EQ(expected, address);
     82 }
     83 
     84 TEST_F(AddressInputHelperTest, AddressWithPostalCodeMatchingAdmin) {
     85   AddressData address;
     86   address.region_code = "US";
     87   address.postal_code = "58098";
     88   // Other data should be left alone.
     89   address.address_line.push_back("10 High St");
     90 
     91   // North Dakota has post codes starting with 58.
     92   AddressData expected = address;
     93   expected.administrative_area = "ND";
     94   FillAddress(&address);
     95   EXPECT_EQ(expected, address);
     96 
     97   address.administrative_area = "CA";  // Override the admin area.
     98   // Now, since the admin area was already filled in, we don't fix it, even
     99   // though it was correct.
    100   expected.administrative_area = "CA";
    101   FillAddress(&address);
    102   EXPECT_EQ(expected, address);
    103 }
    104 
    105 TEST_F(AddressInputHelperTest, AddressWithPostalCodeMatchingLowerLevel) {
    106   AddressData address;
    107   address.region_code = "TW";
    108   address.postal_code = "53012";
    109 
    110   /* This matches  - Ershuei Township. */
    111   AddressData expected = address;
    112   /* This locality is in  - Changhua County. */
    113   expected.administrative_area = "\xE5\xBD\xB0\xE5\x8C\x96\xE7\xB8\xA3";
    114   expected.locality = "\xE4\xBA\x8C\xE6\xB0\xB4\xE9\x84\x89";
    115   FillAddress(&address);
    116   EXPECT_EQ(expected, address);
    117 
    118   // Override the admin area.
    119   address.administrative_area = "Already filled in";
    120   expected.administrative_area = "Already filled in";
    121   address.locality = "";
    122   // However, the locality will still be filled in.
    123   FillAddress(&address);
    124   EXPECT_EQ(expected, address);
    125 }
    126 
    127 TEST_F(AddressInputHelperTest, AddressWithPostalCodeMatchingLowerLevelLatin) {
    128   AddressData address;
    129   address.region_code = "TW";
    130   address.postal_code = "53012";
    131   address.language_code = "zh-Latn";
    132 
    133   /* This matches  - Ershuei Township. */
    134   AddressData expected = address;
    135   /* This locality is in  - Changhua County. */
    136   expected.locality = "Ershuei Township";
    137   expected.administrative_area = "Changhua County";
    138   FillAddress(&address);
    139   EXPECT_EQ(expected, address);
    140 
    141   // Override the admin area.
    142   address.administrative_area = "Already filled in";
    143   expected.administrative_area = "Already filled in";
    144   address.locality = "";
    145   // However, the locality will still be filled in.
    146   FillAddress(&address);
    147   EXPECT_EQ(expected, address);
    148 }
    149 
    150 TEST_F(AddressInputHelperTest, AddressWithPostalCodeMatchingDependentLocality) {
    151   AddressData address;
    152   address.region_code = "KR";
    153   // This matches Danwon-gu district.
    154   address.postal_code = "425-111";
    155 
    156   AddressData expected = address;
    157   /* The province is Gyeonggi - . */
    158   expected.administrative_area = "\xEA\xB2\xBD\xEA\xB8\xB0\xEB\x8F\x84";
    159   /* The city is Ansan-si - . */
    160   expected.locality = "\xEC\x95\x88\xEC\x82\xB0\xEC\x8B\x9C";
    161   /* The district is Danwon-gu -  */
    162   expected.dependent_locality = "\xEB\x8B\xA8\xEC\x9B\x90\xEA\xB5\xAC";
    163 
    164   FillAddress(&address);
    165   EXPECT_EQ(expected, address);
    166 
    167   AddressData address_ko_latn;
    168   address_ko_latn.region_code = "KR";
    169   address_ko_latn.postal_code = "425-111";
    170   address_ko_latn.language_code = "ko-latn";
    171 
    172   expected = address_ko_latn;
    173   /* The province is Gyeonggi - . */
    174   expected.administrative_area = "Gyeonggi";
    175   /* The city is Ansan-si - . */
    176   expected.locality = "Ansan-si";
    177   /* The district is Danwon-gu -  */
    178   expected.dependent_locality = "Danwon-gu";
    179 
    180   FillAddress(&address_ko_latn);
    181   EXPECT_EQ(expected, address_ko_latn);
    182 }
    183 
    184 TEST_F(AddressInputHelperTest, AddressWithPostalCodeMatchingMultipleValues) {
    185   AddressData address;
    186   address.region_code = "KR";
    187   // This matches Wando-gun and Ganjin-gun, both in Jeonnam province.
    188   address.postal_code = "527-111";
    189 
    190   AddressData expected = address;
    191   /* The province, Jeonnam -  - is known, but we have several locality
    192    * matches so none of them are populated. */
    193   expected.administrative_area =
    194       "\xEC\xA0\x84\xEB\x9D\xBC\xEB\x82\xA8\xEB\x8F\x84";
    195   FillAddress(&address);
    196   EXPECT_EQ(expected, address);
    197 }
    198 
    199 TEST_F(AddressInputHelperTest, AddressWithInvalidPostalCode) {
    200   AddressData address;
    201   address.postal_code = "970";
    202   address.region_code = "US";
    203 
    204   // We don't expect any changes, since the postal code couldn't be determined
    205   // as valid.
    206   AddressData expected = address;
    207   FillAddress(&address);
    208   EXPECT_EQ(expected, address);
    209 }
    210 
    211 TEST_F(AddressInputHelperTest, AddressWithNoPostalCodeValidation) {
    212   AddressData address;
    213   address.postal_code = "123";
    214   address.region_code = "GA";
    215 
    216   // We don't expect any changes, since the postal code couldn't be determined
    217   // as valid - we have no information about postal codes in Gabon (or even that
    218   // they are in use).
    219   AddressData expected = address;
    220   FillAddress(&address);
    221   EXPECT_EQ(expected, address);
    222 }
    223 
    224 TEST_F(AddressInputHelperTest, AddressWithInvalidOrMissingRegionCode) {
    225   AddressData address;
    226   address.postal_code = "XXX";
    227   address.administrative_area = "YYY";
    228 
    229   // We don't expect any changes, since there was no region code.
    230   AddressData expected = address;
    231   FillAddress(&address);
    232   EXPECT_EQ(expected, address);
    233 
    234   address.region_code = "XXXX";
    235   expected.region_code = "XXXX";
    236   // Again, nothing should change.
    237   FillAddress(&address);
    238   EXPECT_EQ(expected, address);
    239 }
    240 
    241 class AddressInputHelperMockDataTest : public testing::Test {
    242  protected:
    243   AddressInputHelperMockDataTest()
    244       : source_(new MockSource),
    245         // Our PreloadSupplier loads all data for a country at a time.
    246         supplier_(source_, new NullStorage),
    247         address_input_helper_(&supplier_),
    248         loaded_(BuildCallback(this, &AddressInputHelperMockDataTest::Loaded)) {}
    249 
    250   // Helper method to test FillAddress that ensures the PreloadSupplier has the
    251   // necessary data preloaded.
    252   void FillAddress(AddressData* address) {
    253     const std::string& region_code = address->region_code;
    254     if (!region_code.empty()) {
    255       supplier_.LoadRules(region_code, *loaded_);
    256     }
    257     address_input_helper_.FillAddress(address);
    258   }
    259 
    260   MockSource* const source_;
    261 
    262  private:
    263   // Our mock source we assume will always succeed.
    264   void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
    265 
    266   PreloadSupplier supplier_;
    267   const AddressInputHelper address_input_helper_;
    268   const scoped_ptr<const PreloadSupplier::Callback> loaded_;
    269   DISALLOW_COPY_AND_ASSIGN(AddressInputHelperMockDataTest);
    270 };
    271 
    272 TEST_F(AddressInputHelperMockDataTest,
    273        PostalCodeSharedAcrossDifferentHierarchies) {
    274   // Note that this data is in the format of data that would be returned from
    275   // the aggregate server.
    276   source_->data_.insert(std::make_pair(
    277       // We use KR since we need a country where we format all fields down to
    278       // dependent locality, or the hierarchy won't be loaded.
    279       "data/KR",
    280       "{\"data/KR\": "
    281       // The top-level ZIP expression must be present for sub-key matches to be
    282       // evaluated.
    283       "{\"id\":\"data/KR\", \"sub_keys\":\"A~B\", \"zip\":\"\\\\d{5}\"}, "
    284       "\"data/KR/A\": "
    285       "{\"id\":\"data/KR/A\", \"sub_keys\":\"A1\"}, "
    286       "\"data/KR/A/A1\": "
    287       "{\"id\":\"data/KR/A/A1\", \"zip\":\"1\"}, "
    288       "\"data/KR/B\": "
    289       "{\"id\":\"data/KR/B\", \"sub_keys\":\"B1\"}, "
    290       "\"data/KR/B/B1\": "
    291       "{\"id\":\"data/KR/B/B1\", \"zip\":\"12\"}}"));
    292 
    293   AddressData address;
    294   address.region_code = "KR";
    295   address.postal_code = "12345";
    296   address.administrative_area = "";
    297 
    298   AddressData expected = address;
    299   FillAddress(&address);
    300   // Nothing should have changed, since the ZIP code matches both of the cities,
    301   // and they aren't even in the same state.
    302   EXPECT_EQ(expected, address);
    303 }
    304 
    305 TEST_F(AddressInputHelperMockDataTest,
    306        PostalCodeSharedAcrossDifferentHierarchiesSameState) {
    307   // Create data where one state matches the ZIP code, but the other doesn't:
    308   // within the state which does, multiple cities and sub-cities match. The only
    309   // thing we can be certain of is therefore the state.
    310   source_->data_.insert(std::make_pair(
    311       // We use KR since we need a country where we format all fields down to
    312       // dependent locality, or the hierarchy won't be loaded.
    313       "data/KR",
    314       "{\"data/KR\": "
    315       // The top-level ZIP expression must be present for sub-key matches to be
    316       // evaluated.
    317       "{\"id\":\"data/KR\", \"sub_keys\":\"A~B\", \"zip\":\"\\\\d{5}\"}, "
    318       "\"data/KR/A\": "
    319       "{\"id\":\"data/KR/A\", \"sub_keys\":\"A1~A2\"}, "
    320       "\"data/KR/A/A1\": "
    321       "{\"id\":\"data/KR/A/A1\", \"sub_keys\":\"A1a\", \"zip\":\"1\"}, "
    322       // This key matches the ZIP code.
    323       "\"data/KR/A/A1/A1a\": "
    324       "{\"id\":\"data/KR/A/A1/A1a\", \"zip\":\"12\"}, "
    325       "\"data/KR/A/A2\": "
    326       "{\"id\":\"data/KR/A/A2\", \"sub_keys\":\"A2a\", \"zip\":\"1\"}, "
    327       // This key, also in state A, but in city A2, matches the ZIP code.
    328       "\"data/KR/A/A2/A2a\": "
    329       "{\"id\":\"data/KR/A/A2/A2a\", \"zip\":\"123\"}, "
    330       // This key, in state B, does not match the ZIP code.
    331       "\"data/KR/B\": "
    332       "{\"id\":\"data/KR/B\", \"zip\":\"2\"}}"));
    333 
    334   AddressData address;
    335   address.region_code = "KR";
    336   address.postal_code = "12345";
    337   address.administrative_area = "";
    338 
    339   AddressData expected = address;
    340   expected.administrative_area = "A";
    341   FillAddress(&address);
    342   // The ZIP code matches multiple city districts and cities; but only one
    343   // state, so we fill this in.
    344   EXPECT_EQ(expected, address);
    345 }
    346 
    347 }  // namespace
    348