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