Skip to content

Commit 61d6022

Browse files
committed
Squashed 'json/' changes from 3627cc1..15ec577
15ec577 Merge pull request #471 from json-schema-org/ether/id-anchor-in-enum 9f97865 test for confusing not-identifiers in enums 0f7ecd4 Merge pull request #475 from marksparkza/marksparkza-patch-1 783d22a Add jschon fc68499 Merge pull request #472 from json-schema-org/ether/unevaluatedProperties_uncles ed4cf5f more test cases for unevaluatedItems, unevaluatedProperties d0d814d Merge pull request #469 from json-schema-org/ether/ipv4-vulnerability 7ca5f36 reject ipv4 strings with an octet with a leading zero 8e1e1c1 fix spelling error in test descriptions 77f1d10 Merge pull request #462 from jdesrosiers/dynamic-ref-tests 72a32fe Merge pull request #468 from json-schema-org/ether/combine-test-cases 0c48ffb Merge pull request #453 from notEthan/float-overflow-d4-int 76a4ba0 these test cases can be combined since the schemas are the same cd73775 Merge pull request #464 from json-schema-org/ether/format-by-default-always-validates 043dc63 by default, "format" only annotates, not validates 3c45b81 Merge pull request #460 from amosonn/remove-remotes-from-script b09e48d Fix $ref with siblings in pre-2019-09 tests ff9f22e Add tests for $dynamicRef/$dynamicAnchor 0faaf09 Fix refs to Draft 2019-09 schema to be refs to 2020-12 ebbcbc8 Use flask to server remotes directly bb98b03 Remove remotes from bin/jsonschema_suite fcae732 Merge pull request #455 from jdesrosiers/bootstrap-202012 e002409 Update tests for 2020-12 405b3fb Copy 2019-09 tests to bootstrap 2020-12 tests 1636a22 draft4 float-overflow instance may be considered not an integer 8daea3f Merge pull request #451 from json-schema-org/ether/more-relative-json-pointer 69fe40f some more relative-json-pointer tests 6505944 Merge pull request #450 from json-schema-org/ether/recursiveRef-dynamic-path afd0cd3 Move content* keyword tests to non-optional e2b2a4b Change all content* keyword tests to always validate 8999eae $recursiveRef example demonstrating dynamic nature of the resolution scope f47003f fix duplicate test description bcf1dc8 Merge pull request #391 from ether/recursiveRef (rebased, squashed) 3d88f34 test $recursiveRef + $recursiveAnchor 3b79a45 Merge pull request #418 from ChALkeR/chalker/contentSchema 29f609b Add tests for contentSchema git-subtree-dir: json git-subtree-split: 15ec577f5ddee0115319f4e7f856cd57567a9c78
1 parent 037b443 commit 61d6022

File tree

103 files changed

+11736
-217
lines changed

Some content is hidden

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

103 files changed

