Skip to content

Commit

Permalink
Add an --http option to validate, test, and bundle
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti committed Jun 1, 2024
1 parent 5b7c910 commit 2ddb606
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 17 deletions.
5 changes: 3 additions & 2 deletions src/command_bundle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

auto intelligence::jsonschema::cli::bundle(
const std::span<const std::string> &arguments) -> int {
const auto options{parse_options(arguments, {})};
const auto options{parse_options(arguments, {"h", "http"})};
CLI_ENSURE(!options.at("").empty(), "You must pass a JSON Schema as input");
auto schema{sourcemeta::jsontoolkit::from_file(options.at("").front())};
sourcemeta::jsontoolkit::bundle(
schema, sourcemeta::jsontoolkit::default_schema_walker, resolver(options))
schema, sourcemeta::jsontoolkit::default_schema_walker,
resolver(options, options.contains("h") || options.contains("http")))
.wait();
sourcemeta::jsontoolkit::prettify(
schema, std::cout, sourcemeta::jsontoolkit::schema_format_compare);
Expand Down
6 changes: 3 additions & 3 deletions src/command_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
#include "utils.h"

// TODO: Add a flag to first validate schema against its metaschema
// TODO: Add a flag to prevent the use of HTTP resolution
auto intelligence::jsonschema::cli::test(
const std::span<const std::string> &arguments) -> int {
const auto options{parse_options(arguments, {})};
const auto options{parse_options(arguments, {"h", "http"})};
bool result{true};
const auto test_resolver{resolver(options)};
const auto test_resolver{
resolver(options, options.contains("h") || options.contains("http"))};

for (const auto &entry : for_each_json(options.at(""))) {
const sourcemeta::jsontoolkit::JSON test{
Expand Down
6 changes: 3 additions & 3 deletions src/command_validate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@

// TODO: Add a flag to first validate schema against its metaschema
// TODO: Add a flag to emit output using the standard JSON Schema output format
// TODO: Add a flag to prevent the use of HTTP resolution
auto intelligence::jsonschema::cli::validate(
const std::span<const std::string> &arguments) -> int {
const auto options{parse_options(arguments, {})};
const auto options{parse_options(arguments, {"h", "http"})};
CLI_ENSURE(options.at("").size() >= 2,
"You must pass a schema followed by an instance")
const auto &schema_path{options.at("").at(0)};
Expand All @@ -23,7 +22,8 @@ auto intelligence::jsonschema::cli::validate(
const auto schema{sourcemeta::jsontoolkit::from_file(schema_path)};

const auto schema_template{sourcemeta::jsontoolkit::compile(
schema, sourcemeta::jsontoolkit::default_schema_walker, resolver(options),
schema, sourcemeta::jsontoolkit::default_schema_walker,
resolver(options, options.contains("h") || options.contains("http")),
sourcemeta::jsontoolkit::default_schema_compiler)};

const auto instance{sourcemeta::jsontoolkit::from_file(instance_path)};
Expand Down
19 changes: 14 additions & 5 deletions src/main.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <sourcemeta/jsontoolkit/jsonschema.h>

#include <algorithm> // std::min
#include <cstdlib> // EXIT_FAILURE, EXIT_SUCCESS
#include <filesystem> // std::filesystem
Expand All @@ -18,17 +20,20 @@ Global Options:
Commands:
validate <schema.json> <instance.json>
validate <schema.json> <instance.json> [--http/-h]
Validate an instance against a schema, printing error information, if
any, in a human-readable manner.
any, in a human-readable manner. The `--http/-h` option enables resolving
remote schemas over the HTTP protocol.
test [schema.json...]
test [schema.json...] [--http/-h]
A schema test runner inspired by the official JSON Schema test suite.
Passing directories as input will run every `.json` file in such
directory (recursively) as a test. If no argument is passed, run every
`.json` file in the current working directory (recursively) as a test.
The `--http/-h` option enables resolving remote schemas over the HTTP
protocol.
fmt [schema.json...] [--check/-c]
Expand All @@ -46,12 +51,13 @@ Global Options:
(recursively). The `--fix/-f` option will attempt to automatically
fix the linter errors.
bundle <schema.json>
bundle <schema.json> [--http/-h]
Perform JSON Schema Bundling on a schema to inline remote references,
printing the result to standard output. Read
https://json-schema.org/blog/posts/bundling-json-schema-compound-documents
to learn more.
to learn more. The `--http/-h` option enables resolving remote schemas
over the HTTP protocol.
frame <schema.json>
Expand Down Expand Up @@ -91,6 +97,9 @@ auto main(int argc, char *argv[]) noexcept -> int {
const std::vector<std::string> arguments{argv + std::min(2, argc),
argv + argc};
return jsonschema_main(program, command, arguments);
} catch (const sourcemeta::jsontoolkit::SchemaResolutionError &error) {
std::cerr << error.what() << ": " << error.id() << "\n";
return EXIT_FAILURE;
} catch (const std::exception &error) {
std::cerr << "Error: " << error.what() << "\n";
return EXIT_FAILURE;
Expand Down
6 changes: 3 additions & 3 deletions src/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ static auto fallback_resolver(std::string_view identifier)
return promise.get_future();
}

auto resolver(const std::map<std::string, std::vector<std::string>> &options)
-> sourcemeta::jsontoolkit::SchemaResolver {
auto resolver(const std::map<std::string, std::vector<std::string>> &options,
const bool remote) -> sourcemeta::jsontoolkit::SchemaResolver {
sourcemeta::jsontoolkit::MapSchemaResolver dynamic_resolver{
fallback_resolver};
remote ? fallback_resolver : sourcemeta::jsontoolkit::official_resolver};

if (options.contains("resolve")) {
for (const auto &schema_path : options.at("resolve")) {
Expand Down
3 changes: 2 additions & 1 deletion src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ auto pretty_evaluate_callback(
const sourcemeta::jsontoolkit::JSON &,
const sourcemeta::jsontoolkit::JSON &) -> void;

auto resolver(const std::map<std::string, std::vector<std::string>> &options)
auto resolver(const std::map<std::string, std::vector<std::string>> &options,
const bool remote = false)
-> sourcemeta::jsontoolkit::SchemaResolver;

auto log_verbose(const std::map<std::string, std::vector<std::string>> &options)
Expand Down
5 changes: 5 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ add_jsonschema_test_unix(format_cwd)
add_jsonschema_test_unix(frame)
add_jsonschema_test_unix(validate_pass)
add_jsonschema_test_unix(validate_fail)
add_jsonschema_test_unix(validate_fail_remote_no_http)
add_jsonschema_test_unix(validate_non_supported)
add_jsonschema_test_unix(bundle_non_remote)
add_jsonschema_test_unix(bundle_remote_single_schema)
add_jsonschema_test_unix(bundle_remote_no_http)
add_jsonschema_test_unix(test_single_pass)
add_jsonschema_test_unix(test_single_fail)
add_jsonschema_test_unix(test_single_unsupported)
add_jsonschema_test_unix(lint_pass)
add_jsonschema_test_unix(lint_fail)
add_jsonschema_test_unix(lint_fix)

# TODO: Enable certain tests (if a given CMake option
# is set) that perform outbound HTTP requests
26 changes: 26 additions & 0 deletions test/bundle_remote_no_http.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/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",
"$id": "https://example.com",
"$ref": "nested"
}
EOF

"$1" bundle "$TMP/schema.json" && CODE="$?" || CODE="$?"

if [ "$CODE" = "0" ]
then
echo "FAIL" 1>&2
exit 1
else
echo "PASS" 1>&2
fi
30 changes: 30 additions & 0 deletions test/validate_fail_remote_no_http.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/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",
"$id": "https://example.com",
"$ref": "nested"
}
EOF

cat << 'EOF' > "$TMP/instance.json"
{ "foo": 1 }
EOF

"$1" validate "$TMP/schema.json" "$TMP/instance.json" && CODE="$?" || CODE="$?"

if [ "$CODE" = "0" ]
then
echo "FAIL" 1>&2
exit 1
else
echo "PASS" 1>&2
fi

0 comments on commit 2ddb606

Please sign in to comment.