summaryrefslogtreecommitdiff
path: root/json
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2013-02-15 16:30:59 -0500
committerJulian Berman <Julian@GrayVines.com>2013-02-15 16:30:59 -0500
commit784f5d9d712a8a6e06c6aa968a5e51d988f6b87a (patch)
tree0ebd93a9214f86bb2185140d84e7f1f35eab1451 /json
parent7f2950edc9a3eca0a58da82ba6829f80e55173ef (diff)
downloadjsonschema-784f5d9d712a8a6e06c6aa968a5e51d988f6b87a.tar.gz
Update the test suite.
Diffstat (limited to 'json')
-rw-r--r--json/.travis.yml2
-rw-r--r--json/README.md28
-rwxr-xr-xjson/bin/jsonschema_suite (renamed from json/bin/suite_sanity_check)75
-rw-r--r--json/tests/draft3/optional/bignum.json14
-rw-r--r--json/tests/draft3/optional/format.json4
-rw-r--r--json/tests/draft3/optional/jsregex.json18
-rw-r--r--json/tests/draft3/optional/zeroTerminatedFloats.json15
-rw-r--r--json/tests/draft3/patternProperties.json31
-rw-r--r--json/tests/draft3/type.json5
-rw-r--r--json/tests/draft4/additionalItems.json82
-rw-r--r--json/tests/draft4/additionalProperties.json63
-rw-r--r--json/tests/draft4/allOf.json112
-rw-r--r--json/tests/draft4/anyOf.json68
-rw-r--r--json/tests/draft4/definitions.json32
-rw-r--r--json/tests/draft4/dependencies.json113
-rw-r--r--json/tests/draft4/enum.json39
-rw-r--r--json/tests/draft4/items.json46
-rw-r--r--json/tests/draft4/maxItems.json28
-rw-r--r--json/tests/draft4/maxLength.json28
-rw-r--r--json/tests/draft4/maxProperties.json28
-rw-r--r--json/tests/draft4/maximum.json42
-rw-r--r--json/tests/draft4/minItems.json28
-rw-r--r--json/tests/draft4/minLength.json28
-rw-r--r--json/tests/draft4/minProperties.json28
-rw-r--r--json/tests/draft4/minimum.json42
-rw-r--r--json/tests/draft4/multipleOf.json60
-rw-r--r--json/tests/draft4/not.json73
-rw-r--r--json/tests/draft4/oneOf.json68
-rw-r--r--json/tests/draft4/optional/bignum.json49
-rw-r--r--json/tests/draft4/optional/format.json139
-rw-r--r--json/tests/draft4/optional/jsregex.json18
-rw-r--r--json/tests/draft4/optional/zeroTerminatedFloats.json15
-rw-r--r--json/tests/draft4/pattern.json23
-rw-r--r--json/tests/draft4/patternProperties.json110
-rw-r--r--json/tests/draft4/properties.json92
-rw-r--r--json/tests/draft4/ref.json84
-rw-r--r--json/tests/draft4/required.json39
-rw-r--r--json/tests/draft4/type.json330
-rw-r--r--json/tests/draft4/uniqueItems.json79
39 files changed, 2130 insertions, 48 deletions
diff --git a/json/.travis.yml b/json/.travis.yml
index 186bd12..deecd61 100644
--- a/json/.travis.yml
+++ b/json/.travis.yml
@@ -1,4 +1,4 @@
language: python
python: "2.7"
install: pip install jsonschema
-script: bin/suite_sanity_check -v
+script: bin/jsonschema_suite check
diff --git a/json/README.md b/json/README.md
index 9bb15bd..38d83a0 100644
--- a/json/README.md
+++ b/json/README.md
@@ -56,41 +56,17 @@ Currently, draft 3 should have essentially full coverage for the core schema.
The beginnings of draft 4 are underway.
-Optional Tests
---------------
-
-Tests for optional validation are available in the "optional" directory,
-including for bignums (large integers), and for several of the values of the
-"format" property.
-
-Values of "format" covered are:
-
- * regex
- * date-time
- * date
- * time
- * uri
- * email
- * ip-address
- * ipv6
- * host-name
- * color
-
-Those also mentioned in draft 3, but currently omitted in the tests are:
-
- * utc-millisec
- * style
- * phone
-
Who Uses the Test Suite
-----------------------
This suite is being used by:
+ * [json-schema-validator (Java)](https://github.com/fge/json-schema-validator)
* [jsonschema (python)](https://github.com/Julian/jsonschema)
* [aeson-schema (haskell)](https://github.com/timjb/aeson-schema)
* [direct-schema (javascript)](https://github.com/IreneKnapp/direct-schema)
* [jsonschema (javascript)](https://github.com/tdegrunt/jsonschema)
+ * [JaySchema (javascript)](https://github.com/natesilva/jayschema)
If you use it as well, please fork and send a pull request adding yourself to
the list :).
diff --git a/json/bin/suite_sanity_check b/json/bin/jsonschema_suite
index 69d56b5..55a2a5e 100755
--- a/json/bin/suite_sanity_check
+++ b/json/bin/jsonschema_suite
@@ -1,9 +1,12 @@
#! /usr/bin/env python
-from unittest import TestCase, skipIf
+import argparse
import fnmatch
import json
import logging
import os
+import random
+import sys
+import unittest
try:
import jsonschema
@@ -37,7 +40,7 @@ TESTSUITE_SCHEMA = {
}
},
"additionalProperties": False,
- "minItems": 1
+ "minItems": 1
}
}
@@ -67,7 +70,7 @@ def collect(root_dir):
yield os.path.join(root, filename)
-class SanityTests(TestCase):
+class SanityTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
logging.info("Looking for tests in %s", SUITE_ROOT_DIR)
@@ -101,16 +104,22 @@ class SanityTests(TestCase):
"%r contains a duplicate description" % (group,)
)
- @skipIf(jsonschema is None, "Validation library not present! Skipping.")
+ @unittest.skipIf(jsonschema is None, "Validation library not present!")
def test_all_schemas_are_valid(self):
- for case in cases(self.test_files):
- # XXX: Add the other versions for the other drafts
- try:
- jsonschema.Draft3Validator.check_schema(case["schema"])
- except jsonschema.SchemaError as error:
- self.fail("%s contains an invalid schema (%s)" % (case, error))
-
- @skipIf(jsonschema is None, "Validation library not present! Skipping.")
+ for schema in os.listdir(SUITE_ROOT_DIR):
+ schema_validator = jsonschema.validators.get(schema)
+ if schema_validator:
+ test_files = collect(os.path.join(SUITE_ROOT_DIR, schema))
+ for case in cases(test_files):
+ try:
+ schema_validator.check_schema(case["schema"])
+ except jsonschema.SchemaError as error:
+ self.fail("%s contains an invalid schema (%s)" %
+ (case, error))
+ else:
+ logging.warning("No schema validator for %s" % schema)
+
+ @unittest.skipIf(jsonschema is None, "Validation library not present!")
def test_suites_are_valid(self):
validator = jsonschema.Draft3Validator(TESTSUITE_SCHEMA)
for tests in files(self.test_files):
@@ -120,6 +129,44 @@ class SanityTests(TestCase):
self.fail(str(error))
+def main(arguments):
+ if arguments.command == "check":
+ suite = unittest.TestLoader().loadTestsFromTestCase(SanityTests)
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(not result.wasSuccessful())
+ elif arguments.command == "flatten":
+ selected_cases = [case for case in cases(collect(arguments.version))]
+
+ if arguments.randomize:
+ random.shuffle(selected_cases)
+
+ json.dump(selected_cases, arguments.out, indent=4)
+
+
+parser = argparse.ArgumentParser(
+ description="JSON Schema Test Suite utilities",
+)
+subparsers = parser.add_subparsers(help="utility commands", dest="command")
+
+check = subparsers.add_parser("check", help="Sanity check the test suite.")
+
+flatten = subparsers.add_parser(
+ "flatten",
+ help="Output a flattened file containing the test cases and any "
+ "additionally specified optional test cases."
+)
+flatten.add_argument(
+ "--randomize",
+ action="store_true",
+ help="randomize the order of the outputted cases",
+)
+flatten.add_argument(
+ "version", help="the directory containing the version to output",
+)
+flatten.add_argument(
+ "out", help="the output file to write to", type=argparse.FileType("w"),
+)
+
+
if __name__ == "__main__":
- from unittest import main
- main()
+ main(parser.parse_args())
diff --git a/json/tests/draft3/optional/bignum.json b/json/tests/draft3/optional/bignum.json
index e37cf86..7b4755c 100644
--- a/json/tests/draft3/optional/bignum.json
+++ b/json/tests/draft3/optional/bignum.json
@@ -31,5 +31,19 @@
"valid": false
}
]
+ },
+ {
+ "description": "float comparison with high precision",
+ "schema": {
+ "maximum": 972783798187987123879878123.18878137,
+ "exclusiveMaximum": true
+ },
+ "tests": [
+ {
+ "description": "comparison works for high numbers",
+ "data": 972783798187987123879878123.188781371,
+ "valid": false
+ }
+ ]
}
]
diff --git a/json/tests/draft3/optional/format.json b/json/tests/draft3/optional/format.json
index f6958e3..82f7f13 100644
--- a/json/tests/draft3/optional/format.json
+++ b/json/tests/draft3/optional/format.json
@@ -21,7 +21,7 @@
"tests": [
{
"description": "a valid date-time string",
- "data": "1963-06-19T08:30:06.283185",
+ "data": "1963-06-19T08:30:06.283185Z",
"valid": true
},
{
@@ -204,4 +204,4 @@
}
]
}
-] \ No newline at end of file
+]
diff --git a/json/tests/draft3/optional/jsregex.json b/json/tests/draft3/optional/jsregex.json
new file mode 100644
index 0000000..d0e047c
--- /dev/null
+++ b/json/tests/draft3/optional/jsregex.json
@@ -0,0 +1,18 @@
+[
+ {
+ "description": "ECMA 262 regex dialect recognition",
+ "schema": { "format": "pattern" },
+ "tests": [
+ {
+ "description": "[^] is a valid regex",
+ "data": "[^]",
+ "valid": true
+ },
+ {
+ "description": "ECMA 262 has no support for lookbehind",
+ "data": "(?<=foo)bar",
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft3/optional/zeroTerminatedFloats.json b/json/tests/draft3/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..9b50ea2
--- /dev/null
+++ b/json/tests/draft3/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+ {
+ "description": "some languages do not distinguish between different types of numeric value",
+ "schema": {
+ "type": "integer"
+ },
+ "tests": [
+ {
+ "description": "a float is not an integer even without fractional part",
+ "data": 1.0,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft3/patternProperties.json b/json/tests/draft3/patternProperties.json
index 59ba56c..18586e5 100644
--- a/json/tests/draft3/patternProperties.json
+++ b/json/tests/draft3/patternProperties.json
@@ -75,5 +75,36 @@
"valid": false
}
]
+ },
+ {
+ "description": "regexes are not anchored by default and are case sensitive",
+ "schema": {
+ "patternProperties": {
+ "[0-9]{2,}": { "type": "boolean" },
+ "X_": { "type": "string" }
+ }
+ },
+ "tests": [
+ {
+ "description": "non recognized members are ignored",
+ "data": { "answer 1": "42" },
+ "valid": true
+ },
+ {
+ "description": "recognized members are accounted for",
+ "data": { "a31b": null },
+ "valid": false
+ },
+ {
+ "description": "regexes are case sensitive",
+ "data": { "a_x_3": 3 },
+ "valid": true
+ },
+ {
+ "description": "regexes are case sensitive, 2",
+ "data": { "a_X_3": 3 },
+ "valid": false
+ }
+ ]
}
]
diff --git a/json/tests/draft3/type.json b/json/tests/draft3/type.json
index 2679ce3..8f10889 100644
--- a/json/tests/draft3/type.json
+++ b/json/tests/draft3/type.json
@@ -14,11 +14,6 @@
"valid": false
},
{
- "description": "a float is not an integer even without fractional part",
- "data": 1.0,
- "valid": false
- },
- {
"description": "a string is not an integer",
"data": "foo",
"valid": false
diff --git a/json/tests/draft4/additionalItems.json b/json/tests/draft4/additionalItems.json
new file mode 100644
index 0000000..521745c
--- /dev/null
+++ b/json/tests/draft4/additionalItems.json
@@ -0,0 +1,82 @@
+[
+ {
+ "description": "additionalItems as schema",
+ "schema": {
+ "items": [{}],
+ "additionalItems": {"type": "integer"}
+ },
+ "tests": [
+ {
+ "description": "additional items match schema",
+ "data": [ null, 2, 3, 4 ],
+ "valid": true
+ },
+ {
+ "description": "additional items do not match schema",
+ "data": [ null, 2, 3, "foo" ],
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "items is schema, no additionalItems",
+ "schema": {
+ "items": {},
+ "additionalItems": false
+ },
+ "tests": [
+ {
+ "description": "all items match schema",
+ "data": [ 1, 2, 3, 4, 5 ],
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "array of items with no additionalItems",
+ "schema": {
+ "items": [{}, {}, {}],
+ "additionalItems": false
+ },
+ "tests": [
+ {
+ "description": "no additional items present",
+ "data": [ 1, 2, 3 ],
+ "valid": true
+ },
+ {
+ "description": "additional items are not permitted",
+ "data": [ 1, 2, 3, 4 ],
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "additionalItems as false without items",
+ "schema": {"additionalItems": false},
+ "tests": [
+ {
+ "description":
+ "items defaults to empty schema so everything is valid",
+ "data": [ 1, 2, 3, 4, 5 ],
+ "valid": true
+ },
+ {
+ "description": "ignores non-arrays",
+ "data": {"foo" : "bar"},
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "additionalItems are allowed by default",
+ "schema": {"items": [{"type": "integer"}]},
+ "tests": [
+ {
+ "description": "only the first item is validated",
+ "data": [1, "foo", false],
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/additionalProperties.json b/json/tests/draft4/additionalProperties.json
new file mode 100644
index 0000000..c997f75
--- /dev/null
+++ b/json/tests/draft4/additionalProperties.json
@@ -0,0 +1,63 @@
+[
+ {
+ "description":
+ "additionalProperties being false does not allow other properties",
+ "schema": {
+ "properties": {"foo": {}, "bar": {}},
+ "additionalProperties": false
+ },
+ "tests": [
+ {
+ "description": "no additional properties is valid",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "an additional property is invalid",
+ "data": {"foo" : 1, "bar" : 2, "quux" : "boom"},
+ "valid": false
+ },
+ {
+ "description": "ignores non-objects",
+ "data": [1, 2, 3],
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description":
+ "additionalProperties allows a schema which should validate",
+ "schema": {
+ "properties": {"foo": {}, "bar": {}},
+ "additionalProperties": {"type": "boolean"}
+ },
+ "tests": [
+ {
+ "description": "no additional properties is valid",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "an additional valid property is valid",
+ "data": {"foo" : 1, "bar" : 2, "quux" : true},
+ "valid": true
+ },
+ {
+ "description": "an additional invalid property is invalid",
+ "data": {"foo" : 1, "bar" : 2, "quux" : 12},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "additionalProperties are allowed by default",
+ "schema": {"properties": {"foo": {}, "bar": {}}},
+ "tests": [
+ {
+ "description": "additional properties are allowed",
+ "data": {"foo": 1, "bar": 2, "quux": true},
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/allOf.json b/json/tests/draft4/allOf.json
new file mode 100644
index 0000000..bbb5f89
--- /dev/null
+++ b/json/tests/draft4/allOf.json
@@ -0,0 +1,112 @@
+[
+ {
+ "description": "allOf",
+ "schema": {
+ "allOf": [
+ {
+ "properties": {
+ "bar": {"type": "integer"}
+ },
+ "required": ["bar"]
+ },
+ {
+ "properties": {
+ "foo": {"type": "string"}
+ },
+ "required": ["foo"]
+ }
+ ]
+ },
+ "tests": [
+ {
+ "description": "allOf",
+ "data": {"foo": "baz", "bar": 2},
+ "valid": true
+ },
+ {
+ "description": "mismatch second",
+ "data": {"foo": "baz"},
+ "valid": false
+ },
+ {
+ "description": "mismatch first",
+ "data": {"bar": 2},
+ "valid": false
+ },
+ {
+ "description": "wrong type",
+ "data": {"foo": "baz", "bar": "quux"},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "allOf with base schema",
+ "schema": {
+ "properties": {"bar": {"type": "integer"}},
+ "required": ["bar"],
+ "allOf" : [
+ {
+ "properties": {
+ "foo": {"type": "string"}
+ },
+ "required": ["foo"]
+ },
+ {
+ "properties": {
+ "baz": {"type": "null"}
+ },
+ "required": ["baz"]
+ }
+ ]
+ },
+ "tests": [
+ {
+ "description": "valid",
+ "data": {"foo": "quux", "bar": 2, "baz": null},
+ "valid": true
+ },
+ {
+ "description": "mismatch base schema",
+ "data": {"foo": "quux", "baz": null},
+ "valid": false
+ },
+ {
+ "description": "mismatch first allOf",
+ "data": {"bar": 2, "baz": null},
+ "valid": false
+ },
+ {
+ "description": "mismatch second allOf",
+ "data": {"foo": "quux", "bar": 2},
+ "valid": false
+ },
+ {
+ "description": "mismatch both",
+ "data": {"bar": 2},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "allOf simple types",
+ "schema": {
+ "allOf": [
+ {"maximum": 30},
+ {"minimum": 20}
+ ]
+ },
+ "tests": [
+ {
+ "description": "valid",
+ "data": 25,
+ "valid": true
+ },
+ {
+ "description": "mismatch one",
+ "data": 35,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/anyOf.json b/json/tests/draft4/anyOf.json
new file mode 100644
index 0000000..a58714a
--- /dev/null
+++ b/json/tests/draft4/anyOf.json
@@ -0,0 +1,68 @@
+[
+ {
+ "description": "anyOf",
+ "schema": {
+ "anyOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "minimum": 2
+ }
+ ]
+ },
+ "tests": [
+ {
+ "description": "first anyOf valid",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "second anyOf valid",
+ "data": 2.5,
+ "valid": true
+ },
+ {
+ "description": "both anyOf valid",
+ "data": 3,
+ "valid": true
+ },
+ {
+ "description": "neither anyOf valid",
+ "data": 1.5,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "anyOf with base schema",
+ "schema": {
+ "type": "string",
+ "anyOf" : [
+ {
+ "maxLength": 2
+ },
+ {
+ "minLength": 4
+ }
+ ]
+ },
+ "tests": [
+ {
+ "description": "mismatch base schema",
+ "data": 3,
+ "valid": false
+ },
+ {
+ "description": "one anyOf valid",
+ "data": "foobar",
+ "valid": true
+ },
+ {
+ "description": "both anyOf invalid",
+ "data": "foo",
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/definitions.json b/json/tests/draft4/definitions.json
new file mode 100644
index 0000000..cf935a3
--- /dev/null
+++ b/json/tests/draft4/definitions.json
@@ -0,0 +1,32 @@
+[
+ {
+ "description": "valid definition",
+ "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
+ "tests": [
+ {
+ "description": "valid definition schema",
+ "data": {
+ "definitions": {
+ "foo": {"type": "integer"}
+ }
+ },
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "invalid definition",
+ "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},
+ "tests": [
+ {
+ "description": "invalid definition schema",
+ "data": {
+ "definitions": {
+ "foo": {"type": 1}
+ }
+ },
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/dependencies.json b/json/tests/draft4/dependencies.json
new file mode 100644
index 0000000..7b9b16a
--- /dev/null
+++ b/json/tests/draft4/dependencies.json
@@ -0,0 +1,113 @@
+[
+ {
+ "description": "dependencies",
+ "schema": {
+ "dependencies": {"bar": ["foo"]}
+ },
+ "tests": [
+ {
+ "description": "neither",
+ "data": {},
+ "valid": true
+ },
+ {
+ "description": "nondependant",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "with dependency",
+ "data": {"foo": 1, "bar": 2},
+ "valid": true
+ },
+ {
+ "description": "missing dependency",
+ "data": {"bar": 2},
+ "valid": false
+ },
+ {
+ "description": "ignores non-objects",
+ "data": "foo",
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "multiple dependencies",
+ "schema": {
+ "dependencies": {"quux": ["foo", "bar"]}
+ },
+ "tests": [
+ {
+ "description": "neither",
+ "data": {},
+ "valid": true
+ },
+ {
+ "description": "nondependants",
+ "data": {"foo": 1, "bar": 2},
+ "valid": true
+ },
+ {
+ "description": "with dependencies",
+ "data": {"foo": 1, "bar": 2, "quux": 3},
+ "valid": true
+ },
+ {
+ "description": "missing dependency",
+ "data": {"foo": 1, "quux": 2},
+ "valid": false
+ },
+ {
+ "description": "missing other dependency",
+ "data": {"bar": 1, "quux": 2},
+ "valid": false
+ },
+ {
+ "description": "missing both dependencies",
+ "data": {"quux": 1},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "multiple dependencies subschema",
+ "schema": {
+ "dependencies": {
+ "bar": {
+ "properties": {
+ "foo": {"type": "integer"},
+ "bar": {"type": "integer"}
+ }
+ }
+ }
+ },
+ "tests": [
+ {
+ "description": "valid",
+ "data": {"foo": 1, "bar": 2},
+ "valid": true
+ },
+ {
+ "description": "no dependency",
+ "data": {"foo": "quux"},
+ "valid": true
+ },
+ {
+ "description": "wrong type",
+ "data": {"foo": "quux", "bar": 2},
+ "valid": false
+ },
+ {
+ "description": "wrong type other",
+ "data": {"foo": 2, "bar": "quux"},
+ "valid": false
+ },
+ {
+ "description": "wrong type both",
+ "data": {"foo": "quux", "bar": "quux"},
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/enum.json b/json/tests/draft4/enum.json
new file mode 100644
index 0000000..a539edb
--- /dev/null
+++ b/json/tests/draft4/enum.json
@@ -0,0 +1,39 @@
+[
+ {
+ "description": "simple enum validation",
+ "schema": {"enum": [1, 2, 3]},
+ "tests": [
+ {
+ "description": "one of the enum is valid",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "something else is invalid",
+ "data": 4,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "heterogeneous enum validation",
+ "schema": {"enum": [6, "foo", [], true, {"foo": 12}]},
+ "tests": [
+ {
+ "description": "one of the enum is valid",
+ "data": [],
+ "valid": true
+ },
+ {
+ "description": "something else is invalid",
+ "data": null,
+ "valid": false
+ },
+ {
+ "description": "objects are deep compared",
+ "data": {"foo": false},
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/items.json b/json/tests/draft4/items.json
new file mode 100644
index 0000000..f5e18a1
--- /dev/null
+++ b/json/tests/draft4/items.json
@@ -0,0 +1,46 @@
+[
+ {
+ "description": "a schema given for items",
+ "schema": {
+ "items": {"type": "integer"}
+ },
+ "tests": [
+ {
+ "description": "valid items",
+ "data": [ 1, 2, 3 ],
+ "valid": true
+ },
+ {
+ "description": "wrong type of items",
+ "data": [1, "x"],
+ "valid": false
+ },
+ {
+ "description": "ignores non-arrays",
+ "data": {"foo" : "bar"},
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "an array of schemas for items",
+ "schema": {
+ "items": [
+ {"type": "integer"},
+ {"type": "string"}
+ ]
+ },
+ "tests": [
+ {
+ "description": "correct types",
+ "data": [ 1, "foo" ],
+ "valid": true
+ },
+ {
+ "description": "wrong types",
+ "data": [ "foo", 1 ],
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/maxItems.json b/json/tests/draft4/maxItems.json
new file mode 100644
index 0000000..3b53a6b
--- /dev/null
+++ b/json/tests/draft4/maxItems.json
@@ -0,0 +1,28 @@
+[
+ {
+ "description": "maxItems validation",
+ "schema": {"maxItems": 2},
+ "tests": [
+ {
+ "description": "shorter is valid",
+ "data": [1],
+ "valid": true
+ },
+ {
+ "description": "exact length is valid",
+ "data": [1, 2],
+ "valid": true
+ },
+ {
+ "description": "too long is invalid",
+ "data": [1, 2, 3],
+ "valid": false
+ },
+ {
+ "description": "ignores non-arrays",
+ "data": "foobar",
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/maxLength.json b/json/tests/draft4/maxLength.json
new file mode 100644
index 0000000..561767b
--- /dev/null
+++ b/json/tests/draft4/maxLength.json
@@ -0,0 +1,28 @@
+[
+ {
+ "description": "maxLength validation",
+ "schema": {"maxLength": 2},
+ "tests": [
+ {
+ "description": "shorter is valid",
+ "data": "f",
+ "valid": true
+ },
+ {
+ "description": "exact length is valid",
+ "data": "fo",
+ "valid": true
+ },
+ {
+ "description": "too long is invalid",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "ignores non-strings",
+ "data": 10,
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/maxProperties.json b/json/tests/draft4/maxProperties.json
new file mode 100644
index 0000000..d282446
--- /dev/null
+++ b/json/tests/draft4/maxProperties.json
@@ -0,0 +1,28 @@
+[
+ {
+ "description": "maxProperties validation",
+ "schema": {"maxProperties": 2},
+ "tests": [
+ {
+ "description": "shorter is valid",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "exact length is valid",
+ "data": {"foo": 1, "bar": 2},
+ "valid": true
+ },
+ {
+ "description": "too long is invalid",
+ "data": {"foo": 1, "bar": 2, "baz": 3},
+ "valid": false
+ },
+ {
+ "description": "ignores non-objects",
+ "data": "foobar",
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/maximum.json b/json/tests/draft4/maximum.json
new file mode 100644
index 0000000..86c7b89
--- /dev/null
+++ b/json/tests/draft4/maximum.json
@@ -0,0 +1,42 @@
+[
+ {
+ "description": "maximum validation",
+ "schema": {"maximum": 3.0},
+ "tests": [
+ {
+ "description": "below the maximum is valid",
+ "data": 2.6,
+ "valid": true
+ },
+ {
+ "description": "above the maximum is invalid",
+ "data": 3.5,
+ "valid": false
+ },
+ {
+ "description": "ignores non-numbers",
+ "data": "x",
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "exclusiveMaximum validation",
+ "schema": {
+ "maximum": 3.0,
+ "exclusiveMaximum": true
+ },
+ "tests": [
+ {
+ "description": "below the maximum is still valid",
+ "data": 2.2,
+ "valid": true
+ },
+ {
+ "description": "boundary point is invalid",
+ "data": 3.0,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/minItems.json b/json/tests/draft4/minItems.json
new file mode 100644
index 0000000..ed51188
--- /dev/null
+++ b/json/tests/draft4/minItems.json
@@ -0,0 +1,28 @@
+[
+ {
+ "description": "minItems validation",
+ "schema": {"minItems": 1},
+ "tests": [
+ {
+ "description": "longer is valid",
+ "data": [1, 2],
+ "valid": true
+ },
+ {
+ "description": "exact length is valid",
+ "data": [1],
+ "valid": true
+ },
+ {
+ "description": "too short is invalid",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "ignores non-arrays",
+ "data": "",
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/minLength.json b/json/tests/draft4/minLength.json
new file mode 100644
index 0000000..e9c14b1
--- /dev/null
+++ b/json/tests/draft4/minLength.json
@@ -0,0 +1,28 @@
+[
+ {
+ "description": "minLength validation",
+ "schema": {"minLength": 2},
+ "tests": [
+ {
+ "description": "longer is valid",
+ "data": "foo",
+ "valid": true
+ },
+ {
+ "description": "exact length is valid",
+ "data": "fo",
+ "valid": true
+ },
+ {
+ "description": "too short is invalid",
+ "data": "f",
+ "valid": false
+ },
+ {
+ "description": "ignores non-strings",
+ "data": 1,
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/minProperties.json b/json/tests/draft4/minProperties.json
new file mode 100644
index 0000000..a72c7d2
--- /dev/null
+++ b/json/tests/draft4/minProperties.json
@@ -0,0 +1,28 @@
+[
+ {
+ "description": "minProperties validation",
+ "schema": {"minProperties": 1},
+ "tests": [
+ {
+ "description": "longer is valid",
+ "data": {"foo": 1, "bar": 2},
+ "valid": true
+ },
+ {
+ "description": "exact length is valid",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "too short is invalid",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "ignores non-objects",
+ "data": "",
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/minimum.json b/json/tests/draft4/minimum.json
new file mode 100644
index 0000000..d5bf000
--- /dev/null
+++ b/json/tests/draft4/minimum.json
@@ -0,0 +1,42 @@
+[
+ {
+ "description": "minimum validation",
+ "schema": {"minimum": 1.1},
+ "tests": [
+ {
+ "description": "above the minimum is valid",
+ "data": 2.6,
+ "valid": true
+ },
+ {
+ "description": "below the minimum is invalid",
+ "data": 0.6,
+ "valid": false
+ },
+ {
+ "description": "ignores non-numbers",
+ "data": "x",
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "exclusiveMinimum validation",
+ "schema": {
+ "minimum": 1.1,
+ "exclusiveMinimum": true
+ },
+ "tests": [
+ {
+ "description": "above the minimum is still valid",
+ "data": 1.2,
+ "valid": true
+ },
+ {
+ "description": "boundary point is invalid",
+ "data": 1.1,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/multipleOf.json b/json/tests/draft4/multipleOf.json
new file mode 100644
index 0000000..ca3b761
--- /dev/null
+++ b/json/tests/draft4/multipleOf.json
@@ -0,0 +1,60 @@
+[
+ {
+ "description": "by int",
+ "schema": {"multipleOf": 2},
+ "tests": [
+ {
+ "description": "int by int",
+ "data": 10,
+ "valid": true
+ },
+ {
+ "description": "int by int fail",
+ "data": 7,
+ "valid": false
+ },
+ {
+ "description": "ignores non-numbers",
+ "data": "foo",
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "by number",
+ "schema": {"multipleOf": 1.5},
+ "tests": [
+ {
+ "description": "zero is multiple of anything",
+ "data": 0,
+ "valid": true
+ },
+ {
+ "description": "4.5 is multiple of 1.5",
+ "data": 4.5,
+ "valid": true
+ },
+ {
+ "description": "35 is not multiple of 1.5",
+ "data": 35,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "by small number",
+ "schema": {"multipleOf": 0.0001},
+ "tests": [
+ {
+ "description": "0.0075 is multiple of 0.0001",
+ "data": 0.0075,
+ "valid": true
+ },
+ {
+ "description": "0.00751 is not multiple of 0.0001",
+ "data": 0.00751,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/not.json b/json/tests/draft4/not.json
new file mode 100644
index 0000000..2cdc979
--- /dev/null
+++ b/json/tests/draft4/not.json
@@ -0,0 +1,73 @@
+[
+ {
+ "description": "not",
+ "schema": {
+ "not": {"type": "integer"}
+ },
+ "tests": [
+ {
+ "description": "allowed",
+ "data": "foo",
+ "valid": true
+ },
+ {
+ "description": "disallowed",
+ "data": 1,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "not multiple types",
+ "schema": {
+ "not": {"type": ["integer", "boolean"]}
+ },
+ "tests": [
+ {
+ "description": "valid",
+ "data": "foo",
+ "valid": true
+ },
+ {
+ "description": "mismatch",
+ "data": 1,
+ "valid": false
+ },
+ {
+ "description": "other mismatch",
+ "data": true,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "not more complex schema",
+ "schema": {
+ "not": {
+ "type": "object",
+ "properties": {
+ "foo": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "tests": [
+ {
+ "description": "match",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "other match",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "mismatch",
+ "data": {"foo": "bar"},
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/oneOf.json b/json/tests/draft4/oneOf.json
new file mode 100644
index 0000000..1eaa4e4
--- /dev/null
+++ b/json/tests/draft4/oneOf.json
@@ -0,0 +1,68 @@
+[
+ {
+ "description": "oneOf",
+ "schema": {
+ "oneOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "minimum": 2
+ }
+ ]
+ },
+ "tests": [
+ {
+ "description": "first oneOf valid",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "second oneOf valid",
+ "data": 2.5,
+ "valid": true
+ },
+ {
+ "description": "both oneOf valid",
+ "data": 3,
+ "valid": false
+ },
+ {
+ "description": "neither oneOf valid",
+ "data": 1.5,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "oneOf with base schema",
+ "schema": {
+ "type": "string",
+ "oneOf" : [
+ {
+ "minLength": 2
+ },
+ {
+ "maxLength": 4
+ }
+ ]
+ },
+ "tests": [
+ {
+ "description": "mismatch base schema",
+ "data": 3,
+ "valid": false
+ },
+ {
+ "description": "one oneOf valid",
+ "data": "foobar",
+ "valid": true
+ },
+ {
+ "description": "both oneOf valid",
+ "data": "foo",
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/optional/bignum.json b/json/tests/draft4/optional/bignum.json
new file mode 100644
index 0000000..7b4755c
--- /dev/null
+++ b/json/tests/draft4/optional/bignum.json
@@ -0,0 +1,49 @@
+[
+ {
+ "description": "integer",
+ "schema": {"type": "integer"},
+ "tests": [
+ {
+ "description": "a bignum is an integer",
+ "data": 12345678910111213141516171819202122232425262728293031,
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "number",
+ "schema": {"type": "number"},
+ "tests": [
+ {
+ "description": "a bignum is a number",
+ "data": 98249283749234923498293171823948729348710298301928331,
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "string",
+ "schema": {"type": "string"},
+ "tests": [
+ {
+ "description": "a bignum is not a string",
+ "data": 98249283749234923498293171823948729348710298301928331,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "float comparison with high precision",
+ "schema": {
+ "maximum": 972783798187987123879878123.18878137,
+ "exclusiveMaximum": true
+ },
+ "tests": [
+ {
+ "description": "comparison works for high numbers",
+ "data": 972783798187987123879878123.188781371,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/optional/format.json b/json/tests/draft4/optional/format.json
new file mode 100644
index 0000000..ad998ca
--- /dev/null
+++ b/json/tests/draft4/optional/format.json
@@ -0,0 +1,139 @@
+[
+ {
+ "description": "validation of regular expressions",
+ "schema": {"format": "regex"},
+ "tests": [
+ {
+ "description": "a valid regular expression",
+ "data": "([abc])+\\s+$",
+ "valid": true
+ },
+ {
+ "description": "a regular expression with unclosed parens is invalid",
+ "data": "^(abc]",
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "validation of date-time strings",
+ "schema": {"format": "date-time"},
+ "tests": [
+ {
+ "description": "a valid date-time string",
+ "data": "1963-06-19T08:30:06.283185Z",
+ "valid": true
+ },
+ {
+ "description": "an invalid date-time string",
+ "data": "06/19/1963 08:30:06 PST",
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "validation of URIs",
+ "schema": {"format": "uri"},
+ "tests": [
+ {
+ "description": "a valid URI",
+ "data": "http://foo.bar/?baz=qux#quux",
+ "valid": true
+ },
+ {
+ "description": "an invalid URI",
+ "data": "\\\\WINDOWS\\fileshare",
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "validation of e-mail addresses",
+ "schema": {"format": "email"},
+ "tests": [
+ {
+ "description": "a valid e-mail address",
+ "data": "joe.bloggs@example.com",
+ "valid": true
+ },
+ {
+ "description": "an invalid e-mail address",
+ "data": "2962",
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "validation of IP addresses",
+ "schema": {"format": "ipv4"},
+ "tests": [
+ {
+ "description": "a valid IP address",
+ "data": "192.168.0.1",
+ "valid": true
+ },
+ {
+ "description": "an IP address with too many components",
+ "data": "127.0.0.0.1",
+ "valid": false
+ },
+ {
+ "description": "an IP address with out-of-range values",
+ "data": "256.256.256.256",
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "validation of IPv6 addresses",
+ "schema": {"format": "ipv6"},
+ "tests": [
+ {
+ "description": "a valid IPv6 address",
+ "data": "::1",
+ "valid": true
+ },
+ {
+ "description": "an IPv6 address with out-of-range values",
+ "data": "12345::",
+ "valid": false
+ },
+ {
+ "description": "an IPv6 address with too many components",
+ "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",
+ "valid": false
+ },
+ {
+ "description": "an IPv6 address containing illegal characters",
+ "data": "::laptop",
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "validation of host names",
+ "schema": {"format": "hostname"},
+ "tests": [
+ {
+ "description": "a valid host name",
+ "data": "www.example.com",
+ "valid": true
+ },
+ {
+ "description": "a host name starting with an illegal character",
+ "data": "-a-host-name-that-starts-with--",
+ "valid": false
+ },
+ {
+ "description": "a host name containing illegal characters",
+ "data": "not_a_valid_host_name",
+ "valid": false
+ },
+ {
+ "description": "a host name with a component too long",
+ "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/optional/jsregex.json b/json/tests/draft4/optional/jsregex.json
new file mode 100644
index 0000000..03fe977
--- /dev/null
+++ b/json/tests/draft4/optional/jsregex.json
@@ -0,0 +1,18 @@
+[
+ {
+ "description": "ECMA 262 regex dialect recognition",
+ "schema": { "format": "regex" },
+ "tests": [
+ {
+ "description": "[^] is a valid regex",
+ "data": "[^]",
+ "valid": true
+ },
+ {
+ "description": "ECMA 262 has no support for lookbehind",
+ "data": "(?<=foo)bar",
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/optional/zeroTerminatedFloats.json b/json/tests/draft4/optional/zeroTerminatedFloats.json
new file mode 100644
index 0000000..9b50ea2
--- /dev/null
+++ b/json/tests/draft4/optional/zeroTerminatedFloats.json
@@ -0,0 +1,15 @@
+[
+ {
+ "description": "some languages do not distinguish between different types of numeric value",
+ "schema": {
+ "type": "integer"
+ },
+ "tests": [
+ {
+ "description": "a float is not an integer even without fractional part",
+ "data": 1.0,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/pattern.json b/json/tests/draft4/pattern.json
new file mode 100644
index 0000000..befc4b5
--- /dev/null
+++ b/json/tests/draft4/pattern.json
@@ -0,0 +1,23 @@
+[
+ {
+ "description": "pattern validation",
+ "schema": {"pattern": "^a*$"},
+ "tests": [
+ {
+ "description": "a matching pattern is valid",
+ "data": "aaa",
+ "valid": true
+ },
+ {
+ "description": "a non-matching pattern is invalid",
+ "data": "abc",
+ "valid": false
+ },
+ {
+ "description": "ignores non-strings",
+ "data": true,
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/patternProperties.json b/json/tests/draft4/patternProperties.json
new file mode 100644
index 0000000..18586e5
--- /dev/null
+++ b/json/tests/draft4/patternProperties.json
@@ -0,0 +1,110 @@
+[
+ {
+ "description":
+ "patternProperties validates properties matching a regex",
+ "schema": {
+ "patternProperties": {
+ "f.*o": {"type": "integer"}
+ }
+ },
+ "tests": [
+ {
+ "description": "a single valid match is valid",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "multiple valid matches is valid",
+ "data": {"foo": 1, "foooooo" : 2},
+ "valid": true
+ },
+ {
+ "description": "a single invalid match is invalid",
+ "data": {"foo": "bar", "fooooo": 2},
+ "valid": false
+ },
+ {
+ "description": "multiple invalid matches is invalid",
+ "data": {"foo": "bar", "foooooo" : "baz"},
+ "valid": false
+ },
+ {
+ "description": "ignores non-objects",
+ "data": 12,
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "multiple simultaneous patternProperties are validated",
+ "schema": {
+ "patternProperties": {
+ "a*": {"type": "integer"},
+ "aaa*": {"maximum": 20}
+ }
+ },
+ "tests": [
+ {
+ "description": "a single valid match is valid",
+ "data": {"a": 21},
+ "valid": true
+ },
+ {
+ "description": "a simultaneous match is valid",
+ "data": {"aaaa": 18},
+ "valid": true
+ },
+ {
+ "description": "multiple matches is valid",
+ "data": {"a": 21, "aaaa": 18},
+ "valid": true
+ },
+ {
+ "description": "an invalid due to one is invalid",
+ "data": {"a": "bar"},
+ "valid": false
+ },
+ {
+ "description": "an invalid due to the other is invalid",
+ "data": {"aaaa": 31},
+ "valid": false
+ },
+ {
+ "description": "an invalid due to both is invalid",
+ "data": {"aaa": "foo", "aaaa": 31},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "regexes are not anchored by default and are case sensitive",
+ "schema": {
+ "patternProperties": {
+ "[0-9]{2,}": { "type": "boolean" },
+ "X_": { "type": "string" }
+ }
+ },
+ "tests": [
+ {
+ "description": "non recognized members are ignored",
+ "data": { "answer 1": "42" },
+ "valid": true
+ },
+ {
+ "description": "recognized members are accounted for",
+ "data": { "a31b": null },
+ "valid": false
+ },
+ {
+ "description": "regexes are case sensitive",
+ "data": { "a_x_3": 3 },
+ "valid": true
+ },
+ {
+ "description": "regexes are case sensitive, 2",
+ "data": { "a_X_3": 3 },
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/properties.json b/json/tests/draft4/properties.json
new file mode 100644
index 0000000..cd1644d
--- /dev/null
+++ b/json/tests/draft4/properties.json
@@ -0,0 +1,92 @@
+[
+ {
+ "description": "object properties validation",
+ "schema": {
+ "properties": {
+ "foo": {"type": "integer"},
+ "bar": {"type": "string"}
+ }
+ },
+ "tests": [
+ {
+ "description": "both properties present and valid is valid",
+ "data": {"foo": 1, "bar": "baz"},
+ "valid": true
+ },
+ {
+ "description": "one property invalid is invalid",
+ "data": {"foo": 1, "bar": {}},
+ "valid": false
+ },
+ {
+ "description": "both properties invalid is invalid",
+ "data": {"foo": [], "bar": {}},
+ "valid": false
+ },
+ {
+ "description": "doesn't invalidate other properties",
+ "data": {"quux": []},
+ "valid": true
+ },
+ {
+ "description": "ignores non-objects",
+ "data": [],
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description":
+ "properties, patternProperties, additionalProperties interaction",
+ "schema": {
+ "properties": {
+ "foo": {"type": "array", "maxItems": 3},
+ "bar": {"type": "array"}
+ },
+ "patternProperties": {"f.o": {"minItems": 2}},
+ "additionalProperties": {"type": "integer"}
+ },
+ "tests": [
+ {
+ "description": "property validates property",
+ "data": {"foo": [1, 2]},
+ "valid": true
+ },
+ {
+ "description": "property invalidates property",
+ "data": {"foo": [1, 2, 3, 4]},
+ "valid": false
+ },
+ {
+ "description": "patternProperty invalidates property",
+ "data": {"foo": []},
+ "valid": false
+ },
+ {
+ "description": "patternProperty validates nonproperty",
+ "data": {"fxo": [1, 2]},
+ "valid": true
+ },
+ {
+ "description": "patternProperty invalidates nonproperty",
+ "data": {"fxo": []},
+ "valid": false
+ },
+ {
+ "description": "additionalProperty ignores property",
+ "data": {"bar": []},
+ "valid": true
+ },
+ {
+ "description": "additionalProperty validates others",
+ "data": {"quux": 3},
+ "valid": true
+ },
+ {
+ "description": "additionalProperty invalidates others",
+ "data": {"quux": "foo"},
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/ref.json b/json/tests/draft4/ref.json
new file mode 100644
index 0000000..e5f01a6
--- /dev/null
+++ b/json/tests/draft4/ref.json
@@ -0,0 +1,84 @@
+[
+ {
+ "description": "root pointer ref",
+ "schema": {
+ "properties": {
+ "foo": {"$ref": "#"}
+ },
+ "additionalProperties": false
+ },
+ "tests": [
+ {
+ "description": "match",
+ "data": {"foo": false},
+ "valid": true
+ },
+ {
+ "description": "recursive match",
+ "data": {"foo": {"foo": false}},
+ "valid": true
+ },
+ {
+ "description": "mismatch",
+ "data": {"bar": false},
+ "valid": false
+ },
+ {
+ "description": "recursive mismatch",
+ "data": {"foo": {"bar": false}},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "relative pointer ref",
+ "schema": {
+ "properties": {
+ "foo": {"type": "integer"},
+ "bar": {"$ref": "#/properties/foo"}
+ }
+ },
+ "tests": [
+ {
+ "description": "match",
+ "data": {"bar": 3},
+ "valid": true
+ },
+ {
+ "description": "mismatch",
+ "data": {"bar": true},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "escaped pointer ref",
+ "schema": {
+ "tilda~field": {"type": "integer"},
+ "slash/field": {"type": "integer"},
+ "percent%field": {"type": "integer"},
+ "properties": {
+ "tilda": {"$ref": "#/tilda~0field"},
+ "slash": {"$ref": "#/slash~1field"},
+ "percent": {"$ref": "#/percent%25field"}
+ }
+ },
+ "tests": [
+ {
+ "description": "slash",
+ "data": {"slash": "aoeu"},
+ "valid": false
+ },
+ {
+ "description": "tilda",
+ "data": {"tilda": "aoeu"},
+ "valid": false
+ },
+ {
+ "description": "percent",
+ "data": {"percent": "aoeu"},
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/required.json b/json/tests/draft4/required.json
new file mode 100644
index 0000000..612f73f
--- /dev/null
+++ b/json/tests/draft4/required.json
@@ -0,0 +1,39 @@
+[
+ {
+ "description": "required validation",
+ "schema": {
+ "properties": {
+ "foo": {},
+ "bar": {}
+ },
+ "required": ["foo"]
+ },
+ "tests": [
+ {
+ "description": "present required property is valid",
+ "data": {"foo": 1},
+ "valid": true
+ },
+ {
+ "description": "non-present required property is invalid",
+ "data": {"bar": 1},
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "required default validation",
+ "schema": {
+ "properties": {
+ "foo": {}
+ }
+ },
+ "tests": [
+ {
+ "description": "not required by default",
+ "data": {},
+ "valid": true
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/type.json b/json/tests/draft4/type.json
new file mode 100644
index 0000000..257f051
--- /dev/null
+++ b/json/tests/draft4/type.json
@@ -0,0 +1,330 @@
+[
+ {
+ "description": "integer type matches integers",
+ "schema": {"type": "integer"},
+ "tests": [
+ {
+ "description": "an integer is an integer",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "a float is not an integer",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "a string is not an integer",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "an object is not an integer",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is not an integer",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is not an integer",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is not an integer",
+ "data": null,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "number type matches numbers",
+ "schema": {"type": "number"},
+ "tests": [
+ {
+ "description": "an integer is a number",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "a float is a number",
+ "data": 1.1,
+ "valid": true
+ },
+ {
+ "description": "a string is not a number",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "an object is not a number",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is not a number",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is not a number",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is not a number",
+ "data": null,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "string type matches strings",
+ "schema": {"type": "string"},
+ "tests": [
+ {
+ "description": "1 is not a string",
+ "data": 1,
+ "valid": false
+ },
+ {
+ "description": "a float is not a string",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "a string is a string",
+ "data": "foo",
+ "valid": true
+ },
+ {
+ "description": "an object is not a string",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is not a string",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is not a string",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is not a string",
+ "data": null,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "object type matches objects",
+ "schema": {"type": "object"},
+ "tests": [
+ {
+ "description": "an integer is not an object",
+ "data": 1,
+ "valid": false
+ },
+ {
+ "description": "a float is not an object",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "a string is not an object",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "an object is an object",
+ "data": {},
+ "valid": true
+ },
+ {
+ "description": "an array is not an object",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is not an object",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is not an object",
+ "data": null,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "array type matches arrays",
+ "schema": {"type": "array"},
+ "tests": [
+ {
+ "description": "an integer is not an array",
+ "data": 1,
+ "valid": false
+ },
+ {
+ "description": "a float is not an array",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "a string is not an array",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "an object is not an array",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is not an array",
+ "data": [],
+ "valid": true
+ },
+ {
+ "description": "a boolean is not an array",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is not an array",
+ "data": null,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "boolean type matches booleans",
+ "schema": {"type": "boolean"},
+ "tests": [
+ {
+ "description": "an integer is not a boolean",
+ "data": 1,
+ "valid": false
+ },
+ {
+ "description": "a float is not a boolean",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "a string is not a boolean",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "an object is not a boolean",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is not a boolean",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is not a boolean",
+ "data": true,
+ "valid": true
+ },
+ {
+ "description": "null is not a boolean",
+ "data": null,
+ "valid": false
+ }
+ ]
+ },
+ {
+ "description": "null type matches only the null object",
+ "schema": {"type": "null"},
+ "tests": [
+ {
+ "description": "an integer is not null",
+ "data": 1,
+ "valid": false
+ },
+ {
+ "description": "a float is not null",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "a string is not null",
+ "data": "foo",
+ "valid": false
+ },
+ {
+ "description": "an object is not null",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is not null",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is not null",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is null",
+ "data": null,
+ "valid": true
+ }
+ ]
+ },
+ {
+ "description": "multiple types can be specified in an array",
+ "schema": {"type": ["integer", "string"]},
+ "tests": [
+ {
+ "description": "an integer is valid",
+ "data": 1,
+ "valid": true
+ },
+ {
+ "description": "a string is valid",
+ "data": "foo",
+ "valid": true
+ },
+ {
+ "description": "a float is invalid",
+ "data": 1.1,
+ "valid": false
+ },
+ {
+ "description": "an object is invalid",
+ "data": {},
+ "valid": false
+ },
+ {
+ "description": "an array is invalid",
+ "data": [],
+ "valid": false
+ },
+ {
+ "description": "a boolean is invalid",
+ "data": true,
+ "valid": false
+ },
+ {
+ "description": "null is invalid",
+ "data": null,
+ "valid": false
+ }
+ ]
+ }
+]
diff --git a/json/tests/draft4/uniqueItems.json b/json/tests/draft4/uniqueItems.json
new file mode 100644
index 0000000..c1f4ab9
--- /dev/null
+++ b/json/tests/draft4/uniqueItems.json
@@ -0,0 +1,79 @@
+[
+ {
+ "description": "uniqueItems validation",
+ "schema": {"uniqueItems": true},
+ "tests": [
+ {
+ "description": "unique array of integers is valid",
+ "data": [1, 2],
+ "valid": true
+ },
+ {
+ "description": "non-unique array of integers is invalid",
+ "data": [1, 1],
+ "valid": false
+ },
+ {
+ "description": "numbers are unique if mathematically unequal",
+ "data": [1.0, 1.00, 1],
+ "valid": false
+ },
+ {
+ "description": "unique array of objects is valid",
+ "data": [{"foo": "bar"}, {"foo": "baz"}],
+ "valid": true
+ },
+ {
+ "description": "non-unique array of objects is invalid",
+ "data": [{"foo": "bar"}, {"foo": "bar"}],
+ "valid": false
+ },
+ {
+ "description": "unique array of nested objects is valid",
+ "data": [
+ {"foo": {"bar" : {"baz" : true}}},
+ {"foo": {"bar" : {"baz" : false}}}
+ ],
+ "valid": true
+ },
+ {
+ "description": "non-unique array of nested objects is invalid",
+ "data": [
+ {"foo": {"bar" : {"baz" : true}}},
+ {"foo": {"bar" : {"baz" : true}}}
+ ],
+ "valid": false
+ },
+ {
+ "description": "unique array of arrays is valid",
+ "data": [["foo"], ["bar"]],
+ "valid": true
+ },
+ {
+ "description": "non-unique array of arrays is invalid",
+ "data": [["foo"], ["foo"]],
+ "valid": false
+ },
+ {
+ "description": "1 and true are unique",
+ "data": [1, true],
+ "valid": true
+ },
+ {
+ "description": "0 and false are unique",
+ "data": [0, false],
+ "valid": true
+ },
+ {
+ "description": "unique heterogeneous types are valid",
+ "data": [{}, [1], true, null, 1],
+ "valid": true
+ },
+ {
+ "description": "non-unique heterogeneous types are invalid",
+ "data": [{}, [1], true, null, {}, 1],
+ "valid": false
+ }
+ ]
+ }
+]