You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2019/05/10 19:50:08 UTC

[maven-surefire] branch SUREFIRE-1617 updated (25fd49d -> fa2419f)

This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a change to branch SUREFIRE-1617
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git.


 discard 25fd49d  [SUREFIRE-1617] Surefire fails with bad message when path contains whitespaces and colon
     new fa2419f  [SUREFIRE-1617] Surefire fails with bad message when path contains whitespaces and colon

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (25fd49d)
            \
             N -- N -- N   refs/heads/SUREFIRE-1617 (fa2419f)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/site/apt/examples/cwd.apt.vm               | 50 ++++++++++++++++++++++
 maven-surefire-plugin/src/site/site.xml            |  1 +
 .../org/apache/maven/surefire/its/UmlautDirIT.java |  2 +-
 3 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm


[maven-surefire] 01/01: [SUREFIRE-1617] Surefire fails with bad message when path contains whitespaces and colon

Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

tibordigana pushed a commit to branch SUREFIRE-1617
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit fa2419fb9785657f905889ae2cf8b955e61515b1
Author: tibordigana <ti...@apache.org>
AuthorDate: Sun Apr 7 23:06:45 2019 +0200

    [SUREFIRE-1617] Surefire fails with bad message when path contains whitespaces and colon
---
 .../booterclient/JarManifestForkConfiguration.java |  56 +++++----
 .../JarManifestForkConfigurationTest.java          |  61 ++++++++-
 .../src/site/apt/examples/cwd.apt.vm               |  50 ++++++++
 maven-surefire-plugin/src/site/site.xml            |   1 +
 .../org/apache/maven/surefire/its/UmlautDirIT.java | 139 +++++++++++++++++++--
 .../maven/surefire/its/fixture/MavenLauncher.java  |  12 +-
 .../test/resources/junit-pathWithUmlaut/pom.xml    |   9 ++
 7 files changed, 296 insertions(+), 32 deletions(-)

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 62fa4c1..1a3dd4f 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
@@ -31,8 +31,9 @@ import javax.annotation.Nullable;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Iterator;
@@ -43,8 +44,11 @@ import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.nio.file.Files.isDirectory;
 import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
