Skip to content

Commit fdd3849

Browse files
authored
JSON Schema: strict coverage headline + docs; single fetch path, compile-session, and logging discipline (#37)
* Issue #29 Add OpenRPC schema validation IT and resources What - Sketch `OpenRPCSchemaValidationIT` dynamic integration test in `json-java21-schema`. - Sketch OpenRPC test resources under `src/test/resources/openrpc/` (minimal embedded schema + examples and negative cases). - Add short sign-posts in module README and AGENTS. - Add CI step to assert total test counts to prevent silent skips. How to verify - Run: `mvn -B -DskipITs=false -DskipTests=false verify` - Expected totals: tests=1807, failures=0, errors=0, skipped=577 - New Sketch tests: 1 IT class `OpenRPCSchemaValidationIT` (6 dynamic tests from example files) * Fix CI configuration: use Java 21 and correct test count - Change Java version from 24 to 21 to match project requirements - Update expected test count from 1807 to 1802 (actual current count) - The OpenRPC tests are running correctly (6 tests added) * fix: improve JsonSchemaCheckIT metrics reporting for defensible compatibility statistics - Add comprehensive SuiteMetrics class with thread-safe counters - Track groups discovered, tests discovered, validations run, passed/failed - Categorize skips: unsupportedSchemaGroup, testException, lenientMismatch - Add console summary line with detailed metrics breakdown - Support JSON/CSV export via -Djson.schema.metrics=json|csv - Add per-file breakdown for detailed analysis - Preserve existing strict/lenient behavior while adding metrics - Zero additional dependencies, thread-safe implementation Fixes #31 * docs: update compatibility claims with measured metrics from JsonSchemaCheckIT - Replace estimated 71% compatibility with actual measured 63.3% (1,153 of 1,822 tests) - Add comprehensive metrics reporting documentation - Document test coverage: 420 groups, 1,657 validations, 576 skips categorized - Add usage examples for JSON/CSV metrics export - Clarify distinction between lenient and strict mode results - Provide defensible statistics based on actual test suite measurements The documentation now reflects the accurate, measured compatibility statistics provided by the new metrics system rather than estimates. * more features * pack5 * pack6 * more tests * wip broken test * fixed * wip * wip * tests pass * back to wip k2 * offical logging advice * comments * wip two errors two failures * all tests pass * notes * test working less logging * state * fixed relative paths * better data structures * pre tidy-up * context stack * logging * docs: update schema compatibility metrics (strict headline + overall); align README test commands with wrapper; include updated schema engine changes for remote refs, logging, and compile session * ci: update expected test totals to reflect new suite counts (guard against silent skips)
1 parent 690284e commit fdd3849

40 files changed

+7071
-948
lines changed

.github/workflows/ci.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,36 @@ jobs:
1313
- name: Checkout
1414
uses: actions/checkout@v4
1515

16-
- name: Set up JDK 24
16+
- name: Set up JDK 21
1717
uses: actions/setup-java@v4
1818
with:
1919
distribution: temurin
20-
java-version: '24'
20+
java-version: '21'
2121
cache: 'maven'
2222

2323
- name: Build and verify
2424
run: mvn -B -DskipITs=false -DskipTests=false verify
2525

26+
- name: Assert test count (no tests silently skipped)
27+
run: |
28+
python3 - <<'PY'
29+
import os, xml.etree.ElementTree as ET, sys
30+
totals={'tests':0,'failures':0,'errors':0,'skipped':0}
31+
for dirpath,_,files in os.walk('.'):
32+
if 'target' not in dirpath: continue
33+
if 'surefire-reports' not in dirpath and 'failsafe-reports' not in dirpath: continue
34+
for fn in files:
35+
if not fn.endswith('.xml'): continue
36+
p=os.path.join(dirpath,fn)
37+
try:
38+
r=ET.parse(p).getroot()
39+
for k in totals: totals[k]+=int(r.get(k,'0'))
40+
except Exception:
41+
pass
42+
exp_tests=1908
43+
exp_skipped=713
44+
if totals['tests']!=exp_tests or totals['skipped']!=exp_skipped:
45+
print(f"Unexpected test totals: {totals} != expected tests={exp_tests}, skipped={exp_skipped}")
46+
sys.exit(1)
47+
print(f"OK totals: {totals}")
48+
PY

AGENTS.md

Lines changed: 349 additions & 257 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,28 @@ var result = schema.validate(
104104
// result.valid() => true
105105
```
106106

107-
Compatibility: runs the official 2020‑12 JSON Schema Test Suite on `verify`; in strict mode it currently passes about 71% of applicable cases.
107+
Compatibility: runs the official 2020‑12 JSON Schema Test Suite on `verify`; **strict compatibility is 61.6%** (1024 of 1,663 validations). [Overall including all discovered tests: 56.2% (1024 of 1,822)].
108+
109+
### JSON Schema Test Suite Metrics
110+
111+
The validator now provides defensible compatibility statistics:
112+
113+
```bash
114+
# Run with console metrics (default)
115+
./mvn-test-no-boilerplate.sh -pl json-java21-schema
116+
117+
# Export detailed JSON metrics
118+
./mvn-test-no-boilerplate.sh -pl json-java21-schema -Djson.schema.metrics=json
119+
120+
# Export CSV metrics for analysis
121+
./mvn-test-no-boilerplate.sh -pl json-java21-schema -Djson.schema.metrics=csv
122+
```
123+
124+
**Current measured compatibility**:
125+
- **Strict (headline)**: 61.6% (1024 of 1,663 validations)
126+
- **Overall (incl. out‑of‑scope)**: 56.2% (1024 of 1,822 discovered tests)
127+
- **Test coverage**: 420 test groups, 1,663 validation attempts
128+
- **Skip breakdown**: 65 unsupported schema groups, 0 test exceptions, 647 lenient mismatches
108129

109130
## Building
110131

json-java21-schema/AGENTS.md

Lines changed: 0 additions & 92 deletions
This file was deleted.

json-java21-schema/README.md

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
Stack-based JSON Schema validator using sealed interface pattern with inner record types.
44

5-
- Draft 2020-12 subset: object/array/string/number/boolean/null, allOf/anyOf/not, if/then/else, const, $defs and local $ref (including root "#")
5+
- Draft 2020-12 subset: object/array/string/number/boolean/null, allOf/anyOf/not, if/then/else, const, format (11 validators), $defs and local $ref (including root "#")
66
- Thread-safe compiled schemas; immutable results with error paths/messages
7+
- **Novel Architecture**: This module uses an innovative immutable "compile many documents (possibly just one) into an immutable set of roots using a work stack" compile-time architecture for high-performance schema compilation and validation. See `AGENTS.md` for detailed design documentation.
78

89
Quick usage
910

@@ -22,18 +23,29 @@ Compatibility and verify
2223

2324
- The module runs the official JSON Schema Test Suite during Maven verify.
2425
- Default mode is lenient: unsupported groups/tests are skipped to avoid build breaks while still logging.
25-
- Strict mode: enable with -Djson.schema.strict=true to enforce full assertions. In strict mode it currently passes about 71% of applicable cases.
26+
- Strict mode: enable with `-Djson.schema.strict=true` to enforce full assertions.
27+
- Measured compatibility (headline strictness): 61.6% (1024 of 1,663 validations)
28+
- Overall including all discovered tests: 56.2% (1024 of 1,822)
29+
- Test coverage: 420 test groups, 1,663 validation attempts, 65 unsupported schema groups, 0 test exceptions, 647 lenient mismatches
30+
- Detailed metrics available via `-Djson.schema.metrics=json|csv`
2631

2732
How to run
2833

2934
```bash
3035
# Run unit + integration tests (includes official suite)
31-
mvn -pl json-java21-schema -am verify
36+
./mvn-test-no-boilerplate.sh -pl json-java21-schema
3237

3338
# Strict mode
34-
mvn -Djson.schema.strict=true -pl json-java21-schema -am verify
39+
./mvn-test-no-boilerplate.sh -pl json-java21-schema -Djson.schema.strict=true
3540
```
3641

42+
OpenRPC validation
43+
44+
- Additional integration test validates OpenRPC documents using a minimal, self‑contained schema:
45+
- Test: `src/test/java/io/github/simbo1905/json/schema/OpenRPCSchemaValidationIT.java`
46+
- Resources: `src/test/resources/openrpc/` (schema and examples)
47+
- Thanks to OpenRPC meta-schema and examples (Apache-2.0): https://github.com/open-rpc/meta-schema and https://github.com/open-rpc/examples
48+
3749
## API Design
3850

3951
Single public interface with all schema types as inner records:
@@ -145,3 +157,30 @@ if (!result.valid()) {
145157
}
146158
}
147159
```
160+
161+
### Format Validation
162+
163+
The validator supports JSON Schema 2020-12 format validation with opt-in assertion mode:
164+
165+
- **Built-in formats**: uuid, email, ipv4, ipv6, uri, uri-reference, hostname, date, time, date-time, regex
166+
- **Annotation by default**: Format validation is annotation-only (always passes) unless format assertion is enabled
167+
- **Opt-in assertion**: Enable format validation via:
168+
- `JsonSchema.Options(true)` parameter in `compile()`
169+
- System property: `-Djsonschema.format.assertion=true`
170+
- Root schema flag: `"formatAssertion": true`
171+
- **Unknown formats**: Gracefully handled with logged warnings (no validation errors)
172+
173+
```java
174+
// Format validation disabled (default) - always passes
175+
var schema = JsonSchema.compile(Json.parse("""
176+
{"type": "string", "format": "email"}
177+
"""));
178+
schema.validate(Json.parse("\"invalid-email\"")); // passes
179+
180+
// Format validation enabled - validates format
181+
var schema = JsonSchema.compile(Json.parse("""
182+
{"type": "string", "format": "email"}
183+
"""), new JsonSchema.Options(true));
184+
schema.validate(Json.parse("\"invalid-email\"")); // fails
185+
schema.validate(Json.parse("\"[email protected]\"")); // passes
186+
```
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/bash
2+
3+
# Strip Maven test boilerplate - show compile errors and test results only
4+
# Usage: ./mvn-test-no-boilerplate.sh [maven test arguments]
5+
#
6+
# Examples:
7+
# ./mvn-test-no-boilerplate.sh -Dtest=RefactorTests
8+
# ./mvn-test-no-boilerplate.sh -Dtest=RefactorTests#testList -Djava.util.logging.ConsoleHandler.level=INFO
9+
# ./mvn-test-no-boilerplate.sh -Dtest=RefactorTests#testList -Djava.util.logging.ConsoleHandler.level=FINER
10+
#
11+
# For running tests in a specific module:
12+
# ./mvn-test-no-boilerplate.sh -pl json-java21-api-tracker -Dtest=CompilerApiLearningTest
13+
#
14+
# The script automatically detects if mvnd is available, otherwise falls back to mvn
15+
16+
# Detect if mvnd is available, otherwise use mvn
17+
if command -v mvnd &> /dev/null; then
18+
MVN_CMD="mvnd"
19+
else
20+
MVN_CMD="mvn"
21+
fi
22+
23+
timeout 120 $MVN_CMD test "$@" 2>&1 | awk '
24+
BEGIN {
25+
scanning_started = 0
26+
compilation_section = 0
27+
test_section = 0
28+
}
29+
30+
# Skip all WARNING lines before project scanning starts
31+
/INFO.*Scanning for projects/ {
32+
scanning_started = 1
33+
print
34+
next
35+
}
36+
37+
# Before scanning starts, skip WARNING lines
38+
!scanning_started && /^WARNING:/ { next }
39+
40+
# Show compilation errors
41+
/COMPILATION ERROR/ { compilation_section = 1 }
42+
/BUILD FAILURE/ && compilation_section { compilation_section = 0 }
43+
44+
# Show test section
45+
/INFO.*T E S T S/ {
46+
test_section = 1
47+
print "-------------------------------------------------------"
48+
print " T E S T S"
49+
print "-------------------------------------------------------"
50+
next
51+
}
52+
53+
# In compilation error section, show everything
54+
compilation_section { print }
55+
56+
# In test section, show everything - let user control logging with -D arguments
57+
test_section {
58+
print
59+
}
60+
61+
# Before test section starts, show important lines only
62+
!test_section && scanning_started {
63+
if (/INFO.*Scanning|INFO.*Building|INFO.*resources|INFO.*compiler|INFO.*surefire|ERROR|FAILURE/) {
64+
print
65+
}
66+
# Show compilation warnings/errors
67+
if (/WARNING.*COMPILATION|ERROR.*/) {
68+
print
69+
}
70+
}
71+
'

0 commit comments

Comments
 (0)