Home | History | Annotate | Download | only in common
      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 
     21 namespace {
     22 
     23 #define TEST_SOURCE base::StringPrintf("%s:%i", __FILE__, __LINE__)
     24 
     25 Value* 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 
     39 Value* 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 
     50 ListValue* LoadList(const std::string& filename) {
     51   return static_cast<ListValue*>(
     52       LoadValue(filename, Value::TYPE_LIST));
     53 }
     54 
     55 DictionaryValue* LoadDictionary(const std::string& filename) {
     56   return static_cast<DictionaryValue*>(
     57       LoadValue(filename, Value::TYPE_DICTIONARY));
     58 }
     59 
     60 }  // namespace
     61 
     62 
     63 JSONSchemaValidatorTestBase::JSONSchemaValidatorTestBase(
     64     JSONSchemaValidatorTestBase::ValidatorType type)
     65     : type_(type) {
     66 }
     67 
     68 void 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 
     84 void 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 
    110 void 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 
    132 void 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 
    153 void 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 
    179 void JSONSchemaValidatorTestBase::TestExtends() {
    180   // TODO(aa): JS only
    181 }
    182 
    183 void 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 
    249 void 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 
    308 void 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 
    367 void 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 
    400 void 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 
    427 void 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 
    461 void 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 
    504 void 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