+import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri.absolute;
+import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri.relative;
 import static org.apache.maven.surefire.util.internal.StringUtils.NL;
 
 /**
@@ -168,14 +172,11 @@ public final class JarManifestForkConfiguration
                                          @Nonnull Path classPathElement,
                                          @Nonnull File dumpLogDirectory,
                                          boolean dumpError )
-            throws IOException
     {
         try
         {
-            String relativeUriPath = relativize( parent, classPathElement )
-                    .replace( '\\', '/' );
-
-            return new ClasspathElementUri( new URI( null, relativeUriPath, null ) );
+            String relativePath = relativize( parent, classPathElement );
+            return relative( escapeUri( relativePath, UTF_8 ) );
         }
         catch ( IllegalArgumentException e )
         {
@@ -190,15 +191,7 @@ public final class JarManifestForkConfiguration
                         .dumpStreamText( error, dumpLogDirectory );
             }
 
-            return new ClasspathElementUri( toAbsoluteUri( classPathElement ) );
-        }
-        catch ( URISyntaxException e )
-        {
-            // This is really unexpected, so fail
-            throw new IOException( "Could not create a relative path "
-                    + classPathElement
-                    + " against "
-                    + parent, e );
+            return absolute( toAbsoluteUri( classPathElement ) );
         }
     }
 
@@ -207,16 +200,37 @@ public final class JarManifestForkConfiguration
         final String uri;
         final boolean absolute;
 
-        ClasspathElementUri( String uri )
+        private ClasspathElementUri( String uri, boolean absolute )
         {
             this.uri = uri;
-            absolute = true;
+            this.absolute = absolute;
         }
 
-        ClasspathElementUri( URI uri )
+        static ClasspathElementUri absolute( String uri )
+        {
+            return new ClasspathElementUri( uri, true );
+        }
+
+        static ClasspathElementUri relative( String uri )
+        {
+            return new ClasspathElementUri( uri, false );
+        }
+    }
+
+    static String escapeUri( String input, Charset encoding )
+    {
+        try
+        {
+            String uriFormEncoded = URLEncoder.encode( input, encoding.name() );
+
+            String uriPathEncoded = uriFormEncoded.replaceAll( "\\+", "%20" );
+            uriPathEncoded = uriPathEncoded.replaceAll( "%2F|%5C", "/" );
+
+            return uriPathEncoded;
+        }
+        catch ( UnsupportedEncodingException e )
         {
-            this.uri = uri.toASCIIString();
-            absolute = false;
+            throw new IllegalStateException( "avoided by using Charset" );
         }
     }
 }
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 5e71238..08b3030 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
@@ -22,14 +22,18 @@ package org.apache.maven.plugin.surefire.booterclient;
 import java.io.File;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.nio.charset.Charset;
 import java.nio.file.Path;
 
 import org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri;
 import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
 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.plugin.surefire.booterclient.JarManifestForkConfiguration.escapeUri;
 import static org.fest.assertions.Assertions.assertThat;
 
 import org.junit.AfterClass;
@@ -39,7 +43,9 @@ import org.junit.runner.RunWith;
 
 import static org.fest.util.Files.delete;
 import static org.fest.util.Files.newTemporaryFolder;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.same;
 import static org.powermock.api.mockito.PowerMockito.mock;
 import static org.powermock.api.mockito.PowerMockito.mockStatic;
@@ -88,6 +94,8 @@ public class JarManifestForkConfigurationTest
                 .thenReturn( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" );
         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
                 .thenCallRealMethod();
+        when( escapeUri( anyString(), any( Charset.class ) ) )
+                .thenCallRealMethod();
         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
                 .isEqualTo( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" );
     }
@@ -105,6 +113,8 @@ public class JarManifestForkConfigurationTest
                 .thenReturn( "../../../../../the Maven repo/grp/art/1.0/art-1.0.jar" );
         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
                 .thenCallRealMethod();
+        when( escapeUri( anyString(), any( Charset.class ) ) )
+                .thenCallRealMethod();
         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
                 .isEqualTo( "../../../../../the%20Maven%20repo/grp/art/1.0/art-1.0.jar" );
     }
@@ -122,6 +132,8 @@ public class JarManifestForkConfigurationTest
                 .thenReturn( "..\\..\\..\\Users\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
                 .thenCallRealMethod();
+        when( escapeUri( anyString(), any( Charset.class )  ) )
+                .thenCallRealMethod();
         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
                 .isEqualTo( "../../../Users/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
     }
@@ -134,11 +146,14 @@ public class JarManifestForkConfigurationTest
         Path parent = mock( Path.class );
         when( parent.toString() ).thenReturn( "C:\\Windows\\Temp\\surefire" );
         Path classPathElement = mock( Path.class );
-        when( classPathElement.toString() ).thenReturn( "C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
+        when( classPathElement.toString() )
+                .thenReturn("C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar");
         when( relativize( parent, classPathElement ) )
                 .thenReturn( "..\\..\\..\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
                 .thenCallRealMethod();
+        when( escapeUri( anyString(), any( Charset.class ) ) )
+                .thenCallRealMethod();
         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
                 .isEqualTo( "../../../Test%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
     }
@@ -168,6 +183,8 @@ public class JarManifestForkConfigurationTest
                 .thenThrow( new IllegalArgumentException() );
         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 )
@@ -175,6 +192,46 @@ public class JarManifestForkConfigurationTest
     }
 
     @Test
+    public void shouldEscapeUri()
+            throws Exception
+    {
+        assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" );
+        assertThat( escapeUri( " ", UTF_8 ) ).isEqualTo( "%20" );
+        assertThat( escapeUri( "%", UTF_8 ) ).isEqualTo( "%25" );
+        assertThat( escapeUri( "+", UTF_8 ) ).isEqualTo( "%2B" );
+        assertThat( escapeUri( ",", UTF_8 ) ).isEqualTo( "%2C" );
+        assertThat( escapeUri( "/", UTF_8 ) ).isEqualTo( "/" );
+        assertThat( escapeUri( "7", UTF_8 ) ).isEqualTo( "7" );
+        assertThat( escapeUri( ":", UTF_8 ) ).isEqualTo( "%3A" );
+        assertThat( escapeUri( "@", UTF_8 ) ).isEqualTo( "%40" );
+        assertThat( escapeUri( "A", UTF_8 ) ).isEqualTo( "A" );
+        assertThat( escapeUri( "[", UTF_8 ) ).isEqualTo( "%5B" );
+        assertThat( escapeUri( "\\", UTF_8 ) ).isEqualTo( "/" );
+        assertThat( escapeUri( "]", UTF_8 ) ).isEqualTo( "%5D" );
+        assertThat( escapeUri( "`", UTF_8 ) ).isEqualTo( "%60" );
+        assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" );
+        assertThat( escapeUri( "{", UTF_8 ) ).isEqualTo( "%7B" );
+        assertThat( escapeUri( "" + (char) 0xFF, UTF_8 ) ).isEqualTo( "%C3%BF" );
+
+        assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar",
+                UTF_8 ) )
+                .isEqualTo( "../../../Test%20%3A%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
+
+        assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar",
+                Charset.defaultCharset() ) )
+                .isEqualTo( "../../../Test%20%3A%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
+
+        assertThat( escapeUri( "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire", UTF_8 ) )
+                .isEqualTo( "../../surefire-its/target/junit-pathWith%C3%9Cmlaut_1/target/surefire" );
+
+        String source = "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire";
+        String encoded = escapeUri( "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire", UTF_8 );
+        String decoded = URLDecoder.decode( encoded, UTF_8.name() );
+        assertThat( decoded )
+                .isEqualTo( source );
+    }
+
+    @Test
     public void shouldRelativizeOnRealPlatform()
     {
         Path parentDir = new File( TMP, "test-parent-1" )
@@ -218,6 +275,6 @@ public class JarManifestForkConfigurationTest
         ClasspathElementUri testDirUriPath = toClasspathElementUri( parentDir, testDir, dumpDirectory, true );
 
         assertThat( testDirUriPath.uri )
-                .isEqualTo( "../@3%20test%20with%20white%20spaces" );
+                .isEqualTo( "../%403%20test%20with%20white%20spaces" );
     }
 }
diff --git a/maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm b/maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm
new file mode 100644
index 0000000..36248cd
--- /dev/null
+++ b/maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm
@@ -0,0 +1,50 @@
+ ------
+ Special characters in directories
+ ------
+ Tibor Digana
+ ------
+ 2019-05-10
+ ------
+
+ ~~ Licensed to the Apache Software Foundation (ASF) under one
+ ~~ or more contributor license agreements.  See the NOTICE file
+ ~~ distributed with this work for additional information
+ ~~ regarding copyright ownership.  The ASF licenses this file
+ ~~ to you under the Apache License, Version 2.0 (the
+ ~~ "License"); you may not use this file except in compliance
+ ~~ with the License.  You may obtain a copy of the License at
+ ~~
+ ~~   http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing,
+ ~~ software distributed under the License is distributed on an
+ ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~~ KIND, either express or implied.  See the License for the
+ ~~ specific language governing permissions and limitations
+ ~~ under the License.
+
+ ~~ NOTE: For help with the syntax of this file, see:
+ ~~ http://maven.apache.org/doxia/references/apt-format.html
+
+
+Working Directory with special characters
+
+ You can use a colon (<<<:>>>) in the cwd on Linux but you have to turn the path separator from colon to
+ some other character, see {{{https://issues.apache.org/jira/browse/SUREFIRE-1617}SUREFIRE-1617}}
+
+ You should change the classpath separator (we do not guarantee that your application and test would run seamlessly)
+ in order to avoid collisions with paths within the forked JVM:
+
++---+
+<argLine>-Dpath.separator=;</argLine>
++---+
+
+ For more information about the configuration parameter <<<workingDirectory>>>
+ see the chapter {{{./fork-options-and-parallel-execution.html#Forked_Test_Execution}Forked Test Execution}}.
+
+
+Local Repository with special characters
+
+ The plugin supports special characters (i.e. a colon (<<<:>>>)) in the path of Maven local repository.
+ The compiler does not support it and therefore the sources have to be compiled by another command in advance.
+
diff --git a/maven-surefire-plugin/src/site/site.xml b/maven-surefire-plugin/src/site/site.xml
index fb60c3b..87efd78 100644
--- a/maven-surefire-plugin/src/site/site.xml
+++ b/maven-surefire-plugin/src/site/site.xml
@@ -43,6 +43,7 @@
       <item name="Using JUnit 5 Platform" href="examples/junit-platform.html"/>
       <item name="Using POJO Tests" href="examples/pojo-test.html"/>
       <item name="Using Cucumber" href="examples/cucumber.html"/>
+      <item name="Special characters in directories" href="examples/cwd.html"/>
       <item name="Skipping Tests" href="examples/skipping-tests.html"/>
       <item name="Skip After Failure" href="examples/skip-after-failure.html"/>
       <item name="Inclusions and Exclusions of Tests" href="examples/inclusion-exclusion.html"/>
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java
index 7b008bc..9bff03e 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java
@@ -19,28 +19,112 @@ package org.apache.maven.surefire.its;
  * under the License.
  */
 