+11736
-217
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ which also welcomes your contributions!
176176
* [jsonschema](https://github.com/Julian/jsonschema)
177177
* [fastjsonschema](https://github.com/seznam/python-fastjsonschema)
178178
* [hypothesis-jsonschema](https://github.com/Zac-HD/hypothesis-jsonschema)
179+
* [jschon](https://github.com/marksparkza/jschon)
179180

180181
### Ruby
181182

bin/jsonschema_suite

Lines changed: 25 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,12 @@ ROOT_DIR = os.path.abspath(
2626
os.path.join(os.path.dirname(__file__), os.pardir).rstrip("__pycache__"),
2727
)
2828
SUITE_ROOT_DIR = os.path.join(ROOT_DIR, "tests")
29-
30-
REMOTES = {
31-
"integer.json": {u"type": u"integer"},
32-
"name.json": {
33-
u"type": "string",
34-
u"definitions": {
35-
u"orNull": {u"anyOf": [{u"type": u"null"}, {u"$ref": u"#"}]},
36-
},
37-
},
38-
"name-defs.json": {
39-
u"type": "string",
40-
u"$defs": {
41-
u"orNull": {u"anyOf": [{u"type": u"null"}, {u"$ref": u"#"}]},
42-
},
43-
},
44-
"subSchemas.json": {
45-
u"integer": {u"type": u"integer"},
46-
u"refToInteger": {u"$ref": u"#/integer"},
47-
},
48-
"subSchemas-defs.json": {
49-
u"$defs": {
50-
u"integer": {u"type": u"integer"},
51-
u"refToInteger": {u"$ref": u"#/$defs/integer"},
52-
}
53-
},
54-
"baseUriChange/folderInteger.json": {u"type": u"integer"},
55-
"baseUriChangeFolder/folderInteger.json": {u"type": u"integer"},
56-
"baseUriChangeFolderInSubschema/folderInteger.json": {u"type": u"integer"},
57-
}
5829
REMOTES_DIR = os.path.join(ROOT_DIR, "remotes")
5930

6031
with open(os.path.join(ROOT_DIR, "test-schema.json")) as schema:
6132
TESTSUITE_SCHEMA = json.load(schema)
6233

34+
6335
def files(paths):
6436
for path in paths:
6537
with open(path) as test_file:
@@ -80,7 +52,7 @@ def cases(paths):
8052

8153

8254
def collect(root_dir):
83-
for root, dirs, files in os.walk(root_dir):
55+
for root, _, files in os.walk(root_dir):
8456
for filename in fnmatch.filter(files, "*.json"):
8557
yield os.path.join(root, filename)
8658

@@ -89,18 +61,30 @@ class SanityTests(unittest.TestCase):
8961
@classmethod
9062
def setUpClass(cls):
9163
print("Looking for tests in %s" % SUITE_ROOT_DIR)
64+
print("Looking for remotes in %s" % REMOTES_DIR)
9265
cls.test_files = list(collect(SUITE_ROOT_DIR))
66+
cls.remote_files = list(collect(REMOTES_DIR))
9367
print("Found %s test files" % len(cls.test_files))
68+
print("Found %s remote files" % len(cls.remote_files))
9469
assert cls.test_files, "Didn't find the test files!"
70+
assert cls.remote_files, "Didn't find the remote files!"
9571

96-
def test_all_files_are_valid_json(self):
72+
def test_all_test_files_are_valid_json(self):
9773
for path in self.test_files:
9874
with open(path) as test_file:
9975
try:
10076
json.load(test_file)
10177
except ValueError as error:
10278
self.fail("%s contains invalid JSON (%s)" % (path, error))
10379

80+
def test_all_remote_files_are_valid_json(self):
81+
for path in self.remote_files:
82+
with open(path) as remote_file:
83+
try:
84+
json.load(remote_file)
85+
except ValueError as error:
86+
self.fail("%s contains invalid JSON (%s)" % (path, error))
87+
10488
def test_all_descriptions_have_reasonable_length(self):
10589
for case in cases(self.test_files):
10690
description = case["description"]
@@ -146,48 +130,6 @@ class SanityTests(unittest.TestCase):
146130
except jsonschema.ValidationError as error:
147131
self.fail(str(error))
148132

149-
def test_remote_schemas_are_updated(self):
150-
files = {}
151-
for parent, _, paths in os.walk(REMOTES_DIR):
152-
for path in paths:
153-
absolute_path = os.path.join(parent, path)
154-
with open(absolute_path) as schema_file:
155-
files[absolute_path] = json.load(schema_file)
156-
157-
expected = {
158-
os.path.join(REMOTES_DIR, path): contents
159-
for path, contents in REMOTES.items()
160-
}
161-
162-
missing = set(files).symmetric_difference(expected)
163-
changed = {
164-
path
165-
for path, contents in expected.items()
166-
if path in files
167-
and contents != files[path]
168-
}
169-
170-
self.assertEqual(
171-
files,
172-
expected,
173-
msg=textwrap.dedent(
174-
"""
175-
Remotes in the remotes/ directory do not match those in the
176-
``jsonschema_suite`` Python script.
177-
178-
Unfortunately for the minute, each remote file is duplicated in
179-
two places.""" + ("""
180-
181-
Only present in one location:
182-
183-
{}""".format("\n".join(missing)) if missing else "") + ("""
184-
185-
Conflicting between the two:
186-
187-
{}""".format("\n".join(changed)) if changed else "")
188-
)
189-
)
190-
191133

192134
def main(arguments):
193135
if arguments.command == "check":
@@ -202,34 +144,26 @@ def main(arguments):
202144

203145
json.dump(selected_cases, sys.stdout, indent=4, sort_keys=True)
204146
elif arguments.command == "remotes":
205-
json.dump(REMOTES, sys.stdout, indent=4, sort_keys=True)
147+
remotes = {}
148+
for path in collect(REMOTES_DIR):
149+
relative_path = os.path.relpath(path, REMOTES_DIR)
150+
with open(path) as schema_file:
151+
remotes[relative_path] = json.load(schema_file)
152+
json.dump(remotes, sys.stdout, indent=4, sort_keys=True)
206153
elif arguments.command == "dump_remotes":
207154
if arguments.update:
208155
shutil.rmtree(arguments.out_dir, ignore_errors=True)
209156

210157
try:
211-
os.makedirs(arguments.out_dir)
158+
shutil.copytree(REMOTES_DIR, arguments.out_dir)
212159
except OSError as e:
213160
if e.errno == errno.EEXIST:
214161
print("%s already exists. Aborting." % arguments.out_dir)
215162
sys.exit(1)
216163
raise
217-
218-
for url, schema in REMOTES.items():
219-
filepath = os.path.join(arguments.out_dir, url)
220-
221-
try:
222-
os.makedirs(os.path.dirname(filepath))
223-
except OSError as e:
224-
if e.errno != errno.EEXIST:
225-
raise
226-
227-
with open(filepath, "w") as out_file:
228-
json.dump(schema, out_file, indent=4, sort_keys=True)
229-
out_file.write("\n")
230164
elif arguments.command == "serve":
231165
try:
232-
from flask import Flask, jsonify
166+
import flask
233167
except ImportError:
234168
print(textwrap.dedent("""
235169
The Flask library is required to serve the remote schemas.
@@ -242,13 +176,11 @@ def main(arguments):
242176
""".strip("\n")))
243177
sys.exit(1)
244178

245-
app = Flask(__name__)
179+
app = flask.Flask(__name__)
246180

247181
@app.route("/<path:path>")
248182
def serve_path(path):
249-
if path in REMOTES:
250-
return jsonify(REMOTES[path])
251-
return "Document does not exist.", 404
183+
return flask.send_from_directory(REMOTES_DIR, path)
252184

253185
app.run(port=1234)
254186

tests/draft2019-09/anchor.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,62 @@
7777
"valid": false
7878
}
7979
]
80+
},
81+
{
82+
"description": "$anchor inside an enum is not a real identifier",
83+
"comment": "the implementation must not be confused by an $anchor buried in the enum",
84+
"schema": {
85+
"$defs": {
86+
"anchor_in_enum": {
87+
"enum": [
88+
{
89+
"$anchor": "my_anchor",
90+
"type": "null"
91+
}
92+
]
93+
},
94+
"real_identifier_in_schema": {
95+
"$anchor": "my_anchor",
96+
"type": "string"
97+
},
98+
"zzz_anchor_in_const": {
99+
"const": {
100+
"$anchor": "my_anchor",
101+
"type": "null"
102+
}
103+
}
104+
},
105+
"anyOf": [
106+
{ "$ref": "#/$defs/anchor_in_enum" },
107+
{ "$ref": "#my_anchor" }
108+
]
109+
},
110+
"tests": [
111+
{
112+
"description": "exact match to enum, and type matches",
113+
"data": {
114+
"$anchor": "my_anchor",
115+
"type": "null"
116+
},
117+
"valid": true
118+
},
119+
{
120+
"description": "in implementations that strip $anchor, this may match either $def",
121+
"data": {
122+
"type": "null"
123+
},
124+
"valid": false
125+
},
126+
{
127+
"description": "match $ref to $anchor",
128+
"data": "a string to match #/$defs/anchor_in_enum",
129+
"valid": true
130+
},
131+
{
132+
"description": "no match on enum or $ref to $anchor",
133+
"data": 1,
134+
"valid": false
135+
}
136+
]
80137
}
81138
]

