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
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@
class CodegenSpecConformanceTest extends CodegenTestBase {

static Stream<Arguments> cases() throws IOException {
final var raw = CodegenSpecConformanceTest.class.getClassLoader()
.getResourceAsStream("jtd-spec-validation.json");
assert raw != null : "jtd-spec-validation.json not found on classpath";
final var jsonText = new String(raw.readAllBytes(), StandardCharsets.UTF_8);
final var root = Json.parse(jsonText);
assert root instanceof JsonObject : "expected top-level object";
final var obj = (JsonObject) root;
// Extract test suite from ZIP (same data as IT tests, avoids committing large JSON)
try (final var raw = JtdTestDataExtractor.getValidationTestDataStream()) {
final var jsonText = new String(raw.readAllBytes(), StandardCharsets.UTF_8);
final var root = Json.parse(jsonText);
assert root instanceof JsonObject : "expected top-level object";
final var obj = (JsonObject) root;

return obj.members().entrySet().stream()
.map(entry -> Arguments.of(
entry.getKey(),
entry.getValue()));
return obj.members().entrySet().stream()
.map(entry -> Arguments.of(
entry.getKey(),
entry.getValue()));
}
}

@ParameterizedTest(name = "{0}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package json.java21.jtd.codegen;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/// Shared utility for extracting the JTD test suite from the embedded ZIP file.
/// Used by both unit tests and integration tests to avoid committing large JSON files.
final class JtdTestDataExtractor {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is significant code duplication. This class is nearly identical to json-java21-jtd/src/test/java/json/java21/jtd/JtdTestDataExtractor.java. Duplicating utility code across modules makes maintenance harder.

Consider creating a shared test utility module or using Maven's test-jar feature to share this code from one module to the other. This would ensure that any future changes to the extraction logic only need to be made in one place.

This would also solve the problem of the fragile relative path used to locate the ZIP file (line 19), as the test resource could be loaded from the classpath via getResourceAsStream.


private static final Logger LOG = Logger.getLogger("json.java21.jtd.codegen");
// Reference the ZIP file from the sibling json-java21-jtd module
private static final Path ZIP_FILE = Paths.get("../json-java21-jtd/src/test/resources/jtd-test-suite.zip");
private static final Path TARGET_DIR = Paths.get("target/test-data");
Comment on lines +18 to +20

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid hard dependency on sibling module test data

The codegen test suite now hard-codes the ZIP path to ../json-java21-jtd/src/test/resources/jtd-test-suite.zip. If json-java21-jtd-codegen is built or tested in isolation (for example, from a source release or checkout that does not include the sibling module), this will throw JTD test suite ZIP not found and the conformance tests will fail immediately. Previously the module had its own jtd-spec-validation.json, so this is a regression in test portability. Consider keeping the ZIP in this module’s test resources or loading it from the classpath to keep tests self-contained.

Useful? React with 👍 / 👎.

private static final Path VALIDATION_FILE = TARGET_DIR.resolve("json-typedef-spec-2025-09-27/tests/validation.json");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The path to validation.json includes a hardcoded version string (json-typedef-spec-2025-09-27). This is brittle and will break if the test suite is updated to a new version. The extraction logic should dynamically locate the validation.json file within the extracted contents instead of relying on a hardcoded path. For example, you could scan the extracted directory for tests/validation.json after extraction.


private JtdTestDataExtractor() {
// Utility class
}

/// Ensures the test suite is extracted and returns the path to validation.json.
/// Extraction happens at most once per build (target/ is cleaned between builds).
static synchronized Path ensureValidationTestData() throws IOException {
if (Files.exists(VALIDATION_FILE)) {
LOG.fine(() -> "JTD test suite already extracted at: " + VALIDATION_FILE);
return VALIDATION_FILE;
}

if (!Files.exists(ZIP_FILE)) {
throw new RuntimeException("JTD test suite ZIP not found: " + ZIP_FILE.toAbsolutePath());
}

LOG.info(() -> "Extracting JTD test suite from: " + ZIP_FILE);
Files.createDirectories(TARGET_DIR);

try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(ZIP_FILE))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (!entry.isDirectory() && entry.getName().startsWith("json-typedef-spec-")) {
Path outputPath = TARGET_DIR.resolve(entry.getName());
Files.createDirectories(outputPath.getParent());
Files.copy(zis, outputPath, StandardCopyOption.REPLACE_EXISTING);
}
zis.closeEntry();
}
}

if (!Files.exists(VALIDATION_FILE)) {
throw new RuntimeException("Extraction completed but validation.json not found: " + VALIDATION_FILE);
}

LOG.info(() -> "JTD test suite extracted successfully");
return VALIDATION_FILE;
}

/// Returns an InputStream for the validation test data, extracting if necessary.
/// Suitable for use with classpath-style resource loading patterns.
static InputStream getValidationTestDataStream() throws IOException {
Path dataFile = ensureValidationTestData();
return Files.newInputStream(dataFile);
}
}
Loading
Loading