1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/json_schema/json_schema_validator_unittest_base.h"
6
7 #include <cfloat>
8 #include <cmath>
9 #include <limits>
10 #include <memory>
11
12 #include "base/base_paths.h"
13 #include "base/files/file_util.h"
14 #include "base/json/json_file_value_serializer.h"
15 #include "base/logging.h"
16 #include "base/path_service.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/values.h"
19 #include "components/json_schema/json_schema_constants.h"
20 #include "components/json_schema/json_schema_validator.h"
21
22 namespace schema = json_schema_constants;
23
24 namespace {
25
26 #define TEST_SOURCE base::StringPrintf("%s:%i", __FILE__, __LINE__)
27
LoadValue(const std::string & filename)28 base::Value* LoadValue(const std::string& filename) {
29 base::FilePath path;
30 base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
31 path = path.AppendASCII("components")
32 .AppendASCII("test")
33 .AppendASCII("data")
34 .AppendASCII("json_schema")
35 .AppendASCII(filename);
36 EXPECT_TRUE(base::PathExists(path));
37
38 std::string error_message;
39 JSONFileValueDeserializer deserializer(path);
40 base::Value* result =
41 deserializer.Deserialize(nullptr, &error_message).release();
42 if (!result)
43 ADD_FAILURE() << "Could not parse JSON: " << error_message;
44 return result;
45 }
46
LoadValue(const std::string & filename,base::Value::Type type)47 base::Value* LoadValue(const std::string& filename, base::Value::Type type) {
48 std::unique_ptr<base::Value> result(LoadValue(filename));
49 if (!result)
50 return nullptr;
51 if (result->type() != type) {
52 ADD_FAILURE() << "Expected type " << type << ", got: " << result->type();
53 return nullptr;
54 }
55 return result.release();
56 }
57
LoadList(const std::string & filename)58 base::ListValue* LoadList(const std::string& filename) {
59 return static_cast<base::ListValue*>(
60 LoadValue(filename, base::Value::Type::LIST));
61 }
62
LoadDictionary(const std::string & filename)63 base::DictionaryValue* LoadDictionary(const std::string& filename) {
64 return static_cast<base::DictionaryValue*>(
65 LoadValue(filename, base::Value::Type::DICTIONARY));
66 }
67
68 } // namespace
69
70
JSONSchemaValidatorTestBase()71 JSONSchemaValidatorTestBase::JSONSchemaValidatorTestBase() {
72 }
73
RunTests()74 void JSONSchemaValidatorTestBase::RunTests() {
75 TestComplex();
76 TestStringPattern();
77 TestEnum();
78 TestChoices();
79 TestExtends();
80 TestObject();
81 TestTypeReference();
82 TestArrayTuple();
83 TestArrayNonTuple();
84 TestString();
85 TestNumber();
86 TestTypeClassifier();
87 TestTypes();
88 }
89
TestComplex()90 void JSONSchemaValidatorTestBase::TestComplex() {
91 std::unique_ptr<base::DictionaryValue> schema(
92 LoadDictionary("complex_schema.json"));
93 std::unique_ptr<base::ListValue> instance(LoadList("complex_instance.json"));
94
95 ASSERT_TRUE(schema.get());
96 ASSERT_TRUE(instance.get());
97
98 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
99 instance->Remove(instance->GetSize() - 1, nullptr);
100 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
101 instance->Append(std::make_unique<base::DictionaryValue>());
102 ExpectNotValid(
103 TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
104 JSONSchemaValidator::FormatErrorMessage(
105 JSONSchemaValidator::kInvalidType, schema::kNumber, schema::kObject));
106 instance->Remove(instance->GetSize() - 1, nullptr);
107
108 base::DictionaryValue* item = nullptr;
109 ASSERT_TRUE(instance->GetDictionary(0, &item));
110 item->SetString("url", "xxxxxxxxxxx");
111
112 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0.url",
113 JSONSchemaValidator::FormatErrorMessage(
114 JSONSchemaValidator::kStringMaxLength, "10"));
115 }
116
TestStringPattern()117 void JSONSchemaValidatorTestBase::TestStringPattern() {
118 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
119 schema->SetString(schema::kType, schema::kString);
120 schema->SetString(schema::kPattern, "foo+");
121
122 ExpectValid(TEST_SOURCE,
123 std::unique_ptr<base::Value>(new base::Value("foo")).get(),
124 schema.get(), nullptr);
125 ExpectValid(TEST_SOURCE,
126 std::unique_ptr<base::Value>(new base::Value("foooooo")).get(),
127 schema.get(), nullptr);
128 ExpectNotValid(TEST_SOURCE,
129 std::unique_ptr<base::Value>(new base::Value("bar")).get(),
130 schema.get(), nullptr, std::string(),
131 JSONSchemaValidator::FormatErrorMessage(
132 JSONSchemaValidator::kStringPattern, "foo+"));
133 }
134
TestEnum()135 void JSONSchemaValidatorTestBase::TestEnum() {
136 std::unique_ptr<base::DictionaryValue> schema(
137 LoadDictionary("enum_schema.json"));
138
139 ExpectValid(TEST_SOURCE,
140 std::unique_ptr<base::Value>(new base::Value("foo")).get(),
141 schema.get(), nullptr);
142 ExpectValid(TEST_SOURCE,
143 std::unique_ptr<base::Value>(new base::Value(42)).get(),
144 schema.get(), nullptr);
145 ExpectValid(TEST_SOURCE,
146 std::unique_ptr<base::Value>(new base::Value(false)).get(),
147 schema.get(), nullptr);
148
149 ExpectNotValid(
150 TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value("42")).get(),
151 schema.get(), nullptr, std::string(), JSONSchemaValidator::kInvalidEnum);
152 ExpectNotValid(TEST_SOURCE, std::make_unique<base::Value>().get(),
153 schema.get(), nullptr, std::string(),
154 JSONSchemaValidator::kInvalidEnum);
155 }
156
TestChoices()157 void JSONSchemaValidatorTestBase::TestChoices() {
158 std::unique_ptr<base::DictionaryValue> schema(
159 LoadDictionary("choices_schema.json"));
160
161 ExpectValid(TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(),
162 nullptr);
163 ExpectValid(TEST_SOURCE,
164 std::unique_ptr<base::Value>(new base::Value(42)).get(),
165 schema.get(), nullptr);
166
167 std::unique_ptr<base::DictionaryValue> instance(new base::DictionaryValue());
168 instance->SetString("foo", "bar");
169 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
170
171 ExpectNotValid(TEST_SOURCE,
172 std::unique_ptr<base::Value>(new base::Value("foo")).get(),
173 schema.get(), nullptr, std::string(),
174 JSONSchemaValidator::kInvalidChoice);
175 ExpectNotValid(TEST_SOURCE,
176 std::unique_ptr<base::Value>(new base::ListValue()).get(),
177 schema.get(), nullptr, std::string(),
178 JSONSchemaValidator::kInvalidChoice);
179
180 instance->SetInteger("foo", 42);
181 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
182 std::string(), JSONSchemaValidator::kInvalidChoice);
183 }
184
TestExtends()185 void JSONSchemaValidatorTestBase::TestExtends() {
186 // TODO(aa): JS only
187 }
188
TestObject()189 void JSONSchemaValidatorTestBase::TestObject() {
190 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
191 schema->SetString(schema::kType, schema::kObject);
192 schema->SetString("properties.foo.type", schema::kString);
193 schema->SetString("properties.bar.type", schema::kInteger);
194
195 std::unique_ptr<base::DictionaryValue> instance(new base::DictionaryValue());
196 instance->SetString("foo", "foo");
197 instance->SetInteger("bar", 42);
198
199 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
200
201 instance->SetBoolean("extra", true);
202 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extra",
203 JSONSchemaValidator::kUnexpectedProperty);
204 instance->Remove("extra", nullptr);
205
206 instance->Remove("bar", nullptr);
207 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
208 JSONSchemaValidator::kObjectPropertyIsRequired);
209
210 instance->SetString("bar", "42");
211 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
212 JSONSchemaValidator::FormatErrorMessage(
213 JSONSchemaValidator::kInvalidType, schema::kInteger,
214 schema::kString));
215 instance->SetInteger("bar", 42);
216
217 // Test "patternProperties".
218 instance->SetInteger("extra", 42);
219 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extra",
220 JSONSchemaValidator::kUnexpectedProperty);
221 schema->SetString("patternProperties.extra+.type",
222 schema::kInteger);
223 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
224 instance->Remove("extra", nullptr);
225 instance->SetInteger("extraaa", 42);
226 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
227 instance->Remove("extraaa", nullptr);
228 instance->SetInteger("extr", 42);
229 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extr",
230 JSONSchemaValidator::kUnexpectedProperty);
231 instance->Remove("extr", nullptr);
232 schema->Remove(schema::kPatternProperties, nullptr);
233
234 // Test "patternProperties" and "properties" schemas are both checked if
235 // applicable.
236 schema->SetString("patternProperties.fo+.type", schema::kInteger);
237 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "foo",
238 JSONSchemaValidator::FormatErrorMessage(
239 JSONSchemaValidator::kInvalidType, schema::kInteger,
240 schema::kString));
241 instance->SetInteger("foo", 123);
242 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "foo",
243 JSONSchemaValidator::FormatErrorMessage(
244 JSONSchemaValidator::kInvalidType, schema::kString,
245 schema::kInteger));
246 instance->SetString("foo", "foo");
247 schema->Remove(schema::kPatternProperties, nullptr);
248
249 // Test additional properties.
250 base::DictionaryValue* additional_properties = schema->SetDictionary(
251 schema::kAdditionalProperties, std::make_unique<base::DictionaryValue>());
252 additional_properties->SetString(schema::kType, schema::kAny);
253
254 instance->SetBoolean("extra", true);
255 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
256
257 instance->SetString("extra", "foo");
258 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
259
260 additional_properties->SetString(schema::kType, schema::kBoolean);
261 instance->SetBoolean("extra", true);
262 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
263
264 instance->SetString("extra", "foo");
265 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extra",
266 JSONSchemaValidator::FormatErrorMessage(
267 JSONSchemaValidator::kInvalidType, schema::kBoolean,
268 schema::kString));
269 instance->Remove("extra", nullptr);
270
271 base::DictionaryValue* properties = nullptr;
272 base::DictionaryValue* bar_property = nullptr;
273 ASSERT_TRUE(schema->GetDictionary(schema::kProperties, &properties));
274 ASSERT_TRUE(properties->GetDictionary("bar", &bar_property));
275
276 bar_property->SetBoolean(schema::kOptional, true);
277 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
278 instance->Remove("bar", nullptr);
279 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
280 instance->Set("bar", std::make_unique<base::Value>());
281 ExpectNotValid(
282 TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
283 JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
284 schema::kInteger, schema::kNull));
285 instance->SetString("bar", "42");
286 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
287 JSONSchemaValidator::FormatErrorMessage(
288 JSONSchemaValidator::kInvalidType, schema::kInteger,
289 schema::kString));
290
291 // Verify that JSON parser handles dot in "patternProperties" well.
292 schema.reset(LoadDictionary("pattern_properties_dot.json"));
293 ASSERT_TRUE(schema->GetDictionary(schema::kPatternProperties, &properties));
294 ASSERT_TRUE(properties->HasKey("^.$"));
295
296 instance.reset(new base::DictionaryValue());
297 instance->SetString("a", "whatever");
298 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
299 instance->SetString("foo", "bar");
300 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "foo",
301 JSONSchemaValidator::kUnexpectedProperty);
302 }
303
TestTypeReference()304 void JSONSchemaValidatorTestBase::TestTypeReference() {
305 std::unique_ptr<base::ListValue> types(LoadList("reference_types.json"));
306 ASSERT_TRUE(types.get());
307
308 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
309 schema->SetString(schema::kType, schema::kObject);
310 schema->SetString("properties.foo.type", schema::kString);
311 schema->SetString("properties.bar.$ref", "Max10Int");
312 schema->SetString("properties.baz.$ref", "MinLengthString");
313
314 std::unique_ptr<base::DictionaryValue> schema_inline(
315 new base::DictionaryValue());
316 schema_inline->SetString(schema::kType, schema::kObject);
317 schema_inline->SetString("properties.foo.type", schema::kString);
318 schema_inline->SetString("properties.bar.id", "NegativeInt");
319 schema_inline->SetString("properties.bar.type", schema::kInteger);
320 schema_inline->SetInteger("properties.bar.maximum", 0);
321 schema_inline->SetString("properties.baz.$ref", "NegativeInt");
322
323 std::unique_ptr<base::DictionaryValue> instance(new base::DictionaryValue());
324 instance->SetString("foo", "foo");
325 instance->SetInteger("bar", 4);
326 instance->SetString("baz", "ab");
327
328 std::unique_ptr<base::DictionaryValue> instance_inline(
329 new base::DictionaryValue());
330 instance_inline->SetString("foo", "foo");
331 instance_inline->SetInteger("bar", -4);
332 instance_inline->SetInteger("baz", -2);
333
334 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), types.get());
335 ExpectValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(), nullptr);
336
337 // Validation failure, but successful schema reference.
338 instance->SetString("baz", "a");
339 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), types.get(),
340 "baz", JSONSchemaValidator::FormatErrorMessage(
341 JSONSchemaValidator::kStringMinLength, "2"));
342
343 instance_inline->SetInteger("bar", 20);
344 ExpectNotValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(),
345 nullptr, "bar",
346 JSONSchemaValidator::FormatErrorMessage(
347 JSONSchemaValidator::kNumberMaximum, "0"));
348
349 // Remove MinLengthString type.
350 types->Remove(types->GetSize() - 1, nullptr);
351 instance->SetString("baz", "ab");
352 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), types.get(),
353 "bar", JSONSchemaValidator::FormatErrorMessage(
354 JSONSchemaValidator::kUnknownTypeReference,
355 "Max10Int"));
356
357 // Remove internal type "NegativeInt".
358 schema_inline->Remove("properties.bar", nullptr);
359 instance_inline->Remove("bar", nullptr);
360 ExpectNotValid(
361 TEST_SOURCE, instance_inline.get(), schema_inline.get(), nullptr, "baz",
362 JSONSchemaValidator::FormatErrorMessage(
363 JSONSchemaValidator::kUnknownTypeReference, "NegativeInt"));
364 }
365
TestArrayTuple()366 void JSONSchemaValidatorTestBase::TestArrayTuple() {
367 std::unique_ptr<base::DictionaryValue> schema(
368 LoadDictionary("array_tuple_schema.json"));
369 ASSERT_TRUE(schema.get());
370
371 std::unique_ptr<base::ListValue> instance(new base::ListValue());
372 instance->AppendString("42");
373 instance->AppendInteger(42);
374
375 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
376
377 instance->AppendString("anything");
378 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
379 std::string(),
380 JSONSchemaValidator::FormatErrorMessage(
381 JSONSchemaValidator::kArrayMaxItems, "2"));
382
383 instance->Remove(1, nullptr);
384 instance->Remove(1, nullptr);
385 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
386 JSONSchemaValidator::kArrayItemRequired);
387
388 instance->Set(0, std::make_unique<base::Value>(42));
389 instance->AppendInteger(42);
390 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0",
391 JSONSchemaValidator::FormatErrorMessage(
392 JSONSchemaValidator::kInvalidType, schema::kString,
393 schema::kInteger));
394
395 base::DictionaryValue* additional_properties = schema->SetDictionary(
396 schema::kAdditionalProperties, std::make_unique<base::DictionaryValue>());
397 additional_properties->SetString(schema::kType, schema::kAny);
398 instance->Set(0, std::make_unique<base::Value>("42"));
399 instance->AppendString("anything");
400 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
401 instance->Set(2, std::make_unique<base::ListValue>());
402 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
403
404 additional_properties->SetString(schema::kType, schema::kBoolean);
405 ExpectNotValid(
406 TEST_SOURCE, instance.get(), schema.get(), nullptr, "2",
407 JSONSchemaValidator::FormatErrorMessage(
408 JSONSchemaValidator::kInvalidType, schema::kBoolean, schema::kArray));
409 instance->Set(2, std::make_unique<base::Value>(false));
410 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
411
412 base::ListValue* items_schema = nullptr;
413 base::DictionaryValue* item0_schema = nullptr;
414 ASSERT_TRUE(schema->GetList(schema::kItems, &items_schema));
415 ASSERT_TRUE(items_schema->GetDictionary(0, &item0_schema));
416 item0_schema->SetBoolean(schema::kOptional, true);
417 instance->Remove(2, nullptr);
418 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
419 // TODO(aa): I think this is inconsistent with the handling of NULL+optional
420 // for objects.
421 instance->Set(0, std::make_unique<base::Value>());
422 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
423 instance->Set(0, std::make_unique<base::Value>(42));
424 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0",
425 JSONSchemaValidator::FormatErrorMessage(
426 JSONSchemaValidator::kInvalidType, schema::kString,
427 schema::kInteger));
428 }
429
TestArrayNonTuple()430 void JSONSchemaValidatorTestBase::TestArrayNonTuple() {
431 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
432 schema->SetString(schema::kType, schema::kArray);
433 schema->SetString("items.type", schema::kString);
434 schema->SetInteger(schema::kMinItems, 2);
435 schema->SetInteger(schema::kMaxItems, 3);
436
437 std::unique_ptr<base::ListValue> instance(new base::ListValue());
438 instance->AppendString("x");
439 instance->AppendString("x");
440
441 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
442 instance->AppendString("x");
443 ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
444
445 instance->AppendString("x");
446 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
447 std::string(),
448 JSONSchemaValidator::FormatErrorMessage(
449 JSONSchemaValidator::kArrayMaxItems, "3"));
450 instance->Remove(1, nullptr);
451 instance->Remove(1, nullptr);
452 instance->Remove(1, nullptr);
453 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
454 std::string(),
455 JSONSchemaValidator::FormatErrorMessage(
456 JSONSchemaValidator::kArrayMinItems, "2"));
457
458 instance->Remove(1, nullptr);
459 instance->AppendInteger(42);
460 ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
461 JSONSchemaValidator::FormatErrorMessage(
462 JSONSchemaValidator::kInvalidType, schema::kString,
463 schema::kInteger));
464 }
465
TestString()466 void JSONSchemaValidatorTestBase::TestString() {
467 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
468 schema->SetString(schema::kType, schema::kString);
469 schema->SetInteger(schema::kMinLength, 1);
470 schema->SetInteger(schema::kMaxLength, 10);
471
472 ExpectValid(TEST_SOURCE,
473 std::unique_ptr<base::Value>(new base::Value("x")).get(),
474 schema.get(), nullptr);
475 ExpectValid(TEST_SOURCE,
476 std::unique_ptr<base::Value>(new base::Value("xxxxxxxxxx")).get(),
477 schema.get(), nullptr);
478
479 ExpectNotValid(
480 TEST_SOURCE,
481 std::unique_ptr<base::Value>(new base::Value(std::string())).get(),
482 schema.get(), nullptr, std::string(),
483 JSONSchemaValidator::FormatErrorMessage(
484 JSONSchemaValidator::kStringMinLength, "1"));
485 ExpectNotValid(
486 TEST_SOURCE,
487 std::unique_ptr<base::Value>(new base::Value("xxxxxxxxxxx")).get(),
488 schema.get(), nullptr, std::string(),
489 JSONSchemaValidator::FormatErrorMessage(
490 JSONSchemaValidator::kStringMaxLength, "10"));
491 }
492
TestNumber()493 void JSONSchemaValidatorTestBase::TestNumber() {
494 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
495 schema->SetString(schema::kType, schema::kNumber);
496 schema->SetInteger(schema::kMinimum, 1);
497 schema->SetInteger(schema::kMaximum, 100);
498 schema->SetInteger("maxDecimal", 2);
499
500 ExpectValid(TEST_SOURCE,
501 std::unique_ptr<base::Value>(new base::Value(1)).get(),
502 schema.get(), nullptr);
503 ExpectValid(TEST_SOURCE,
504 std::unique_ptr<base::Value>(new base::Value(50)).get(),
505 schema.get(), nullptr);
506 ExpectValid(TEST_SOURCE,
507 std::unique_ptr<base::Value>(new base::Value(100)).get(),
508 schema.get(), nullptr);
509 ExpectValid(TEST_SOURCE,
510 std::unique_ptr<base::Value>(new base::Value(88.88)).get(),
511 schema.get(), nullptr);
512
513 ExpectNotValid(TEST_SOURCE,
514 std::unique_ptr<base::Value>(new base::Value(0.5)).get(),
515 schema.get(), nullptr, std::string(),
516 JSONSchemaValidator::FormatErrorMessage(
517 JSONSchemaValidator::kNumberMinimum, "1"));
518 ExpectNotValid(TEST_SOURCE,
519 std::unique_ptr<base::Value>(new base::Value(100.1)).get(),
520 schema.get(), nullptr, std::string(),
521 JSONSchemaValidator::FormatErrorMessage(
522 JSONSchemaValidator::kNumberMaximum, "100"));
523 }
524
TestTypeClassifier()525 void JSONSchemaValidatorTestBase::TestTypeClassifier() {
526 EXPECT_EQ(std::string(schema::kBoolean),
527 JSONSchemaValidator::GetJSONSchemaType(
528 std::unique_ptr<base::Value>(new base::Value(true)).get()));
529 EXPECT_EQ(std::string(schema::kBoolean),
530 JSONSchemaValidator::GetJSONSchemaType(
531 std::unique_ptr<base::Value>(new base::Value(false)).get()));
532
533 // It doesn't matter whether the C++ type is 'integer' or 'real'. If the
534 // number is integral and within the representable range of integers in
535 // double, it's classified as 'integer'.
536 EXPECT_EQ(std::string(schema::kInteger),
537 JSONSchemaValidator::GetJSONSchemaType(
538 std::unique_ptr<base::Value>(new base::Value(42)).get()));
539 EXPECT_EQ(std::string(schema::kInteger),
540 JSONSchemaValidator::GetJSONSchemaType(
541 std::unique_ptr<base::Value>(new base::Value(0)).get()));
542 EXPECT_EQ(std::string(schema::kInteger),
543 JSONSchemaValidator::GetJSONSchemaType(
544 std::unique_ptr<base::Value>(new base::Value(42)).get()));
545 EXPECT_EQ(
546 std::string(schema::kInteger),
547 JSONSchemaValidator::GetJSONSchemaType(
548 std::unique_ptr<base::Value>(new base::Value(pow(2.0, DBL_MANT_DIG)))
549 .get()));
550 EXPECT_EQ(
551 std::string(schema::kInteger),
552 JSONSchemaValidator::GetJSONSchemaType(
553 std::unique_ptr<base::Value>(new base::Value(pow(-2.0, DBL_MANT_DIG)))
554 .get()));
555
556 // "number" is only used for non-integral numbers, or numbers beyond what
557 // double can accurately represent.
558 EXPECT_EQ(std::string(schema::kNumber),
559 JSONSchemaValidator::GetJSONSchemaType(
560 std::unique_ptr<base::Value>(new base::Value(88.8)).get()));
561 EXPECT_EQ(std::string(schema::kNumber),
562 JSONSchemaValidator::GetJSONSchemaType(
563 std::unique_ptr<base::Value>(
564 new base::Value(pow(2.0, DBL_MANT_DIG) * 2))
565 .get()));
566 EXPECT_EQ(std::string(schema::kNumber),
567 JSONSchemaValidator::GetJSONSchemaType(
568 std::unique_ptr<base::Value>(
569 new base::Value(pow(-2.0, DBL_MANT_DIG) * 2))
570 .get()));
571
572 EXPECT_EQ(std::string(schema::kString),
573 JSONSchemaValidator::GetJSONSchemaType(
574 std::unique_ptr<base::Value>(new base::Value("foo")).get()));
575 EXPECT_EQ(std::string(schema::kArray),
576 JSONSchemaValidator::GetJSONSchemaType(
577 std::unique_ptr<base::Value>(new base::ListValue()).get()));
578 EXPECT_EQ(
579 std::string(schema::kObject),
580 JSONSchemaValidator::GetJSONSchemaType(
581 std::unique_ptr<base::Value>(new base::DictionaryValue()).get()));
582 EXPECT_EQ(std::string(schema::kNull),
583 JSONSchemaValidator::GetJSONSchemaType(
584 std::make_unique<base::Value>().get()));
585 }
586
TestTypes()587 void JSONSchemaValidatorTestBase::TestTypes() {
588 std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
589
590 // valid
591 schema->SetString(schema::kType, schema::kObject);
592 ExpectValid(TEST_SOURCE,
593 std::unique_ptr<base::Value>(new base::DictionaryValue()).get(),
594 schema.get(), nullptr);
595
596 schema->SetString(schema::kType, schema::kArray);
597 ExpectValid(TEST_SOURCE,
598 std::unique_ptr<base::Value>(new base::ListValue()).get(),
599 schema.get(), nullptr);
600
601 schema->SetString(schema::kType, schema::kString);
602 ExpectValid(TEST_SOURCE,
603 std::unique_ptr<base::Value>(new base::Value("foobar")).get(),
604 schema.get(), nullptr);
605
606 schema->SetString(schema::kType, schema::kNumber);
607 ExpectValid(TEST_SOURCE,
608 std::unique_ptr<base::Value>(new base::Value(88.8)).get(),
609 schema.get(), nullptr);
610 ExpectValid(TEST_SOURCE,
611 std::unique_ptr<base::Value>(new base::Value(42)).get(),
612 schema.get(), nullptr);
613 ExpectValid(TEST_SOURCE,
614 std::unique_ptr<base::Value>(new base::Value(42)).get(),
615 schema.get(), nullptr);
616 ExpectValid(TEST_SOURCE,
617 std::unique_ptr<base::Value>(new base::Value(0)).get(),
618 schema.get(), nullptr);
619
620 schema->SetString(schema::kType, schema::kInteger);
621 ExpectValid(TEST_SOURCE,
622 std::unique_ptr<base::Value>(new base::Value(42)).get(),
623 schema.get(), nullptr);
624 ExpectValid(TEST_SOURCE,
625 std::unique_ptr<base::Value>(new base::Value(42)).get(),
626 schema.get(), nullptr);
627 ExpectValid(TEST_SOURCE,
628 std::unique_ptr<base::Value>(new base::Value(0)).get(),
629 schema.get(), nullptr);
630 ExpectValid(
631 TEST_SOURCE,
632 std::unique_ptr<base::Value>(new base::Value(pow(2.0, DBL_MANT_DIG)))
633 .get(),
634 schema.get(), nullptr);
635 ExpectValid(
636 TEST_SOURCE,
637 std::unique_ptr<base::Value>(new base::Value(pow(-2.0, DBL_MANT_DIG)))
638 .get(),
639 schema.get(), nullptr);
640
641 schema->SetString(schema::kType, schema::kBoolean);
642 ExpectValid(TEST_SOURCE,
643 std::unique_ptr<base::Value>(new base::Value(false)).get(),
644 schema.get(), nullptr);
645 ExpectValid(TEST_SOURCE,
646 std::unique_ptr<base::Value>(new base::Value(true)).get(),
647 schema.get(), nullptr);
648
649 schema->SetString(schema::kType, schema::kNull);
650 ExpectValid(TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(),
651 nullptr);
652
653 // not valid
654 schema->SetString(schema::kType, schema::kObject);
655 ExpectNotValid(
656 TEST_SOURCE, std::unique_ptr<base::Value>(new base::ListValue()).get(),
657 schema.get(), nullptr, std::string(),
658 JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
659 schema::kObject, schema::kArray));
660
661 schema->SetString(schema::kType, schema::kObject);
662 ExpectNotValid(
663 TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(), nullptr,
664 std::string(),
665 JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
666 schema::kObject, schema::kNull));
667
668 schema->SetString(schema::kType, schema::kArray);
669 ExpectNotValid(
670 TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value(42)).get(),
671 schema.get(), nullptr, std::string(),
672 JSONSchemaValidator::FormatErrorMessage(
673 JSONSchemaValidator::kInvalidType, schema::kArray, schema::kInteger));
674
675 schema->SetString(schema::kType, schema::kString);
676 ExpectNotValid(TEST_SOURCE,
677 std::unique_ptr<base::Value>(new base::Value(42)).get(),
678 schema.get(), nullptr, std::string(),
679 JSONSchemaValidator::FormatErrorMessage(
680 JSONSchemaValidator::kInvalidType, schema::kString,
681 schema::kInteger));
682
683 schema->SetString(schema::kType, schema::kNumber);
684 ExpectNotValid(
685 TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value("42")).get(),
686 schema.get(), nullptr, std::string(),
687 JSONSchemaValidator::FormatErrorMessage(
688 JSONSchemaValidator::kInvalidType, schema::kNumber, schema::kString));
689
690 schema->SetString(schema::kType, schema::kInteger);
691 ExpectNotValid(TEST_SOURCE,
692 std::unique_ptr<base::Value>(new base::Value(88.8)).get(),
693 schema.get(), nullptr, std::string(),
694 JSONSchemaValidator::kInvalidTypeIntegerNumber);
695
696 schema->SetString(schema::kType, schema::kBoolean);
697 ExpectNotValid(TEST_SOURCE,
698 std::unique_ptr<base::Value>(new base::Value(1)).get(),
699 schema.get(), nullptr, std::string(),
700 JSONSchemaValidator::FormatErrorMessage(
701 JSONSchemaValidator::kInvalidType, schema::kBoolean,
702 schema::kInteger));
703
704 schema->SetString(schema::kType, schema::kNull);
705 ExpectNotValid(
706 TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value(false)).get(),
707 schema.get(), nullptr, std::string(),
708 JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
709 schema::kNull, schema::kBoolean));
710 }
711