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 org.apache.commons.io.FileUtils;
23  import org.apache.commons.lang3.RandomStringUtils;
24  import org.apache.commons.lang3.SystemUtils;
25  import org.apache.maven.plugin.surefire.JdkAttributes;
26  import org.apache.maven.shared.utils.StringUtils;
27  import org.apache.maven.shared.utils.cli.Commandline;
28  import org.apache.maven.surefire.booter.Classpath;
29  import org.apache.maven.surefire.booter.SurefireBooterForkException;
30  import org.junit.Test;
31  
32  import java.io.File;
33  import java.io.IOException;
34  import java.util.Collections;
35  import java.util.Properties;
36  
37  import static org.junit.Assert.assertEquals;
38  import static org.junit.Assert.assertTrue;
39  import static org.junit.Assert.fail;
40  
41  public class ForkConfigurationTest
42  {
43      @Test
44      public void testCreateCommandLine_UseSystemClassLoaderForkOnce_ShouldConstructManifestOnlyJar()
45          throws IOException, SurefireBooterForkException
46      {
47          ForkConfiguration config = getForkConfiguration( (String) null );
48          File cpElement = getTempClasspathFile();
49  
50          Commandline cli =
51              config.createCommandLine( Collections.singletonList( cpElement.getAbsolutePath() ), true, false, null, 1 );
52  
53          String line = StringUtils.join( cli.getCommandline(), " " );
54          assertTrue( line.contains( "-jar" ) );
55      }
56  
57      @Test
58      public void testArglineWithNewline()
59          throws IOException, SurefireBooterForkException
60      {
61          // SUREFIRE-657
62          File cpElement = getTempClasspathFile();
63          ForkConfiguration forkConfiguration = getForkConfiguration( "abc\ndef" );
64  
65          final Commandline commandLine =
66              forkConfiguration.createCommandLine( Collections.singletonList( cpElement.getAbsolutePath() ), false, false,
67                                                   null, 1 );
68          assertTrue( commandLine.toString().contains( "abc def" ) );
69      }
70  
71      @Test
72      public void testCurrentWorkingDirectoryPropagationIncludingForkNumberExpansion()
73          throws IOException, SurefireBooterForkException
74      {
75          // SUREFIRE-1136
76          File baseDir =
77              new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + RandomStringUtils.randomAlphabetic( 3 ) );
78          assertTrue( baseDir.mkdirs() );
79          baseDir.deleteOnExit();
80  
81          File cwd = new File( baseDir, "fork_${surefire.forkNumber}" );
82  
83          ForkConfiguration config = getForkConfiguration( null, cwd.getCanonicalFile() );
84          Commandline commandLine = config.createCommandLine( Collections.<String>emptyList(), true, false, null, 1 );
85  
86          File forkDirectory = new File( baseDir, "fork_1" );
87          forkDirectory.deleteOnExit();
88          assertTrue( forkDirectory.getCanonicalPath().equals(
89              commandLine.getShell().getWorkingDirectory().getCanonicalPath() ) );
90      }
91  
92      @Test
93      public void testExceptionWhenCurrentDirectoryIsNotRealDirectory()
94          throws IOException, SurefireBooterForkException
95      {
96          // SUREFIRE-1136
97          File baseDir =
98              new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + RandomStringUtils.randomAlphabetic( 3 ) );
99          assertTrue( baseDir.mkdirs() );
100         baseDir.deleteOnExit();
101 
102         File cwd = new File( baseDir, "cwd.txt" );
103         FileUtils.touch( cwd );
104         cwd.deleteOnExit();
105 
106         ForkConfiguration config = getForkConfiguration( null, cwd.getCanonicalFile() );
107 
108         try
109         {
110             config.createCommandLine( Collections.<String>emptyList(), true, false, null, 1 );
111         }
112         catch ( SurefireBooterForkException sbfe )
113         {
114             // To handle issue with ~ expansion on Windows
115             String absolutePath = cwd.getCanonicalPath();
116             assertEquals( "WorkingDirectory " + absolutePath + " exists and is not a directory", sbfe.getMessage() );
117             return;
118         }
119 
120         fail();
121     }
122 
123     @Test
124     public void testExceptionWhenCurrentDirectoryCannotBeCreated()
125         throws IOException, SurefireBooterForkException
126     {
127         // SUREFIRE-1136
128         File baseDir =
129             new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + RandomStringUtils.randomAlphabetic( 3 ) );
130         assertTrue( baseDir.mkdirs() );
131         baseDir.deleteOnExit();
132 
133         // NULL is invalid for JDK starting from 1.7.60 - https://github.com/openjdk-mirror/jdk/commit/e5389115f3634d25d101e2dcc71f120d4fd9f72f
134         // ? character is invalid on Windows, seems to be imposable to create invalid directory using Java on Linux
135         File cwd = new File( baseDir, "?\u0000InvalidDirectoryName" );
136         ForkConfiguration config = getForkConfiguration( null, cwd.getAbsoluteFile() );
137 
138         try
139         {
140             config.createCommandLine( Collections.<String>emptyList(), true, false, null, 1 );
141         }
142         catch ( SurefireBooterForkException sbfe )
143         {
144             assertEquals( "Cannot create workingDirectory " + cwd.getAbsolutePath(), sbfe.getMessage() );
145             return;
146         }
147 
148         if ( SystemUtils.IS_OS_WINDOWS || isJavaVersionAtLeast( 7, 60 ) )
149         {
150             fail();
151         }
152     }
153 
154     private File getTempClasspathFile()
155         throws IOException
156     {
157         File cpElement = File.createTempFile( "ForkConfigurationTest.", ".file" );
158         cpElement.deleteOnExit();
159         return cpElement;
160     }
161 
162     public static ForkConfiguration getForkConfiguration( File javaExec )
163             throws IOException
164     {
165         return getForkConfiguration( null, javaExec.getAbsolutePath(), new File( "." ).getCanonicalFile() );
166     }
167 
168     public static ForkConfiguration getForkConfiguration( String argLine )
169         throws IOException
170     {
171         File jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" );
172         return getForkConfiguration( argLine, jvm.getAbsolutePath(), new File( "." ).getCanonicalFile() );
173     }
174 
175     public static ForkConfiguration getForkConfiguration( String argLine, File cwd )
176             throws IOException
177     {
178         File jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" );
179         return getForkConfiguration( argLine, jvm.getAbsolutePath(), cwd );
180     }
181 
182     private static ForkConfiguration getForkConfiguration( String argLine, String jvm, File cwd )
183         throws IOException
184     {
185         return new ForkConfiguration( Classpath.emptyClasspath(), null, null, new JdkAttributes( jvm, false ),
186                                             cwd, new Properties(), argLine, null, false, 1, false, new Platform() );
187     }
188 
189     // based on http://stackoverflow.com/questions/2591083/getting-version-of-java-in-runtime
190     private boolean isJavaVersionAtLeast( int major, int update )
191     {
192         String[] javaVersionElements = System.getProperty( "java.runtime.version" ).split( "\\.|_|-b" );
193         return Integer.valueOf( javaVersionElements[1] ) >= major
194             && Integer.valueOf( javaVersionElements[3] ) >= update;
195     }
196 }