Skip to content

Commit f3d5aeb

Browse files
committed
Merge branch 'develop'
* develop: (105 commits) Port to draft4. Fixed incorrect negative description of a sub test Minor shuffling. updated node.js info in README.md Add the README note on develop. JavaScript should written in upper camel case added ajv validator to readme Add another Go implementation Update pattern.json Update ref.json Add valid instances for escaped ref tests Add a test that checks for implicit anchoring Add jsen to the list of validators Use tox to run tests Add test case for protocol-relative uri validation [README] JSONSchema.swift uses these tests too Revert "Add jon, JSON parser for the fishshell." Add jon, JSON parser for the fishshell. Add new Rust library to the list Add new haskell implementation. Add json-schema-benchmark to list of users of this test suite Added Newtonsoft.Json.Schema implementation Added skeemas to list of suite users Make the implementation list a bit less unwieldy now that it's so long (hooray!) Add request-validator as a user of the test suite Update README.md Add tests for additionalProperties by itself. Added tests around the default property Added the json-schema ruby gem to the list of libraries using the test suite Applies to Draft4 as well. Check comparisons for very negative numbers as well. jsck uses JSON Schema Test Suite fixed maxLength test case Add a test for large int comparisons. Add a note to the README about running sanity checks. Shorten the descriptions slightly. Add string length tests for supplementary Unicode code points As per the spec, only dotted-quad is an acceptable format for IPv4 addresses. add json-schema-valid to list of validators add 'forbidden property' test (not with blank schema) Add the enum/required test to draft4 too Add tests for required/not required values with enums Add Jsonary and tv4 to the list Added Jassi library to the list. Add a test for valid URI reference, but invalid URI (which is not valid overall). patternProperties are not additionalProperties in draft3 either. add test to draft4 that checks that patternProperties are not counted as additionalProperties added entry for Dart Added z-schema to the list Update README.md ...
2 parents 3e1321e + 5bcf11a commit f3d5aeb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3419
-193
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
language: python
22
python: "2.7"
3-
install: pip install jsonschema
4-
script: bin/suite_sanity_check -v
3+
install: pip install tox
4+
script: tox

README.md

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,88 @@ they should be valid or invalid.
5252
Coverage
5353
--------
5454

55-
Currently, draft 3 should have essentially full coverage for the core schema.
56-
57-
The beginnings of draft 4 are underway.
55+
Draft 3 and 4 should have full coverage. If you see anything missing or think
56+
there is a useful test missing, please send a pull request or open an issue.
5857

5958
Who Uses the Test Suite
6059
-----------------------
6160

6261
This suite is being used by:
6362

