diff --git a/platforms/jvm/testing-jvm/src/integTest/groovy/org/gradle/testing/AbstractTestTaskIntegrationTest.groovy b/platforms/jvm/testing-jvm/src/integTest/groovy/org/gradle/testing/AbstractTestTaskIntegrationTest.groovy index 4b37f9df04273..c184eeb36353d 100644 --- a/platforms/jvm/testing-jvm/src/integTest/groovy/org/gradle/testing/AbstractTestTaskIntegrationTest.groovy +++ b/platforms/jvm/testing-jvm/src/integTest/groovy/org/gradle/testing/AbstractTestTaskIntegrationTest.groovy @@ -27,6 +27,7 @@ import org.gradle.testing.fixture.AbstractTestingMultiVersionIntegrationTest import spock.lang.Issue import java.time.Duration +import java.nio.file.attribute.PosixFilePermission import static org.hamcrest.Matchers.greaterThanOrEqualTo @@ -397,6 +398,25 @@ abstract class AbstractTestTaskIntegrationTest extends AbstractTestingMultiVersi "after" | afterClassAnnotation } + @Requires(UnitTestPreconditions.FilePermissions) + def "binary test result files have correct permissions"() { + given: + file('src/test/java/MyTest.java') << standaloneTestClass + + when: + succeeds 'test' + + then: + def binaryDir = file("build/test-results/test/binary") + java.nio.file.Files.walk(binaryDir.toPath()) + .filter { java.nio.file.Files.isRegularFile(it) } + .each { path -> + def perms = java.nio.file.Files.getPosixFilePermissions(path) + assert perms.contains(PosixFilePermission.OTHERS_READ) + assert perms.contains(PosixFilePermission.GROUP_READ) + } + } + private String buildRequestingNewerJavaVersion() { """ java { diff --git a/platforms/software/testing-base/src/main/java/org/gradle/api/internal/tasks/testing/results/serializable/SerializableTestResultStore.java b/platforms/software/testing-base/src/main/java/org/gradle/api/internal/tasks/testing/results/serializable/SerializableTestResultStore.java index 7fa93787b3773..35c946076d28e 100644 --- a/platforms/software/testing-base/src/main/java/org/gradle/api/internal/tasks/testing/results/serializable/SerializableTestResultStore.java +++ b/platforms/software/testing-base/src/main/java/org/gradle/api/internal/tasks/testing/results/serializable/SerializableTestResultStore.java @@ -97,12 +97,12 @@ private static int depth(TestDescriptorInternal descriptor) { private final Set flatteningIds; private final List extraFlattenedDescriptors; private final List extraFlattenedResults; - private final Path serializedResultsFile; private final int diskSkipLevels; - private final Path temporaryResultsFile; /** * Encoder storing the serialized test results. */ + private final Path serializedResultsFile; + private final Path temporaryResultsFile; private final KryoBackedEncoder resultsEncoder; private final TestOutputWriter outputWriter; private long nextId = 1; @@ -111,14 +111,14 @@ private static int depth(TestDescriptorInternal descriptor) { private final Multimap metadatas = LinkedHashMultimap.create(); private Writer(Path serializedResultsFile, Path outputEventsFile, int diskSkipLevels) throws IOException { - this.serializedResultsFile = serializedResultsFile; this.diskSkipLevels = diskSkipLevels; + this.serializedResultsFile = serializedResultsFile; + this.temporaryResultsFile = serializedResultsFile.resolveSibling("in-progress-results-generic.bin"); // Use constants to avoid allocating empty collections if flattening is not enabled flatteningIds = isDiskSkipEnabled() ? new HashSet<>() : Collections.emptySet(); extraFlattenedDescriptors = isDiskSkipEnabled() ? new ArrayList<>() : Collections.emptyList(); extraFlattenedResults = isDiskSkipEnabled() ? new ArrayList<>() : Collections.emptyList(); Files.createDirectories(serializedResultsFile.getParent()); - temporaryResultsFile = Files.createTempFile(serializedResultsFile.getParent(), "in-progress-results-generic", ".bin"); resultsEncoder = new KryoBackedEncoder(Files.newOutputStream(temporaryResultsFile)); Serializer testOutputEventSerializer = TestEventSerializer.create().build(TestOutputEvent.class); try { @@ -296,7 +296,7 @@ public void close() throws IOException { } finally { CompositeStoppable.stoppable(resultsEncoder, outputWriter).stop(); } - // Move the temporary results file to the final location, if successful + // Move the completed in-progress file to the final location Files.move(temporaryResultsFile, serializedResultsFile, StandardCopyOption.REPLACE_EXISTING); } }