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/address_validator.h>
16
17#include <libaddressinput/address_data.h>
18#include <libaddressinput/address_field.h>
19#include <libaddressinput/address_problem.h>
20#include <libaddressinput/callback.h>
21#include <libaddressinput/null_storage.h>
22#include <libaddressinput/ondemand_supplier.h>
23#include <libaddressinput/preload_supplier.h>
24#include <libaddressinput/util/basictypes.h>
25#include <libaddressinput/util/scoped_ptr.h>
26
27#include <string>
28#include <utility>
29
30#include <gtest/gtest.h>
31
32#include "testdata_source.h"
33
34namespace {
35
36using i18n::addressinput::AddressData;
37using i18n::addressinput::AddressValidator;
38using i18n::addressinput::BuildCallback;
39using i18n::addressinput::FieldProblemMap;
40using i18n::addressinput::NullStorage;
41using i18n::addressinput::OndemandSupplier;
42using i18n::addressinput::PreloadSupplier;
43using i18n::addressinput::scoped_ptr;
44using i18n::addressinput::TestdataSource;
45
46using i18n::addressinput::COUNTRY;
47using i18n::addressinput::ADMIN_AREA;
48using i18n::addressinput::LOCALITY;
49using i18n::addressinput::POSTAL_CODE;
50using i18n::addressinput::STREET_ADDRESS;
51
52using i18n::addressinput::UNEXPECTED_FIELD;
53using i18n::addressinput::MISSING_REQUIRED_FIELD;
54using i18n::addressinput::UNKNOWN_VALUE;
55using i18n::addressinput::INVALID_FORMAT;
56using i18n::addressinput::MISMATCHING_VALUE;
57
58class ValidatorWrapper {
59 public:
60  virtual ~ValidatorWrapper() {}
61  virtual void Validate(const AddressData& address,
62                        bool allow_postal,
63                        bool require_name,
64                        const FieldProblemMap* filter,
65                        FieldProblemMap* problems,
66                        const AddressValidator::Callback& validated) = 0;
67};
68
69class OndemandValidatorWrapper : public ValidatorWrapper {
70 public:
71  static ValidatorWrapper* Build() { return new OndemandValidatorWrapper; }
72
73  virtual void Validate(const AddressData& address,
74                        bool allow_postal,
75                        bool require_name,
76                        const FieldProblemMap* filter,
77                        FieldProblemMap* problems,
78                        const AddressValidator::Callback& validated) {
79    validator_.Validate(
80        address,
81        allow_postal,
82        require_name,
83        filter,
84        problems,
85        validated);
86  }
87
88 private:
89  OndemandValidatorWrapper()
90      : supplier_(new TestdataSource(false), new NullStorage),
91        validator_(&supplier_) {}
92
93  OndemandSupplier supplier_;
94  const AddressValidator validator_;
95  DISALLOW_COPY_AND_ASSIGN(OndemandValidatorWrapper);
96};
97
98class PreloadValidatorWrapper : public ValidatorWrapper {
99 public:
100  static ValidatorWrapper* Build() { return new PreloadValidatorWrapper; }
101
102  virtual void Validate(const AddressData& address,
103                        bool allow_postal,
104                        bool require_name,
105                        const FieldProblemMap* filter,
106                        FieldProblemMap* problems,
107                        const AddressValidator::Callback& validated) {
108    const std::string& region_code = address.region_code;
109    if (!region_code.empty() && !supplier_.IsLoaded(region_code)) {
110      supplier_.LoadRules(region_code, *loaded_);
111    }
112    validator_.Validate(
113        address,
114        allow_postal,
115        require_name,
116        filter,
117        problems,
118        validated);
119  }
120
121 private:
122  PreloadValidatorWrapper()
123      : supplier_(new TestdataSource(true), new NullStorage),
124        validator_(&supplier_),
125        loaded_(BuildCallback(this, &PreloadValidatorWrapper::Loaded)) {}
126
127  void Loaded(bool success, const std::string&, int) { ASSERT_TRUE(success); }
128
129  PreloadSupplier supplier_;
130  const AddressValidator validator_;
131  const scoped_ptr<const PreloadSupplier::Callback> loaded_;
132  DISALLOW_COPY_AND_ASSIGN(PreloadValidatorWrapper);
133};
134
135class AddressValidatorTest
136    : public testing::TestWithParam<ValidatorWrapper* (*)()> {
137 protected:
138  AddressValidatorTest()
139      : address_(),
140        allow_postal_(false),
141        require_name_(false),
142        filter_(),
143        problems_(),
144        expected_(),
145        called_(false),
146        validator_wrapper_((*GetParam())()),
147        validated_(BuildCallback(this, &AddressValidatorTest::Validated)) {}
148
149  void Validate() {
150    validator_wrapper_->Validate(
151        address_,
152        allow_postal_,
153        require_name_,
154        &filter_,
155        &problems_,
156        *validated_);
157  }
158
159  AddressData address_;
160  bool allow_postal_;
161  bool require_name_;
162  FieldProblemMap filter_;
163  FieldProblemMap problems_;
164  FieldProblemMap expected_;
165  bool called_;
166
167 private:
168  void Validated(bool success,
169                 const AddressData& address,
170                 const FieldProblemMap& problems) {
171    ASSERT_TRUE(success);
172    ASSERT_EQ(&address_, &address);
173    ASSERT_EQ(&problems_, &problems);
174    called_ = true;
175  }
176
177  const scoped_ptr<ValidatorWrapper> validator_wrapper_;
178  const scoped_ptr<const AddressValidator::Callback> validated_;
179
180  DISALLOW_COPY_AND_ASSIGN(AddressValidatorTest);
181};
182
183INSTANTIATE_TEST_CASE_P(OndemandSupplier,
184                        AddressValidatorTest,
185                        testing::Values(&OndemandValidatorWrapper::Build));
186
187INSTANTIATE_TEST_CASE_P(PreloadSupplier,
188                        AddressValidatorTest,
189                        testing::Values(&PreloadValidatorWrapper::Build));
190
191TEST_P(AddressValidatorTest, EmptyAddress) {
192  expected_.insert(std::make_pair(COUNTRY, MISSING_REQUIRED_FIELD));
193
194  ASSERT_NO_FATAL_FAILURE(Validate());
195  ASSERT_TRUE(called_);
196  EXPECT_EQ(expected_, problems_);
197}
198
199TEST_P(AddressValidatorTest, InvalidCountry) {
200  address_.region_code = "QZ";
201
202  expected_.insert(std::make_pair(COUNTRY, UNKNOWN_VALUE));
203
204  ASSERT_NO_FATAL_FAILURE(Validate());
205  ASSERT_TRUE(called_);
206  EXPECT_EQ(expected_, problems_);
207}
208
209TEST_P(AddressValidatorTest, ValidAddressUS) {
210  address_.region_code = "US";
211  address_.administrative_area = "CA";  // California
212  address_.locality = "Mountain View";
213  address_.postal_code = "94043";
214  address_.address_line.push_back("1600 Amphitheatre Parkway");
215  address_.language_code = "en";
216
217  ASSERT_NO_FATAL_FAILURE(Validate());
218  ASSERT_TRUE(called_);
219  EXPECT_EQ(expected_, problems_);
220}
221
222TEST_P(AddressValidatorTest, InvalidAddressUS) {
223  address_.region_code = "US";
224  address_.postal_code = "123";
225
226  expected_.insert(std::make_pair(ADMIN_AREA, MISSING_REQUIRED_FIELD));
227  expected_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
228  expected_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
229  expected_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
230
231  ASSERT_NO_FATAL_FAILURE(Validate());
232  ASSERT_TRUE(called_);
233  EXPECT_EQ(expected_, problems_);
234}
235
236TEST_P(AddressValidatorTest, ValidAddressCH) {
237  address_.region_code = "CH";
238  address_.locality = "ZH";  /* Zürich */
239  address_.postal_code = "8002";
240  address_.address_line.push_back("Brandschenkestrasse 110");
241  address_.language_code = "de";
242
243  ASSERT_NO_FATAL_FAILURE(Validate());
244  ASSERT_TRUE(called_);
245  EXPECT_EQ(expected_, problems_);
246}
247
248TEST_P(AddressValidatorTest, InvalidAddressCH) {
249  address_.region_code = "CH";
250  address_.postal_code = "123";
251
252  expected_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
253  expected_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
254  expected_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
255
256  ASSERT_NO_FATAL_FAILURE(Validate());
257  ASSERT_TRUE(called_);
258  EXPECT_EQ(expected_, problems_);
259}
260
261TEST_P(AddressValidatorTest, ValidPostalCodeMX) {
262  address_.region_code = "MX";
263  address_.locality = "Villahermosa";
264  address_.administrative_area = "TAB";  // Tabasco
265  address_.postal_code = "86070";
266  address_.address_line.push_back(
267      /* Av Gregorio Méndez Magaña 1400 */
268      "Av Gregorio M\xC3\xA9ndez Maga\xC3\xB1""a 1400");
269  address_.language_code = "es";
270
271  ASSERT_NO_FATAL_FAILURE(Validate());
272  ASSERT_TRUE(called_);
273  EXPECT_EQ(expected_, problems_);
274}
275
276TEST_P(AddressValidatorTest, MismatchingPostalCodeMX) {
277  address_.region_code = "MX";
278  address_.locality = "Villahermosa";
279  address_.administrative_area = "TAB";  // Tabasco
280  address_.postal_code = "80000";
281  address_.address_line.push_back(
282      /* Av Gregorio Méndez Magaña 1400 */
283      "Av Gregorio M\xC3\xA9ndez Maga\xC3\xB1""a 1400");
284  address_.language_code = "es";
285
286  expected_.insert(std::make_pair(POSTAL_CODE, MISMATCHING_VALUE));
287
288  ASSERT_NO_FATAL_FAILURE(Validate());
289  ASSERT_TRUE(called_);
290  EXPECT_EQ(expected_, problems_);
291}
292
293TEST_P(AddressValidatorTest, ValidateFilter) {
294  address_.region_code = "CH";
295  address_.postal_code = "123";
296
297  filter_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
298
299  expected_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
300
301  ASSERT_NO_FATAL_FAILURE(Validate());
302  ASSERT_TRUE(called_);
303  EXPECT_EQ(expected_, problems_);
304}
305
306TEST_P(AddressValidatorTest, ValidateClearsProblems) {
307  address_.region_code = "CH";
308  address_.locality = "ZH";  /* Zürich */
309  address_.postal_code = "123";
310  address_.address_line.push_back("Brandschenkestrasse 110");
311  address_.language_code = "de";
312
313  problems_.insert(std::make_pair(LOCALITY, UNEXPECTED_FIELD));
314  problems_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
315  problems_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
316
317  expected_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
318
319  ASSERT_NO_FATAL_FAILURE(Validate());
320  ASSERT_TRUE(called_);
321  EXPECT_EQ(expected_, problems_);
322}
323
324TEST_P(AddressValidatorTest, ValidKanjiAddressJP) {
325  address_.region_code = "JP";
326  address_.administrative_area =
327      "\xE5\xBE\xB3\xE5\xB3\xB6\xE7\x9C\x8C"; /* 徳島県 */
328  address_.locality =
329      "\xE5\xBE\xB3\xE5\xB3\xB6\xE5\xB8\x82";  /* 徳島市 */
330  address_.postal_code = "770-0847";
331  address_.address_line.push_back("...");
332  address_.language_code = "ja";
333
334  ASSERT_NO_FATAL_FAILURE(Validate());
335  ASSERT_TRUE(called_);
336  EXPECT_EQ(expected_, problems_);
337}
338
339TEST_P(AddressValidatorTest, ValidLatinAddressJP) {
340  // Skip this test case when using the OndemandSupplier, which depends on the
341  // address metadata server to map Latin script names to local script names.
342  if (GetParam() == &OndemandValidatorWrapper::Build) return;
343
344  address_.region_code = "JP";
345  address_.administrative_area = "Tokushima";
346  address_.locality = "Tokushima";
347  address_.postal_code = "770-0847";
348  address_.address_line.push_back("...");
349  address_.language_code = "ja-Latn";
350
351  ASSERT_NO_FATAL_FAILURE(Validate());
352  ASSERT_TRUE(called_);
353  EXPECT_EQ(expected_, problems_);
354}
355
356TEST_P(AddressValidatorTest, ValidAddressBR) {
357  // Skip this test case when using the OndemandSupplier, which depends on the
358  // address metadata server to map natural language names to metadata IDs.
359  if (GetParam() == &OndemandValidatorWrapper::Build) return;
360
361  address_.region_code = "BR";
362  address_.administrative_area = "S\xC3\xA3o Paulo";  /* São Paulo */
363  address_.locality = "Presidente Prudente";
364  address_.postal_code = "19063-008";
365  address_.address_line.push_back("Rodovia Raposo Tavares, 6388-6682");
366  address_.language_code = "pt";
367
368  ASSERT_NO_FATAL_FAILURE(Validate());
369  ASSERT_TRUE(called_);
370  EXPECT_EQ(expected_, problems_);
371}
372
373TEST_P(AddressValidatorTest, ValidAddressCA_en) {
374  // Skip this test case when using the OndemandSupplier, which depends on the
375  // address metadata server to map natural language names to metadata IDs.
376  if (GetParam() == &OndemandValidatorWrapper::Build) return;
377
378  address_.region_code = "CA";
379  address_.administrative_area = "New Brunswick";
380  address_.locality = "Saint John County";
381  address_.postal_code = "E2L 4Z6";
382  address_.address_line.push_back("...");
383  address_.language_code = "en";
384
385  ASSERT_NO_FATAL_FAILURE(Validate());
386  ASSERT_TRUE(called_);
387  EXPECT_EQ(expected_, problems_);
388}
389
390TEST_P(AddressValidatorTest, ValidAddressCA_fr) {
391  // Skip this test case when using the OndemandSupplier, which depends on the
392  // address metadata server to map natural language names to metadata IDs.
393  if (GetParam() == &OndemandValidatorWrapper::Build) return;
394
395  address_.region_code = "CA";
396  address_.administrative_area = "Nouveau-Brunswick";
397  address_.locality = "Comt\xC3\xA9 de Saint-Jean";  /* Comté de Saint-Jean */
398  address_.postal_code = "E2L 4Z6";
399  address_.address_line.push_back("...");
400  address_.language_code = "fr";
401
402  ASSERT_NO_FATAL_FAILURE(Validate());
403  ASSERT_TRUE(called_);
404  EXPECT_EQ(expected_, problems_);
405}
406
407}  // namespace
408