From 3b4aa9954a8e9d92c90dba70b1f40a7456c14b7f Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Sat, 25 Jun 2022 10:23:10 -0400 Subject: [PATCH] Re-add the future keywords tests. The intent of them is *not* to express that an implementation might wish to recognize these keywords. The intent of them is precisely the same as the original intent -- to allow an implementation to test itself for *not* recognizing new keywords. Such an implementation should enable these tests, as it is free to do so, and these tests will help ensure it does not accidentally leak newer keywords backwards in time if it doesn't mean to. All of the previous discussion was strictly centered on not putting these in the required directory. The reason is that all drafts *allow* implementations to add extra keywords. So a compliant implementation may indeed decide it actively *wants* to implement new keywords. Then this file would not help them, and they wouldn't run it. They would presumably love a version of this file that *did* contain all the future assertions as correct for future drafts, and in the future we could provide one. But given no implementations really do do this, at least as far as I'm aware, and given that this version of the file is here and written and more common, it would seem perfectly reasonable to have it and hope for the other version if or when someone wants it. Further discussion is in #383 and later #559. This reverts commit f605fbfe463333b72ead7a156195f1317f72d45f. --- .../optional/future-keywords.json | 80 +++ tests/draft4/optional/future-keywords.json | 540 ++++++++++++++++++ tests/draft6/optional/future-keywords.json | 465 +++++++++++++++ tests/draft7/optional/future-keywords.json | 433 ++++++++++++++ 4 files changed, 1518 insertions(+) create mode 100644 tests/draft2019-09/optional/future-keywords.json create mode 100644 tests/draft4/optional/future-keywords.json create mode 100644 tests/draft6/optional/future-keywords.json create mode 100644 tests/draft7/optional/future-keywords.json diff --git a/tests/draft2019-09/optional/future-keywords.json b/tests/draft2019-09/optional/future-keywords.json new file mode 100644 index 00000000..a67b71e9 --- /dev/null +++ b/tests/draft2019-09/optional/future-keywords.json @@ -0,0 +1,80 @@ +[ + { + "description": "$dynamicRef without $dynamicAnchor works like $ref", + "schema": { + "$schema": "https://json-schema.org/draft/2019-09/schema", + "properties": { + "foo": {"$dynamicRef": "#"} + }, + "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 (but $dynamicRef is ignored)", + "data": {"foo": {"bar": false}}, + "valid": true + } + ] + }, + { + "description": "prefixItems: an array of schemas for items", + "schema": { + "$schema": "https://json-schema.org/draft/2019-09/schema", + "prefixItems": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": true + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + } +] diff --git a/tests/draft4/optional/future-keywords.json b/tests/draft4/optional/future-keywords.json new file mode 100644 index 00000000..49404635 --- /dev/null +++ b/tests/draft4/optional/future-keywords.json @@ -0,0 +1,540 @@ +[ + { + "description": "$dynamicRef without $dynamicAnchor works like $ref", + "schema": { + "properties": { + "foo": {"$dynamicRef": "#"} + }, + "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 (but $dynamicRef is ignored)", + "data": {"foo": {"bar": false}}, + "valid": true + } + ] + }, + { + "description": "prefixItems: an array of schemas for items", + "schema": { + "prefixItems": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": true + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + }, + { + "description": "dependentSchemas: single dependency", + "schema": { + "dependentSchemas": { + "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": true + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": true + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": true + } + ] + }, + { + "description": "dependentRequired: single dependency", + "schema": {"dependentRequired": {"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": true + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "unevaluatedItems false", + "schema": { + "type": "array", + "unevaluatedItems": false + }, + "tests": [ + { + "description": "with no unevaluated items", + "data": [], + "valid": true + }, + { + "description": "with unevaluated items", + "data": ["foo"], + "valid": true + } + ] + }, + { + "description": "unevaluatedProperties schema", + "schema": { + "type": "object", + "unevaluatedProperties": { + "type": "string", + "minLength": 3 + } + }, + "tests": [ + { + "description": "with no unevaluated properties", + "data": {}, + "valid": true + }, + { + "description": "with valid unevaluated properties", + "data": { + "foo": "foo" + }, + "valid": true + }, + { + "description": "with invalid unevaluated properties", + "data": { + "foo": "fo" + }, + "valid": true + } + ] + }, + { + "description": "maxContains with contains", + "schema": { + "contains": {"const": 1}, + "maxContains": 1 + }, + "tests": [ + { + "description": "empty data", + "data": [ ], + "valid": true + }, + { + "description": "all elements match, valid maxContains", + "data": [ 1 ], + "valid": true + }, + { + "description": "all elements match, invalid maxContains", + "data": [ 1, 1 ], + "valid": true + }, + { + "description": "some elements match, valid maxContains", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "some elements match, invalid maxContains", + "data": [ 1, 2, 1 ], + "valid": true + } + ] + }, + { + "description": "minContains=2 with contains", + "schema": { + "contains": {"const": 1}, + "minContains": 2 + }, + "tests": [ + { + "description": "empty data", + "data": [ ], + "valid": true + }, + { + "description": "all elements match, invalid minContains", + "data": [ 1 ], + "valid": true + }, + { + "description": "some elements match, invalid minContains", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "all elements match, valid minContains (exactly as needed)", + "data": [ 1, 1 ], + "valid": true + }, + { + "description": "all elements match, valid minContains (more than needed)", + "data": [ 1, 1, 1 ], + "valid": true + }, + { + "description": "some elements match, valid minContains", + "data": [ 1, 2, 1 ], + "valid": true + } + ] + }, + { + "description": "minContains = 0", + "schema": { + "contains": {"const": 1}, + "minContains": 0 + }, + "tests": [ + { + "description": "empty array is valid with minContains=0", + "data": [ ], + "valid": true + }, + { + "description": "minContains = 0 would make contains always pass", + "data": [ 2 ], + "valid": true + } + ] + }, + { + "description": "if with boolean schema true", + "schema": { "if": true, "then": { "const": "then" }, "else": { "const": "else" } }, + "tests": [ + { + "description": "boolean schema true in if (invalid when supported)", + "data": "then", + "valid": true + }, + { + "description": "boolean schema true in if (valid when supported)", + "data": "else", + "valid": true + } + ] + }, + { + "description": "contains keyword validation", + "schema": { + "contains": {"minimum": 5} + }, + "tests": [ + { + "description": "array with item matching schema (5) is valid", + "data": [3, 4, 5], + "valid": true + }, + { + "description": "array with item matching schema (6) is valid", + "data": [3, 4, 6], + "valid": true + }, + { + "description": "array with two items matching schema (5, 6) is valid", + "data": [3, 4, 5, 6], + "valid": true + }, + { + "description": "array without items matching schema is valid", + "data": [2, 3, 4], + "valid": true + }, + { + "description": "empty array is valid", + "data": [], + "valid": true + }, + { + "description": "not array is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "if with boolean schema false", + "schema": { "if": false, "then": { "const": "then" }, "else": { "const": "else" } }, + "tests": [ + { + "description": "boolean schema false in if (invalid when supported)", + "data": "then", + "valid": true + }, + { + "description": "boolean schema false in if (valid when supported)", + "data": "else", + "valid": true + } + ] + }, + { + "description": "propertyNames with boolean schema false", + "schema": {"propertyNames": false}, + "tests": [ + { + "description": "object with any properties is invalid", + "data": {"foo": 1}, + "valid": true + }, + { + "description": "empty object is valid", + "data": {}, + "valid": true + } + ] + }, + { + "description": "const validation", + "schema": {"const": 2}, + "tests": [ + { + "description": "same value is valid", + "data": 2, + "valid": true + }, + { + "description": "another value is invalid", + "data": 5, + "valid": true + }, + { + "description": "another type is invalid", + "data": "a", + "valid": true + } + ] + }, + { + "description": "$recursiveRef without $recursiveAnchor works like $ref", + "schema": { + "properties": { + "foo": { "$recursiveRef": "#" } + }, + "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": true + } + ] + }, + { + "description": "$recursiveRef without using nesting", + "schema": { + "$id": "http://localhost:4242", + "definitions": { + "myobject": { + "$id": "myobject.json", + "$recursiveAnchor": true, + "anyOf": [ + { "type": "string" }, + { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" } + } + ] + } + }, + "anyOf": [ + { "type": "integer" }, + { "$ref": "#/definitions/myobject" } + ] + }, + "tests": [ + { + "description": "integer matches at the outer level", + "data": 1, + "valid": true + }, + { + "description": "single level match", + "data": { "foo": "hi" }, + "valid": true + }, + { + "description": "integer does not match as a property value", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "two levels, additionalProperties always matches, 1", + "data": { "foo": { "bar": "hi" } }, + "valid": true + }, + { + "description": "two levels, additionalProperties always matches, 2", + "data": { "foo": { "bar": 1 } }, + "valid": true + } + ] + }, + { + "description": "$recursiveRef with nesting", + "schema": { + "$id": "http://localhost:4242", + "$recursiveAnchor": true, + "definitions": { + "myobject": { + "$id": "myobject.json", + "$recursiveAnchor": true, + "anyOf": [ + { "type": "string" }, + { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" } + } + ] + } + }, + "anyOf": [ + { "type": "integer" }, + { "$ref": "#/definitions/myobject" } + ] + }, + "tests": [ + { + "description": "integer matches at the outer level", + "data": 1, + "valid": true + }, + { + "description": "single level match", + "data": { "foo": "hi" }, + "valid": true + }, + { + "description": "integer now matches as a property value", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "two levels, properties match with inner definition", + "data": { "foo": { "bar": "hi" } }, + "valid": true + }, + { + "description": "two levels, properties match with $recursiveRef", + "data": { "foo": { "bar": 1 } }, + "valid": true + } + ] + } +] diff --git a/tests/draft6/optional/future-keywords.json b/tests/draft6/optional/future-keywords.json new file mode 100644 index 00000000..af2f7913 --- /dev/null +++ b/tests/draft6/optional/future-keywords.json @@ -0,0 +1,465 @@ +[ + { + "description": "$dynamicRef without $dynamicAnchor works like $ref", + "schema": { + "properties": { + "foo": {"$dynamicRef": "#"} + }, + "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 (but $dynamicRef is ignored)", + "data": {"foo": {"bar": false}}, + "valid": true + } + ] + }, + { + "description": "prefixItems: an array of schemas for items", + "schema": { + "prefixItems": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": true + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + }, + { + "description": "dependentSchemas: single dependency", + "schema": { + "dependentSchemas": { + "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": true + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": true + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": true + } + ] + }, + { + "description": "dependentRequired: single dependency", + "schema": {"dependentRequired": {"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": true + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "unevaluatedItems false", + "schema": { + "type": "array", + "unevaluatedItems": false + }, + "tests": [ + { + "description": "with no unevaluated items", + "data": [], + "valid": true + }, + { + "description": "with unevaluated items", + "data": ["foo"], + "valid": true + } + ] + }, + { + "description": "unevaluatedProperties schema", + "schema": { + "type": "object", + "unevaluatedProperties": { + "type": "string", + "minLength": 3 + } + }, + "tests": [ + { + "description": "with no unevaluated properties", + "data": {}, + "valid": true + }, + { + "description": "with valid unevaluated properties", + "data": { + "foo": "foo" + }, + "valid": true + }, + { + "description": "with invalid unevaluated properties", + "data": { + "foo": "fo" + }, + "valid": true + } + ] + }, + { + "description": "maxContains with contains", + "schema": { + "contains": {"const": 1}, + "maxContains": 1 + }, + "tests": [ + { + "description": "empty data", + "data": [ ], + "valid": false + }, + { + "description": "all elements match, valid maxContains", + "data": [ 1 ], + "valid": true + }, + { + "description": "all elements match, invalid maxContains", + "data": [ 1, 1 ], + "valid": true + }, + { + "description": "some elements match, valid maxContains", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "some elements match, invalid maxContains", + "data": [ 1, 2, 1 ], + "valid": true + } + ] + }, + { + "description": "minContains=2 with contains", + "schema": { + "contains": {"const": 1}, + "minContains": 2 + }, + "tests": [ + { + "description": "empty data", + "data": [ ], + "valid": false + }, + { + "description": "all elements match, invalid minContains", + "data": [ 1 ], + "valid": true + }, + { + "description": "some elements match, invalid minContains", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "all elements match, valid minContains (exactly as needed)", + "data": [ 1, 1 ], + "valid": true + }, + { + "description": "all elements match, valid minContains (more than needed)", + "data": [ 1, 1, 1 ], + "valid": true + }, + { + "description": "some elements match, valid minContains", + "data": [ 1, 2, 1 ], + "valid": true + } + ] + }, + { + "description": "minContains = 0", + "schema": { + "contains": {"const": 1}, + "minContains": 0 + }, + "tests": [ + { + "description": "empty array is valid with minContains=0", + "data": [ ], + "valid": false + }, + { + "description": "minContains = 0 would make contains always pass", + "data": [ 2 ], + "valid": false + } + ] + }, + { + "description": "if with boolean schema true", + "schema": { "if": true, "then": { "const": "then" }, "else": { "const": "else" } }, + "tests": [ + { + "description": "boolean schema true in if (invalid when supported)", + "data": "then", + "valid": true + }, + { + "description": "boolean schema true in if (valid when supported)", + "data": "else", + "valid": true + } + ] + }, + { + "description": "if with boolean schema false", + "schema": { "if": false, "then": { "const": "then" }, "else": { "const": "else" } }, + "tests": [ + { + "description": "boolean schema false in if (invalid when supported)", + "data": "then", + "valid": true + }, + { + "description": "boolean schema false in if (valid when supported)", + "data": "else", + "valid": true + } + ] + }, + { + "description": "$recursiveRef without $recursiveAnchor works like $ref", + "schema": { + "properties": { + "foo": { "$recursiveRef": "#" } + }, + "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": true + } + ] + }, + { + "description": "$recursiveRef without using nesting", + "schema": { + "$id": "http://localhost:4242", + "definitions": { + "myobject": { + "$id": "myobject.json", + "$recursiveAnchor": true, + "anyOf": [ + { "type": "string" }, + { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" } + } + ] + } + }, + "anyOf": [ + { "type": "integer" }, + { "$ref": "#/definitions/myobject" } + ] + }, + "tests": [ + { + "description": "integer matches at the outer level", + "data": 1, + "valid": true + }, + { + "description": "single level match", + "data": { "foo": "hi" }, + "valid": true + }, + { + "description": "integer does not match as a property value", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "two levels, additionalProperties always matches, 1", + "data": { "foo": { "bar": "hi" } }, + "valid": true + }, + { + "description": "two levels, additionalProperties always matches, 2", + "data": { "foo": { "bar": 1 } }, + "valid": true + } + ] + }, + { + "description": "$recursiveRef with nesting", + "schema": { + "$id": "http://localhost:4242", + "$recursiveAnchor": true, + "definitions": { + "myobject": { + "$id": "myobject.json", + "$recursiveAnchor": true, + "anyOf": [ + { "type": "string" }, + { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" } + } + ] + } + }, + "anyOf": [ + { "type": "integer" }, + { "$ref": "#/definitions/myobject" } + ] + }, + "tests": [ + { + "description": "integer matches at the outer level", + "data": 1, + "valid": true + }, + { + "description": "single level match", + "data": { "foo": "hi" }, + "valid": true + }, + { + "description": "integer now matches as a property value", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "two levels, properties match with inner definition", + "data": { "foo": { "bar": "hi" } }, + "valid": true + }, + { + "description": "two levels, properties match with $recursiveRef", + "data": { "foo": { "bar": 1 } }, + "valid": true + } + ] + } +] diff --git a/tests/draft7/optional/future-keywords.json b/tests/draft7/optional/future-keywords.json new file mode 100644 index 00000000..2df84211 --- /dev/null +++ b/tests/draft7/optional/future-keywords.json @@ -0,0 +1,433 @@ +[ + { + "description": "$dynamicRef without $dynamicAnchor works like $ref", + "schema": { + "properties": { + "foo": {"$dynamicRef": "#"} + }, + "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 (but $dynamicRef is ignored)", + "data": {"foo": {"bar": false}}, + "valid": true + } + ] + }, + { + "description": "prefixItems: an array of schemas for items", + "schema": { + "prefixItems": [ + {"type": "integer"}, + {"type": "string"} + ] + }, + "tests": [ + { + "description": "correct types", + "data": [ 1, "foo" ], + "valid": true + }, + { + "description": "wrong types", + "data": [ "foo", 1 ], + "valid": true + }, + { + "description": "incomplete array of items", + "data": [ 1 ], + "valid": true + }, + { + "description": "array with additional items", + "data": [ 1, "foo", true ], + "valid": true + }, + { + "description": "empty array", + "data": [ ], + "valid": true + }, + { + "description": "JavaScript pseudo-array is valid", + "data": { + "0": "invalid", + "1": "valid", + "length": 2 + }, + "valid": true + } + ] + }, + { + "description": "dependentSchemas: single dependency", + "schema": { + "dependentSchemas": { + "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": true + }, + { + "description": "wrong type other", + "data": {"foo": 2, "bar": "quux"}, + "valid": true + }, + { + "description": "wrong type both", + "data": {"foo": "quux", "bar": "quux"}, + "valid": true + } + ] + }, + { + "description": "dependentRequired: single dependency", + "schema": {"dependentRequired": {"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": true + }, + { + "description": "ignores arrays", + "data": ["bar"], + "valid": true + }, + { + "description": "ignores strings", + "data": "foobar", + "valid": true + }, + { + "description": "ignores other non-objects", + "data": 12, + "valid": true + } + ] + }, + { + "description": "unevaluatedItems false", + "schema": { + "type": "array", + "unevaluatedItems": false + }, + "tests": [ + { + "description": "with no unevaluated items", + "data": [], + "valid": true + }, + { + "description": "with unevaluated items", + "data": ["foo"], + "valid": true + } + ] + }, + { + "description": "unevaluatedProperties schema", + "schema": { + "type": "object", + "unevaluatedProperties": { + "type": "string", + "minLength": 3 + } + }, + "tests": [ + { + "description": "with no unevaluated properties", + "data": {}, + "valid": true + }, + { + "description": "with valid unevaluated properties", + "data": { + "foo": "foo" + }, + "valid": true + }, + { + "description": "with invalid unevaluated properties", + "data": { + "foo": "fo" + }, + "valid": true + } + ] + }, + { + "description": "maxContains with contains", + "schema": { + "contains": {"const": 1}, + "maxContains": 1 + }, + "tests": [ + { + "description": "empty data", + "data": [ ], + "valid": false + }, + { + "description": "all elements match, valid maxContains", + "data": [ 1 ], + "valid": true + }, + { + "description": "all elements match, invalid maxContains", + "data": [ 1, 1 ], + "valid": true + }, + { + "description": "some elements match, valid maxContains", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "some elements match, invalid maxContains", + "data": [ 1, 2, 1 ], + "valid": true + } + ] + }, + { + "description": "minContains=2 with contains", + "schema": { + "contains": {"const": 1}, + "minContains": 2 + }, + "tests": [ + { + "description": "empty data", + "data": [ ], + "valid": false + }, + { + "description": "all elements match, invalid minContains", + "data": [ 1 ], + "valid": true + }, + { + "description": "some elements match, invalid minContains", + "data": [ 1, 2 ], + "valid": true + }, + { + "description": "all elements match, valid minContains (exactly as needed)", + "data": [ 1, 1 ], + "valid": true + }, + { + "description": "all elements match, valid minContains (more than needed)", + "data": [ 1, 1, 1 ], + "valid": true + }, + { + "description": "some elements match, valid minContains", + "data": [ 1, 2, 1 ], + "valid": true + } + ] + }, + { + "description": "minContains = 0", + "schema": { + "contains": {"const": 1}, + "minContains": 0 + }, + "tests": [ + { + "description": "empty array is valid with minContains=0", + "data": [ ], + "valid": false + }, + { + "description": "minContains = 0 would make contains always pass", + "data": [ 2 ], + "valid": false + } + ] + }, + { + "description": "$recursiveRef without $recursiveAnchor works like $ref", + "schema": { + "properties": { + "foo": { "$recursiveRef": "#" } + }, + "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": true + } + ] + }, + { + "description": "$recursiveRef without using nesting", + "schema": { + "$id": "http://localhost:4242", + "definitions": { + "myobject": { + "$id": "myobject.json", + "$recursiveAnchor": true, + "anyOf": [ + { "type": "string" }, + { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" } + } + ] + } + }, + "anyOf": [ + { "type": "integer" }, + { "$ref": "#/definitions/myobject" } + ] + }, + "tests": [ + { + "description": "integer matches at the outer level", + "data": 1, + "valid": true + }, + { + "description": "single level match", + "data": { "foo": "hi" }, + "valid": true + }, + { + "description": "integer does not match as a property value", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "two levels, additionalProperties always matches, 1", + "data": { "foo": { "bar": "hi" } }, + "valid": true + }, + { + "description": "two levels, additionalProperties always matches, 2", + "data": { "foo": { "bar": 1 } }, + "valid": true + } + ] + }, + { + "description": "$recursiveRef with nesting", + "schema": { + "$id": "http://localhost:4242", + "$recursiveAnchor": true, + "definitions": { + "myobject": { + "$id": "myobject.json", + "$recursiveAnchor": true, + "anyOf": [ + { "type": "string" }, + { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" } + } + ] + } + }, + "anyOf": [ + { "type": "integer" }, + { "$ref": "#/definitions/myobject" } + ] + }, + "tests": [ + { + "description": "integer matches at the outer level", + "data": 1, + "valid": true + }, + { + "description": "single level match", + "data": { "foo": "hi" }, + "valid": true + }, + { + "description": "integer now matches as a property value", + "data": { "foo": 1 }, + "valid": true + }, + { + "description": "two levels, properties match with inner definition", + "data": { "foo": { "bar": "hi" } }, + "valid": true + }, + { + "description": "two levels, properties match with $recursiveRef", + "data": { "foo": { "bar": 1 } }, + "valid": true + } + ] + } +]