hjsonschema 0.1.0.0 → 0.1.1.0
raw patch · 34 files changed
+2196/−97 lines, 34 filesdep ~aesondep ~basedep ~bytestring
Dependency ranges changed: aeson, base, bytestring, text, unordered-containers, vector
Files
- JSON-Schema-Test-Suite/tests/draft4/additionalItems.json +82/−0
- JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json +88/−0
- JSON-Schema-Test-Suite/tests/draft4/allOf.json +112/−0
- JSON-Schema-Test-Suite/tests/draft4/anyOf.json +68/−0
- JSON-Schema-Test-Suite/tests/draft4/default.json +49/−0
- JSON-Schema-Test-Suite/tests/draft4/definitions.json +32/−0
- JSON-Schema-Test-Suite/tests/draft4/dependencies.json +113/−0
- JSON-Schema-Test-Suite/tests/draft4/enum.json +72/−0
- JSON-Schema-Test-Suite/tests/draft4/items.json +46/−0
- JSON-Schema-Test-Suite/tests/draft4/maxItems.json +28/−0
- JSON-Schema-Test-Suite/tests/draft4/maxLength.json +33/−0
- JSON-Schema-Test-Suite/tests/draft4/maxProperties.json +28/−0
- JSON-Schema-Test-Suite/tests/draft4/maximum.json +42/−0
- JSON-Schema-Test-Suite/tests/draft4/minItems.json +28/−0
- JSON-Schema-Test-Suite/tests/draft4/minLength.json +33/−0
- JSON-Schema-Test-Suite/tests/draft4/minProperties.json +28/−0
- JSON-Schema-Test-Suite/tests/draft4/minimum.json +42/−0
- JSON-Schema-Test-Suite/tests/draft4/multipleOf.json +60/−0
- JSON-Schema-Test-Suite/tests/draft4/not.json +96/−0
- JSON-Schema-Test-Suite/tests/draft4/oneOf.json +68/−0
- JSON-Schema-Test-Suite/tests/draft4/pattern.json +23/−0
- JSON-Schema-Test-Suite/tests/draft4/patternProperties.json +110/−0
- JSON-Schema-Test-Suite/tests/draft4/properties.json +92/−0
- JSON-Schema-Test-Suite/tests/draft4/ref.json +144/−0
- JSON-Schema-Test-Suite/tests/draft4/refRemote.json +74/−0
- JSON-Schema-Test-Suite/tests/draft4/required.json +39/−0
- JSON-Schema-Test-Suite/tests/draft4/type.json +330/−0
- JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json +79/−0
- hjsonschema.cabal +26/−4
- src/Data/JsonSchema/JsonReference.hs +2/−2
- tests/Lib.hs +93/−0
- tests/Local.hs +18/−0
- tests/Remote.hs +18/−0
- tests/Test.hs +0/−91
+ JSON-Schema-Test-Suite/tests/draft4/additionalItems.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/additionalProperties.json view
@@ -0,0 +1,88 @@+[+ {+ "description":+ "additionalProperties being false does not allow other properties",+ "schema": {+ "properties": {"foo": {}, "bar": {}},+ "patternProperties": { "^v": {} },+ "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": "patternProperties are not additional properties",+ "data": {"foo":1, "vroom": 2},+ "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 can exist by itself",+ "schema": {+ "additionalProperties": {"type": "boolean"}+ },+ "tests": [+ {+ "description": "an additional valid property is valid",+ "data": {"foo" : true},+ "valid": true+ },+ {+ "description": "an additional invalid property is invalid",+ "data": {"foo" : 1},+ "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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/allOf.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/anyOf.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/default.json view
@@ -0,0 +1,49 @@+[+ {+ "description": "invalid type for default",+ "schema": {+ "properties": {+ "foo": {+ "type": "integer",+ "default": []+ }+ }+ },+ "tests": [+ {+ "description": "valid when property is specified",+ "data": {"foo": 13},+ "valid": true+ },+ {+ "description": "still valid when the invalid default is used",+ "data": {},+ "valid": true+ }+ ]+ },+ {+ "description": "invalid string value for default",+ "schema": {+ "properties": {+ "bar": {+ "type": "string",+ "minLength": 4,+ "default": "bad"+ }+ }+ },+ "tests": [+ {+ "description": "valid when property is specified",+ "data": {"bar": "good"},+ "valid": true+ },+ {+ "description": "still valid when the invalid default is used",+ "data": {},+ "valid": true+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/definitions.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/dependencies.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/enum.json view
@@ -0,0 +1,72 @@+[+ {+ "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+ }+ ]+ },+ {+ "description": "enums in properties",+ "schema": {+ "type":"object",+ "properties": {+ "foo": {"enum":["foo"]},+ "bar": {"enum":["bar"]}+ },+ "required": ["bar"]+ },+ "tests": [+ {+ "description": "both properties are valid",+ "data": {"foo":"foo", "bar":"bar"},+ "valid": true+ },+ {+ "description": "missing optional property is valid",+ "data": {"bar":"bar"},+ "valid": true+ },+ {+ "description": "missing required property is invalid",+ "data": {"foo":"foo"},+ "valid": false+ },+ {+ "description": "missing all properties is invalid",+ "data": {},+ "valid": false+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/items.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/maxItems.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/maxLength.json view
@@ -0,0 +1,33 @@+[+ {+ "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": 100,+ "valid": true+ },+ {+ "description": "two supplementary Unicode code points is long enough",+ "data": "\uD83D\uDCA9\uD83D\uDCA9",+ "valid": true+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/maxProperties.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/maximum.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/minItems.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/minLength.json view
@@ -0,0 +1,33 @@+[+ {+ "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+ },+ {+ "description": "one supplementary Unicode code point is not long enough",+ "data": "\uD83D\uDCA9",+ "valid": false+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/minProperties.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/minimum.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/multipleOf.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/not.json view
@@ -0,0 +1,96 @@+[+ {+ "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+ }+ ]+ },+ {+ "description": "forbidden property",+ "schema": {+ "properties": {+ "foo": { + "not": {}+ }+ }+ },+ "tests": [+ {+ "description": "property present",+ "data": {"foo": 1, "bar": 2},+ "valid": false+ },+ {+ "description": "property absent",+ "data": {"bar": 1, "baz": 2},+ "valid": true+ }+ ]+ }++]
+ JSON-Schema-Test-Suite/tests/draft4/oneOf.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/pattern.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/patternProperties.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/properties.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/ref.json view
@@ -0,0 +1,144 @@+[+ {+ "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 to object",+ "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": "relative pointer ref to array",+ "schema": {+ "items": [+ {"type": "integer"},+ {"$ref": "#/items/0"}+ ]+ },+ "tests": [+ {+ "description": "match array",+ "data": [1, 2],+ "valid": true+ },+ {+ "description": "mismatch array",+ "data": [1, "foo"],+ "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+ }+ ]+ },+ {+ "description": "nested refs",+ "schema": {+ "definitions": {+ "a": {"type": "integer"},+ "b": {"$ref": "#/definitions/a"},+ "c": {"$ref": "#/definitions/b"}+ },+ "$ref": "#/definitions/c"+ },+ "tests": [+ {+ "description": "nested ref valid",+ "data": 5,+ "valid": true+ },+ {+ "description": "nested ref invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "remote ref, containing refs itself",+ "schema": {"$ref": "http://json-schema.org/draft-04/schema#"},+ "tests": [+ {+ "description": "remote ref valid",+ "data": {"minLength": 1},+ "valid": true+ },+ {+ "description": "remote ref invalid",+ "data": {"minLength": -1},+ "valid": false+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/refRemote.json view
@@ -0,0 +1,74 @@+[+ {+ "description": "remote ref",+ "schema": {"$ref": "http://localhost:1234/integer.json"},+ "tests": [+ {+ "description": "remote ref valid",+ "data": 1,+ "valid": true+ },+ {+ "description": "remote ref invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "fragment within remote ref",+ "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},+ "tests": [+ {+ "description": "remote fragment valid",+ "data": 1,+ "valid": true+ },+ {+ "description": "remote fragment invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "ref within remote ref",+ "schema": {+ "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"+ },+ "tests": [+ {+ "description": "ref within ref valid",+ "data": 1,+ "valid": true+ },+ {+ "description": "ref within ref invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "change resolution scope",+ "schema": {+ "id": "http://localhost:1234/",+ "items": {+ "id": "folder/",+ "items": {"$ref": "folderInteger.json"}+ }+ },+ "tests": [+ {+ "description": "changed scope ref valid",+ "data": [[1]],+ "valid": true+ },+ {+ "description": "changed scope ref invalid",+ "data": [["a"]],+ "valid": false+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/required.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/type.json view
@@ -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+ }+ ]+ }+]
+ JSON-Schema-Test-Suite/tests/draft4/uniqueItems.json view
@@ -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+ }+ ]+ }+]
hjsonschema.cabal view
@@ -1,5 +1,5 @@ name: hjsonschema-version: 0.1.0.0+version: 0.1.1.0 synopsis: Haskell implementation of JSON Schema v4. homepage: https://github.com/seagreen/hjsonschema license: MIT@@ -8,8 +8,10 @@ maintainer: ian@housejeffries.com category: Data build-type: Simple-extra-source-files: README.md cabal-version: >=1.10+extra-source-files: README.md+ JSON-Schema-Test-Suite/tests/draft4/*.json+ tests/Lib.hs library hs-source-dirs: src@@ -33,10 +35,30 @@ , vector >= 0.10 && < 0.11 , wreq >= 0.3 && < 0.4 -test-suite official+test-suite local type: exitcode-stdio-1.0 hs-source-dirs: tests- main-is: Test.hs+ main-is: Local.hs+ default-language: Haskell2010+ ghc-options: -Wall+ default-extensions: OverloadedStrings+ build-depends: aeson+ , base+ , bytestring+ , hjsonschema+ , unordered-containers+ , text+ , vector+ , directory >= 1.2 && < 1.3+ , filepath >= 1.3 && < 1.4+ , HUnit >= 1.2 && < 1.3+ , test-framework >= 0.8 && < 0.9+ , test-framework-hunit >= 0.3 && < 0.4++test-suite remote+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: Remote.hs default-language: Haskell2010 ghc-options: -Wall default-extensions: OverloadedStrings
src/Data/JsonSchema/JsonReference.hs view
@@ -1,6 +1,6 @@-module Data.JsonSchema.JsonReference where- -- | There should be a JSON Reference library for haskell.++module Data.JsonSchema.JsonReference where import Control.Exception import Control.Lens
+ tests/Lib.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE TemplateHaskell #-}++module Lib where++import Control.Applicative+import Control.Monad+import Data.Aeson+import Data.Aeson.TH+import qualified Data.ByteString.Lazy as LBS+import Data.Char (toLower)+import qualified Data.HashMap.Strict as H+import Data.JsonSchema+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Vector as V+import System.FilePath ((</>))+import Test.Framework+import Test.Framework.Providers.HUnit+import qualified Test.HUnit as HU++data SchemaTest = SchemaTest+ { _stDescription :: Text+ , _stSchema :: RawSchema+ , _stCases :: [SchemaTestCase]+ }++data SchemaTestCase = SchemaTestCase+ { _scDescription :: Text+ , _scData :: Value+ , _scValid :: Bool+ }++instance FromJSON RawSchema where+ parseJSON = withObject "Schema" $ \o ->+ return $ RawSchema "" o++instance FromJSON SchemaTest where+ parseJSON = withObject "SchemaTest" $ \o -> SchemaTest+ <$> o .: "description"+ <*> o .: "schema"+ <*> o .: "tests" -- I wish this were "cases"++isLocal :: String -> Bool+isLocal file = (file /= "definitions.json")+ && (file /= "ref.json")+ && (file /= "refRemote.json")++readSchemaTests :: String -> [String] -> IO [SchemaTest]+readSchemaTests dir jsonFiles = concatMapM fileToCases jsonFiles+ where+ -- Each file contains an array of SchemaTests, not just one.+ fileToCases :: String -> IO [SchemaTest]+ fileToCases name = do+ let fullPath = dir </> name+ jsonBS <- LBS.readFile fullPath+ case eitherDecode jsonBS of+ Left e -> fail $ "couldn't parse file '" <> fullPath <> "': " <> e+ Right schemaTests -> return $ prependFileName name <$> schemaTests++ prependFileName :: String -> SchemaTest -> SchemaTest+ prependFileName fileName s = s+ { _stDescription = T.pack fileName <> ": " <> _stDescription s+ }++ concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]+ concatMapM f xs = liftM concat (mapM f xs)++toTest :: SchemaTest -> Test+toTest st = testGroup groupName (mkCase <$> _stCases st)+ where+ groupName :: String+ groupName = T.unpack $ _stDescription st++ mkCase :: SchemaTestCase -> Test+ mkCase sc = testCase caseName assertion+ where+ caseName = T.unpack $ _scDescription sc+ assertion = if _scValid sc+ then assertValid (_stSchema st) (_scData sc)+ else assertInvalid (_stSchema st) (_scData sc)++assertValid, assertInvalid :: RawSchema -> Value -> HU.Assertion+assertValid r v = do+ g <- fetchRefs r H.empty+ let es = validate (compile draft4 g r) v+ unless (V.length es == 0) $ HU.assertFailure (show es)+assertInvalid r v = do+ g <- fetchRefs r H.empty+ let es = validate (compile draft4 g r) v+ when (V.length es == 0) $ HU.assertFailure "expected a validation error"++$(deriveFromJSON defaultOptions { fieldLabelModifier = map toLower . drop 3 } ''SchemaTestCase)
+ tests/Local.hs view
@@ -0,0 +1,18 @@+module Main where++import Control.Applicative+import Data.List (isSuffixOf)+import Lib+import System.Directory (getDirectoryContents)+import Test.Framework++main :: IO ()+main = do+ files <- filter isLocal . filter (".json" `isSuffixOf`)+ <$> getDirectoryContents dir+ ts <- readSchemaTests dir files+ defaultMain (toTest <$> ts)++ where+ dir :: String+ dir = "JSON-Schema-Test-Suite/tests/draft4"
+ tests/Remote.hs view
@@ -0,0 +1,18 @@+module Main where++import Control.Applicative+import Data.List (isSuffixOf)+import Lib+import System.Directory (getDirectoryContents)+import Test.Framework++main :: IO ()+main = do+ files <- filter (not . isLocal) . filter (".json" `isSuffixOf`)+ <$> getDirectoryContents dir+ ts <- readSchemaTests dir files+ defaultMain (toTest <$> ts)++ where+ dir :: String+ dir = "JSON-Schema-Test-Suite/tests/draft4"
− tests/Test.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Main where--import Control.Applicative-import Control.Monad-import Data.Aeson-import Data.Aeson.TH-import qualified Data.ByteString.Lazy as LBS-import Data.Char (toLower)-import qualified Data.HashMap.Strict as H-import Data.JsonSchema-import Data.List (isSuffixOf)-import Data.Monoid-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Vector as V-import System.Directory (getDirectoryContents)-import System.FilePath ((</>))-import Test.Framework-import Test.Framework.Providers.HUnit-import qualified Test.HUnit as HU--main :: IO ()-main = do- ts <- readSchemaTests- defaultMain (toTest <$> ts)--data SchemaTest = SchemaTest- { _stDescription :: Text- , _stSchema :: RawSchema- , _stCases :: [SchemaTestCase]- }--data SchemaTestCase = SchemaTestCase- { _scDescription :: Text- , _scData :: Value- , _scValid :: Bool- }--instance FromJSON RawSchema where- parseJSON = withObject "Schema" $ \o ->- return $ RawSchema "" o--instance FromJSON SchemaTest where- parseJSON = withObject "SchemaTest" $ \o -> SchemaTest- <$> o .: "description"- <*> o .: "schema"- <*> o .: "tests" -- I wish this were "cases"--readSchemaTests :: IO [SchemaTest]-readSchemaTests = do- jsonFiles <- filter (".json" `isSuffixOf`) <$> getDirectoryContents dir- fmap concat $ forM jsonFiles $ \file -> do- let fullPath = dir </> file- jsonBS <- LBS.readFile fullPath- case eitherDecode jsonBS of- Left err -> fail $ "couldn't parse file '" <> fullPath <> "': " <> err- Right schemas -> return $ prependFileName file <$> schemas- where- dir = "JSON-Schema-Test-Suite/tests/draft4"- prependFileName :: String -> SchemaTest -> SchemaTest- prependFileName fileName s = s- { _stDescription = T.pack fileName <> ": " <> _stDescription s- }--toTest :: SchemaTest -> Test-toTest st = testGroup groupName (mkCase <$> _stCases st)- where- groupName :: String- groupName = T.unpack $ _stDescription st-- mkCase :: SchemaTestCase -> Test- mkCase sc = testCase caseName assertion- where- caseName = T.unpack $ _scDescription sc- assertion = if _scValid sc- then assertValid (_stSchema st) (_scData sc)- else assertInvalid (_stSchema st) (_scData sc)--assertValid, assertInvalid :: RawSchema -> Value -> HU.Assertion-assertValid r v = do- g <- fetchRefs r H.empty- let es = validate (compile draft4 g r) v- unless (V.length es == 0) $ HU.assertFailure (show es)-assertInvalid r v = do- g <- fetchRefs r H.empty- let es = validate (compile draft4 g r) v- when (V.length es == 0) $ HU.assertFailure "expected a validation error"--$(deriveFromJSON defaultOptions { fieldLabelModifier = map toLower . drop 3 } ''SchemaTestCase)