diff --git a/src/resolver.h b/src/resolver.h index ded3287f..5f4f89e6 100644 --- a/src/resolver.h +++ b/src/resolver.h @@ -198,13 +198,32 @@ class CustomResolver { << " at " << entry.first << "\n" << "Are you sure this schema sets any identifiers?\n"; } + } catch (const sourcemeta::core::SchemaKeywordError &error) { + throw FileError( + entry.resolution_base, error); } catch (const sourcemeta::core::SchemaFrameError &error) { throw FileError( entry.resolution_base, std::string{error.identifier()}, error.what()); + } catch (const sourcemeta::core::SchemaReferenceError &error) { + throw FileError( + entry.resolution_base, std::string{error.identifier()}, + error.location(), error.what()); } catch (const sourcemeta::core::SchemaUnknownBaseDialectError &) { throw FileError( entry.resolution_base); + } catch (const sourcemeta::core::SchemaRelativeMetaschemaResolutionError + &error) { + throw FileError< + sourcemeta::core::SchemaRelativeMetaschemaResolutionError>( + entry.resolution_base, error); + } catch (const sourcemeta::core::SchemaResolutionError &error) { + throw FileError( + entry.resolution_base, std::string{error.identifier()}, + error.what()); + } catch (const sourcemeta::core::SchemaError &error) { + throw FileError(entry.resolution_base, + error.what()); } } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 320e5116..a145842f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,11 @@ add_jsonschema_test_unix(validate/fail_schema_enoent) add_jsonschema_test_unix(validate/fail_schema_invalid_json) add_jsonschema_test_unix(validate/fail_schema_non_schema) add_jsonschema_test_unix(validate/fail_schema_unknown_dialect) +add_jsonschema_test_unix(validate/fail_resolve_unknown_dialect) +add_jsonschema_test_unix(validate/fail_resolve_invalid_id) +add_jsonschema_test_unix(validate/fail_resolve_invalid_recursive_ref) +add_jsonschema_test_unix(validate/fail_resolve_missing_core_vocabulary) +add_jsonschema_test_unix(validate/fail_resolve_relative_metaschema) add_jsonschema_test_unix(validate/pass_jsonl_bigint) add_jsonschema_test_unix(validate/fail_trace) add_jsonschema_test_unix(validate/fail_trace_fast) diff --git a/test/validate/fail_resolve_invalid_id.sh b/test/validate/fail_resolve_invalid_id.sh new file mode 100755 index 00000000..88559e3a --- /dev/null +++ b/test/validate/fail_resolve_invalid_id.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +TMP="$(mktemp -d)" +clean() { rm -rf "$TMP"; } +trap clean EXIT + +cat << 'EOF' > "$TMP/schema.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object" +} +EOF + +cat << 'EOF' > "$TMP/resolve.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "not a valid uri ::", + "type": "string" +} +EOF + +cat << 'EOF' > "$TMP/instance.json" +{ "foo": "bar" } +EOF + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" 2>"$TMP/stderr.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +error: The identifier is not a valid URI + at value not a valid uri :: + at keyword \$id + at file path $(realpath "$TMP")/resolve.json + +Are you sure the input is a valid JSON Schema and it is valid according to its meta-schema? +EOF + +diff "$TMP/stderr.txt" "$TMP/expected.txt" + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" --json >"$TMP/stdout.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +{ + "error": "The identifier is not a valid URI", + "value": "not a valid uri ::", + "keyword": "\$id", + "filePath": "$(realpath "$TMP")/resolve.json" +} +EOF + +diff "$TMP/stdout.txt" "$TMP/expected.txt" diff --git a/test/validate/fail_resolve_invalid_recursive_ref.sh b/test/validate/fail_resolve_invalid_recursive_ref.sh new file mode 100755 index 00000000..6a46b8a4 --- /dev/null +++ b/test/validate/fail_resolve_invalid_recursive_ref.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +TMP="$(mktemp -d)" +clean() { rm -rf "$TMP"; } +trap clean EXIT + +cat << 'EOF' > "$TMP/schema.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object" +} +EOF + +cat << 'EOF' > "$TMP/resolve.json" +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://example.com/bad-recref", + "$recursiveRef": "not-hash" +} +EOF + +cat << 'EOF' > "$TMP/instance.json" +{ "foo": "bar" } +EOF + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" 2>"$TMP/stderr.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +error: Invalid recursive reference + at identifier https://example.com/bad-recref + at file path $(realpath "$TMP")/resolve.json + at location "/\$recursiveRef" +EOF + +diff "$TMP/stderr.txt" "$TMP/expected.txt" + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" --json >"$TMP/stdout.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +{ + "error": "Invalid recursive reference", + "identifier": "https://example.com/bad-recref", + "filePath": "$(realpath "$TMP")/resolve.json", + "location": "/\$recursiveRef" +} +EOF + +diff "$TMP/stdout.txt" "$TMP/expected.txt" diff --git a/test/validate/fail_resolve_missing_core_vocabulary.sh b/test/validate/fail_resolve_missing_core_vocabulary.sh new file mode 100755 index 00000000..868aad3f --- /dev/null +++ b/test/validate/fail_resolve_missing_core_vocabulary.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +TMP="$(mktemp -d)" +clean() { rm -rf "$TMP"; } +trap clean EXIT + +cat << 'EOF' > "$TMP/schema.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object" +} +EOF + +cat << 'EOF' > "$TMP/meta.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/my-meta", + "$vocabulary": { + "https://example.com/fake-vocab": true + } +} +EOF + +cat << 'EOF' > "$TMP/resolve.json" +{ + "$schema": "https://example.com/my-meta", + "$id": "https://example.com/my-schema", + "type": "string" +} +EOF + +cat << 'EOF' > "$TMP/instance.json" +{ "foo": "bar" } +EOF + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/meta.json" --resolve "$TMP/resolve.json" 2>"$TMP/stderr.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +error: The core vocabulary must always be present + at file path $(realpath "$TMP")/resolve.json +EOF + +diff "$TMP/stderr.txt" "$TMP/expected.txt" + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/meta.json" --resolve "$TMP/resolve.json" --json >"$TMP/stdout.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +{ + "error": "The core vocabulary must always be present", + "filePath": "$(realpath "$TMP")/resolve.json" +} +EOF + +diff "$TMP/stdout.txt" "$TMP/expected.txt" diff --git a/test/validate/fail_resolve_relative_metaschema.sh b/test/validate/fail_resolve_relative_metaschema.sh new file mode 100755 index 00000000..c8c6c6d9 --- /dev/null +++ b/test/validate/fail_resolve_relative_metaschema.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +TMP="$(mktemp -d)" +clean() { rm -rf "$TMP"; } +trap clean EXIT + +cat << 'EOF' > "$TMP/schema.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object" +} +EOF + +cat << 'EOF' > "$TMP/resolve.json" +{ + "$schema": "relative/path", + "$id": "https://example.com/relative-test", + "type": "string" +} +EOF + +cat << 'EOF' > "$TMP/instance.json" +{ "foo": "bar" } +EOF + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" 2>"$TMP/stderr.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +error: Relative meta-schema URIs are not valid according to the JSON Schema specification + at identifier relative/path + at file path $(realpath "$TMP")/resolve.json +EOF + +diff "$TMP/stderr.txt" "$TMP/expected.txt" + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" --json >"$TMP/stdout.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +{ + "error": "Relative meta-schema URIs are not valid according to the JSON Schema specification", + "identifier": "relative/path", + "filePath": "$(realpath "$TMP")/resolve.json" +} +EOF + +diff "$TMP/stdout.txt" "$TMP/expected.txt" diff --git a/test/validate/fail_resolve_unknown_dialect.sh b/test/validate/fail_resolve_unknown_dialect.sh new file mode 100755 index 00000000..2b8d0a72 --- /dev/null +++ b/test/validate/fail_resolve_unknown_dialect.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +TMP="$(mktemp -d)" +clean() { rm -rf "$TMP"; } +trap clean EXIT + +cat << 'EOF' > "$TMP/schema.json" +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object" +} +EOF + +cat << 'EOF' > "$TMP/resolve.json" +{ + "$schema": "https://example.com/unknown-metaschema", + "$id": "https://example.com/resolve", + "type": "string" +} +EOF + +cat << 'EOF' > "$TMP/instance.json" +{ "foo": "bar" } +EOF + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" 2>"$TMP/stderr.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +error: Could not resolve the metaschema of the schema + at identifier https://example.com/unknown-metaschema + at file path $(realpath "$TMP")/resolve.json + +This is likely because you forgot to import such schema using \`--resolve/-r\` +EOF + +diff "$TMP/stderr.txt" "$TMP/expected.txt" + +"$1" validate "$TMP/schema.json" "$TMP/instance.json" \ + --resolve "$TMP/resolve.json" --json >"$TMP/stdout.txt" \ + && EXIT_CODE="$?" || EXIT_CODE="$?" +test "$EXIT_CODE" = "1" || exit 1 + +cat << EOF > "$TMP/expected.txt" +{ + "error": "Could not resolve the metaschema of the schema", + "identifier": "https://example.com/unknown-metaschema", + "filePath": "$(realpath "$TMP")/resolve.json" +} +EOF + +diff "$TMP/stdout.txt" "$TMP/expected.txt"