-import org.apache.maven.it.VerificationException;
+import org.apache.maven.shared.utils.io.FileUtils;
 import org.apache.maven.surefire.its.fixture.MavenLauncher;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
 import org.apache.maven.surefire.its.fixture.SurefireLauncher;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static java.nio.file.Files.copy;
+import static java.nio.file.Files.createDirectories;
+import static java.nio.file.Files.exists;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Test a directory with an umlaut
  *
  * @author <a href="mailto:dfabulich@apache.org">Dan Fabulich</a>
  */
-public class UmlautDirIT
-    extends SurefireJUnit4IntegrationTestCase
+public class UmlautDirIT extends SurefireJUnit4IntegrationTestCase
 {
+    private String localRepo;
+
+    @Before
+    public void backupLocalRepo()
+    {
+        localRepo = System.getProperty( "maven.repo.local" );
+    }
+
+    @After
+    public void restoreLocalRepo()
+    {
+        if ( localRepo == null )
+        {
+            System.clearProperty( "maven.repo.local" );
+        }
+        else
+        {
+            System.setProperty( "maven.repo.local", localRepo );
+        }
+    }
+
+    @Test
+    public void surefire1617WithColonInLocalRepo()
+            throws Exception
+    {
+        assumeTrue( IS_OS_LINUX );
+
+        unpack( "junit-pathWithUmlaut", "_compiled" )
+                .maven()
+                .execute( "compiler:testCompile" );
+
+        String cwd = System.getProperty( "user.dir" );
+
+        Path from = Paths.get( cwd, "target", "UmlautDirIT_surefire1617WithSpacesInLocalRepo_compiled", "target",
+                "test-classes", "umlautTest" );
+
+        Path to = Paths.get( cwd, "target", "UmlautDirIT_surefire1617WithSpacesInLocalRepo", "target",
+                "test-classes", "umlautTest" );
+
+        MavenLauncher mavenLauncher = unpackWithColonsInLocalRepo()
+                .maven();
+
+        mavenLauncher.setForkJvm( true );
+        mavenLauncher.setAutoclean( false );
+
+        if ( !Files.exists( to ) )
+        {
+            Files.createDirectories( to );
+        }
+
+        FileUtils.copyDirectory( from.toFile(), to.toFile() );
+
+        mavenLauncher.sysProp( "skipCompiler", true )
+                .debugLogging()
+                .executeTest()
+                .verifyErrorFreeLog()
+                .assertTestSuiteResults( 1, 0, 0, 0 );
+    }
+
+    @Test
+    public void surefire1617WithColonInProjectDir()
+            throws Exception
+    {
+        assumeTrue( IS_OS_LINUX );
+        unpackWithNewProjectDirectory( "this is: a test", "_surefire-1617" )
+                .setForkJvm()
+                .sysProp( "argLine", "-Dpath.separator=;" )
+                .executeTest()
+                .verifyErrorFreeLog()
+                .assertTestSuiteResults( 1, 0, 0, 0 );
+    }
+
     @Test
     public void testUmlaut()
         throws Exception
     {
-        specialUnpack( "1" )
+        unpackWithNewProjectDirectory( "/junit-pathWith\u00DCmlaut_", "1" )
                 .executeTest()
                 .verifyErrorFreeLog()
                 .assertTestSuiteResults( 1, 0, 0, 0 );
@@ -50,20 +134,59 @@ public class UmlautDirIT
     public void testUmlautIsolatedClassLoader()
         throws Exception
     {
-        specialUnpack( "2" )
+        unpackWithNewProjectDirectory( "/junit-pathWith\u00DCmlaut_", "2" )
                 .useSystemClassLoader( false )
                 .executeTest()
                 .assertTestSuiteResults( 1, 0, 0, 0 );
     }
 
-    SurefireLauncher specialUnpack( String postfix )
-        throws IOException
+    private SurefireLauncher unpackWithNewProjectDirectory( String projectDirectory, String postfix )
+            throws IOException
     {
         SurefireLauncher unpack = unpack( "junit-pathWithUmlaut" );
         MavenLauncher maven = unpack.maven();
 
-        File dest = new File( maven.getUnpackedAt().getParentFile().getPath(), "/junit-pathWith\u00DCmlaut_" + postfix );
+        File dest = new File( maven.getUnpackedAt().getParentFile().getPath(), projectDirectory + postfix );
         maven.moveUnpackTo( dest );
         return unpack;
     }
+
+    private SurefireLauncher unpackWithColonsInLocalRepo()
+            throws IOException
+    {
+        String newLocalRepo =
+                Paths.get( System.getProperty( "user.dir" ), "target", "local repo for: SUREFIRE-1617" ).toString();
+        String defaultLocalRepo = new MavenLauncher( getClass(), "junit-pathWithUmlaut", null ).getLocalRepository();
+
+        copyFolder( Paths.get( defaultLocalRepo, "org", "apache", "maven", "surefire" ),
+                Paths.get( newLocalRepo, "org", "apache", "maven", "surefire" ) );
+
+        copyFolder( Paths.get( defaultLocalRepo, "org", "apache", "maven", "plugins", "maven-surefire-plugin" ),
+                Paths.get( newLocalRepo, "org", "apache", "maven", "plugins", "maven-surefire-plugin" ) );
+
+        System.setProperty( "maven.repo.local", newLocalRepo );
+        return unpack( "junit-pathWithUmlaut" );
+    }
+
+    private static void copyFolder( Path src, Path dest )
+            throws IOException
+    {
+        if ( !exists( dest ) )
+        {
+            createDirectories( dest );
+        }
+
+        for ( File from : requireNonNull( src.toFile().listFiles() ) )
+        {
+            Path to = dest.resolve( from.getName() );
+            if ( from.isDirectory() )
+            {
+                copyFolder( from.toPath(), to );
+            }
+            else if ( from.isFile() )
+            {
+                copy( from.toPath(), to, REPLACE_EXISTING );
+            }
+        }
+    }
 }
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
index c36da47..de1d5f8 100755
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java
@@ -77,7 +77,7 @@ public final class MavenLauncher
         resetCliOptions();
     }
 
