diff --git a/tests/conftest.py b/tests/conftest.py index 1b12f5c..b7270c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,3 +24,21 @@ def validate_v3(schema): def _validate(*args, **kwargs): validate(args[0], schema, cls=validator_for(schema, Draft7Validator)) return _validate + +@pytest.fixture +def validate_manifest_formatting(): + def _validate(*args, **kwargs): + raw_manifest = args[0] + try: + manifest_dict = json.loads(raw_manifest) + except json.JSONDecodeError: + raise Exception("Invalid JSON") + + if raw_manifest[-1:] == "\n": + raise Exception("Invalid trailing newline") + + sorted_manifest = json.dumps(manifest_dict, sort_keys=True, separators=(",", ":")) + if raw_manifest != sorted_manifest: + raise Exception("Invalid manifest has unsorted keys, duplicate keys, or is not tightly packed.") + + return _validate diff --git a/tests/fixtures/formatting/invalid/duplicateKeys0.json b/tests/fixtures/formatting/invalid/duplicateKeys0.json new file mode 100644 index 0000000..92151c7 --- /dev/null +++ b/tests/fixtures/formatting/invalid/duplicateKeys0.json @@ -0,0 +1,9 @@ +{ + "package": "{\"manifest\":\"ethpm/3\",\"manifest\":\"ethpm/3\"}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "duplicate keys" + } +} diff --git a/tests/fixtures/formatting/invalid/duplicateKeys1.json b/tests/fixtures/formatting/invalid/duplicateKeys1.json new file mode 100644 index 0000000..53b1496 --- /dev/null +++ b/tests/fixtures/formatting/invalid/duplicateKeys1.json @@ -0,0 +1,9 @@ +{ + "package": "{\"contractTypes\":{\"ABCContract\":{\"abi\":[]},\"ABCContract\":{\"abi\":[]}},\"manifest\":\"ethpm/3\"}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "duplicate keys" + } +} diff --git a/tests/fixtures/formatting/invalid/invalidJson0.json b/tests/fixtures/formatting/invalid/invalidJson0.json new file mode 100644 index 0000000..9cf92a9 --- /dev/null +++ b/tests/fixtures/formatting/invalid/invalidJson0.json @@ -0,0 +1,9 @@ +{ + "package": "{{\"manifest\":\"ethpm/3\"}}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid JSON" + } +} diff --git a/tests/fixtures/formatting/invalid/invalidJson1.json b/tests/fixtures/formatting/invalid/invalidJson1.json new file mode 100644 index 0000000..c6bb1ed --- /dev/null +++ b/tests/fixtures/formatting/invalid/invalidJson1.json @@ -0,0 +1,9 @@ +{ + "package": "{\"manifest\",\"ethpm/3\"}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid JSON" + } +} diff --git a/tests/fixtures/formatting/invalid/trailingNewline0.json b/tests/fixtures/formatting/invalid/trailingNewline0.json new file mode 100644 index 0000000..463afb1 --- /dev/null +++ b/tests/fixtures/formatting/invalid/trailingNewline0.json @@ -0,0 +1,9 @@ +{ + "package": "{\"manifest\":\"ethpm/3\"}\n", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid trailing newline" + } +} diff --git a/tests/fixtures/formatting/invalid/trailingNewline1.json b/tests/fixtures/formatting/invalid/trailingNewline1.json new file mode 100644 index 0000000..e6d2eb6 --- /dev/null +++ b/tests/fixtures/formatting/invalid/trailingNewline1.json @@ -0,0 +1,9 @@ +{ + "package": "\n{\"manifest\":\"ethpm/3\"}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "is not tightly packed" + } +} diff --git a/tests/fixtures/formatting/invalid/trailingNewline2.json b/tests/fixtures/formatting/invalid/trailingNewline2.json new file mode 100644 index 0000000..78e84e4 --- /dev/null +++ b/tests/fixtures/formatting/invalid/trailingNewline2.json @@ -0,0 +1,9 @@ +{ + "package": "{\"manifest\":\"ethpm/3\"}\n\n", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid trailing newline" + } +} diff --git a/tests/fixtures/formatting/invalid/unsortedKeys0.json b/tests/fixtures/formatting/invalid/unsortedKeys0.json new file mode 100644 index 0000000..374c0ff --- /dev/null +++ b/tests/fixtures/formatting/invalid/unsortedKeys0.json @@ -0,0 +1,9 @@ +{ + "package": "{\"contractTypes\":{\"XYZContract\":{},\"ABCContract\":{}},\"manifest\":\"ethpm/3\"}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid manifest has unsorted keys" + } +} diff --git a/tests/fixtures/formatting/invalid/unsortedKeys1.json b/tests/fixtures/formatting/invalid/unsortedKeys1.json new file mode 100644 index 0000000..f7efcbb --- /dev/null +++ b/tests/fixtures/formatting/invalid/unsortedKeys1.json @@ -0,0 +1,9 @@ +{ + "package": "{\"manifest\":\"ethpm/3\",\"contractTypes\":{\"MyContract\":{}}}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid manifest has unsorted keys" + } +} diff --git a/tests/fixtures/formatting/invalid/unsortedKeys2.json b/tests/fixtures/formatting/invalid/unsortedKeys2.json new file mode 100644 index 0000000..2d1a7c9 --- /dev/null +++ b/tests/fixtures/formatting/invalid/unsortedKeys2.json @@ -0,0 +1,9 @@ +{ + "package": "{\"manifest\":\"ethpm/3\",\"contractTypes\":{\"ABCContract\":{\"userdoc\":{},\"abi\":[]}}}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "Invalid manifest has unsorted keys" + } +} diff --git a/tests/fixtures/formatting/invalid/whitespace0.json b/tests/fixtures/formatting/invalid/whitespace0.json new file mode 100644 index 0000000..dcd3035 --- /dev/null +++ b/tests/fixtures/formatting/invalid/whitespace0.json @@ -0,0 +1,9 @@ +{ + "package": "{\"contractTypes\": {\"ABCContract\":{}},\"manifest\":\"ethpm/3\"}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "is not tightly packed" + } +} diff --git a/tests/fixtures/formatting/invalid/whitespace1.json b/tests/fixtures/formatting/invalid/whitespace1.json new file mode 100644 index 0000000..6f06441 --- /dev/null +++ b/tests/fixtures/formatting/invalid/whitespace1.json @@ -0,0 +1,9 @@ +{ + "package": "{\n \"contractTypes\":{\n \"ABCContract\":{}\n },\n \"manifest\":\"ethpm/3\"\n}", + "testCase": "invalid", + "errorInfo": { + "errorCode": "N0010", + "errorPointer": "/", + "reason": "is not tightly packed" + } +} diff --git a/tests/test_examples.py b/tests/test_examples.py index de10ff3..4f9525a 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -16,7 +16,7 @@ 'wallet' ) ) -def test_schema_accepts_v3_examples(validate_v3, ethpm_spec_dir, example): +def test_schema_validates_v3_examples(validate_v3, ethpm_spec_dir, example): examples_dir = ethpm_spec_dir / 'examples' manifest = json.loads((examples_dir / example / 'v3.json').read_text()) assert validate_v3(manifest) is None diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py index f16f5aa..d0f1b5a 100644 --- a/tests/test_fixtures.py +++ b/tests/test_fixtures.py @@ -7,28 +7,39 @@ ) FIXTURE_DIR = Path(__file__).parent.parent / 'tests' / 'fixtures' +SCHEMA_VALIDATION_DIR = FIXTURE_DIR / 'schemaValidation' +FORMATTING_DIR = FIXTURE_DIR / 'formatting' def pytest_generate_tests(metafunc): - if 'valid_fixture' in metafunc.fixturenames: - valid_fixtures = [fixture for fixture in FIXTURE_DIR.glob('**/*.json') if fixture.parent.name == 'valid'] - metafunc.parametrize("valid_fixture", valid_fixtures) - elif 'invalid_fixture' in metafunc.fixturenames: - invalid_fixtures = [fixture for fixture in FIXTURE_DIR.glob('**/*.json') if fixture.parent.name == 'invalid'] - metafunc.parametrize("invalid_fixture", invalid_fixtures) + if 'valid_schema_fixture' in metafunc.fixturenames: + valid_fixtures = [fixture for fixture in SCHEMA_VALIDATION_DIR.glob('**/*.json') if fixture.parent.name == 'valid'] + metafunc.parametrize("valid_schema_fixture", valid_fixtures) + elif 'invalid_schema_fixture' in metafunc.fixturenames: + invalid_fixtures = [fixture for fixture in SCHEMA_VALIDATION_DIR.glob('**/*.json') if fixture.parent.name == 'invalid'] + metafunc.parametrize("invalid_schema_fixture", invalid_fixtures) + elif 'invalid_formatting_fixture' in metafunc.fixturenames: + invalid_fixtures = [fixture for fixture in FORMATTING_DIR.glob('**/*.json') if fixture.parent.name == 'invalid'] + metafunc.parametrize("invalid_formatting_fixture", invalid_fixtures) -def test_valid_fixtures(valid_fixture, validate_v3): - fixture_json = json.loads(valid_fixture.read_text()) +def test_valid_schema_fixtures(valid_schema_fixture, validate_v3): + fixture_json = json.loads(valid_schema_fixture.read_text()) manifest_json = json.loads(fixture_json['package']) assert fixture_json['testCase'] == 'valid' assert validate_v3(manifest_json) is None -def test_invalid_fixtures(invalid_fixture, validate_v3): - fixture_json = json.loads(invalid_fixture.read_text()) +def test_invalid_schema_fixtures(invalid_schema_fixture, validate_v3): + fixture_json = json.loads(invalid_schema_fixture.read_text()) manifest_json = json.loads(fixture_json['package']) escaped_reason = re.escape(fixture_json['errorInfo']['reason']) assert fixture_json['testCase'] == 'invalid' with pytest.raises(jsonValidationError, match=escaped_reason): validate_v3(manifest_json) + + +def test_invalid_formatting_fixtures(invalid_formatting_fixture, validate_manifest_formatting): + fixture_json = json.loads(invalid_formatting_fixture.read_text()) + with pytest.raises(Exception, match=fixture_json['errorInfo']['reason']): + validate_manifest_formatting(fixture_json['package'])