Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 39 additions & 7 deletions src/command_fmt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
#include <sourcemeta/core/jsonschema.h>

#include <fstream> // std::ofstream
#include <iostream> // std::cerr
#include <iostream> // std::cerr, std::cout
#include <sstream> // std::ostringstream
#include <utility> // std::move
#include <vector> // std::vector

#include "command.h"
#include "error.h"
Expand All @@ -14,6 +16,9 @@

auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
-> void {
const bool output_json{options.contains("json")};
bool result{true};
std::vector<std::string> failed_files;
const auto indentation{parse_indentation(options)};
for (const auto &entry : for_each_json(options)) {
if (entry.first.extension() == ".yaml" ||
Expand Down Expand Up @@ -51,13 +56,13 @@ auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)

if (options.contains("check")) {
if (current.str() == expected.str()) {
LOG_VERBOSE(options) << "PASS: " << entry.first.string() << "\n";
LOG_VERBOSE(options) << "ok: " << entry.first.string() << "\n";
} else if (output_json) {
failed_files.push_back(entry.first.string());
result = false;
} else {
std::cerr << "FAIL: " << entry.first.string() << "\n";
std::cerr << "Got:\n"
<< current.str() << "\nBut expected:\n"
<< expected.str() << "\n";
throw Fail{EXIT_FAILURE};
std::cerr << "fail: " << entry.first.string() << "\n";
result = false;
}
} else {
if (current.str() != expected.str()) {
Expand All @@ -66,4 +71,31 @@ auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
}
}
}

if (options.contains("check") && output_json) {
auto output_json_object{sourcemeta::core::JSON::make_object()};
output_json_object.assign("valid", sourcemeta::core::JSON{result});

if (!result) {
auto errors_array{sourcemeta::core::JSON::make_array()};
for (auto &file_path : failed_files) {
errors_array.push_back(sourcemeta::core::JSON{std::move(file_path)});
}

output_json_object.assign("errors", sourcemeta::core::JSON{errors_array});
}

sourcemeta::core::prettify(output_json_object, std::cout, indentation);
std::cout << "\n";
}

if (!result) {
if (!output_json) {
std::cerr << "\nRun the `fmt` command without `--check/-c` to fix the "
"formatting"
<< "\n";
}

throw Fail{EXIT_FAILURE};
}
}
6 changes: 6 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ add_jsonschema_test_unix(format/pass_multi_extension)
add_jsonschema_test_unix(format/pass_yaml)
add_jsonschema_test_unix(format/pass_check_yaml)
add_jsonschema_test_unix(format/fail_check_single)
add_jsonschema_test_unix(format/fail_check_many)
add_jsonschema_test_unix(format/pass_check_single)
add_jsonschema_test_unix(format/pass_check_single_verbose)
add_jsonschema_test_unix(format/pass_check_single_keep_ordering)
add_jsonschema_test_unix(format/pass_directory_ignore_directory)
add_jsonschema_test_unix(format/pass_directory_ignore_file)
Expand All @@ -53,6 +55,10 @@ add_jsonschema_test_unix(format/pass_default_dialect)
add_jsonschema_test_unix(format/pass_default_dialect_config)
add_jsonschema_test_unix(format/pass_default_dialect_config_relative)
add_jsonschema_test_unix(format/pass_bignum_real)
add_jsonschema_test_unix(format/pass_check_single_json)
add_jsonschema_test_unix(format/fail_check_single_json)
add_jsonschema_test_unix(format/fail_check_many_json)
add_jsonschema_test_unix(format/fail_check_single_json_indentation)

# Validate
add_jsonschema_test_unix(validate/fail_instance_enoent)
Expand Down
42 changes: 42 additions & 0 deletions test/format/fail_check_many.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/sh

set -o errexit
set -o nounset

TMP="$(mktemp -d)"
clean() { rm -rf "$TMP"; }
trap clean EXIT

mkdir "$TMP/schemas"

