From 55ccd06a027f1693557c2a3ec3690ac91dcc59ba Mon Sep 17 00:00:00 2001 From: Robert Seidel Date: Fri, 1 Dec 2023 13:52:43 +0100 Subject: [PATCH] [SUREFIRE-2211] additionalClasspathElement with UNC path not working with Maven Failsafe Plugin This closes #689 --- .../JarManifestForkConfiguration.java | 5 +++ .../JarManifestForkConfigurationTest.java | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java index 5e29d1ed31..a13de8fb86 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java @@ -179,6 +179,11 @@ static String relativize(@Nonnull Path parent, @Nonnull Path child) throws Illeg } static String toAbsoluteUri(@Nonnull Path absolutePath) { + // UNC paths need to be written as file://// + // see https://bugs.openjdk.org/browse/JDK-8320760 + if (absolutePath.toString().startsWith("\\\\")) { + return absolutePath.toFile().toURI().toASCIIString(); + } return absolutePath.toUri().toASCIIString(); } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java index 23d850de89..9a9bf430ff 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java @@ -31,20 +31,24 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.escapeUri; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.relativize; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toAbsoluteUri; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toClasspathElementUri; +import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Files.delete; import static org.assertj.core.util.Files.newTemporaryFolder; +import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; @@ -57,6 +61,7 @@ * Unit tests for {@link JarManifestForkConfiguration}. */ @RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(JUnit4.class) @PrepareForTest({JarManifestForkConfiguration.class, InPluginProcessDumpSingleton.class}) @PowerMockIgnore({"org.jacoco.agent.rt.*", "com.vladium.emma.rt.*"}) public class JarManifestForkConfigurationTest { @@ -163,6 +168,33 @@ public URI answer(InvocationOnMock invocation) throws URISyntaxException { .isEqualTo("file:///X:/Users/me/.m2/repository/grp/art/1.0/art-1.0.jar"); } + @Test + public void uncWindows() throws Exception { + assumeTrue(IS_OS_WINDOWS); + mockStatic(JarManifestForkConfiguration.class); + mockStatic(InPluginProcessDumpSingleton.class); + when(InPluginProcessDumpSingleton.getSingleton()).thenReturn(mock(InPluginProcessDumpSingleton.class)); + Path parent = mock(Path.class); + when(parent.toString()).thenReturn("C:\\Windows\\Temp\\surefire"); + Path classPathElement = mock(Path.class); + when(classPathElement.toString()).thenReturn("\\\\server\\grp\\art\\1.0\\art-1.0.jar"); + when(classPathElement.toFile()).thenAnswer(new Answer() { + @Override + public File answer(InvocationOnMock invocation) { + String path = invocation.getMock().toString(); + return new File(path); + } + }); + when(relativize(same(parent), same(classPathElement))) + .thenThrow(new IllegalArgumentException("'other' has different root")); + when(toClasspathElementUri(same(parent), same(classPathElement), same(dumpDirectory), anyBoolean())) + .thenCallRealMethod(); + when(escapeUri(anyString(), any(Charset.class))).thenCallRealMethod(); + when(toAbsoluteUri(same(classPathElement))).thenCallRealMethod(); + assertThat(toClasspathElementUri(parent, classPathElement, dumpDirectory, true).uri) + .isEqualTo("file:////server/grp/art/1.0/art-1.0.jar"); + } + @Test @SuppressWarnings("checkstyle:magicnumber") public void shouldEscapeUri() throws Exception {