tests/draft2019-09/content.json

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
[
2+
{
3+
"description": "validation of string-encoded content based on media type",
4+
"schema": {
5+
"contentMediaType": "application/json"
6+
},
7+
"tests": [
8+
{
9+
"description": "a valid JSON document",
10+
"data": "{\"foo\": \"bar\"}",
11+
"valid": true
12+
},
13+
{
14+
"description": "an invalid JSON document; validates true",
15+
"data": "{:}",
16+
"valid": true
17+
},
18+
{
19+
"description": "ignores non-strings",
20+
"data": 100,
21+
"valid": true
22+
}
23+
]
24+
},
25+
{
26+
"description": "validation of binary string-encoding",
27+
"schema": {
28+
"contentEncoding": "base64"
29+
},
30+
"tests": [
31+
{
32+
"description": "a valid base64 string",
33+
"data": "eyJmb28iOiAiYmFyIn0K",
34+
"valid": true
35+
},
36+
{
37+
"description": "an invalid base64 string (% is not a valid character); validates true",
38+
"data": "eyJmb28iOi%iYmFyIn0K",
39+
"valid": true
40+
},
41+
{
42+
"description": "ignores non-strings",
43+
"data": 100,
44+
"valid": true
45+
}
46+
]
47+
},
48+
{
49+
"description": "validation of binary-encoded media type documents",
50+
"schema": {
51+
"contentMediaType": "application/json",
52+
"contentEncoding": "base64"
53+
},
54+
"tests": [
55+
{
56+
"description": "a valid base64-encoded JSON document",
57+
"data": "eyJmb28iOiAiYmFyIn0K",
58+
"valid": true
59+
},
60+
{
61+
"description": "a validly-encoded invalid JSON document; validates true",
62+
"data": "ezp9Cg==",
63+
"valid": true
64+
},
65+
{
66+
"description": "an invalid base64 string that is valid JSON; validates true",
67+
"data": "{}",
68+
"valid": true
69+
},
70+
{
71+
"description": "ignores non-strings",
72+
"data": 100,
73+
"valid": true
74+
}
75+
]
76+
},
77+
{
78+
"description": "validation of binary-encoded media type documents with schema",
79+
"schema": {
80+
"contentMediaType": "application/json",
81+
"contentEncoding": "base64",
82+
"contentSchema": { "required": ["foo"], "properties": { "foo": { "type": "string" } } }
83+
},
84+
"tests": [
85+
{
86+
"description": "a valid base64-encoded JSON document",
87+
"data": "eyJmb28iOiAiYmFyIn0K",
88+
"valid": true
89+
},
90+
{
91+
"description": "another valid base64-encoded JSON document",
92+
"data": "eyJib28iOiAyMCwgImZvbyI6ICJiYXoifQ==",
93+
"valid": true
94+
},
95+
{
96+
"description": "an invalid base64-encoded JSON document; validates true",
97+
"data": "eyJib28iOiAyMH0=",
98+
"valid": true
99+
},
100+
{
101+
"description": "an empty object as a base64-encoded JSON document; validates true",
102+
"data": "e30=",
103+
"valid": true
104+
},
105+
{
106+
"description": "an empty array as a base64-encoded JSON document",
107+
"data": "W10=",
108+
"valid": true
109+
},
110+
{
111+
"description": "a validly-encoded invalid JSON document; validates true",
112+
"data": "ezp9Cg==",
113+
"valid": true
114+
},
115+
{
116+
"description": "an invalid base64 string that is valid JSON; validates true",
117+
"data": "{}",
118+
"valid": true
119+
},
120+
{
121+
"description": "ignores non-strings",
122+
"data": 100,
123+
"valid": true
124+
}
125+
]
126+
}
127+
]

0 commit comments

Comments
 (0)