S19: consume versioned engineering resources and move landscape documentation
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s

This commit is contained in:
2026-11-08 15:23:10 +01:00
parent bd898e92d2
commit c6a495a93c
100 changed files with 1869 additions and 4274 deletions

View File

@@ -0,0 +1,372 @@
import static org.junit.jupiter.api.Assertions.*;
import java.nio.file.*;
import java.util.*;
import net.sourceforge.pmd.*;
import net.sourceforge.pmd.lang.*;
import net.sourceforge.pmd.lang.document.FileId;
import net.sourceforge.pmd.lang.java.ast.*;
import net.sourceforge.pmd.lang.rule.RuleSet;
import org.junit.jupiter.api.*;
class StandardsTest {
private List<String> analyze(String text) throws Exception {
Standards.root = Path.of("").toAbsolutePath();
Standards.module = "backend";
Standards.ownedTypes.clear();
Standards.findings.clear();
Standards.units.clear();
Standards.types.clear();
Standards.codeLines.clear();
final var config = new PMDConfiguration();
config.setThreads(1);
config.prependAuxClasspath(
Path.of(System.getProperty("java.home"), "lib/jrt-fs.jar").toString());
config.prependAuxClasspath(
System.getProperty("surefire.test.class.path", System.getProperty("java.class.path")));
config.setIgnoreIncrementalAnalysis(true);
config.setDefaultLanguageVersion(
LanguageRegistry.PMD.getLanguageById("java").getVersion("25"));
try (var analysis = PmdAnalysis.create(config)) {
analysis.addRuleSet(RuleSet.forSingleRule(new Standards.Measurements()));
analysis.files().addSourceFile(FileId.fromPath(Standards.root.resolve("Fixture.java")), text);
var report = analysis.performAnalysisAndCollectReport();
assertTrue(
report.getProcessingErrors().isEmpty(),
report.getProcessingErrors().toString());
}
return List.copyOf(Standards.findings);
}
private boolean contains(List<String> findings, String prefix, String metric) {
return findings.stream().anyMatch(s -> s.startsWith(prefix) && s.endsWith(metric));
}
@Test
void cyclomaticAndCognitiveBoundaries() throws Exception {
var at = analyze("class Fixture { public void run(final boolean b) { " + "if (b) {}".repeat(9) + "} }");
assertTrue(contains(at, "REVIEW", "cyclomatic=10.0"));
var over = analyze("class Fixture { public void run(final boolean b) { " + "if (b) {}".repeat(10) + "} }");
assertTrue(contains(over, "BLOCK", "cyclomatic=11.0"));
assertTrue(contains(
analyze("class Fixture { public void run(final boolean b) {" + "if (b) {}".repeat(15) + "} }"),
"REVIEW",
"cognitive=15.0"));
assertTrue(contains(
analyze("class Fixture { public void run(final boolean b) {" + "if (b) {}".repeat(16) + "} }"),
"BLOCK",
"cognitive=16.0"));
}
@Test
void methodAndConstructorParameterBoundariesAndImplicitRecords() throws Exception {
assertTrue(contains(
analyze("class Fixture { public void run(final int a, final int b, final int c, final int d,"
+ " final int e) {} }"),
"REVIEW",
"parameters=5.0"));
assertTrue(contains(
analyze("class Fixture { public void run(final int a, final int b, final int c, final int d,"
+ " final int e, final int f) {} }"),
"BLOCK",
"parameters=6.0"));
var implicit = analyze("record Fixture(int a, int b, int c, int d, int e, int f, int g, int h) {}");
assertFalse(implicit.stream().anyMatch(s -> s.contains("parameters=")));
var compact = analyze(
"record Fixture(int a, int b, int c, int d, int e, int f, int g, int h) { public Fixture" + " {} }");
assertTrue(contains(compact, "BLOCK", "parameters=8.0"));
}
@Test
void physicalLinesExcludeCommentsAndCountBraces() throws Exception {
var findings = analyze("class Fixture {\n"
+ "public void run() {\n"
+ "// comment\n"
+ "/* multi\n"
+ " comment */\n\n"
+ "System.out.println(1); // code\n"
+ "}\n"
+ "}");
assertTrue(contains(findings, "METRIC", "executableLines=3.0"));
assertTrue(contains(findings, "METRIC", "classLines=5.0"));
assertTrue(contains(
analyze("class Fixture {\npublic void run() {\n" + "System.out.println(1);\n".repeat(48) + "}\n}"),
"REVIEW",
"executableLines=50.0"));
assertTrue(contains(
analyze("class Fixture {\npublic void run() {\n" + "System.out.println(1);\n".repeat(49) + "}\n}"),
"BLOCK",
"executableLines=51.0"));
}
@Test
void nestingElseIfCatchSwitchLambdaAndNestedMethods() throws Exception {
var chain = analyze(
"class Fixture { public void run(final boolean b) { if (b) {} else if (b) {} else if (b)" + " {} } }");
assertTrue(contains(chain, "METRIC", "nesting=1.0"));
var nested = analyze("class Fixture { public void run(final boolean b) { if (b) { while (b) { switch (1) {"
+ " default -> { try {} catch (Exception e) { Runnable r = () -> { if (b) {} }; } } }"
+ " } } } }");
assertTrue(contains(nested, "BLOCK", "nesting=5.0"));
var separate = analyze("class Fixture { public void run(final boolean b) { if (b) { class Inner { public void"
+ " go() { if (b) {} } } } } }");
assertFalse(separate.stream().anyMatch(s -> s.endsWith("nesting=2.0")));
}
@Test
void lambdaComplexityContributesAndNestedClassDoesNot() throws Exception {
var findings = analyze("class Fixture { public void run(final boolean b) { Runnable r = () -> { if (b) {} };"
+ " class Inner { public void nested() { if (b) {} } } } }");
assertEquals(
2, findings.stream().filter(s -> s.endsWith("cyclomatic=2.0")).count(), findings.toString());
}
@Test
void varAndFinalRules() throws Exception {
var findings =
analyze("class Fixture { public void run(int p) { var a = new Object(); var b = (Object) a; var c"
+ " = name(); int count = 0; count++; } private String name() { return \"x\"; } }");
assertEquals(
1, findings.stream().filter(s -> s.contains("var requires")).count());
assertTrue(findings.stream().anyMatch(s -> s.contains("requires final: p")));
assertFalse(findings.stream().anyMatch(s -> s.contains("requires final: count")));
}
@Test
void patternBindingsRequireFinalOnlyWhenAssignedOnce() throws Exception {
var findings = analyze("""
record Pair(Object key, Object value) {}
class Fixture {
public void run(final Object input) {
if (input instanceof String unchanged) { System.out.println(unchanged); }
if (input instanceof final String protectedValue) { System.out.println(protectedValue); }
if (input instanceof String reassigned) { reassigned = reassigned.trim(); System.out.println(reassigned); }
switch (input) {
case String switched -> System.out.println(switched);
default -> {}
}
if (input instanceof Pair(var key, var value)) {
System.out.println(key);
System.out.println(value);
}
}
}
""");
for (String binding : List.of("unchanged", "switched", "key", "value"))
assertTrue(findings.stream().anyMatch(s -> s.contains("requires final: " + binding)), findings.toString());
for (String binding : List.of("protectedValue", "reassigned"))
assertFalse(findings.stream().anyMatch(s -> s.contains("requires final: " + binding)), findings.toString());
assertFalse(findings.stream().anyMatch(s -> s.contains("var requires")), findings.toString());
}
@Test
void inheritanceCountsOnlyProjectSuperclasses() throws Exception {
var findings = analyze("class A {} class B extends A {} class C extends B {} class D extends C {} class Fixture"
+ " extends D {} class External extends java.util.ArrayList<String> {}");
assertTrue(contains(findings, "REVIEW", "ownSuperclassDepth=3.0"));
assertTrue(contains(findings, "BLOCK", "ownSuperclassDepth=4.0"));
assertTrue(contains(findings, "METRIC", "ownSuperclassDepth=0.0"));
}
@Test
void injectionUsesResolvedTypesQualifiersInheritedMembersAndImplicitConstructors() throws Exception {
var findings = analyze("""
class Parent {
@jakarta.inject.Inject private String inherited;
@jakarta.inject.Inject public void setValue(final Integer value) {}
}
@jakarta.inject.Singleton class Fixture extends Parent {
private final String value;
public Fixture(@jakarta.inject.Named("a") final String first,
@jakarta.inject.Named("a") final String repeated,
@jakarta.inject.Named("b") final String second) { value = first; }
@jakarta.inject.Inject private String repeatedInherited;
}
""");
assertTrue(contains(findings, "METRIC", "injectedDependencies=4.0"), findings.toString());
String fields = "";
for (int i = 0; i < 7; i++)
fields += "@jakarta.inject.Inject @jakarta.inject.Named(\"" + i + "\") private String d" + i + ";";
assertTrue(contains(analyze("class Fixture {" + fields + "}"), "REVIEW", "injectedDependencies=7.0"));
assertTrue(contains(
analyze("class Fixture {" + fields + "@jakarta.inject.Inject private Integer eighth;}"),
"BLOCK",
"injectedDependencies=8.0"));
}
@Test
void fanoutCountsDistinctJdkTypesAndPublicMethodsExcludeOnlyTrueAccessors() throws Exception {
var findings = analyze("""
class Fixture {
private String name;
private java.util.List<String> values;
private java.util.List<String> repeated;
public String getName() { return name; }
public void setName(final String value) { this.name = value; }
public String getOther() { return name; }
public String getValidatedName() { if (name == null) { throw new IllegalStateException(); } return name; }
public static int calculate() { return 1; }
}
""");
assertTrue(contains(findings, "METRIC", "fanOut=3.0"), findings.toString());
assertTrue(contains(findings, "METRIC", "publicMethods=3.0"), findings.toString());
}
@Test
void commentedAccessorsRemainTrivialWhileAdditionalWorkStillCounts() throws Exception {
var findings = analyze("""
class Fixture {
private String name;
private String trimmed;
private String logged;
private String calculated;
private String appended;
public String getName() { /* Intent comment. */ return name; }
public void setName(final String value) { this./* Field comment. */name = value; }
public String name() { // Read the stored value.
return this.name;
}
public void setName(final String value, final boolean validate) { this.name = value; }
public void setTrimmed(final String value) { this.trimmed = value.trim(); }
public String getLogged() { System.out.println(logged); return logged; }
public String getCalculated() { return calculated.trim(); }
public void setAppended(final String value) { this.appended += value; }
}
""");
assertTrue(contains(findings, "METRIC", "publicMethods=5.0"), findings.toString());
}
@Test
void classLengthBoundaryAndNestedTypeLines() throws Exception {
assertTrue(contains(
analyze("class Fixture {\n" + "private int field;\n".repeat(498) + "}"), "REVIEW", "classLines=500.0"));
assertTrue(contains(
analyze("class Fixture {\n" + "private int field;\n".repeat(499) + "}"), "BLOCK", "classLines=501.0"));
var separate = analyze("class Fixture {\nprivate class Inner {\nprivate int value;\n}\nprivate int other;\n}");
assertEquals(
2, separate.stream().filter(s -> s.endsWith("classLines=3.0")).count());
assertTrue(contains(analyze("class Fixture { private class Inner {} }"), "METRIC", "classLines=1.0"));
}
@Test
void switchBooleanAndThrowTreatmentIsPinned() throws Exception {
var findings = analyze("class Fixture { public int run(final boolean a, final boolean b) { if (a && b) { throw"
+ " new IllegalStateException(); } return switch (1) { case 0, 1 -> 1; default -> 2;"
+ " }; } }");
assertTrue(contains(findings, "METRIC", "cyclomatic=6.0"), findings.toString());
}
private Path project(String production, String tests) throws Exception {
Path directory = Files.createTempDirectory("s7-fixture-");
Files.writeString(directory.resolve("engineering.properties"), "BACKEND_MODULE=backend\n");
Path prod = directory.resolve("backend/src/main/java");
Path test = directory.resolve("backend/src/test/java");
Files.createDirectories(prod);
Files.createDirectories(test);
Path config = directory.resolve("generated/tooling/standards/checkstyle.xml");
Files.createDirectories(config.getParent());
Files.copy(Path.of(System.getProperty("basedir"), "checkstyle.xml"), config);
if (production != null) Files.writeString(prod.resolve("Fixture.java"), production);
if (tests != null) Files.writeString(test.resolve("ExampleTest.java"), tests);
return directory;
}
@Test
void checksFailWithoutRewritingSourcesAndExposeReviewSignals() throws Exception {
String source = "package example;\n"
+ "import java.util.*;\n"
+ "class Fixture { public void run(int x) { if (x == 0) System.out.println(x); } }";
Path directory = project(source, null);
assertThrows(IllegalStateException.class, () -> Standards.main(new String[] {directory.toString()}));
assertEquals(source, Files.readString(directory.resolve("backend/src/main/java/Fixture.java")));
String report = Files.readString(directory.resolve("backend/target/standards/report.txt"));
assertTrue(report.contains("form of import"), report);
assertTrue(report.contains("must use '{}'s"), report);
assertTrue(report.contains("requires final: x"), report);
}
@Test
void productionCpdCountsEveryOccurrenceAndTestClonesDoNotGate() throws Exception {
String method = "public void first() {\n" + "System.out.println(123);\n".repeat(30) + "}\n";
String source = "package example;\nclass Fixture {\n" + method + method.replace("first", "second") + "}";
Path directory = project(source, null);
assertThrows(IllegalStateException.class, () -> Standards.main(new String[] {directory.toString()}));
String report = Files.readString(directory.resolve("backend/target/standards/report.txt"));
assertTrue(report.contains("BLOCK productionDuplication=") && report.contains("(64/67)"), report);
assertTrue(report.lines().filter(l -> l.startsWith("CLONE")).count() >= 2, report);
Path testProject =
project("package example; class Fixture {}", source.replace("class Fixture", "class ExampleTest"));
Standards.main(new String[] {testProject.toString()});
String testReport = Files.readString(testProject.resolve("backend/target/standards/report.txt"));
assertTrue(testReport.contains("productionDuplication=0.0%"), testReport);
}
@Test
void parserFailureNamesTheAffectedFileAndFails() throws Exception {
Path directory = project("package example; class Fixture { public void broken( }", null);
Exception failure = assertThrows(Exception.class, () -> Standards.main(new String[] {directory.toString()}));
assertTrue(
failure.toString().contains("Fixture.java")
|| Standards.findings.stream().anyMatch(f -> f.contains("Fixture.java")),
failure.toString());
}
@Test
void exactCoverageGateAcceptsEightyPercentAndRejectsRoundedNearMiss() throws Exception {
Path directory = Files.createTempDirectory("s7-coverage-");
Path xml = directory.resolve("report.xml");
Path helper = Path.of(System.getProperty("basedir"), "../coverage/Coverage.java")
.normalize();
for (long[] counts : List.of(new long[] {4, 1, 0}, new long[] {799999, 200001, 1}, new long[] {0, 0, 1})) {
Files.writeString(
xml,
"<report><counter type=\"LINE\" covered=\"" + counts[0] + "\" missed=\"" + counts[1]
+ "\"/></report>");
Process process = new ProcessBuilder(
Path.of(System.getProperty("java.home"), "bin/java").toString(),
helper.toString(),
xml.toString())
.redirectErrorStream(true)
.redirectOutput(directory.resolve("output.log").toFile())
.start();
assertEquals(counts[2], process.waitFor(), Files.readString(directory.resolve("output.log")));
}
}
@Test
void overridesAndImplicitRecordInjectionAreMeasured() throws Exception {
var override = analyze("class Fixture extends java.util.ArrayList<String> { public void clear() {} }");
assertTrue(override.stream().anyMatch(f -> f.contains("require @Override")), override.toString());
var record = analyze("@jakarta.inject.Singleton record Fixture(String one, String repeated, Integer two) {}");
assertTrue(contains(record, "METRIC", "injectedDependencies=2.0"), record.toString());
var inherited = analyze("class Parent<T> { @jakarta.inject.Inject private T dependency; } class Fixture extends"
+ " Parent<String> { @jakarta.inject.Inject private String repeated; }");
assertEquals(
2,
inherited.stream()
.filter(f -> f.endsWith("injectedDependencies=1.0"))
.count(),
inherited.toString());
}
@Test
void waiverMatchesOnlyTheExactMetricSignatureAndRetainedValue() throws Exception {
Standards.waivers.add(new Standards.Waiver(
"parameters",
"Fixture#run(int,int,int,int,int,int)",
6,
"Test fixture agreement: preserve an example signature"));
try {
var waived = analyze("class Fixture { public void run(final int a, final int b, final int c, final int d,"
+ " final int e, final int f) {} }");
assertTrue(
waived.stream().anyMatch(f -> f.startsWith("WAIVER") && f.contains("parameters=6.0")),
waived.toString());
var changed = analyze("class Fixture { public void run(final int a, final int b, final int c, final int d,"
+ " final int e, final int f, final int g) {} }");
assertTrue(contains(changed, "BLOCK", "parameters=7.0"));
} finally {
Standards.waivers.clear();
}
}
}