Skip to content

Commit 1869ed9

Browse files
authored
Do not stop after the first failure in fmt and support --json (#551)
Signed-off-by: Juan Cruz Viotti <[email protected]>
1 parent c66d7b7 commit 1869ed9

33 files changed

+391
-76
lines changed

src/command_fmt.cc

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#include <sourcemeta/core/jsonschema.h>
33

44
#include <fstream> // std::ofstream
5-
#include <iostream> // std::cerr
5+
#include <iostream> // std::cerr, std::cout
66
#include <sstream> // std::ostringstream
7+
#include <utility> // std::move
8+
#include <vector> // std::vector
79

810
#include "command.h"
911
#include "error.h"
@@ -14,6 +16,9 @@
1416

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

5257
if (options.contains("check")) {
5358
if (current.str() == expected.str()) {
54-
LOG_VERBOSE(options) << "PASS: " << entry.first.string() << "\n";
59+
LOG_VERBOSE(options) << "ok: " << entry.first.string() << "\n";
60+
} else if (output_json) {
61+
failed_files.push_back(entry.first.string());
62+
result = false;
5563
} else {
56-
std::cerr << "FAIL: " << entry.first.string() << "\n";
57-
std::cerr << "Got:\n"
58-
<< current.str() << "\nBut expected:\n"
59-
<< expected.str() << "\n";
60-
throw Fail{EXIT_FAILURE};
64+
std::cerr << "fail: " << entry.first.string() << "\n";
65+
result = false;
6166
}
6267
} else {
6368
if (current.str() != expected.str()) {
@@ -66,4 +71,31 @@ auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
6671
}
6772
}
6873
}
74+
75+
if (options.contains("check") && output_json) {
76+
auto output_json_object{sourcemeta::core::JSON::make_object()};
77+
output_json_object.assign("valid", sourcemeta::core::JSON{result});
78+
79+
if (!result) {
80+
auto errors_array{sourcemeta::core::JSON::make_array()};
81+
for (auto &file_path : failed_files) {
82+
errors_array.push_back(sourcemeta::core::JSON{std::move(file_path)});
83+
}
84+
85+
output_json_object.assign("errors", sourcemeta::core::JSON{errors_array});
86+
}
87+
88+
sourcemeta::core::prettify(output_json_object, std::cout, indentation);
89+
std::cout << "\n";
90+
}
91+
92+
if (!result) {
93+
if (!output_json) {
94+
std::cerr << "\nRun the `fmt` command without `--check/-c` to fix the "
95+
"formatting"
96+
<< "\n";
97+
}
98+
99+
throw Fail{EXIT_FAILURE};
100+
}
69101
}

test/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ add_jsonschema_test_unix(format/pass_multi_extension)
3737
add_jsonschema_test_unix(format/pass_yaml)
3838
add_jsonschema_test_unix(format/pass_check_yaml)
3939
add_jsonschema_test_unix(format/fail_check_single)
40+
add_jsonschema_test_unix(format/fail_check_many)
4041
add_jsonschema_test_unix(format/pass_check_single)
42+
add_jsonschema_test_unix(format/pass_check_single_verbose)
4143
add_jsonschema_test_unix(format/pass_check_single_keep_ordering)
4244
add_jsonschema_test_unix(format/pass_directory_ignore_directory)
4345
add_jsonschema_test_unix(format/pass_directory_ignore_file)
@@ -53,6 +55,10 @@ add_jsonschema_test_unix(format/pass_default_dialect)
5355
add_jsonschema_test_unix(format/pass_default_dialect_config)
5456
add_jsonschema_test_unix(format/pass_default_dialect_config_relative)
5557
add_jsonschema_test_unix(format/pass_bignum_real)
58+
add_jsonschema_test_unix(format/pass_check_single_json)
59+
add_jsonschema_test_unix(format/fail_check_single_json)
60+
add_jsonschema_test_unix(format/fail_check_many_json)
61+
add_jsonschema_test_unix(format/fail_check_single_json_indentation)
5662

