-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsonTestSuiteTest.java
More file actions
138 lines (118 loc) · 5.75 KB
/
JsonTestSuiteTest.java
File metadata and controls
138 lines (118 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package jdk.sandbox.compatibility;
import jdk.sandbox.java.util.json.Json;
import jdk.sandbox.java.util.json.JsonParseException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Logger;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.*;
/// Runs the JSON Test Suite against our implementation.
/// Files are categorized:
/// - y_*.json: Valid JSON that MUST parse successfully
/// - n_*.json: Invalid JSON that MUST fail to parse
/// - i_*.json: Implementation-defined (may accept or reject)
public class JsonTestSuiteTest {
private static final Logger LOGGER = Logger.getLogger(JsonTestSuiteTest.class.getName());
private static final Path TEST_DIR = Paths.get("target/test-resources/JSONTestSuite-master/test_parsing");
@TestFactory
@Disabled("This is now a reporting tool, not a blocking test. Use JsonTestSuiteSummary instead.")
Stream<DynamicTest> runJsonTestSuite() throws Exception {
if (!Files.exists(TEST_DIR)) {
System.err.println("Test suite not found. Run: mvn test-compile");
return Stream.empty();
}
return Files.walk(TEST_DIR)
.filter(p -> p.toString().endsWith(".json"))
.sorted()
.map(this::createTest);
}
private DynamicTest createTest(Path file) {
String filename = file.getFileName().toString();
return DynamicTest.dynamicTest(filename, () -> {
String content = null;
char[] charContent = null;
try {
content = Files.readString(file, StandardCharsets.UTF_8);
charContent = content.toCharArray();
} catch (MalformedInputException e) {
LOGGER.warning("UTF-8 failed for " + filename + ", using robust encoding detection");
try {
byte[] rawBytes = Files.readAllBytes(file);
charContent = RobustCharDecoder.decodeToChars(rawBytes, filename);
} catch (Exception ex) {
throw new RuntimeException("Failed to read test file " + filename + " - this is a fundamental I/O failure, not an encoding issue: " + ex.getMessage(), ex);
}
}
if (filename.startsWith("y_")) {
// Valid JSON - must parse successfully
testValidJson(filename, content, charContent);
} else if (filename.startsWith("n_")) {
// Invalid JSON - must fail to parse
testInvalidJson(filename, content, charContent);
} else if (filename.startsWith("i_")) {
// Implementation defined - just verify no crash
testImplementationDefinedJson(filename, content, charContent);
}
});
}
private void testValidJson(String filename, String content, char[] charContent) {
// Test String API if content is available
if (content != null) {
assertThatCode(() -> Json.parse(content))
.as("File %s should parse successfully with String API", filename)
.doesNotThrowAnyException();
}
// Test char[] API
assertThatCode(() -> Json.parse(charContent))
.as("File %s should parse successfully with char[] API", filename)
.doesNotThrowAnyException();
}
private void testInvalidJson(String filename, String content, char[] charContent) {
// Test String API if content is available
if (content != null) {
assertThatThrownBy(() -> Json.parse(content))
.as("File %s should fail to parse with String API", filename)
.satisfiesAnyOf(
e -> assertThat(e).isInstanceOf(JsonParseException.class),
e -> assertThat(e).isInstanceOf(StackOverflowError.class)
.describedAs("StackOverflowError is acceptable for deeply nested structures like " + filename)
);
}
// Test char[] API
assertThatThrownBy(() -> Json.parse(charContent))
.as("File %s should fail to parse with char[] API", filename)
.satisfiesAnyOf(
e -> assertThat(e).isInstanceOf(JsonParseException.class),
e -> assertThat(e).isInstanceOf(StackOverflowError.class)
.describedAs("StackOverflowError is acceptable for deeply nested structures like " + filename)
);
}
private void testImplementationDefinedJson(String filename, String content, char[] charContent) {
// Test String API if content is available
if (content != null) {
testImplementationDefinedSingle(filename + " (String API)", () -> Json.parse(content));
}
// Test char[] API
testImplementationDefinedSingle(filename + " (char[] API)", () -> Json.parse(charContent));
}
private void testImplementationDefinedSingle(String description, Runnable parseAction) {
try {
parseAction.run();
// OK - we accepted it
} catch (JsonParseException e) {
// OK - we rejected it
} catch (StackOverflowError e) {
// OK - acceptable for deeply nested structures
LOGGER.warning("StackOverflowError on implementation-defined: " + description);
} catch (Exception e) {
// NOT OK - unexpected exception type
fail("Unexpected exception for %s: %s", description, e);
}
}
}