Skip to content

Commit d960e71

Browse files
committed
FIX?
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 7a18cae commit d960e71

File tree

7 files changed

+153
-2
lines changed

7 files changed

+153
-2
lines changed

src/index/error.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,39 @@ class CustomRuleError : public std::exception {
100100
std::filesystem::path path_;
101101
};
102102

103+
class UnsupportedVocabularyError : public std::exception {
104+
public:
105+
UnsupportedVocabularyError(std::filesystem::path schema_path,
106+
std::filesystem::path metaschema_path,
107+
std::string vocabulary)
108+
: schema_path_{std::move(schema_path)},
109+
metaschema_path_{std::move(metaschema_path)},
110+
vocabulary_{std::move(vocabulary)} {}
111+
112+
[[nodiscard]] auto what() const noexcept -> const char * override {
113+
return "The schema requires an unrecognised vocabulary";
114+
}
115+
116+
[[nodiscard]] auto schema_path() const noexcept
117+
-> const std::filesystem::path & {
118+
return this->schema_path_;
119+
}
120+
121+
[[nodiscard]] auto metaschema_path() const noexcept
122+
-> const std::filesystem::path & {
123+
return this->metaschema_path_;
124+
}
125+
126+
[[nodiscard]] auto vocabulary() const noexcept -> const std::string & {
127+
return this->vocabulary_;
128+
}
129+
130+
private:
131+
std::filesystem::path schema_path_;
132+
std::filesystem::path metaschema_path_;
133+
std::string vocabulary_;
134+
};
135+
103136
} // namespace sourcemeta::one
104137

105138
#endif

src/index/generators.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ struct GENERATE_MATERIALISED_SCHEMA {
117117
const auto metaschema{resolver(dialect_identifier)};
118118
assert(metaschema.has_value());
119119

120+
// Reject schemas whose metaschema requires unrecognised vocabularies
121+
if (!sourcemeta::core::to_base_dialect(dialect_identifier).has_value() &&
122+
metaschema->is_object() && metaschema->defines("$vocabulary") &&
123+
metaschema->at("$vocabulary").is_object()) {
124+
try {
125+
sourcemeta::core::vocabularies(
126+
schema.value(),
127+
[&resolver](const auto identifier) { return resolver(identifier); },
128+
dialect_identifier)
129+
.throw_if_any_unknown_required(
130+
"The schema requires an unrecognised vocabulary");
131+
} catch (const sourcemeta::core::SchemaVocabularyError &error) {
132+
throw UnsupportedVocabularyError(
133+
resolver.entry(action.data).path,
134+
resolver.entry(dialect_identifier).path, std::string{error.uri()});
135+
}
136+
}
137+
120138
// Validate the schemas against their meta-schemas
121139
sourcemeta::blaze::SimpleOutput output{schema.value()};
122140
sourcemeta::blaze::Evaluator evaluator;

src/index/index.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ static auto execute_plan(std::mutex &mutex,
192192
sourcemeta::core::SchemaVocabularyError>(
193193
entry->path, error.uri(), error.what());
194194
}
195+
195196
throw;
196197
}
197198