cat << 'EOF' > "$TMP/schemas/1.json"
{
"type": 1,
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

cat << 'EOF' > "$TMP/schemas/2.json"
{
"type": 1,
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

cat << 'EOF' > "$TMP/schemas/3.json"
{
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

"$1" fmt "$TMP/schemas" --check >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.txt"
fail: $(realpath "$TMP")/schemas/1.json
fail: $(realpath "$TMP")/schemas/2.json

Run the \`fmt\` command without \`--check/-c\` to fix the formatting
EOF

diff "$TMP/output.txt" "$TMP/expected.txt"
45 changes: 45 additions & 0 deletions test/format/fail_check_many_json.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/sh

set -o errexit
set -o nounset

TMP="$(mktemp -d)"
clean() { rm -rf "$TMP"; }
trap clean EXIT

mkdir "$TMP/schemas"

cat << 'EOF' > "$TMP/schemas/1.json"
{
"type": 1,
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

cat << 'EOF' > "$TMP/schemas/2.json"
{
"type": 1,
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

cat << 'EOF' > "$TMP/schemas/3.json"
{
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

"$1" fmt "$TMP/schemas" --check --json >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.json"
{
"valid": false,
"errors": [
"$(realpath "$TMP")/schemas/1.json",
"$(realpath "$TMP")/schemas/2.json"
]
}
EOF

diff "$TMP/output.json" "$TMP/expected.json"
20 changes: 5 additions & 15 deletions test/format/fail_check_single.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,16 @@ cat << 'EOF' > "$TMP/schema.json"
}
EOF

"$1" fmt "$TMP/schema.json" --check 2>"$TMP/stderr.txt" && CODE="$?" || CODE="$?"
"$1" fmt "$TMP/schema.json" --check >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/error.txt"
FAIL: $(realpath "$TMP")/schema.json
Got:
{
"type": 1,
"\$schema": "http://json-schema.org/draft-04/schema#"
}

But expected:
{
"\$schema": "http://json-schema.org/draft-04/schema#",
"type": 1
}
cat << EOF > "$TMP/expected.txt"
fail: $(realpath "$TMP")/schema.json

Run the \`fmt\` command without \`--check/-c\` to fix the formatting
EOF

diff "$TMP/stderr.txt" "$TMP/error.txt"
diff "$TMP/output.txt" "$TMP/expected.txt"

cat << 'EOF' > "$TMP/expected.json"
{
Expand Down
20 changes: 5 additions & 15 deletions test/format/fail_check_single_indentation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,16 @@ cat << 'EOF' > "$TMP/schema.json"
}
EOF

"$1" fmt "$TMP/schema.json" --indentation 4 --check 2>"$TMP/stderr.txt" && CODE="$?" || CODE="$?"
"$1" fmt "$TMP/schema.json" --indentation 4 --check >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/error.txt"
FAIL: $(realpath "$TMP")/schema.json
Got:
{
"\$schema": "http://json-schema.org/draft-04/schema#",
"type": 1
}

But expected:
{
"\$schema": "http://json-schema.org/draft-04/schema#",
"type": 1
}
cat << EOF > "$TMP/expected.txt"
fail: $(realpath "$TMP")/schema.json

Run the \`fmt\` command without \`--check/-c\` to fix the formatting
EOF

diff "$TMP/stderr.txt" "$TMP/error.txt"
diff "$TMP/output.txt" "$TMP/expected.txt"

cat << 'EOF' > "$TMP/expected.json"
{
Expand Down
11 changes: 10 additions & 1 deletion test/format/fail_check_single_invalid.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,14 @@ cat << 'EOF' > "$TMP/schema.json"
}
EOF

"$1" fmt "$TMP/schema.json" --check 2>"$TMP/output.txt" && CODE="$?" || CODE="$?"
"$1" fmt "$TMP/schema.json" --check >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.txt"
error: Failed to parse the JSON document
at line 3
at column 3
at file path $(realpath "$TMP")/schema.json
EOF

diff "$TMP/output.txt" "$TMP/expected.txt"
32 changes: 32 additions & 0 deletions test/format/fail_check_single_json.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

set -o errexit
set -o nounset

TMP="$(mktemp -d)"
clean() { rm -rf "$TMP"; }
trap clean EXIT

mkdir -p "$TMP/this/is/a/very/very/very/long/path"

cat << 'EOF' > "$TMP/this/is/a/very/very/very/long/path/schema.json"
{
"type": 1,
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

"$1" fmt "$TMP/this/is/a/very/very/very/long/path/schema.json" \
--check --json >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.json"
{
"valid": false,
"errors": [
"$(realpath "$TMP")/this/is/a/very/very/very/long/path/schema.json"
]
}
EOF

diff "$TMP/output.json" "$TMP/expected.json"
32 changes: 32 additions & 0 deletions test/format/fail_check_single_json_indentation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

set -o errexit
set -o nounset

TMP="$(mktemp -d)"
clean() { rm -rf "$TMP"; }
trap clean EXIT

mkdir -p "$TMP/this/is/a/very/very/very/long/path"

cat << 'EOF' > "$TMP/this/is/a/very/very/very/long/path/schema.json"
{
"type": 1,
"$schema": "http://json-schema.org/draft-04/schema#"
}
EOF

"$1" fmt "$TMP/this/is/a/very/very/very/long/path/schema.json" \
--check --json --indentation 4 >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.json"
{
"valid": false,
"errors": [
"$(realpath "$TMP")/this/is/a/very/very/very/long/path/schema.json"
]
}
EOF

diff "$TMP/output.json" "$TMP/expected.json"
9 changes: 8 additions & 1 deletion test/format/fail_invalid_path.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,12 @@ TMP="$(mktemp -d)"
clean() { rm -rf "$TMP"; }
trap clean EXIT

"$1" fmt "$TMP/does_not_exist.json" && CODE="$?" || CODE="$?"
"$1" fmt "$TMP/does_not_exist.json" >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.txt"
error: No such file or directory
at file path $(realpath "$TMP")/does_not_exist.json
EOF

diff "$TMP/output.txt" "$TMP/expected.txt"
10 changes: 5 additions & 5 deletions test/format/fail_no_dialect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ cat << 'EOF' > "$TMP/schema.json"
}
EOF

"$1" fmt "$TMP/schema.json" 2>"$TMP/stderr.txt" && CODE="$?" || CODE="$?"
"$1" fmt "$TMP/schema.json" >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << EOF > "$TMP/expected.txt"
Expand All @@ -28,16 +28,16 @@ If the input does not declare the \`\$schema\` keyword, you might want to
explicitly declare a default dialect using \`--default-dialect/-d\`
EOF

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

# JSON error
"$1" fmt "$TMP/schema.json" --json >"$TMP/stdout.txt" && CODE="$?" || CODE="$?"
"$1" fmt "$TMP/schema.json" --json >"$TMP/output_json.txt" 2>&1 && CODE="$?" || CODE="$?"
test "$CODE" = "1" || exit 1

cat << 'EOF' > "$TMP/expected.txt"
cat << 'EOF' > "$TMP/expected_json.txt"
{
"error": "Could not determine the base dialect of the schema"
}
EOF

diff "$TMP/stdout.txt" "$TMP/expected.txt"
diff "$TMP/output_json.txt" "$TMP/expected_json.txt"
Loading