64-
* [json-schema-validator (Java)](https://github.com/fge/json-schema-validator)
65-
* [jsonschema (python)](https://github.com/Julian/jsonschema)
66-
* [aeson-schema (haskell)](https://github.com/timjb/aeson-schema)
67-
* [direct-schema (javascript)](https://github.com/IreneKnapp/direct-schema)
68-
* [jsonschema (javascript)](https://github.com/tdegrunt/jsonschema)
63+
### Coffeescript ###
64+
65+
* [jsck](https://github.com/pandastrike/jsck)
66+
67+
### Dart ###
68+
69+
* [json_schema](https://github.com/patefacio/json_schema)
70+
71+
### Erlang ###
72+
73+
* [jesse](https://github.com/klarna/jesse)
74+
75+
### Go ###
76+
77+
* [gojsonschema](https://github.com/sigu-399/gojsonschema)
78+
* [validate-json](https://github.com/cesanta/validate-json)
79+
80+
### Haskell ###
81+
82+
* [aeson-schema](https://github.com/timjb/aeson-schema)
83+
* [hjsonschema](https://github.com/seagreen/hjsonschema)
84+
85+
### Java ###
86+
87+
* [json-schema-validator](https://github.com/fge/json-schema-validator)
88+
89+
### JavaScript ###
90+
91+
* [json-schema-benchmark](https://github.com/Muscula/json-schema-benchmark)
92+
* [direct-schema](https://github.com/IreneKnapp/direct-schema)
93+
* [is-my-json-valid](https://github.com/mafintosh/is-my-json-valid)
94+
* [jassi](https://github.com/iclanzan/jassi)
95+
* [JaySchema](https://github.com/natesilva/jayschema)
96+
* [json-schema-valid](https://github.com/ericgj/json-schema-valid)
97+
* [Jsonary](https://github.com/jsonary-js/jsonary)
98+
* [jsonschema](https://github.com/tdegrunt/jsonschema)
99+
* [request-validator](https://github.com/bugventure/request-validator)
100+
* [skeemas](https://github.com/Prestaul/skeemas)
101+
* [tv4](https://github.com/geraintluff/tv4)
102+
* [z-schema](https://github.com/zaggino/z-schema)
103+
* [jsen](https://github.com/bugventure/jsen)
104+
* [ajv](https://github.com/epoberezkin/ajv)
105+
106+
### Node.js ###
107+
108+
The JSON Schema Test Suite is also available as an
109+
[npm](https://www.npmjs.com/package/json-schema-test-suite) package.
110+
Node-specific support is maintained on the [node branch](https://github.com/json-schema/JSON-Schema-Test-Suite/tree/node).
111+
See [NODE-README.md](https://github.com/json-schema/JSON-Schema-Test-Suite/blob/node/NODE-README.md)
112+
for more information.
113+
114+
### .NET ###
115+
116+
* [Newtonsoft.Json.Schema](https://github.com/JamesNK/Newtonsoft.Json.Schema)
117+
118+
### PHP ###
119+
120+
* [json-schema](https://github.com/justinrainbow/json-schema)
121+
122+
### Python ###
123+
124+
* [jsonschema](https://github.com/Julian/jsonschema)
125+
126+
### Ruby ###
127+
128+
* [json-schema](https://github.com/hoxworth/json-schema)
129+
130+
### Rust ###
131+
132+
* [valico](https://github.com/rustless/valico)
133+
134+
### Swift ###
135+
136+
* [JSONSchema](https://github.com/kylef/JSONSchema.swift)
69137

70138
If you use it as well, please fork and send a pull request adding yourself to
71139
the list :).
@@ -74,3 +142,7 @@ Contributing
74142
------------
75143

76144
If you see something missing or incorrect, a pull request is most welcome!
145+
146+
There are some sanity checks in place for testing the test suite. You can run
147+
them with `bin/jsonschema_suite check` or `tox`. They will be run automatically by
148+
[Travis CI](https://travis-ci.org/) as well.

bin/jsonschema_suite

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
#! /usr/bin/env python
2+
from __future__ import print_function
3+
import sys
4+
import textwrap
5+
6+
try:
7+
import argparse
8+
except ImportError:
9+
print(textwrap.dedent("""
10+
The argparse library could not be imported. jsonschema_suite requires
11+
either Python 2.7 or for you to install argparse. You can do so by
12+
running `pip install argparse`, `easy_install argparse` or by
13+
downloading argparse and running `python2.6 setup.py install`.
14+
15+
See https://pypi.python.org/pypi/argparse for details.
16+
""".strip("\n")))
17+
sys.exit(1)
18+
19+
import errno
20+
import fnmatch
21+
import json
22+
import os
23+
import random
24+
import shutil
25+
import unittest
26+
import warnings
27+
28+
if getattr(unittest, "skipIf", None) is None:
29+
unittest.skipIf = lambda cond, msg : lambda fn : fn
30+
31+
try:
32+
import jsonschema
33+
except ImportError:
34+
jsonschema = None
35+
else:
36+
validators = getattr(
37+
jsonschema.validators, "validators", jsonschema.validators
38+
)
39+
40+
41+
ROOT_DIR = os.path.join(
42+
os.path.dirname(__file__), os.pardir).rstrip("__pycache__")
43+
SUITE_ROOT_DIR = os.path.join(ROOT_DIR, "tests")
44+
45+
REMOTES = {
46+
"integer.json": {"type": "integer"},
47+
"subSchemas.json": {
48+
"integer": {"type": "integer"},
49+
"refToInteger": {"$ref": "#/integer"},
50+
},
51+
"folder/folderInteger.json": {"type": "integer"}
52+
}
53+
REMOTES_DIR = os.path.join(ROOT_DIR, "remotes")
54+
55+
TESTSUITE_SCHEMA = {
56+
"$schema": "http://json-schema.org/draft-03/schema#",
57+
"type": "array",
58+
"items": {
59+
"type": "object",
60+
"properties": {
61+
"description": {"type": "string", "required": True},
62+
"schema": {"required": True},
63+
"tests": {
64+
"type": "array",
65+
"items": {
66+
"type": "object",
67+
"properties": {
68+
"description": {"type": "string", "required": True},
69+
"data": {"required": True},
70+
"valid": {"type": "boolean", "required": True}
71+
},
72+
"additionalProperties": False
73+
},
74+
"minItems": 1
75+
}
76+
},
77+
"additionalProperties": False,
78+
"minItems": 1
79+
}
80+
}
81+
82+
83+
def files(paths):
84+
for path in paths:
85+
with open(path) as test_file:
86+
yield json.load(test_file)
87+
88+
89+
def groups(paths):
90+
for test_file in files(paths):
91+
for group in test_file:
92+
yield group
93+
94+
95+
def cases(paths):
96+
for test_group in groups(paths):
97+
for test in test_group["tests"]:
98+
test["schema"] = test_group["schema"]
99+
yield test
100+
101+
102+
def collect(root_dir):
103+
for root, dirs, files in os.walk(root_dir):
104+
for filename in fnmatch.filter(files, "*.json"):
105+
yield os.path.join(root, filename)
106+
107+
108+
class SanityTests(unittest.TestCase):
109+
@classmethod
110+
def setUpClass(cls):
111+
print("Looking for tests in %s" % SUITE_ROOT_DIR)
112+
cls.test_files = list(collect(SUITE_ROOT_DIR))
113+
print("Found %s test files" % len(cls.test_files))
114+
assert cls.test_files, "Didn't find the test files!"
115+
116+
def test_all_files_are_valid_json(self):
117+
for path in self.test_files:
118+
with open(path) as test_file:
119+
try:
120+
json.load(test_file)
121+
except ValueError as error:
122+
self.fail("%s contains invalid JSON (%s)" % (path, error))
123+
124+
def test_all_descriptions_have_reasonable_length(self):
125+
for case in cases(self.test_files):
126+
descript = case["description"]
127+
self.assertLess(
128+
len(descript),
129+
60,
130+
"%r is too long! (keep it to less than 60 chars)" % (descript,)
131+
)
132+
133+
def test_all_descriptions_are_unique(self):
134+
for group in groups(self.test_files):
135+
descriptions = set(test["description"] for test in group["tests"])
136+
self.assertEqual(
137+
len(descriptions),
138+
len(group["tests"]),
139+
"%r contains a duplicate description" % (group,)
140+
)
141+
142+
@unittest.skipIf(jsonschema is None, "Validation library not present!")
143+
def test_all_schemas_are_valid(self):
144+
for schema in os.listdir(SUITE_ROOT_DIR):
145+
schema_validator = validators.get(schema)
146+
if schema_validator is not None:
147+
test_files = collect(os.path.join(SUITE_ROOT_DIR, schema))
148+
for case in cases(test_files):
149+
try:
150+
schema_validator.check_schema(case["schema"])
151+
except jsonschema.SchemaError as error:
152+
self.fail("%s contains an invalid schema (%s)" %
153+
(case, error))
154+
else:
155+
warnings.warn("No schema validator for %s" % schema)
156+
157+
@unittest.skipIf(jsonschema is None, "Validation library not present!")
158+
def test_suites_are_valid(self):
159+
validator = jsonschema.Draft3Validator(TESTSUITE_SCHEMA)
160+
for tests in files(self.test_files):
161+
try:
162+
validator.validate(tests)
163+
except jsonschema.ValidationError as error:
164+
self.fail(str(error))
165+
166+
def test_remote_schemas_are_updated(self):
167+
for url, schema in REMOTES.items():
168+
filepath = os.path.join(REMOTES_DIR, url)
169+
with open(filepath) as schema_file:
170+
self.assertEqual(json.load(schema_file), schema)
171+
172+
173+
def main(arguments):
174+
if arguments.command == "check":
175+
suite = unittest.TestLoader().loadTestsFromTestCase(SanityTests)
176+
result = unittest.TextTestRunner(verbosity=2).run(suite)
177+
sys.exit(not result.wasSuccessful())
178+
elif arguments.command == "flatten":
179+
selected_cases = [case for case in cases(collect(arguments.version))]
180+
181+
if arguments.randomize:
182+
random.shuffle(selected_cases)
183+
184+
json.dump(selected_cases, sys.stdout, indent=4, sort_keys=True)
185+
elif arguments.command == "remotes":
186+
json.dump(REMOTES, sys.stdout, indent=4, sort_keys=True)
187+
elif arguments.command == "dump_remotes":
188+
if arguments.update:
189+
shutil.rmtree(arguments.out_dir, ignore_errors=True)
190+
191+
try:
192+
os.makedirs(arguments.out_dir)
193+
except OSError as e:
194+
if e.errno == errno.EEXIST:
195+
print("%s already exists. Aborting." % arguments.out_dir)
196+
sys.exit(1)
197+
raise
198+
199+
for url, schema in REMOTES.items():
200+
filepath = os.path.join(arguments.out_dir, url)
201+
202+
try:
203+
os.makedirs(os.path.dirname(filepath))
204+
except OSError as e:
205+
if e.errno != errno.EEXIST:
206+
raise
207+
208+
with open(filepath, "wb") as out_file:
209+
json.dump(schema, out_file, indent=4, sort_keys=True)
210+
elif arguments.command == "serve":
211+
try:
212+
from flask import Flask, jsonify
213+
except ImportError:
214+
print(textwrap.dedent("""
215+
The Flask library is required to serve the remote schemas.
216+
217+
You can install it by running `pip install Flask`.
218+
219+
Alternatively, see the `jsonschema_suite remotes` or
220+
`jsonschema_suite dump_remotes` commands to create static files
221+
that can be served with your own web server.
222+
""".strip("\n")))
223+
sys.exit(1)
224+
225+
app = Flask(__name__)
226+
227+
@app.route("/<path:path>")
228+
def serve_path(path):
229+
if path in REMOTES:
230+
return jsonify(REMOTES[path])
231+
return "Document does not exist.", 404
232+
233+
app.run(port=1234)
234+
235+
236+
parser = argparse.ArgumentParser(
237+
description="JSON Schema Test Suite utilities",
238+
)
239+
subparsers = parser.add_subparsers(help="utility commands", dest="command")
240+
241+
check = subparsers.add_parser("check", help="Sanity check the test suite.")
242+
243+
flatten = subparsers.add_parser(
244+
"flatten",
245+
help="Output a flattened file containing a selected version's test cases."
246+
)
247+
flatten.add_argument(
248+
"--randomize",
249+
action="store_true",
250+
help="Randomize the order of the outputted cases.",
251+
)
252+
flatten.add_argument(
253+
"version", help="The directory containing the version to output",
254+
)
255+
256+
remotes = subparsers.add_parser(
257+
"remotes",
258+
help="Output the expected URLs and their associated schemas for remote "
259+
"ref tests as a JSON object."
260+
)
261+
262+
dump_remotes = subparsers.add_parser(
263+
"dump_remotes", help="Dump the remote ref schemas into a file tree",
264+
)
265+
dump_remotes.add_argument(
266+
"--update",
267+
action="store_true",
268+
help="Update the remotes in an existing directory.",
269+
)
270+
dump_remotes.add_argument(
271+
"--out-dir",
272+
default=REMOTES_DIR,
273+
type=os.path.abspath,
274+
help="The output directory to create as the root of the file tree",
275+
)
276+
277+
serve = subparsers.add_parser(
278+
"serve",
279+
help="Start a webserver to serve schemas used by remote ref tests."
280+
)
281+
282+
if __name__ == "__main__":
283+
main(parser.parse_args())

0 commit comments

Comments
 (0)