@@ -679,6 +680,12 @@ auto main(int argc, char *argv[]) noexcept -> int {
679680
} catch (const sourcemeta::blaze::LinterMissingNameError &error) {
680681
std::cerr << "error: " << error.what() << "\n";
681682
return EXIT_FAILURE;
683+
} catch (const sourcemeta::one::UnsupportedVocabularyError &error) {
684+
std::cerr << "error: " << error.what() << "\n at vocabulary "
685+
<< error.vocabulary() << "\n at schema "
686+
<< error.schema_path().string() << "\n at metaschema "
687+
<< error.metaschema_path().string() << "\n";
688+
return EXIT_FAILURE;
682689
} catch (
683690
const sourcemeta::core::FileError<sourcemeta::core::SchemaVocabularyError>
684691
&error) {

test/cli/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ if(ONE_INDEX)
6161
sourcemeta_one_test_cli(common index fail-unknown-required-vocabulary)
6262
sourcemeta_one_test_cli(common index fail-no-evaluate-unknown-required-vocabulary)
6363
sourcemeta_one_test_cli(common index fail-unknown-option)
64+
sourcemeta_one_test_cli(common index fail-vocabulary-not-object)
6465
sourcemeta_one_test_cli(common index draft4-ignore-vocabulary)
6566
sourcemeta_one_test_cli(common index extra-files-on-rebuild)
6667
sourcemeta_one_test_cli(common index directory-schema-same-name)

test/cli/index/common/fail-no-evaluate-unknown-required-vocabulary.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,14 @@ Detecting: $(realpath "$TMP")/schemas/custom-meta.json (#1)
6464
Detecting: $(realpath "$TMP")/schemas/test.json (#2)
6565
( 50%) Resolving: custom-meta.json
6666
(100%) Resolving: test.json
67+
( 4%) Producing: configuration.json
68+
( 8%) Producing: version.json
69+
( 12%) Producing: schemas/example/custom-meta/%/schema.metapack
70+
( 16%) Producing: schemas/example/test/%/schema.metapack
6771
error: The schema requires an unrecognised vocabulary
6872
at vocabulary https://example.com/vocab/totally-unknown
69-
at path $(realpath "$TMP")/schemas/custom-meta.json
73+
at schema $(realpath "$TMP")/schemas/test.json
74+
at metaschema $(realpath "$TMP")/schemas/custom-meta.json
7075
EOF
7176

7277
diff "$TMP/output.txt" "$TMP/expected.txt"

test/cli/index/common/fail-unknown-required-vocabulary.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,15 @@ Detecting: $(realpath "$TMP")/schemas/custom-meta.json (#1)
6666
Detecting: $(realpath "$TMP")/schemas/test.json (#2)
6767
( 50%) Resolving: custom-meta.json
6868
(100%) Resolving: test.json
69+
( 2%) Producing: configuration.json
70+
( 5%) Producing: version.json
71+
( 8%) Producing: explorer/%/404.metapack
72+
( 11%) Producing: schemas/example/schemas/custom-meta/%/schema.metapack
73+
( 14%) Producing: schemas/example/schemas/test/%/schema.metapack
6974
error: The schema requires an unrecognised vocabulary
7075
at vocabulary https://example.com/vocab/totally-unknown
71-
at path $(realpath "$TMP")/schemas/custom-meta.json
76+
at schema $(realpath "$TMP")/schemas/test.json
77+
at metaschema $(realpath "$TMP")/schemas/custom-meta.json
7278
EOF
7379

7480
diff "$TMP/output.txt" "$TMP/expected.txt"
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/bin/sh
2+
3+
set -o errexit
4+
set -o nounset
5+
6+
TMP="$(mktemp -d)"
7+
clean() { rm -rf "$TMP"; }
8+
trap clean EXIT
9+
10+
cat << EOF > "$TMP/one.json"
11+
{
12+
"url": "https://sourcemeta.com/",
13+
"contents": {
14+
"example": {
15+
"contents": {
16+
"schemas": {
17+
"baseUri": "https://example.com/",
18+
"path": "./schemas"
19+
}
20+
}
21+
}
22+
}
23+
}
24+
EOF
25+
26+
mkdir "$TMP/schemas"
27+
28+
cat << 'EOF' > "$TMP/schemas/custom-meta.json"
29+
{
30+
"$schema": "https://json-schema.org/draft/2020-12/schema",
31+
"$id": "https://example.com/custom-meta",
32+
"$vocabulary": "not-an-object"
33+
}
34+
EOF
35+
36+
cat << 'EOF' > "$TMP/schemas/test.json"
37+
{
38+
"$schema": "https://example.com/custom-meta",
39+
"$id": "https://example.com/test",
40+
"type": "string"
41+
}
42+
EOF
43+
44+
"$1" --skip-banner "$TMP/one.json" "$TMP/output" --concurrency 1 2> "$TMP/output.txt" && CODE="$?" || CODE="$?"
45+
test "$CODE" = "1" || exit 1
46+
47+
# Remove thread information
48+
if [ "$(uname)" = "Darwin" ]
49+
then
50+
sed -i '' 's/ \[.*\]//g' "$TMP/output.txt"
51+
else
52+
sed -i 's/ \[.*\]//g' "$TMP/output.txt"
53+
fi
54+
55+
cat << EOF > "$TMP/expected.txt"
56+
Writing output to: $(realpath "$TMP")/output
57+
Using configuration: $(realpath "$TMP")/one.json
58+
Detecting: $(realpath "$TMP")/schemas/custom-meta.json (#1)
59+
Detecting: $(realpath "$TMP")/schemas/test.json (#2)
60+
( 50%) Resolving: custom-meta.json
61+
(100%) Resolving: test.json
62+
( 2%) Producing: configuration.json
63+
( 5%) Producing: version.json
64+
( 8%) Producing: explorer/%/404.metapack
65+
( 11%) Producing: schemas/example/schemas/custom-meta/%/schema.metapack
66+
error: The schema does not adhere to its metaschema
67+
The value was expected to be of type object but it was of type string
68+
at instance location "/\$vocabulary"
69+
at evaluate path "/allOf/0/\$ref/properties/\$vocabulary/type"
70+
The object value was expected to validate against the 9 defined properties subschemas
71+
at instance location ""
72+
at evaluate path "/allOf/0/\$ref/properties"
73+
The object value was expected to validate against the referenced schema
74+
at instance location ""
75+
at evaluate path "/allOf/0/\$ref"
76+
The object value was expected to validate against the 7 given subschemas
77+
at instance location ""
78+
at evaluate path "/allOf"
79+
EOF
80+
81+
diff "$TMP/output.txt" "$TMP/expected.txt"

0 commit comments

Comments
 (0)