1 // Copyright (C) 2014 Google Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include <libaddressinput/supplier.h>
17 #include <libaddressinput/address_data.h>
18 #include <libaddressinput/callback.h>
19 #include <libaddressinput/null_storage.h>
20 #include <libaddressinput/ondemand_supplier.h>
21 #include <libaddressinput/preload_supplier.h>
22 #include <libaddressinput/util/basictypes.h>
23 #include <libaddressinput/util/scoped_ptr.h>
29 #include <gtest/gtest.h>
31 #include "lookup_key.h"
33 #include "testdata_source.h"
37 // For compatibility with legacy compilers, that can't handle UTF-8 string
38 // literals in source code (please let them disappear from common use soon),
39 // Chinese strings required in the test code are here provided as string
40 // constants in hex escaped UTF-8 encoding.
43 const char kKowloon[] = "\xE4\xB9\x9D\xE9\xBE\x8D";
46 const char kXinJiang[] = "\xE6\x96\xB0\xE7\x96\x86";
49 const char kKashiDiqu[] = "\xE5\x96\x80\xE4\xBB\x80\xE5\x9C\xB0\xE5\x8C\xBA";
52 const char kKashiShi[] = "\xE5\x96\x80\xE4\xBB\x80\xE5\xB8\x82";
54 using i18n::addressinput::AddressData;
55 using i18n::addressinput::BuildCallback;
56 using i18n::addressinput::LookupKey;
57 using i18n::addressinput::NullStorage;
58 using i18n::addressinput::OndemandSupplier;
59 using i18n::addressinput::PreloadSupplier;
60 using i18n::addressinput::Rule;
61 using i18n::addressinput::scoped_ptr;
62 using i18n::addressinput::Supplier;
63 using i18n::addressinput::TestdataSource;
65 class SupplierWrapper {
67 virtual ~SupplierWrapper() {}
68 virtual void Supply(const LookupKey& lookup_key,
69 const Supplier::Callback& supplied) = 0;
72 class OndemandSupplierWrapper : public SupplierWrapper {
74 static SupplierWrapper* Build() { return new OndemandSupplierWrapper; }
76 virtual void Supply(const LookupKey& lookup_key,
77 const Supplier::Callback& supplied) {
78 ondemand_supplier_.Supply(lookup_key, supplied);
82 OndemandSupplierWrapper()
83 : ondemand_supplier_(new TestdataSource(false), new NullStorage) {}
85 OndemandSupplier ondemand_supplier_;
86 DISALLOW_COPY_AND_ASSIGN(OndemandSupplierWrapper);
89 class PreloadSupplierWrapper : public SupplierWrapper {
91 static SupplierWrapper* Build() { return new PreloadSupplierWrapper; }
93 virtual void Supply(const LookupKey& lookup_key,
94 const Supplier::Callback& supplied) {
95 const std::string& region_code = lookup_key.GetRegionCode();
96 if (!region_code.empty() && !preload_supplier_.IsLoaded(region_code)) {
97 preload_supplier_.LoadRules(region_code, *loaded_);
99 preload_supplier_.Supply(lookup_key, supplied);
103 PreloadSupplierWrapper()
104 : preload_supplier_(new TestdataSource(true), new NullStorage),
105 loaded_(BuildCallback(this, &PreloadSupplierWrapper::Loaded)) {}
107 void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
109 PreloadSupplier preload_supplier_;
110 const scoped_ptr<const PreloadSupplier::Callback> loaded_;
111 DISALLOW_COPY_AND_ASSIGN(PreloadSupplierWrapper);
114 class SupplierTest : public testing::TestWithParam<SupplierWrapper* (*)()> {
121 supplier_wrapper_((*GetParam())()),
122 supplied_(BuildCallback(this, &SupplierTest::Supplied)) {}
125 lookup_key_.FromAddress(address_);
126 supplier_wrapper_->Supply(lookup_key_, *supplied_);
129 AddressData address_;
130 const Rule* rule_[arraysize(LookupKey::kHierarchy)];
134 void Supplied(bool success,
135 const LookupKey& lookup_key,
136 const Supplier::RuleHierarchy& hierarchy) {
137 ASSERT_TRUE(success);
138 ASSERT_EQ(&lookup_key_, &lookup_key);
139 std::memcpy(rule_, hierarchy.rule, sizeof rule_);
143 LookupKey lookup_key_;
144 const scoped_ptr<SupplierWrapper> supplier_wrapper_;
145 const scoped_ptr<const Supplier::Callback> supplied_;
147 DISALLOW_COPY_AND_ASSIGN(SupplierTest);
150 INSTANTIATE_TEST_CASE_P(OndemandSupplier,
152 testing::Values(&OndemandSupplierWrapper::Build));
154 INSTANTIATE_TEST_CASE_P(PreloadSupplier,
156 testing::Values(&PreloadSupplierWrapper::Build));
158 TEST_P(SupplierTest, Invalid) {
159 address_.region_code = "QZ";
161 ASSERT_NO_FATAL_FAILURE(Supply());
162 ASSERT_TRUE(called_);
163 EXPECT_TRUE(rule_[0] == NULL);
164 EXPECT_TRUE(rule_[1] == NULL);
165 EXPECT_TRUE(rule_[2] == NULL);
166 EXPECT_TRUE(rule_[3] == NULL);
169 TEST_P(SupplierTest, Valid) {
170 address_.region_code = "SE";
172 ASSERT_NO_FATAL_FAILURE(Supply());
173 ASSERT_TRUE(called_);
174 EXPECT_TRUE(rule_[0] != NULL);
175 EXPECT_TRUE(rule_[1] == NULL);
176 EXPECT_TRUE(rule_[2] == NULL);
177 EXPECT_TRUE(rule_[3] == NULL);
178 EXPECT_EQ("data/SE", rule_[0]->GetId());
179 EXPECT_FALSE(rule_[0]->GetRequired().empty());
180 EXPECT_FALSE(rule_[0]->GetFormat().empty());
181 EXPECT_TRUE(rule_[0]->GetPostalCodeMatcher() != NULL);
184 TEST_P(SupplierTest, KeyDepthEqualsMaxDepth) {
185 address_.region_code = "HK";
186 address_.administrative_area = kKowloon;
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);
196 TEST_P(SupplierTest, KeyDepthLargerThanMaxDepth) {
197 address_.region_code = "HK";
198 address_.administrative_area = kKowloon;
199 address_.locality = "bbb"; // Ignored!
201 ASSERT_NO_FATAL_FAILURE(Supply());
202 ASSERT_TRUE(called_);
203 EXPECT_TRUE(rule_[0] != NULL);
204 EXPECT_TRUE(rule_[1] != NULL);
205 EXPECT_TRUE(rule_[2] == NULL);
206 EXPECT_TRUE(rule_[3] == NULL);
209 TEST_P(SupplierTest, KeyDepthSmallerThanMaxDepth) {
210 address_.region_code = "HK";
212 ASSERT_NO_FATAL_FAILURE(Supply());
213 ASSERT_TRUE(called_);
214 EXPECT_TRUE(rule_[0] != NULL);
215 EXPECT_TRUE(rule_[1] == NULL);
216 EXPECT_TRUE(rule_[2] == NULL);
217 EXPECT_TRUE(rule_[3] == NULL);
220 TEST_P(SupplierTest, KeyDepth0) {
221 address_.region_code = "CN";
223 ASSERT_NO_FATAL_FAILURE(Supply());
224 ASSERT_TRUE(called_);
225 EXPECT_TRUE(rule_[0] != NULL);
226 EXPECT_TRUE(rule_[1] == NULL);
227 EXPECT_TRUE(rule_[2] == NULL);
228 EXPECT_TRUE(rule_[3] == NULL);
231 TEST_P(SupplierTest, KeyDepth1) {
232 address_.region_code = "CN";
233 address_.administrative_area = kXinJiang;
235 ASSERT_NO_FATAL_FAILURE(Supply());
236 ASSERT_TRUE(called_);
237 EXPECT_TRUE(rule_[0] != NULL);
238 EXPECT_TRUE(rule_[1] != NULL);
239 EXPECT_TRUE(rule_[2] == NULL);
240 EXPECT_TRUE(rule_[3] == NULL);
243 TEST_P(SupplierTest, KeyDepth2) {
244 address_.region_code = "CN";
245 address_.administrative_area = kXinJiang;
246 address_.locality = kKashiDiqu;
248 ASSERT_NO_FATAL_FAILURE(Supply());
249 ASSERT_TRUE(called_);
250 EXPECT_TRUE(rule_[0] != NULL);
251 EXPECT_TRUE(rule_[1] != NULL);
252 EXPECT_TRUE(rule_[2] != NULL);
253 EXPECT_TRUE(rule_[3] == NULL);
256 TEST_P(SupplierTest, KeyDepth3) {
257 address_.region_code = "CN";
258 address_.administrative_area = kXinJiang;
259 address_.locality = kKashiDiqu;
260 address_.dependent_locality = kKashiShi;
262 ASSERT_NO_FATAL_FAILURE(Supply());
263 ASSERT_TRUE(called_);
264 EXPECT_TRUE(rule_[0] != NULL);
265 EXPECT_TRUE(rule_[1] != NULL);
266 EXPECT_TRUE(rule_[2] != NULL);
267 EXPECT_TRUE(rule_[3] != NULL);
270 TEST_P(SupplierTest, RuleCache) {
271 address_.region_code = "US";
272 address_.administrative_area = "CA";
274 ASSERT_NO_FATAL_FAILURE(Supply());
275 ASSERT_TRUE(called_);
276 EXPECT_TRUE(rule_[0] != NULL);
277 EXPECT_TRUE(rule_[1] != NULL);
278 EXPECT_TRUE(rule_[2] == NULL);
279 EXPECT_TRUE(rule_[3] == NULL);
281 // Make a copy of the currently returned pointers to the Rule objects (stored
282 // in the OndemandSupplier cache) and verify that calling Supply() again with
283 // the same LookupKey returns the same pointers again (and doesn't create any
284 // new Rule objects instead).
286 const Rule* rule[arraysize(LookupKey::kHierarchy)];
287 std::memcpy(rule, rule_, sizeof rule);
290 ASSERT_NO_FATAL_FAILURE(Supply());
291 ASSERT_TRUE(called_);
292 EXPECT_EQ(rule[0], rule_[0]);
293 EXPECT_EQ(rule[1], rule_[1]);
294 EXPECT_EQ(rule[2], rule_[2]);
295 EXPECT_EQ(rule[3], rule_[3]);