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 "validation_task.h"
16
17#include <libaddressinput/address_data.h>
18#include <libaddressinput/address_field.h>
19#include <libaddressinput/address_problem.h>
20#include <libaddressinput/address_validator.h>
21#include <libaddressinput/callback.h>
22#include <libaddressinput/supplier.h>
23#include <libaddressinput/util/basictypes.h>
24#include <libaddressinput/util/scoped_ptr.h>
25
26#include <cstddef>
27#include <utility>
28
29#include <gtest/gtest.h>
30
31#include "lookup_key.h"
32#include "rule.h"
33
34namespace i18n {
35namespace addressinput {
36
37class ValidationTaskTest : public testing::Test {
38 protected:
39  ValidationTaskTest()
40      : json_(),
41        success_(true),
42        address_(),
43        allow_postal_(false),
44        require_name_(false),
45        filter_(),
46        problems_(),
47        expected_(),
48        called_(false),
49        validated_(BuildCallback(this, &ValidationTaskTest::Validated)) {
50    // Add all problems to the filter except those affected by the metadata
51    // in region_data_constants.cc.
52    static const AddressField kFields[] = {
53      COUNTRY,
54      ADMIN_AREA,
55      LOCALITY,
56      DEPENDENT_LOCALITY,
57      SORTING_CODE,
58      POSTAL_CODE,
59      STREET_ADDRESS,
60      ORGANIZATION,
61      RECIPIENT
62    };
63
64    static const AddressProblem kProblems[] = {
65      // UNEXPECTED_FIELD is validated using IsFieldUsed().
66      // MISSING_REQUIRED_FIELD is validated using IsFieldRequired().
67      UNKNOWN_VALUE,
68      INVALID_FORMAT,
69      MISMATCHING_VALUE,
70      USES_P_O_BOX
71    };
72
73    for (size_t i = 0; i < arraysize(kFields); ++i) {
74      AddressField field = kFields[i];
75      for (size_t j = 0; j < arraysize(kProblems); ++j) {
76        AddressProblem problem = kProblems[j];
77        filter_.insert(std::make_pair(field, problem));
78      }
79    }
80
81    filter_.insert(std::make_pair(COUNTRY, UNEXPECTED_FIELD));
82    filter_.insert(std::make_pair(COUNTRY, MISSING_REQUIRED_FIELD));
83    filter_.insert(std::make_pair(RECIPIENT, UNEXPECTED_FIELD));
84    filter_.insert(std::make_pair(RECIPIENT, MISSING_REQUIRED_FIELD));
85  }
86
87  void Validate() {
88    Rule rule[arraysize(json_)];
89
90    ValidationTask* task = new ValidationTask(
91        address_,
92        allow_postal_,
93        require_name_,
94        &filter_,
95        &problems_,
96        *validated_);
97
98    Supplier::RuleHierarchy hierarchy;
99
100    for (size_t i = 0; i < arraysize(json_) && json_[i] != NULL; ++i) {
101      ASSERT_TRUE(rule[i].ParseSerializedRule(json_[i]));
102      hierarchy.rule[i] = &rule[i];
103    }
104
105    (*task->supplied_)(success_, *task->lookup_key_, hierarchy);
106  }
107
108  const char* json_[arraysize(LookupKey::kHierarchy)];
109  bool success_;
110  AddressData address_;
111  bool allow_postal_;
112  bool require_name_;
113  FieldProblemMap filter_;
114  FieldProblemMap problems_;
115  FieldProblemMap expected_;
116  bool called_;
117
118 private:
119  void Validated(bool success,
120                 const AddressData& address,
121                 const FieldProblemMap& problems) {
122    ASSERT_EQ(success_, success);
123    ASSERT_EQ(&address_, &address);
124    ASSERT_EQ(&problems_, &problems);
125    called_ = true;
126  }
127
128  const scoped_ptr<const AddressValidator::Callback> validated_;
129
130  DISALLOW_COPY_AND_ASSIGN(ValidationTaskTest);
131};
132
133namespace {
134
135TEST_F(ValidationTaskTest, FailureCountryRuleNull) {
136  success_ = false;
137
138  ASSERT_NO_FATAL_FAILURE(Validate());
139  ASSERT_TRUE(called_);
140  EXPECT_EQ(expected_, problems_);
141}
142
143TEST_F(ValidationTaskTest, FailureCountryRuleEmpty) {
144  json_[0] = "{}";
145  success_ = false;
146
147  ASSERT_NO_FATAL_FAILURE(Validate());
148  ASSERT_TRUE(called_);
149  EXPECT_EQ(expected_, problems_);
150}
151
152TEST_F(ValidationTaskTest, SuccessCountryRuleNullNameEmpty) {
153  expected_.insert(std::make_pair(COUNTRY, MISSING_REQUIRED_FIELD));
154
155  ASSERT_NO_FATAL_FAILURE(Validate());
156  ASSERT_TRUE(called_);
157  EXPECT_EQ(expected_, problems_);
158}
159
160TEST_F(ValidationTaskTest, SuccessCountryRuleNullNameNotEmpty) {
161  address_.region_code = "rrr";
162
163  expected_.insert(std::make_pair(COUNTRY, UNKNOWN_VALUE));
164
165  ASSERT_NO_FATAL_FAILURE(Validate());
166  ASSERT_TRUE(called_);
167  EXPECT_EQ(expected_, problems_);
168}
169
170TEST_F(ValidationTaskTest, SuccessCountryRuleEmptyNameEmpty) {
171  json_[0] = "{}";
172
173  expected_.insert(std::make_pair(COUNTRY, MISSING_REQUIRED_FIELD));
174
175  ASSERT_NO_FATAL_FAILURE(Validate());
176  ASSERT_TRUE(called_);
177  EXPECT_EQ(expected_, problems_);
178}
179
180TEST_F(ValidationTaskTest, SuccessCountryRuleEmptyNameNotEmpty) {
181  json_[0] = "{}";
182
183  address_.region_code = "rrr";
184
185  ASSERT_NO_FATAL_FAILURE(Validate());
186  ASSERT_TRUE(called_);
187  EXPECT_EQ(expected_, problems_);
188}
189
190TEST_F(ValidationTaskTest, MissingRequiredFieldsUS) {
191  json_[0] = "{}";
192
193  address_.region_code = "US";
194
195  filter_.insert(std::make_pair(ADMIN_AREA, MISSING_REQUIRED_FIELD));
196  filter_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
197  filter_.insert(std::make_pair(POSTAL_CODE, MISSING_REQUIRED_FIELD));
198  filter_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
199  expected_.insert(std::make_pair(ADMIN_AREA, MISSING_REQUIRED_FIELD));
200  expected_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
201  expected_.insert(std::make_pair(POSTAL_CODE, MISSING_REQUIRED_FIELD));
202  expected_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
203
204  ASSERT_NO_FATAL_FAILURE(Validate());
205  ASSERT_TRUE(called_);
206  EXPECT_EQ(expected_, problems_);
207}
208
209TEST_F(ValidationTaskTest, MissingNoRequiredFieldsUS) {
210  json_[0] = "{}";
211
212  address_.region_code = "US";
213  address_.administrative_area = "sss";
214  address_.locality = "ccc";
215  address_.postal_code = "zzz";
216  address_.address_line.push_back("aaa");
217  address_.organization = "ooo";
218  address_.recipient = "nnn";
219
220  filter_.insert(std::make_pair(ADMIN_AREA, MISSING_REQUIRED_FIELD));
221  filter_.insert(std::make_pair(LOCALITY, MISSING_REQUIRED_FIELD));
222  filter_.insert(std::make_pair(POSTAL_CODE, MISSING_REQUIRED_FIELD));
223  filter_.insert(std::make_pair(STREET_ADDRESS, MISSING_REQUIRED_FIELD));
224  filter_.insert(std::make_pair(ORGANIZATION, MISSING_REQUIRED_FIELD));
225
226  ASSERT_NO_FATAL_FAILURE(Validate());
227  ASSERT_TRUE(called_);
228  EXPECT_EQ(expected_, problems_);
229}
230
231TEST_F(ValidationTaskTest, UnexpectedFieldUS) {
232  json_[0] = "{}";
233
234  address_.region_code = "US";
235  address_.dependent_locality = "ddd";
236
237  filter_.insert(std::make_pair(DEPENDENT_LOCALITY, UNEXPECTED_FIELD));
238  expected_.insert(std::make_pair(DEPENDENT_LOCALITY, UNEXPECTED_FIELD));
239
240  ASSERT_NO_FATAL_FAILURE(Validate());
241  ASSERT_TRUE(called_);
242  EXPECT_EQ(expected_, problems_);
243}
244
245TEST_F(ValidationTaskTest, MissingRequiredFieldRequireName) {
246  json_[0] = "{}";
247
248  address_.region_code = "rrr";
249
250  require_name_ = true;
251
252  expected_.insert(std::make_pair(RECIPIENT, MISSING_REQUIRED_FIELD));
253
254  ASSERT_NO_FATAL_FAILURE(Validate());
255  ASSERT_TRUE(called_);
256  EXPECT_EQ(expected_, problems_);
257}
258
259TEST_F(ValidationTaskTest, UnknownValueRuleNull) {
260  json_[0] = "{\"fmt\":\"%R%S\",\"require\":\"RS\",\"sub_keys\":\"aa~bb\"}";
261
262  address_.region_code = "rrr";
263  address_.administrative_area = "sss";
264
265  expected_.insert(std::make_pair(ADMIN_AREA, UNKNOWN_VALUE));
266
267  ASSERT_NO_FATAL_FAILURE(Validate());
268  ASSERT_TRUE(called_);
269  EXPECT_EQ(expected_, problems_);
270}
271
272TEST_F(ValidationTaskTest, NoUnknownValueRuleNotNull) {
273  json_[0] = "{\"fmt\":\"%R%S\",\"require\":\"RS\",\"sub_keys\":\"aa~bb\"}";
274  json_[1] = "{}";
275
276  address_.region_code = "rrr";
277  address_.administrative_area = "sss";
278
279  ASSERT_NO_FATAL_FAILURE(Validate());
280  ASSERT_TRUE(called_);
281  EXPECT_EQ(expected_, problems_);
282}
283
284TEST_F(ValidationTaskTest, PostalCodeUnrecognizedFormatTooShort) {
285  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
286
287  address_.region_code = "rrr";
288  address_.postal_code = "12";
289
290  expected_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
291
292  ASSERT_NO_FATAL_FAILURE(Validate());
293  ASSERT_TRUE(called_);
294  EXPECT_EQ(expected_, problems_);
295}
296
297TEST_F(ValidationTaskTest, PostalCodeUnrecognizedFormatTooLong) {
298  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
299
300  address_.region_code = "rrr";
301  address_.postal_code = "1234";
302
303  expected_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
304
305  ASSERT_NO_FATAL_FAILURE(Validate());
306  ASSERT_TRUE(called_);
307  EXPECT_EQ(expected_, problems_);
308}
309
310TEST_F(ValidationTaskTest, PostalCodeRecognizedFormat) {
311  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
312
313  address_.region_code = "rrr";
314  address_.postal_code = "123";
315
316  ASSERT_NO_FATAL_FAILURE(Validate());
317  ASSERT_TRUE(called_);
318  EXPECT_EQ(expected_, problems_);
319}
320
321TEST_F(ValidationTaskTest, PostalCodeMismatchingValue1) {
322  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
323  json_[1] = "{\"zip\":\"1\"}";
324
325  address_.region_code = "rrr";
326  address_.postal_code = "000";
327
328  expected_.insert(std::make_pair(POSTAL_CODE, MISMATCHING_VALUE));
329
330  ASSERT_NO_FATAL_FAILURE(Validate());
331  ASSERT_TRUE(called_);
332  EXPECT_EQ(expected_, problems_);
333}
334
335TEST_F(ValidationTaskTest, PostalCodeMismatchingValue2) {
336  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
337  json_[1] = "{\"zip\":\"1\"}";
338  json_[2] = "{\"zip\":\"12\"}";
339
340  address_.region_code = "rrr";
341  address_.postal_code = "100";
342
343  expected_.insert(std::make_pair(POSTAL_CODE, MISMATCHING_VALUE));
344
345  ASSERT_NO_FATAL_FAILURE(Validate());
346  ASSERT_TRUE(called_);
347  EXPECT_EQ(expected_, problems_);
348}
349
350TEST_F(ValidationTaskTest, PostalCodeMismatchingValue3) {
351  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
352  json_[1] = "{\"zip\":\"1\"}";
353  json_[2] = "{\"zip\":\"12\"}";
354  json_[3] = "{\"zip\":\"123\"}";
355
356  address_.region_code = "rrr";
357  address_.postal_code = "120";
358
359  expected_.insert(std::make_pair(POSTAL_CODE, MISMATCHING_VALUE));
360
361  ASSERT_NO_FATAL_FAILURE(Validate());
362  ASSERT_TRUE(called_);
363  EXPECT_EQ(expected_, problems_);
364}
365
366TEST_F(ValidationTaskTest, PostalCodeMatchingValue) {
367  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{3}\"}";
368  json_[1] = "{\"zip\":\"1\"}";
369  json_[2] = "{\"zip\":\"12\"}";
370  json_[3] = "{\"zip\":\"123\"}";
371
372  address_.region_code = "rrr";
373  address_.postal_code = "123";
374
375  ASSERT_NO_FATAL_FAILURE(Validate());
376  ASSERT_TRUE(called_);
377  EXPECT_EQ(expected_, problems_);
378}
379
380TEST_F(ValidationTaskTest, PostalCodePrefixMismatchingValue) {
381  json_[0] = "{\"fmt\":\"%Z\",\"zip\":\"\\\\d{5}\"}";
382  json_[1] = "{\"zip\":\"9[0-5]|96[01]\"}";
383
384  address_.region_code = "rrr";
385  address_.postal_code = "10960";
386
387  expected_.insert(std::make_pair(POSTAL_CODE, MISMATCHING_VALUE));
388
389  ASSERT_NO_FATAL_FAILURE(Validate());
390  ASSERT_TRUE(called_);
391  EXPECT_EQ(expected_, problems_);
392}
393
394TEST_F(ValidationTaskTest, PostalCodeFilterIgnoresMismatching) {
395  json_[0] = "{\"zip\":\"\\\\d{3}\"}";
396  json_[1] = "{\"zip\":\"1\"}";
397
398  address_.region_code = "rrr";
399  address_.postal_code = "000";
400
401  filter_.erase(POSTAL_CODE);
402  filter_.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
403
404  // (POSTAL_CODE, MISMATCHING_VALUE) should not be reported.
405
406  ASSERT_NO_FATAL_FAILURE(Validate());
407  ASSERT_TRUE(called_);
408  EXPECT_EQ(expected_, problems_);
409}
410
411TEST_F(ValidationTaskTest, UsesPoBoxLanguageUnd) {
412  json_[0] = "{\"fmt\":\"%A\"}";
413
414  address_.region_code = "rrr";
415  address_.address_line.push_back("aaa");
416  address_.address_line.push_back("P.O. Box");
417  address_.address_line.push_back("aaa");
418
419  expected_.insert(std::make_pair(STREET_ADDRESS, USES_P_O_BOX));
420
421  ASSERT_NO_FATAL_FAILURE(Validate());
422  ASSERT_TRUE(called_);
423  EXPECT_EQ(expected_, problems_);
424}
425
426TEST_F(ValidationTaskTest, UsesPoBoxLanguageDa) {
427  json_[0] = "{\"fmt\":\"%A\",\"languages\":\"da\"}";
428
429  address_.region_code = "rrr";
430  address_.address_line.push_back("aaa");
431  address_.address_line.push_back("Postboks");
432  address_.address_line.push_back("aaa");
433
434  expected_.insert(std::make_pair(STREET_ADDRESS, USES_P_O_BOX));
435
436  ASSERT_NO_FATAL_FAILURE(Validate());
437  ASSERT_TRUE(called_);
438  EXPECT_EQ(expected_, problems_);
439}
440
441TEST_F(ValidationTaskTest, UsesPoBoxLanguageDaNotMatchDe) {
442  json_[0] = "{\"fmt\":\"%A\",\"languages\":\"da\"}";
443
444  address_.region_code = "rrr";
445  address_.address_line.push_back("aaa");
446  address_.address_line.push_back("Postfach");
447  address_.address_line.push_back("aaa");
448
449  ASSERT_NO_FATAL_FAILURE(Validate());
450  ASSERT_TRUE(called_);
451  EXPECT_EQ(expected_, problems_);
452}
453
454TEST_F(ValidationTaskTest, UsesPoBoxAllowPostal) {
455  json_[0] = "{\"fmt\":\"%A\"}";
456
457  address_.region_code = "rrr";
458  address_.address_line.push_back("aaa");
459  address_.address_line.push_back("P.O. Box");
460  address_.address_line.push_back("aaa");
461
462  allow_postal_ = true;
463
464  ASSERT_NO_FATAL_FAILURE(Validate());
465  ASSERT_TRUE(called_);
466  EXPECT_EQ(expected_, problems_);
467}
468
469}  // namespace
470}  // namespace addressinput
471}  // namespace i18n
472