5763
# Validate
5864
add_jsonschema_test_unix(validate/fail_instance_enoent)

test/format/fail_check_many.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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+
mkdir "$TMP/schemas"
11+
12+
cat << 'EOF' > "$TMP/schemas/1.json"
13+
{
14+
"type": 1,
15+
"$schema": "http://json-schema.org/draft-04/schema#"
16+
}
17+
EOF
18+
19+
cat << 'EOF' > "$TMP/schemas/2.json"
20+
{
21+
"type": 1,
22+
"$schema": "http://json-schema.org/draft-04/schema#"
23+
}
24+
EOF
25+
26+
cat << 'EOF' > "$TMP/schemas/3.json"
27+
{
28+
"$schema": "http://json-schema.org/draft-04/schema#"
29+
}
30+
EOF
31+
32+
"$1" fmt "$TMP/schemas" --check >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
33+
test "$CODE" = "1" || exit 1
34+
35+
cat << EOF > "$TMP/expected.txt"
36+
fail: $(realpath "$TMP")/schemas/1.json
37+
fail: $(realpath "$TMP")/schemas/2.json
38+
39+
Run the \`fmt\` command without \`--check/-c\` to fix the formatting
40+
EOF
41+
42+
diff "$TMP/output.txt" "$TMP/expected.txt"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
mkdir "$TMP/schemas"
11+
12+
cat << 'EOF' > "$TMP/schemas/1.json"
13+
{
14+
"type": 1,
15+
"$schema": "http://json-schema.org/draft-04/schema#"
16+
}
17+
EOF
18+
19+
cat << 'EOF' > "$TMP/schemas/2.json"
20+
{
21+
"type": 1,
22+
"$schema": "http://json-schema.org/draft-04/schema#"
23+
}
24+
EOF
25+
26+
cat << 'EOF' > "$TMP/schemas/3.json"
27+
{
28+
"$schema": "http://json-schema.org/draft-04/schema#"
29+
}
30+
EOF
31+
32+
"$1" fmt "$TMP/schemas" --check --json >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
33+
test "$CODE" = "1" || exit 1
34+
35+
cat << EOF > "$TMP/expected.json"
36+
{
37+
"valid": false,
38+
"errors": [
39+
"$(realpath "$TMP")/schemas/1.json",
40+
"$(realpath "$TMP")/schemas/2.json"
41+
]
42+
}
43+
EOF
44+
45+
diff "$TMP/output.json" "$TMP/expected.json"

test/format/fail_check_single.sh

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,16 @@ cat << 'EOF' > "$TMP/schema.json"
1414
}
1515
EOF
1616

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

20-
cat << EOF > "$TMP/error.txt"
21-
FAIL: $(realpath "$TMP")/schema.json
22-
Got:
23-
{
24-
"type": 1,
25-
"\$schema": "http://json-schema.org/draft-04/schema#"
26-
}
27-
28-
But expected:
29-
{
30-
"\$schema": "http://json-schema.org/draft-04/schema#",
31-
"type": 1
32-
}
20+
cat << EOF > "$TMP/expected.txt"
21+
fail: $(realpath "$TMP")/schema.json
3322
23+
Run the \`fmt\` command without \`--check/-c\` to fix the formatting
3424
EOF
3525

36-
diff "$TMP/stderr.txt" "$TMP/error.txt"
26+
diff "$TMP/output.txt" "$TMP/expected.txt"
3727

3828
cat << 'EOF' > "$TMP/expected.json"
3929
{

test/format/fail_check_single_indentation.sh

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,16 @@ cat << 'EOF' > "$TMP/schema.json"
1414
}
1515
EOF
1616

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

20-
cat << EOF > "$TMP/error.txt"
21-
FAIL: $(realpath "$TMP")/schema.json
22-
Got:
23-
{
24-
"\$schema": "http://json-schema.org/draft-04/schema#",
25-
"type": 1
26-
}
27-
28-
But expected:
29-
{
30-
"\$schema": "http://json-schema.org/draft-04/schema#",
31-
"type": 1
32-
}
20+
cat << EOF > "$TMP/expected.txt"
21+
fail: $(realpath "$TMP")/schema.json
3322
23+
Run the \`fmt\` command without \`--check/-c\` to fix the formatting
3424
EOF
3525

36-
diff "$TMP/stderr.txt" "$TMP/error.txt"
26+
diff "$TMP/output.txt" "$TMP/expected.txt"
3727

3828
cat << 'EOF' > "$TMP/expected.json"
3929
{

test/format/fail_check_single_invalid.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,14 @@ cat << 'EOF' > "$TMP/schema.json"
1414
}
1515
EOF
1616

17-
"$1" fmt "$TMP/schema.json" --check 2>"$TMP/output.txt" && CODE="$?" || CODE="$?"
17+
"$1" fmt "$TMP/schema.json" --check >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
1818
test "$CODE" = "1" || exit 1
19+
20+
cat << EOF > "$TMP/expected.txt"
21+
error: Failed to parse the JSON document
22+
at line 3
23+
at column 3
24+
at file path $(realpath "$TMP")/schema.json
25+
EOF
26+
27+
diff "$TMP/output.txt" "$TMP/expected.txt"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
mkdir -p "$TMP/this/is/a/very/very/very/long/path"
11+
12+
cat << 'EOF' > "$TMP/this/is/a/very/very/very/long/path/schema.json"
13+
{
14+
"type": 1,
15+
"$schema": "http://json-schema.org/draft-04/schema#"
16+
}
17+
EOF
18+
19+
"$1" fmt "$TMP/this/is/a/very/very/very/long/path/schema.json" \
20+
--check --json >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
21+
test "$CODE" = "1" || exit 1
22+
23+
cat << EOF > "$TMP/expected.json"
24+
{
25+
"valid": false,
26+
"errors": [
27+
"$(realpath "$TMP")/this/is/a/very/very/very/long/path/schema.json"
28+
]
29+
}
30+
EOF
31+
32+
diff "$TMP/output.json" "$TMP/expected.json"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
mkdir -p "$TMP/this/is/a/very/very/very/long/path"
11+
12+
cat << 'EOF' > "$TMP/this/is/a/very/very/very/long/path/schema.json"
13+
{
14+
"type": 1,
15+
"$schema": "http://json-schema.org/draft-04/schema#"
16+
}
17+
EOF
18+
19+
"$1" fmt "$TMP/this/is/a/very/very/very/long/path/schema.json" \
20+
--check --json --indentation 4 >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
21+
test "$CODE" = "1" || exit 1
22+
23+
cat << EOF > "$TMP/expected.json"
24+
{
25+
"valid": false,
26+
"errors": [
27+
"$(realpath "$TMP")/this/is/a/very/very/very/long/path/schema.json"
28+
]
29+
}
30+
EOF
31+
32+
diff "$TMP/output.json" "$TMP/expected.json"

test/format/fail_invalid_path.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,12 @@ TMP="$(mktemp -d)"
77
clean() { rm -rf "$TMP"; }
88
trap clean EXIT
99

10-
"$1" fmt "$TMP/does_not_exist.json" && CODE="$?" || CODE="$?"
10+
"$1" fmt "$TMP/does_not_exist.json" >"$TMP/output.txt" 2>&1 && CODE="$?" || CODE="$?"
1111
test "$CODE" = "1" || exit 1
12+
13+
cat << EOF > "$TMP/expected.txt"
14+
error: No such file or directory
15+
at file path $(realpath "$TMP")/does_not_exist.json
16+
EOF
17+
18+
diff "$TMP/output.txt" "$TMP/expected.txt"

0 commit comments

Comments
 (0)