Home | History | Annotate | Download | only in test
      1 // Copyright (C) 2014 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/supplier.h>
     16 
     17 #include <libaddressinput/address_data.h>
     18 #include <libaddressinput/callback.h>
     19 #include <libaddressinput/downloader.h>
     20 #include <libaddressinput/null_storage.h>
     21 #include <libaddressinput/ondemand_supplier.h>
     22 #include <libaddressinput/preload_supplier.h>
     23 #include <libaddressinput/storage.h>
     24 #include <libaddressinput/util/basictypes.h>
     25 #include <libaddressinput/util/scoped_ptr.h>
     26 
     27 #include <cstddef>
     28 #include <cstring>
     29 #include <string>
     30 
     31 #include <gtest/gtest.h>
     32 
     33 #include "fake_downloader.h"
     34 #include "lookup_key.h"
     35 #include "rule.h"
     36 
     37 namespace {
     38 
     39 // For compatibility with legacy compilers, that can't handle UTF-8 string
     40 // literals in source code (please let them disappear from common use soon),
     41 // Chinese strings required in the test code are here provided as string
     42 // constants in hex escaped UTF-8 encoding.
     43 
     44 /* "" */
     45 const char kKowloon[] = "\xE4\xB9\x9D\xE9\xBE\x8D";
     46 
     47 /* "" */
     48 const char kXinJiang[] = "\xE6\x96\xB0\xE7\x96\x86";
     49 
     50 /* "" */
     51 const char kKashiDiqu[] = "\xE5\x96\x80\xE4\xBB\x80\xE5\x9C\xB0\xE5\x8C\xBA";
     52 
     53 /* "" */
     54 const char kKashiShi[] = "\xE5\x96\x80\xE4\xBB\x80\xE5\xB8\x82";
     55 
     56 using i18n::addressinput::AddressData;
     57 using i18n::addressinput::BuildCallback;
     58 using i18n::addressinput::Downloader;
     59 using i18n::addressinput::FakeDownloader;
     60 using i18n::addressinput::LookupKey;
     61 using i18n::addressinput::NullStorage;
     62 using i18n::addressinput::OndemandSupplier;
     63 using i18n::addressinput::PreloadSupplier;
     64 using i18n::addressinput::Rule;
     65 using i18n::addressinput::scoped_ptr;
     66 using i18n::addressinput::Storage;
     67 using i18n::addressinput::Supplier;
     68 
     69 class SupplierWrapper {
     70  public:
     71   virtual ~SupplierWrapper() {}
     72   virtual void Supply(const LookupKey& lookup_key,
     73                       const Supplier::Callback& supplied) = 0;
     74 };
     75 
     76 class OndemandSupplierWrapper : public SupplierWrapper {
     77  public:
     78   static SupplierWrapper* Build() { return new OndemandSupplierWrapper; }
     79 
     80   virtual ~OndemandSupplierWrapper() {}
     81 
     82   virtual void Supply(const LookupKey& lookup_key,
     83                       const Supplier::Callback& supplied) {
     84     ondemand_supplier_.Supply(lookup_key, supplied);
     85   }
     86 
     87  private:
     88   OndemandSupplierWrapper()
     89       : ondemand_supplier_(FakeDownloader::kFakeDataUrl,
     90                            new FakeDownloader,
     91                            new NullStorage) {}
     92 
     93   OndemandSupplier ondemand_supplier_;
     94   DISALLOW_COPY_AND_ASSIGN(OndemandSupplierWrapper);
     95 };
     96 
     97 class PreloadSupplierWrapper : public SupplierWrapper {
     98  public:
     99   static SupplierWrapper* Build() { return new PreloadSupplierWrapper; }
    100 
    101   virtual ~PreloadSupplierWrapper() {}
    102 
    103   virtual void Supply(const LookupKey& lookup_key,
    104                       const Supplier::Callback& supplied) {
    105     const std::string& region_code = lookup_key.GetRegionCode();
    106     if (!region_code.empty() && !preload_supplier_.IsLoaded(region_code)) {
    107       preload_supplier_.LoadRules(region_code, *loaded_);
    108     }
    109     preload_supplier_.Supply(lookup_key, supplied);
    110   }
    111 
    112  private:
    113   PreloadSupplierWrapper()
    114       : preload_supplier_(FakeDownloader::kFakeAggregateDataUrl,
    115                           new FakeDownloader,
    116                           new NullStorage),
    117         loaded_(BuildCallback(this, &PreloadSupplierWrapper::Loaded)) {}
    118 
    119   void Loaded(bool success, const std::string&, int) {
    120     ASSERT_TRUE(success);
    121   }
    122 
    123   PreloadSupplier preload_supplier_;
    124   const scoped_ptr<const PreloadSupplier::Callback> loaded_;
    125   DISALLOW_COPY_AND_ASSIGN(PreloadSupplierWrapper);
    126 };
    127 
    128 class SupplierTest : public testing::TestWithParam<SupplierWrapper* (*)()> {
    129  protected:
    130   SupplierTest()
    131       : address_(),
    132         rule_(),
    133         called_(false),
    134         lookup_key_(),
    135         supplier_wrapper_((*GetParam())()),
    136         supplied_(BuildCallback(this, &SupplierTest::Supplied)) {}
    137 
    138   virtual ~SupplierTest() {}
    139 
    140   void Supply() {
    141     lookup_key_.FromAddress(address_);
    142     supplier_wrapper_->Supply(lookup_key_, *supplied_);
    143   }
    144 
    145   AddressData address_;
    146   const Rule* rule_[arraysize(LookupKey::kHierarchy)];
    147   bool called_;
    148 
    149  private:
    150   void Supplied(bool success,
    151                 const LookupKey& lookup_key,
    152                 const Supplier::RuleHierarchy& hierarchy) {
    153     ASSERT_TRUE(success);
    154     ASSERT_EQ(&lookup_key_, &lookup_key);
    155     std::memcpy(rule_, hierarchy.rule, sizeof rule_);
    156     called_ = true;
    157   }
    158 
    159   LookupKey lookup_key_;
    160   const scoped_ptr<SupplierWrapper> supplier_wrapper_;
    161   const scoped_ptr<const Supplier::Callback> supplied_;
    162 
    163   DISALLOW_COPY_AND_ASSIGN(SupplierTest);
    164 };
    165 
    166 INSTANTIATE_TEST_CASE_P(OndemandSupplier,
    167                         SupplierTest,
    168                         testing::Values(&OndemandSupplierWrapper::Build));
    169 
    170 INSTANTIATE_TEST_CASE_P(PreloadSupplier,
    171                         SupplierTest,
    172                         testing::Values(&PreloadSupplierWrapper::Build));
    173 
    174 TEST_P(SupplierTest, Invalid) {
    175   address_.region_code = "QZ";
    176 
    177   ASSERT_NO_FATAL_FAILURE(Supply());
    178   ASSERT_TRUE(called_);
    179   EXPECT_TRUE(rule_[0] == NULL);
    180   EXPECT_TRUE(rule_[1] == NULL);
    181   EXPECT_TRUE(rule_[2] == NULL);
    182   EXPECT_TRUE(rule_[3] == NULL);
    183 }
    184 
    185 TEST_P(SupplierTest, Valid) {
    186   address_.region_code = "SE";
    187 
    188   ASSERT_NO_FATAL_FAILURE(Supply());
    189   ASSERT_TRUE(called_);
    190   EXPECT_TRUE(rule_[0] != NULL);
    191   EXPECT_TRUE(rule_[1] == NULL);
    192   EXPECT_TRUE(rule_[2] == NULL);
    193   EXPECT_TRUE(rule_[3] == NULL);
    194   EXPECT_EQ("data/SE", rule_[0]->GetId());
    195   EXPECT_FALSE(rule_[0]->GetRequired().empty());
    196   EXPECT_FALSE(rule_[0]->GetFormat().empty());
    197   EXPECT_TRUE(rule_[0]->GetPostalCodeMatcher() != NULL);
    198 }
    199 
    200 TEST_P(SupplierTest, KeyDepthEqualsMaxDepth) {
    201   address_.region_code = "HK";
    202   address_.administrative_area = kKowloon;
    203 
    204   ASSERT_NO_FATAL_FAILURE(Supply());
    205   ASSERT_TRUE(called_);
    206   EXPECT_TRUE(rule_[0] != NULL);
    207   EXPECT_TRUE(rule_[1] != NULL);
    208   EXPECT_TRUE(rule_[2] == NULL);
    209   EXPECT_TRUE(rule_[3] == NULL);
    210 }
    211 
    212 TEST_P(SupplierTest, KeyDepthLargerThanMaxDepth) {
    213   address_.region_code = "HK";
    214   address_.administrative_area = kKowloon;
    215   address_.locality = "bbb";  // Ignored!
    216 
    217   ASSERT_NO_FATAL_FAILURE(Supply());
    218   ASSERT_TRUE(called_);
    219   EXPECT_TRUE(rule_[0] != NULL);
    220   EXPECT_TRUE(rule_[1] != NULL);
    221   EXPECT_TRUE(rule_[2] == NULL);
    222   EXPECT_TRUE(rule_[3] == NULL);
    223 }
    224 
    225 TEST_P(SupplierTest, KeyDepthSmallerThanMaxDepth) {
    226   address_.region_code = "HK";
    227 
    228   ASSERT_NO_FATAL_FAILURE(Supply());
    229   ASSERT_TRUE(called_);
    230   EXPECT_TRUE(rule_[0] != NULL);
    231   EXPECT_TRUE(rule_[1] == NULL);
    232   EXPECT_TRUE(rule_[2] == NULL);
    233   EXPECT_TRUE(rule_[3] == NULL);
    234 }
    235 
    236 TEST_P(SupplierTest, KeyDepth0) {
    237   address_.region_code = "CN";
    238 
    239   ASSERT_NO_FATAL_FAILURE(Supply());
    240   ASSERT_TRUE(called_);
    241   EXPECT_TRUE(rule_[0] != NULL);
    242   EXPECT_TRUE(rule_[1] == NULL);
    243   EXPECT_TRUE(rule_[2] == NULL);
    244   EXPECT_TRUE(rule_[3] == NULL);
    245 }
    246 
    247 TEST_P(SupplierTest, KeyDepth1) {
    248   address_.region_code = "CN";
    249   address_.administrative_area = kXinJiang;
    250 
    251   ASSERT_NO_FATAL_FAILURE(Supply());
    252   ASSERT_TRUE(called_);
    253   EXPECT_TRUE(rule_[0] != NULL);
    254   EXPECT_TRUE(rule_[1] != NULL);
    255   EXPECT_TRUE(rule_[2] == NULL);
    256   EXPECT_TRUE(rule_[3] == NULL);
    257 }
    258 
    259 TEST_P(SupplierTest, KeyDepth2) {
    260   address_.region_code = "CN";
    261   address_.administrative_area = kXinJiang;
    262   address_.locality = kKashiDiqu;
    263 
    264   ASSERT_NO_FATAL_FAILURE(Supply());
    265   ASSERT_TRUE(called_);
    266   EXPECT_TRUE(rule_[0] != NULL);
    267   EXPECT_TRUE(rule_[1] != NULL);
    268   EXPECT_TRUE(rule_[2] != NULL);
    269   EXPECT_TRUE(rule_[3] == NULL);
    270 }
    271 
    272 TEST_P(SupplierTest, KeyDepth3) {
    273   address_.region_code = "CN";
    274   address_.administrative_area = kXinJiang;
    275   address_.locality = kKashiDiqu;
    276   address_.dependent_locality = kKashiShi;
    277 
    278   ASSERT_NO_FATAL_FAILURE(Supply());
    279   ASSERT_TRUE(called_);
    280   EXPECT_TRUE(rule_[0] != NULL);
    281   EXPECT_TRUE(rule_[1] != NULL);
    282   EXPECT_TRUE(rule_[2] != NULL);
    283   EXPECT_TRUE(rule_[3] != NULL);
    284 }
    285 
    286 TEST_P(SupplierTest, RuleCache) {
    287   address_.region_code = "US";
    288   address_.administrative_area = "CA";
    289 
    290   ASSERT_NO_FATAL_FAILURE(Supply());
    291   ASSERT_TRUE(called_);
    292   EXPECT_TRUE(rule_[0] != NULL);
    293   EXPECT_TRUE(rule_[1] != NULL);
    294   EXPECT_TRUE(rule_[2] == NULL);
    295   EXPECT_TRUE(rule_[3] == NULL);
    296 
    297   // Make a copy of the currently returned pointers to the Rule objects (stored
    298   // in the OndemandSupplier cache) and verify that calling Supply() again with
    299   // the same LookupKey returns the same pointers again (and doesn't create any
    300   // new Rule objects instead).
    301 
    302   const Rule* rule[arraysize(LookupKey::kHierarchy)];
    303   std::memcpy(rule, rule_, sizeof rule);
    304 
    305   called_ = false;
    306   ASSERT_NO_FATAL_FAILURE(Supply());
    307   ASSERT_TRUE(called_);
    308   EXPECT_EQ(rule[0], rule_[0]);
    309   EXPECT_EQ(rule[1], rule_[1]);
    310   EXPECT_EQ(rule[2], rule_[2]);
    311   EXPECT_EQ(rule[3], rule_[3]);
    312 }
    313 
    314 }  // namespace
    315