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