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..9a26ad81c4 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..30aae4f7ea 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 @@ -42,9 +42,11 @@ 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; @@ -163,6 +165,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 {