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
2 changes: 1 addition & 1 deletion gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ repositories {
}

jacoco {
toolVersion = "0.8.13"
toolVersion = "0.8.14"
}

spotbugs {
Expand Down
2 changes: 1 addition & 1 deletion gradle-plugin/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
Comment thread
fabian-barney marked this conversation as resolved.
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.TaskAction;
import org.gradle.work.DisableCachingByDefault;

import java.io.File;
import java.io.IOException;
Expand All @@ -47,6 +48,7 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

@DisableCachingByDefault(because = "Runs analysis with local state and generated reports outside Gradle's cache model.")
public abstract class CrapJavaCheckTask extends DefaultTask {

private static final String LINK_OWNERSHIP = "link";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -447,7 +448,7 @@ void disabledJunitReportPathChangeInvalidatesTaskWithoutDeletingUnownedFile() th
""");
BuildResult firstResult = runBuild("crap-java-check");
assertEquals(TaskOutcome.SUCCESS, firstResult.task(":crap-java-check").getOutcome());
Files.createDirectories(newJunit.getParent());
Files.createDirectories(parentOf(newJunit));
Files.writeString(newJunit, "<testsuites tests=\"99\"/>");
writeSingleModuleProject("""

Expand Down Expand Up @@ -682,17 +683,25 @@ void alphaReturnsOneForTrue() {

private void writeFile(String relativePath, String content) throws IOException {
Path file = tempDir.resolve(relativePath);
Files.createDirectories(file.getParent());
Files.createDirectories(parentOf(file));
Files.writeString(file, content);
}

private List<String> reportFileNames(String relativePath) throws IOException {
try (var files = Files.list(tempDir.resolve(relativePath))) {
return files
.map(path -> path.getFileName().toString())
.map(path -> fileNameOf(path).toString())
.sorted(Comparator.naturalOrder())
.toList();
}
}

private Path parentOf(Path path) {
return Objects.requireNonNull(path.getParent(), () -> "Expected parent path for " + path);
}

private Path fileNameOf(Path path) {
return Objects.requireNonNull(path.getFileName(), () -> "Expected file name for " + path);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -236,7 +237,7 @@ void runCheckAnalyzesConfiguredSourcesWithExistingCoverage() throws Exception {
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Files.writeString(projectRoot.resolve("build.gradle"), "plugins { id 'java' }");
Path source = projectRoot.resolve("src/main/java/demo/Sample.java");
Files.createDirectories(source.getParent());
Files.createDirectories(parentOf(source));
Files.writeString(source, """
package demo;

Expand All @@ -247,7 +248,7 @@ int alpha() {
}
""");
Path jacocoXml = projectRoot.resolve("build/reports/jacoco/test/jacocoTestReport.xml");
Files.createDirectories(jacocoXml.getParent());
Files.createDirectories(parentOf(jacocoXml));
Files.writeString(jacocoXml, """
<report name="demo">
<package name="demo">
Expand Down Expand Up @@ -286,7 +287,7 @@ void runCheckAppliesConfiguredSourceExclusions() throws Exception {
Path projectRoot = tempDir.toRealPath();
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Path source = projectRoot.resolve("src/main/java/demo/Sample.java");
Files.createDirectories(source.getParent());
Files.createDirectories(parentOf(source));
Files.writeString(source, """
package demo;

Expand All @@ -300,7 +301,7 @@ int alpha(boolean a) {
}
""");
Path jacocoXml = projectRoot.resolve("build/reports/jacoco/test/jacocoTestReport.xml");
Files.createDirectories(jacocoXml.getParent());
Files.createDirectories(parentOf(jacocoXml));
Files.writeString(jacocoXml, """
<report name="demo">
<package name="demo">
Expand Down Expand Up @@ -340,7 +341,7 @@ void movedJunitReportDoesNotDeleteUnownedDefaultSidecar() throws Exception {
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Path defaultJunitReport = projectRoot.resolve("build/reports/crap-java/TEST-crap-java.xml");
Path customJunitReport = projectRoot.resolve("custom-junit.xml");
Files.createDirectories(defaultJunitReport.getParent());
Files.createDirectories(parentOf(defaultJunitReport));
Files.writeString(defaultJunitReport, "user-managed");
CrapJavaCheckTask task = project.getTasks().register("crap-java-check", CrapJavaCheckTask.class).get();
task.getAnalysisRoot().fileValue(projectRoot.toFile());
Expand All @@ -358,7 +359,7 @@ void disabledJunitDoesNotDeleteUnownedDefaultSidecar() throws Exception {
Path projectRoot = tempDir.toRealPath();
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Path defaultJunitReport = projectRoot.resolve("build/reports/crap-java/TEST-crap-java.xml");
Files.createDirectories(defaultJunitReport.getParent());
Files.createDirectories(parentOf(defaultJunitReport));
Files.writeString(defaultJunitReport, "user-managed");
CrapJavaCheckTask task = project.getTasks().register("crap-java-check", CrapJavaCheckTask.class).get();
task.getAnalysisRoot().fileValue(projectRoot.toFile());
Expand Down Expand Up @@ -672,7 +673,7 @@ void aliasedFutureReportPathCollisionDoesNotDeleteRememberedOutput() throws Exce
void runCheckRejectsDanglingSymlinkedPrimaryAndJunitReportPath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path report = projectRoot.resolve("reports/collision.xml");
Files.createDirectories(report.getParent());
Files.createDirectories(parentOf(report));
Path outputLink = createFileSymlinkOrSkip(projectRoot.resolve("output-report.xml"), report);
Path junitLink = createFileSymlinkOrSkip(projectRoot.resolve("junit-report.xml"), report);
CrapJavaCheckTask task = newCheckTask(projectRoot);
Expand Down Expand Up @@ -744,8 +745,7 @@ void runCheckRejectsOtherTaskInternalLockPath() throws Exception {
void runCheckRejectsRootReportPath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Path root = projectRoot.getRoot();
assumeTrue(root != null, "Filesystem root is unavailable");
Path root = rootOf(projectRoot);
CrapJavaCheckTask task = project.getTasks().register("crap-java-check", CrapJavaCheckTask.class).get();
task.getAnalysisRoot().fileValue(projectRoot.toFile());
task.getModuleCoverageReports().set(Map.of());
Expand Down Expand Up @@ -850,7 +850,7 @@ void runCheckRejectsSymlinkedInternalExecutionMarkerPath() throws Exception {
void runCheckRejectsFileSymlinkAliasToInternalStatePath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path statePath = projectRoot.resolve(".gradle/crap-java/root/other-task/primary-output.path");
Files.createDirectories(statePath.getParent());
Files.createDirectories(parentOf(statePath));
Files.writeString(statePath, "state");
Path stateAlias = createFileSymlinkOrSkip(projectRoot.resolve("state-report.xml"), statePath);
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Expand All @@ -868,7 +868,7 @@ void runCheckRejectsFileSymlinkAliasToInternalStatePath() throws Exception {
void runCheckRejectsDanglingFileSymlinkAliasToInternalStatePath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path statePath = projectRoot.resolve(".gradle/crap-java/root/other-task/primary-output.path");
Files.createDirectories(statePath.getParent());
Files.createDirectories(parentOf(statePath));
Path stateAlias = createFileSymlinkOrSkip(projectRoot.resolve("state-report.xml"), statePath);
CrapJavaCheckTask task = newCheckTask(projectRoot);
task.getOutput().fileValue(stateAlias.toFile());
Expand All @@ -882,7 +882,7 @@ void runCheckRejectsDanglingFileSymlinkAliasToInternalStatePath() throws Excepti
void runCheckRejectsFileSymlinkAliasToInternalExecutionMarkerPath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path markerPath = projectRoot.resolve("build/tmp/crap-java/crap-java-check/execution.marker");
Files.createDirectories(markerPath.getParent());
Files.createDirectories(parentOf(markerPath));
Files.writeString(markerPath, "ok");
Path markerAlias = createFileSymlinkOrSkip(projectRoot.resolve("marker-report.xml"), markerPath);
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Expand All @@ -900,7 +900,7 @@ void runCheckRejectsFileSymlinkAliasToInternalExecutionMarkerPath() throws Excep
void runCheckRejectsDanglingFileSymlinkAliasToInternalExecutionMarkerPath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path markerPath = projectRoot.resolve("build/tmp/crap-java/crap-java-check/execution.marker");
Files.createDirectories(markerPath.getParent());
Files.createDirectories(parentOf(markerPath));
Path markerAlias = createFileSymlinkOrSkip(projectRoot.resolve("marker-report.xml"), markerPath);
CrapJavaCheckTask task = newCheckTask(projectRoot);
task.getOutput().fileValue(markerAlias.toFile());
Expand All @@ -914,7 +914,7 @@ void runCheckRejectsDanglingFileSymlinkAliasToInternalExecutionMarkerPath() thro
void runCheckRejectsHardLinkAliasToInternalStatePath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path statePath = projectRoot.resolve(".gradle/crap-java/root/other-task/primary-output.path");
Files.createDirectories(statePath.getParent());
Files.createDirectories(parentOf(statePath));
Files.writeString(statePath, "state");
Path stateAlias = createHardLinkOrSkip(projectRoot.resolve("state-report.xml"), statePath);
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Expand Down Expand Up @@ -1002,7 +1002,7 @@ void rememberedStateUsesGradleProjectCacheDir() throws Exception {
Path statePath = junitReportStatePath(task);
assertTrue(Files.exists(statePath));
assertTrue(statePath.startsWith(projectCacheDir.resolve("crap-java")));
assertTrue(statePath.getParent().getParent().getParent().getFileName().toString().startsWith("workspace-"));
assertTrue(fileNameOf(parentOf(parentOf(parentOf(statePath)))).toString().startsWith("workspace-"));
assertFalse(Files.exists(projectRoot.resolve(".gradle/crap-java/root/crap-java-check/junit-report.path")));
}

Expand All @@ -1026,8 +1026,8 @@ void rememberedStateNamespacesSharedCustomProjectCacheByRootProject() throws Exc
assertTrue(Files.exists(firstStatePath));
assertTrue(Files.exists(secondStatePath));
assertFalse(firstStatePath.equals(secondStatePath));
assertFalse(firstStatePath.getParent().getParent().getParent()
.equals(secondStatePath.getParent().getParent().getParent()));
assertFalse(parentOf(parentOf(parentOf(firstStatePath)))
.equals(parentOf(parentOf(parentOf(secondStatePath)))));
}

@Test
Expand Down Expand Up @@ -1109,9 +1109,9 @@ void rememberedStateEscapesProjectPathSeparators() throws Exception {
nestedTask.runCheck();
rootNamedTask.runCheck();

Path stateNamespace = junitReportStatePath(dashTask).getParent().getParent().getParent();
Path stateNamespace = parentOf(parentOf(parentOf(junitReportStatePath(dashTask))));
assertTrue(stateNamespace.startsWith(projectCacheDir.resolve("crap-java")));
assertTrue(stateNamespace.getFileName().toString().startsWith("workspace-"));
assertTrue(fileNameOf(stateNamespace).toString().startsWith("workspace-"));
assertTrue(Files.exists(stateNamespace.resolve("%3Aa-b/crap-java-check/junit-report.path")));
assertTrue(Files.exists(stateNamespace.resolve("%3Aa%3Ab/crap-java-check/junit-report.path")));
assertTrue(Files.exists(stateNamespace.resolve("%3Aroot/crap-java-check/junit-report.path")));
Expand All @@ -1124,7 +1124,7 @@ void rememberedStatePreservesTrailingSpacesInStoredPath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path statePath = projectRoot.resolve(".gradle/crap-java/root/crap-java-check/primary-output.path");
Path storedPath = projectRoot.resolve("report.json ");
Files.createDirectories(statePath.getParent());
Files.createDirectories(parentOf(statePath));
Files.writeString(statePath, storedPath + "\nlink\t1\t2\n");
CrapJavaCheckTask task = newCheckTask(projectRoot);

Expand Down Expand Up @@ -1155,7 +1155,7 @@ void rememberedStatePreservesNewlinesInStoredPath() throws Exception {
void rememberedStateIgnoresMalformedStoredPath() throws Exception {
Path projectRoot = tempDir.toRealPath();
Path statePath = projectRoot.resolve(".gradle/crap-java/root/crap-java-check/primary-output.path");
Files.createDirectories(statePath.getParent());
Files.createDirectories(parentOf(statePath));
Files.writeString(statePath, "\u0000\nlink\t1\t2\n");
CrapJavaCheckTask task = newCheckTask(projectRoot);

Expand All @@ -1168,8 +1168,8 @@ void disabledCustomTaskDoesNotDeleteUnownedDefaultSidecars() throws Exception {
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Path builtInJunit = projectRoot.resolve("build/reports/crap-java/TEST-crap-java.xml");
Path customJunit = projectRoot.resolve("build/reports/crap-java/custom-crap-java-check/TEST-crap-java.xml");
Files.createDirectories(builtInJunit.getParent());
Files.createDirectories(customJunit.getParent());
Files.createDirectories(parentOf(builtInJunit));
Files.createDirectories(parentOf(customJunit));
Files.writeString(builtInJunit, "<testsuites tests=\"1\"/>");
Files.writeString(customJunit, "<testsuites tests=\"2\"/>");

Expand All @@ -1191,7 +1191,7 @@ void disabledCustomTaskOnlyDeletesOwnedDefaultSidecar() throws Exception {
Project project = ProjectBuilder.builder().withProjectDir(projectRoot.toFile()).build();
Path builtInJunit = projectRoot.resolve("build/reports/crap-java/TEST-crap-java.xml");
Path customJunit = projectRoot.resolve("build/reports/crap-java/custom-crap-java-check/TEST-crap-java.xml");
Files.createDirectories(builtInJunit.getParent());
Files.createDirectories(parentOf(builtInJunit));
Files.writeString(builtInJunit, "<testsuites tests=\"1\"/>");
CrapJavaCheckTask firstTask = project.getTasks().register("custom-crap-java-check", CrapJavaCheckTask.class).get();
firstTask.getAnalysisRoot().fileValue(projectRoot.toFile());
Expand Down Expand Up @@ -1274,15 +1274,15 @@ private CrapJavaCheckTask newCheckTask(Project project, Path projectRoot, String
}

private void rememberOwnedReport(Path statePath, Path reportPath) throws Exception {
Files.createDirectories(statePath.getParent());
Files.createDirectories(parentOf(statePath));
Path ownerPath = statePath.resolveSibling("primary-output.owner");
createHardLinkOrSkip(ownerPath, reportPath);
Files.writeString(statePath, reportPath + "\n" + ownership(reportPath) + "\n");
}

private void assumeHardLinksAvailable(Path directory) throws Exception {
Path target = Files.createTempFile(directory, ".crap-java-hard-link-target-", ".tmp");
Path link = target.resolveSibling(target.getFileName() + ".link");
Path link = target.resolveSibling(fileNameOf(target) + ".link");
try {
createHardLinkOrSkip(link, target);
} finally {
Expand Down Expand Up @@ -1350,5 +1350,17 @@ private Object rememberedReport(CrapJavaCheckTask task, Path statePath) throws E
private boolean isWindows() {
return System.getProperty("os.name", "").toLowerCase(Locale.ROOT).contains("win");
}

private Path parentOf(Path path) {
return Objects.requireNonNull(path.getParent(), () -> "Expected parent path for " + path);
}

private Path fileNameOf(Path path) {
return Objects.requireNonNull(path.getFileName(), () -> "Expected file name for " + path);
}

private Path rootOf(Path path) {
return Objects.requireNonNull(path.getRoot(), () -> "Expected filesystem root for " + path);
}
}

24 changes: 21 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cognitive-java.version>0.5.1</cognitive-java.version>
<cognitive-java.version>0.6.0</cognitive-java.version>
<jacoco.version>0.8.14</jacoco.version>
<junit.version>6.0.3</junit.version>
<junit.version>6.1.0</junit.version>
<maven.surefire.plugin.version>3.5.6</maven.surefire.plugin.version>
<jspecify.version>1.0.0</jspecify.version>
<jtoon.version>1.0.9</jtoon.version>
<jackson.version>2.21.3</jackson.version>
Expand Down Expand Up @@ -131,7 +132,24 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.5</version>
<version>${maven.surefire.plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit-platform</artifactId>
<version>${maven.surefire.plugin.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down