1 package org.apache.maven.plugin.surefire.booterclient;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
23 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
24 import org.apache.maven.plugin.surefire.util.Relocator;
25 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
26 import org.apache.maven.surefire.booter.Classpath;
27 import org.apache.maven.surefire.booter.ClasspathConfiguration;
28 import org.apache.maven.surefire.booter.ForkedBooter;
29 import org.apache.maven.surefire.booter.StartupConfiguration;
30 import org.apache.maven.surefire.booter.SurefireBooterForkException;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.powermock.core.classloader.annotations.PrepareForTest;
35 import org.powermock.modules.junit4.PowerMockRunner;
36
37 import javax.annotation.Nonnull;
38 import java.io.File;
39 import java.util.HashMap;
40 import java.util.Map;
41 import java.util.Properties;
42
43 import static java.util.Collections.singleton;
44 import static org.fest.assertions.Assertions.assertThat;
45 import static org.mockito.ArgumentMatchers.anyString;
46 import static org.mockito.ArgumentMatchers.eq;
47 import static org.mockito.Mockito.never;
48 import static org.mockito.Mockito.times;
49 import static org.mockito.Mockito.verify;
50 import static org.powermock.api.mockito.PowerMockito.*;
51 import static org.powermock.reflect.Whitebox.invokeMethod;
52
53
54
55
56
57
58
59 @RunWith( PowerMockRunner.class )
60 @PrepareForTest( { DefaultForkConfiguration.class, Relocator.class } )
61 public class DefaultForkConfigurationTest
62 {
63 private Classpath booterClasspath;
64 private File tempDirectory;
65 private String debugLine;
66 private File workingDirectory;
67 private Properties modelProperties;
68 private String argLine;
69 private Map<String, String> environmentVariables;
70 private boolean debug;
71 private int forkCount;
72 private boolean reuseForks;
73 private Platform pluginPlatform;
74 private ConsoleLogger log;
75
76 @Before
77 public void setup()
78 {
79 booterClasspath = new Classpath( singleton( "provider.jar" ) );
80 tempDirectory = new File( "target/surefire" );
81 debugLine = "";
82 workingDirectory = new File( "." );
83 modelProperties = new Properties();
84 argLine = null;
85 environmentVariables = new HashMap<String, String>();
86 debug = true;
87 forkCount = 2;
88 reuseForks = true;
89 pluginPlatform = new Platform();
90 log = mock( ConsoleLogger.class );
91 }
92
93 @Test
94 public void shouldBeNullArgLine() throws Exception
95 {
96 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
97 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
98 pluginPlatform, log )
99 {
100
101 @Override
102 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
103 @Nonnull String booterThatHasMainMethod,
104 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
105 {
106
107 }
108 };
109
110 DefaultForkConfiguration mockedConfig = spy( config );
111 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
112 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
113 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "" ) );
114 assertThat( newArgLine ).isEmpty();
115 }
116
117 @Test
118 public void shouldBeEmptyArgLine() throws Exception
119 {
120 argLine = "";
121 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
122 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
123 pluginPlatform, log )
124 {
125
126 @Override
127 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
128 @Nonnull String booterThatHasMainMethod,
129 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
130 {
131
132 }
133 };
134
135 DefaultForkConfiguration mockedConfig = spy( config );
136 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
137 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
138 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "" ) );
139 assertThat( newArgLine ).isEmpty();
140 }
141
142 @Test
143 public void shouldBeEmptyArgLineInsteadOfNewLines() throws Exception
144 {
145 argLine = "\n\r";
146 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
147 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
148 pluginPlatform, log )
149 {
150
151 @Override
152 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
153 @Nonnull String booterThatHasMainMethod,
154 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
155 {
156
157 }
158 };
159
160 DefaultForkConfiguration mockedConfig = spy( config );
161 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
162 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
163 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "" ) );
164 assertThat( newArgLine ).isEmpty();
165 }
166
167 @Test
168 public void shouldBeWithoutEscaping() throws Exception
169 {
170 argLine = "-Dfile.encoding=UTF-8";
171 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
172 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
173 pluginPlatform, log )
174 {
175
176 @Override
177 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
178 @Nonnull String booterThatHasMainMethod,
179 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
180 {
181
182 }
183 };
184
185 DefaultForkConfiguration mockedConfig = spy( config );
186 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
187 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
188 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "-Dfile.encoding=UTF-8" ) );
189 assertThat( newArgLine ).isEqualTo( "-Dfile.encoding=UTF-8" );
190 }
191
192 @Test
193 public void shouldBeWithEscaping() throws Exception
194 {
195 modelProperties.put( "encoding", "UTF-8" );
196 argLine = "-Dfile.encoding=@{encoding}";
197 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
198 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
199 pluginPlatform, log )
200 {
201
202 @Override
203 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
204 @Nonnull String booterThatHasMainMethod,
205 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
206 {
207
208 }
209 };
210
211 DefaultForkConfiguration mockedConfig = spy( config );
212 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
213 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
214 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "-Dfile.encoding=UTF-8" ) );
215 assertThat( newArgLine ).isEqualTo( "-Dfile.encoding=UTF-8" );
216 }
217
218 @Test
219 public void shouldBeWhitespaceInsteadOfNewLines() throws Exception
220 {
221 argLine = "a\n\rb";
222 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
223 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
224 pluginPlatform, log )
225 {
226
227 @Override
228 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
229 @Nonnull String booterThatHasMainMethod,
230 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
231 {
232
233 }
234 };
235
236 DefaultForkConfiguration mockedConfig = spy( config );
237 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
238 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
239 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "a b" ) );
240 assertThat( newArgLine ).isEqualTo( "a b" );
241 }
242
243 @Test
244 public void shouldEscapeThreadNumber() throws Exception
245 {
246 argLine = "-Dthread=${surefire.threadNumber}";
247 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
248 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
249 pluginPlatform, log )
250 {
251
252 @Override
253 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
254 @Nonnull String booterThatHasMainMethod,
255 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
256 {
257
258 }
259 };
260
261 DefaultForkConfiguration mockedConfig = spy( config );
262 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
263 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
264 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "-Dthread=" + forkCount ) );
265 assertThat( newArgLine ).isEqualTo( "-Dthread=" + forkCount );
266 }
267
268 @Test
269 public void shouldEscapeForkNumber() throws Exception
270 {
271 argLine = "-Dthread=${surefire.forkNumber}";
272 DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine,
273 workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks,
274 pluginPlatform, log )
275 {
276
277 @Override
278 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli,
279 @Nonnull String booterThatHasMainMethod,
280 @Nonnull StartupConfiguration config ) throws SurefireBooterForkException
281 {
282
283 }
284 };
285
286 DefaultForkConfiguration mockedConfig = spy( config );
287 String newArgLine = invokeMethod( mockedConfig, "newJvmArgLine", new Class[] { int.class }, 2 );
288 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "interpolateArgLineWithPropertyExpressions" );
289 verifyPrivate( mockedConfig, times( 1 ) ).invoke( "extendJvmArgLine", eq( "-Dthread=" + forkCount ) );
290 assertThat( newArgLine ).isEqualTo( "-Dthread=" + forkCount );
291 }
292
293 @Test
294 public void shouldRelocateBooterClassWhenShadefire() throws Exception
295 {
296 ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
297 ClasspathConfiguration cc = new ClasspathConfiguration( true, true );
298 StartupConfiguration conf =
299 new StartupConfiguration( "org.apache.maven.surefire.shadefire.MyProvider", cc, clc, false, false );
300 StartupConfiguration confMock = spy( conf );
301 mockStatic( Relocator.class );
302 when( Relocator.relocate( anyString() ) ).thenCallRealMethod();
303
304 String cls = invokeMethod( DefaultForkConfiguration.class, "findStartClass", confMock );
305
306 verify( confMock, times( 1 ) ).isShadefire();
307 verifyStatic( Relocator.class, times( 1 ) );
308 Relocator.relocate( eq( ForkedBooter.class.getName() ) );
309
310 assertThat( cls ).isEqualTo( "org.apache.maven.surefire.shadefire.booter.ForkedBooter" );
311 assertThat( confMock.isShadefire() ).isTrue();
312 }
313
314 @Test
315 public void shouldNotRelocateBooterClass() throws Exception
316 {
317 ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true );
318 ClasspathConfiguration cc = new ClasspathConfiguration( true, true );
319 StartupConfiguration conf =
320 new StartupConfiguration( "org.apache.maven.surefire.MyProvider", cc, clc, false, false );
321 StartupConfiguration confMock = spy( conf );
322 mockStatic( Relocator.class );
323 when( Relocator.relocate( anyString() ) ).thenCallRealMethod();
324
325 String cls = invokeMethod( DefaultForkConfiguration.class, "findStartClass", confMock );
326
327 verify( confMock, times( 1 ) ).isShadefire();
328 verifyStatic( Relocator.class, never() );
329 Relocator.relocate( eq( ForkedBooter.class.getName() ) );
330
331 assertThat( cls ).isEqualTo( "org.apache.maven.surefire.booter.ForkedBooter" );
332 assertThat( confMock.isShadefire() ).isFalse();
333 }
334 }