View Javadoc
1   package org.apache.maven.plugin.surefire.booterclient;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.net.URI;
24  import java.net.URISyntaxException;
25  import java.net.URLDecoder;
26  import java.nio.charset.Charset;
27  import java.nio.file.Path;
28  
29  import org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri;
30  import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
31  
32  import static java.nio.charset.StandardCharsets.UTF_8;
33  import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.relativize;
34  import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toAbsoluteUri;
35  import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toClasspathElementUri;
36  import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.escapeUri;
37  import static org.fest.assertions.Assertions.assertThat;
38  
39  import org.junit.AfterClass;
40  import org.junit.BeforeClass;
41  import org.junit.Test;
42  import org.junit.runner.RunWith;
43  
44  import static org.fest.util.Files.delete;
45  import static org.fest.util.Files.newTemporaryFolder;
46  import static org.mockito.ArgumentMatchers.any;
47  import static org.mockito.ArgumentMatchers.anyBoolean;
48  import static org.mockito.ArgumentMatchers.anyString;
49  import static org.mockito.ArgumentMatchers.same;
50  import static org.powermock.api.mockito.PowerMockito.mock;
51  import static org.powermock.api.mockito.PowerMockito.mockStatic;
52  import static org.powermock.api.mockito.PowerMockito.when;
53  
54  import org.mockito.invocation.InvocationOnMock;
55  import org.mockito.stubbing.Answer;
56  import org.powermock.core.classloader.annotations.PowerMockIgnore;
57  import org.powermock.core.classloader.annotations.PrepareForTest;
58  import org.powermock.modules.junit4.PowerMockRunner;
59  
60  /**
61   * Unit tests for {@link JarManifestForkConfiguration}.
62   */
63  @RunWith( PowerMockRunner.class )
64  @PrepareForTest( { JarManifestForkConfiguration.class, InPluginProcessDumpSingleton.class } )
65  @PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } )
66  public class JarManifestForkConfigurationTest
67  {
68      private static final File TMP = newTemporaryFolder();
69  
70      private static File dumpDirectory;
71  
72      @BeforeClass
73      public static void createSystemTemporaryDir()
74      {
75          dumpDirectory = new File( TMP, "dump" );
76          assertThat( dumpDirectory.mkdir() )
77                  .isTrue();
78      }
79  
80      @AfterClass
81      public static void deleteSystemTemporaryDir()
82      {
83          delete( TMP );
84      }
85  
86      @Test
87      public void relativeClasspathUnixSimple()
88          throws Exception
89      {
90          mockStatic( JarManifestForkConfiguration.class );
91          Path parent = mock( Path.class );
92          when( parent.toString() ).thenReturn( "/home/me/prj/target/surefire" );
93          Path classPathElement = mock( Path.class );
94          when( classPathElement.toString() ).thenReturn( "/home/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
95          when( relativize( parent, classPathElement ) )
96                  .thenReturn( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" );
97          when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
98                  .thenCallRealMethod();
99          when( escapeUri( anyString(), any( Charset.class ) ) )
100                 .thenCallRealMethod();
101         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
102                 .isEqualTo( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" );
103     }
104 
105     @Test
106     public void relativeClasspathUnixTricky()
107         throws Exception
108     {
109         mockStatic( JarManifestForkConfiguration.class );
110         Path parent = mock( Path.class );
111         when( parent.toString() ).thenReturn( "/home/me/prj/target/surefire" );
112         Path classPathElement = mock( Path.class );
113         when( classPathElement.toString() ).thenReturn( "/the Maven repo/grp/art/1.0/art-1.0.jar" );
114         when( relativize( parent, classPathElement ) )
115                 .thenReturn( "../../../../../the Maven repo/grp/art/1.0/art-1.0.jar" );
116         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
117                 .thenCallRealMethod();
118         when( escapeUri( anyString(), any( Charset.class ) ) )
119                 .thenCallRealMethod();
120         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
121                 .isEqualTo( "../../../../../the%20Maven%20repo/grp/art/1.0/art-1.0.jar" );
122     }
123 
124     @Test
125     public void relativeClasspathWindowsSimple()
126         throws Exception
127     {
128         mockStatic( JarManifestForkConfiguration.class );
129         Path parent = mock( Path.class );
130         when( parent.toString() ).thenReturn( "C:\\Windows\\Temp\\surefire" );
131         Path classPathElement = mock( Path.class );
132         when( classPathElement.toString() ).thenReturn( "C:\\Users\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
133         when( relativize( parent, classPathElement ) )
134                 .thenReturn( "..\\..\\..\\Users\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
135         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
136                 .thenCallRealMethod();
137         when( escapeUri( anyString(), any( Charset.class )  ) )
138                 .thenCallRealMethod();
139         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
140                 .isEqualTo( "../../../Users/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
141     }
142 
143     @Test
144     public void relativeClasspathWindowsTricky()
145         throws Exception
146     {
147         mockStatic( JarManifestForkConfiguration.class );
148         Path parent = mock( Path.class );
149         when( parent.toString() ).thenReturn( "C:\\Windows\\Temp\\surefire" );
150         Path classPathElement = mock( Path.class );
151         when( classPathElement.toString() )
152                 .thenReturn( "C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
153         when( relativize( parent, classPathElement ) )
154                 .thenReturn( "..\\..\\..\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
155         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
156                 .thenCallRealMethod();
157         when( escapeUri( anyString(), any( Charset.class ) ) )
158                 .thenCallRealMethod();
159         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
160                 .isEqualTo( "../../../Test%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
161     }
162 
163     @Test
164     public void crossDriveWindows()
165         throws Exception
166     {
167         mockStatic( JarManifestForkConfiguration.class );
168         mockStatic( InPluginProcessDumpSingleton.class );
169         when( InPluginProcessDumpSingleton.getSingleton() ).thenReturn( mock( InPluginProcessDumpSingleton.class ) );
170         Path parent = mock( Path.class );
171         when( parent.toString() ).thenReturn( "C:\\Windows\\Temp\\surefire" );
172         Path classPathElement = mock( Path.class );
173         when( classPathElement.toString() ).thenReturn( "X:\\Users\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" );
174         when( classPathElement.toUri() )
175                 .thenAnswer( new Answer<URI>()
176                 {
177                     @Override
178                     public URI answer( InvocationOnMock invocation ) throws URISyntaxException
179                     {
180                         String path = invocation.getMock().toString();
181                         return new URI( "file", "", "/" + path.replace( '\\', '/' ), null );
182                     }
183                 } );
184         when( relativize( same( parent ), same( classPathElement ) ) )
185                 .thenThrow( new IllegalArgumentException() );
186         when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) )
187                 .thenCallRealMethod();
188         when( escapeUri( anyString(), any( Charset.class ) ) )
189                 .thenCallRealMethod();
190         when( toAbsoluteUri( same( classPathElement ) ) )
191                 .thenCallRealMethod();
192         assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri )
193                 .isEqualTo( "file:///X:/Users/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
194     }
195 
196     @Test
197     @SuppressWarnings( "checkstyle:magicnumber" )
198     public void shouldEscapeUri()
199             throws Exception
200     {
201         assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" );
202         assertThat( escapeUri( " ", UTF_8 ) ).isEqualTo( "%20" );
203         assertThat( escapeUri( "%", UTF_8 ) ).isEqualTo( "%25" );
204         assertThat( escapeUri( "+", UTF_8 ) ).isEqualTo( "%2B" );
205         assertThat( escapeUri( ",", UTF_8 ) ).isEqualTo( "%2C" );
206         assertThat( escapeUri( "/", UTF_8 ) ).isEqualTo( "/" );
207         assertThat( escapeUri( "7", UTF_8 ) ).isEqualTo( "7" );
208         assertThat( escapeUri( ":", UTF_8 ) ).isEqualTo( "%3A" );
209         assertThat( escapeUri( "@", UTF_8 ) ).isEqualTo( "%40" );
210         assertThat( escapeUri( "A", UTF_8 ) ).isEqualTo( "A" );
211         assertThat( escapeUri( "[", UTF_8 ) ).isEqualTo( "%5B" );
212         assertThat( escapeUri( "\\", UTF_8 ) ).isEqualTo( "/" );
213         assertThat( escapeUri( "]", UTF_8 ) ).isEqualTo( "%5D" );
214         assertThat( escapeUri( "`", UTF_8 ) ).isEqualTo( "%60" );
215         assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" );
216         assertThat( escapeUri( "{", UTF_8 ) ).isEqualTo( "%7B" );
217         assertThat( escapeUri( "" + (char) 0xFF, UTF_8 ) ).isEqualTo( "%C3%BF" );
218 
219         assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar",
220                 UTF_8 ) )
221                 .isEqualTo( "../../../Test%20%3A%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
222 
223         assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar",
224                 Charset.defaultCharset() ) )
225                 .isEqualTo( "../../../Test%20%3A%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" );
226 
227         assertThat( escapeUri( "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire", UTF_8 ) )
228                 .isEqualTo( "../../surefire-its/target/junit-pathWith%C3%9Cmlaut_1/target/surefire" );
229 
230         String source = "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire";
231         String encoded = escapeUri( "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire", UTF_8 );
232         String decoded = URLDecoder.decode( encoded, UTF_8.name() );
233         assertThat( decoded )
234                 .isEqualTo( source );
235     }
236 
237     @Test
238     public void shouldRelativizeOnRealPlatform()
239     {
240         Path parentDir = new File( TMP, "test-parent-1" )
241                 .toPath();
242 
243         Path testDir = new File( TMP, "@1 test with white spaces" )
244                 .toPath();
245 
246         String relativeTestDir = relativize( parentDir, testDir );
247 
248         assertThat( relativeTestDir )
249                 .isEqualTo( ".." + File.separator + "@1 test with white spaces" );
250     }
251 
252     @Test
253     public void shouldMakeAbsoluteUriOnRealPlatform()
254             throws Exception
255     {
256         Path testDir = new File( TMP, "@2 test with white spaces" )
257                 .toPath();
258 
259         URI testDirUri = new URI( toAbsoluteUri( testDir ) );
260 
261         assertThat( testDirUri.getScheme() )
262                 .isEqualTo( "file" );
263 
264         assertThat( testDirUri.getRawPath() )
265                 .isEqualTo( testDir.toUri().getRawPath() );
266     }
267 
268     @Test
269     public void shouldMakeRelativeUriOnRealPlatform()
270             throws Exception
271     {
272         Path parentDir = new File( TMP, "test-parent-2" )
273                 .toPath();
274 
275         Path testDir = new File( TMP, "@3 test with white spaces" )
276                 .toPath();
277 
278         ClasspathElementUri testDirUriPath = toClasspathElementUri( parentDir, testDir, dumpDirectory, true );
279 
280         assertThat( testDirUriPath.uri )
281                 .isEqualTo( "../%403%20test%20with%20white%20spaces" );
282     }
283 }