Skip to content

Commit 3583e01

Browse files
authored
Use separate local Maven repos when file system type is NTFS (#4259)
Prior to this commit, Maven builds triggered from integration tests sometimes failed because another concurrent build was writing to the same file in the temporary local Maven repo.
1 parent 544c3b2 commit 3583e01

File tree

8 files changed

+76
-14
lines changed

8 files changed

+76
-14
lines changed

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
*/
3535
class JavaVersionsTests {
3636

37-
@GlobalResource
37+
@ManagedResource
3838
LocalMavenRepo localMavenRepo;
3939

4040
@TempDir

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/LocalMavenRepo.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,47 @@
1010

1111
package platform.tooling.support.tests;
1212

13+
import static platform.tooling.support.tests.ManagedResource.Scope.GLOBAL;
14+
import static platform.tooling.support.tests.ManagedResource.Scope.PER_CONTEXT;
15+
1316
import java.io.IOException;
1417
import java.io.UncheckedIOException;
1518
import java.nio.file.Files;
1619
import java.nio.file.Path;
1720
import java.util.Comparator;
1821

22+
import org.junit.jupiter.api.extension.ExtensionContext;
23+
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
24+
25+
@ManagedResource.Scoped(LocalMavenRepo.ScopeProvider.class)
1926
public class LocalMavenRepo implements AutoCloseable {
2027

28+
public static class ScopeProvider implements ManagedResource.Scoped.Provider {
29+
30+
private static final Namespace NAMESPACE = Namespace.create(LocalMavenRepo.class);
31+
32+
@Override
33+
public ManagedResource.Scope determineScope(ExtensionContext extensionContext) {
34+
var store = extensionContext.getRoot().getStore(NAMESPACE);
35+
var fileSystemType = store.getOrComputeIfAbsent("tempFileSystemType", key -> {
36+
var type = getFileSystemType(Path.of(System.getProperty("java.io.tmpdir")));
37+
extensionContext.getRoot().publishReportEntry("tempFileSystemType", type);
38+
return type;
39+
}, String.class);
40+
// Writing to the same file from multiple Maven processes may fail the build on Windows
41+
return "NTFS".equalsIgnoreCase(fileSystemType) ? PER_CONTEXT : GLOBAL;
42+
}
43+
44+
private static String getFileSystemType(Path path) {
45+
try {
46+
return Files.getFileStore(path).type();
47+
}
48+
catch (IOException e) {
49+
throw new UncheckedIOException(e);
50+
}
51+
}
52+
}
53+
2154
private final Path tempDir;
2255

2356
public LocalMavenRepo() {

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GlobalResource.java renamed to platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManagedResource.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,30 @@
3232

3333
@Target({ ElementType.PARAMETER, ElementType.FIELD })
3434
@Retention(RUNTIME)
35-
@ExtendWith(GlobalResource.Extension.class)
36-
public @interface GlobalResource {
35+
@ExtendWith(ManagedResource.Extension.class)
36+
public @interface ManagedResource {
37+
38+
@Target(ElementType.TYPE)
39+
@Retention(RUNTIME)
40+
@interface Scoped {
41+
42+
Class<? extends Provider> value();
43+
44+
interface Provider {
45+
Scope determineScope(ExtensionContext extensionContext);
46+
}
47+
}
48+
49+
enum Scope {
50+
GLOBAL, PER_CONTEXT
51+
}
3752

3853
class Extension implements ParameterResolver, TestInstancePostProcessor {
3954

4055
@Override
4156
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
4257
throws ParameterResolutionException {
43-
return parameterContext.isAnnotated(GlobalResource.class);
58+
return parameterContext.isAnnotated(ManagedResource.class);
4459
}
4560

4661
@Override
@@ -50,9 +65,14 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte
5065
return getOrCreateResource(extensionContext, type).get();
5166
}
5267

68+
@Override
69+
public ExtensionContextScope getTestInstantiationExtensionContextScope(ExtensionContext rootContext) {
70+
return ExtensionContextScope.TEST_METHOD;
71+
}
72+
5373
@Override
5474
public void postProcessTestInstance(Object testInstance, ExtensionContext extensionContext) {
55-
streamFields(testInstance.getClass(), field -> AnnotationSupport.isAnnotated(field, GlobalResource.class),
75+
streamFields(testInstance.getClass(), field -> AnnotationSupport.isAnnotated(field, ManagedResource.class),
5676
HierarchyTraversalMode.BOTTOM_UP) //
5777
.forEach(field -> {
5878
try {
@@ -66,7 +86,16 @@ public void postProcessTestInstance(Object testInstance, ExtensionContext extens
6686

6787
@SuppressWarnings("unchecked")
6888
private <T> Resource<T> getOrCreateResource(ExtensionContext extensionContext, Class<T> type) {
69-
return extensionContext.getRoot().getStore(Namespace.GLOBAL) //
89+
var scope = AnnotationSupport.findAnnotation(type, Scoped.class) //
90+
.map(Scoped::value) //
91+
.map(ReflectionSupport::newInstance) //
92+
.map(provider -> provider.determineScope(extensionContext)) //
93+
.orElse(Scope.GLOBAL);
94+
var storingContext = switch (scope) {
95+
case GLOBAL -> extensionContext.getRoot();
96+
case PER_CONTEXT -> extensionContext;
97+
};
98+
return storingContext.getStore(Namespace.GLOBAL) //
7099
.getOrComputeIfAbsent(type, Resource::new, Resource.class);
71100
}
72101
}

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenStarterTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
*/
3333
class MavenStarterTests {
3434

35-
@GlobalResource
35+
@ManagedResource
3636
LocalMavenRepo localMavenRepo;
3737

38-
@GlobalResource
38+
@ManagedResource
3939
MavenRepoProxy mavenRepoProxy;
4040

4141
@Test

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
*/
3434
class MavenSurefireCompatibilityTests {
3535

36-
@GlobalResource
36+
@ManagedResource
3737
LocalMavenRepo localMavenRepo;
3838

3939
@ParameterizedTest

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MultiReleaseJarTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333
*/
3434
class MultiReleaseJarTests {
3535

36-
@GlobalResource
36+
@ManagedResource
3737
LocalMavenRepo localMavenRepo;
3838

39-
@GlobalResource
39+
@ManagedResource
4040
MavenRepoProxy mavenRepoProxy;
4141

4242
@Test

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
*/
3838
class UnalignedClasspathTests {
3939

40-
@GlobalResource
40+
@ManagedResource
4141
LocalMavenRepo localMavenRepo;
4242

43-
@GlobalResource
43+
@ManagedResource
4444
MavenRepoProxy mavenRepoProxy;
4545

4646
@ParameterizedTest

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageMavenIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
class VintageMavenIntegrationTests {
3131

32-
@GlobalResource
32+
@ManagedResource
3333
LocalMavenRepo localMavenRepo;
3434

3535
@TempDir

0 commit comments

Comments
 (0)