Skip to content

Commit 35d4ec8

Browse files
committed
Do not stop after the first failure in fmt and support --json
Signed-off-by: Juan Cruz Viotti <[email protected]>
1 parent c66d7b7 commit 35d4ec8

33 files changed

+388
-78
lines changed

src/command_fmt.cc

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include <sourcemeta/core/json.h>
22
#include <sourcemeta/core/jsonschema.h>
33

4-
#include <fstream> // std::ofstream
5-
#include <iostream> // std::cerr
6-
#include <sstream> // std::ostringstream
4+
#include <filesystem> // std::filesystem::path
5+
#include <fstream> // std::ofstream
6+
#include <functional> // std::reference_wrapper, std::cref
7+
#include <iostream> // std::cerr, std::cout
8+
#include <sstream> // std::ostringstream
9+
#include <vector> // std::vector
710

811
#include "command.h"
912
#include "error.h"
@@ -14,6 +17,9 @@
1417

1518
auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
1619
-> void {
20+
const bool output_json{options.contains("json")};
21+
bool result{true};
22+
std::vector<std::reference_wrapper<const std::filesystem::path>> failed_files;
1723
const auto indentation{parse_indentation(options)};
1824
for (const auto &entry : for_each_json(options)) {
1925
if (entry.first.extension() == ".yaml" ||
@@ -51,13 +57,13 @@ auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
5157

5258
if (options.contains("check")) {
5359
if (current.str() == expected.str()) {
54-
LOG_VERBOSE(options) << "PASS: " << entry.first.string() << "\n";
60+
LOG_VERBOSE(options) << "ok: " << entry.first.string() << "\n";
5561
} 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};
62+
if (!output_json) {
63+
std::cerr << "fail: " << entry.first.string() << "\n";
64+
}
65+
failed_files.push_back(std::cref(entry.first));
66+
result = false;
6167
}
6268
} else {
6369
if (current.str() != expected.str()) {
@@ -66,4 +72,31 @@ auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
6672
}
6773
}
6874
}
75+
76+
if (options.contains("check") && output_json) {
77+
auto output_json_object{sourcemeta::core::JSON::make_object()};
78+
output_json_object.assign("valid", sourcemeta::core::JSON{result});
79+
80+
if (!result) {
81+
auto errors_array{sourcemeta::core::JSON::make_array()};
82+
for (const auto &file_path : failed_files) {
83+
errors_array.push_back(sourcemeta::core::JSON{file_path.get().string()});
84+
}
85+
86+
output_json_object.assign("errors", sourcemeta::core::JSON{errors_array});
87+
}
88+
89+
sourcemeta::core::prettify(output_json_object, std::cout, indentation);
90+
std::cout << "\n";
91+
}
92+
93+
if (!result) {
94+
if (!output_json) {
95+
std::cerr << "\nRun the `fmt` command without `--check/-c` to fix the "
96+
"formatting"
97+
<< "\n";
98+
}
99+
100+
throw Fail{EXIT_FAILURE};
101+
}
69102
}

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: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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/schema.json"
11+
{
12+
"type": 1,
13+
"$schema": "http://json-schema.org/draft-04/schema#"
14+
}
15+
EOF
16+
17+
"$1" fmt "$TMP/schema.json" --check --json >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
18+
test "$CODE" = "1" || exit 1
19+
20+
cat << EOF > "$TMP/expected.json"
21+
{
22+
"valid": false,
23+
"errors": [
24+
"$(realpath "$TMP")/schema.json"
25+
]
26+
}
27+
EOF
28+
29+
diff "$TMP/output.json" "$TMP/expected.json"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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/schema.json"
11+
{
12+
"type": 1,
13+
"$schema": "http://json-schema.org/draft-04/schema#"
14+
}
15+
EOF
16+
17+
"$1" fmt "$TMP/schema.json" --check --json --indentation 4 >"$TMP/output.json" 2>&1 && CODE="$?" || CODE="$?"
18+
test "$CODE" = "1" || exit 1
19+
20+
cat << EOF > "$TMP/expected.json"
21+
{
22+
"valid": false,
23+
"errors": [
24+
"$(realpath "$TMP")/schema.json"
25+
]
26+
}
27+
EOF
28+
29+
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)