-    MavenLauncher( Class testClass, String resourceName, String suffix )
+    public MavenLauncher( Class testClass, String resourceName, String suffix )
     {
         this( testClass, resourceName, suffix, null );
     }
@@ -376,6 +376,16 @@ public final class MavenLauncher
         getVerifier().setForkJvm( forkJvm );
     }
 
+    public String getLocalRepository()
+    {
+        return getVerifier().getLocalRepository();
+    }
+
+    public void setAutoclean( boolean autoclean )
+    {
+        getVerifier().setAutoclean( autoclean );
+    }
+
     private Verifier getVerifier()
     {
         if ( verifier == null )
diff --git a/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml b/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml
index ee65491..6c79c08 100644
--- a/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml
+++ b/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml
@@ -31,6 +31,7 @@
   <properties>
     <maven.compiler.source>1.7</maven.compiler.source>
     <maven.compiler.target>1.7</maven.compiler.target>
+    <skipCompiler>false</skipCompiler>
   </properties>
 
   <dependencies>
@@ -53,6 +54,14 @@
           <artifactId>maven-clean-plugin</artifactId>
           <version>3.0.0</version>
         </plugin>
+        <plugin>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.8.1</version>
+          <configuration>
+            <skip>${skipCompiler}</skip>
+            <skipMain>${skipCompiler}</skipMain>
+          </configuration>
+        </plugin>
       </plugins>
     </pluginManagement>
     <plugins>