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