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