1 package org.apache.maven.plugin.surefire;
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.execution.MavenSession;
23 import org.apache.maven.plugin.MojoFailureException;
24 import org.apache.maven.surefire.shared.io.FilenameUtils;
25 import org.apache.maven.toolchain.Toolchain;
26 import org.apache.maven.toolchain.ToolchainManager;
27 import org.apache.maven.toolchain.java.DefaultJavaToolChain;
28 import org.codehaus.plexus.logging.Logger;
29 import org.fest.assertions.MapAssert;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.ExpectedException;
33 import org.junit.runner.RunWith;
34 import org.mockito.ArgumentCaptor;
35 import org.powermock.core.classloader.annotations.PowerMockIgnore;
36 import org.powermock.core.classloader.annotations.PrepareForTest;
37 import org.powermock.modules.junit4.PowerMockRunner;
38
39 import java.io.File;
40 import java.nio.file.Path;
41 import java.nio.file.Paths;
42 import java.util.Collections;
43 import java.util.List;
44 import java.util.Map;
45
46 import static java.io.File.separatorChar;
47 import static java.util.Collections.emptyMap;
48 import static java.util.Collections.singletonList;
49 import static java.util.Collections.singletonMap;
50 import static junit.framework.TestCase.assertNull;
51 import static org.apache.maven.surefire.booter.SystemUtils.toJdkHomeFromJre;
52 import static org.fest.assertions.Assertions.assertThat;
53 import static org.hamcrest.CoreMatchers.startsWith;
54 import static org.mockito.Mockito.times;
55 import static org.mockito.Mockito.verify;
56 import static org.powermock.api.mockito.PowerMockito.mock;
57 import static org.powermock.api.mockito.PowerMockito.mockStatic;
58 import static org.powermock.api.mockito.PowerMockito.when;
59 import static org.powermock.reflect.Whitebox.invokeMethod;
60
61
62
63
64 @RunWith( PowerMockRunner.class )
65 @PrepareForTest( {AbstractSurefireMojo.class} )
66 @PowerMockIgnore( {"org.jacoco.agent.rt.*", "com.vladium.emma.rt.*"} )
67 public class AbstractSurefireMojoToolchainsTest
68 {
69 @Rule
70 public final ExpectedException e = ExpectedException.none();
71
72
73
74
75
76 @Test
77 public void shouldCallMaven33xMethodWhenSpecSet() throws Exception
78 {
79 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
80 Toolchain expectedFromMaven33Method = mock( Toolchain.class );
81 MockToolchainManager toolchainManager = new MockToolchainManager( null, null );
82 mojo.setToolchainManager( toolchainManager );
83 mojo.setJdkToolchain( singletonMap( "version", "1.8" ) );
84
85 mockStatic( AbstractSurefireMojo.class );
86 when(
87 AbstractSurefireMojo.class,
88 "getToolchainMaven33x",
89 ToolchainManager.class,
90 toolchainManager,
91 mojo.getSession(), mojo.getJdkToolchain() ).thenReturn( expectedFromMaven33Method );
92 Toolchain actual = invokeMethod( mojo, "getToolchain" );
93 assertThat( actual )
94 .isSameAs( expectedFromMaven33Method );
95 }
96
97
98
99
100
101
102 @Test
103 public void shouldFallthroughToBuildContextWhenNoSpecSet() throws Exception
104 {
105 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
106 Toolchain expectedFromContext = mock( Toolchain.class );
107 Toolchain expectedFromSpec = mock( Toolchain.class );
108 mojo.setToolchainManager( new MockToolchainManager( expectedFromSpec, expectedFromContext ) );
109 Toolchain actual = invokeMethod( mojo, "getToolchain" );
110 assertThat( actual )
111 .isSameAs( expectedFromContext );
112 }
113
114 @Test
115 public void shouldReturnNoToolchainInMaven32() throws Exception
116 {
117 Toolchain toolchain = invokeMethod( AbstractSurefireMojo.class,
118 "getToolchainMaven33x",
119 MockToolchainManagerMaven32.class,
120 new MockToolchainManagerMaven32( null ),
121 mock( MavenSession.class ),
122 emptyMap() );
123 assertNull( toolchain );
124 }
125
126 @Test( expected = MojoFailureException.class )
127 public void shouldThrowMaven33xToolchain() throws Exception
128 {
129 invokeMethod(
130 AbstractSurefireMojo.class,
131 "getToolchainMaven33x",
132 MockToolchainManager.class,
133 new MockToolchainManager( null, null ),
134 mock( MavenSession.class ),
135 emptyMap() );
136 }
137
138 @Test
139 public void shouldGetMaven33xToolchain() throws Exception
140 {
141 Toolchain expected = mock( Toolchain.class );
142 Toolchain actual = invokeMethod(
143 AbstractSurefireMojo.class,
144 "getToolchainMaven33x",
145 MockToolchainManager.class,
146 new MockToolchainManager( expected, null ),
147 mock( MavenSession.class ),
148 emptyMap() );
149
150 assertThat( actual )
151 .isSameAs( expected );
152 }
153
154
155
156
157
158 @Test
159 public void shouldChangeJavaHomeFromToolchain() throws Exception
160 {
161 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
162 DefaultJavaToolChain toolchain = mock( DefaultJavaToolChain.class );
163 when( toolchain.findTool( "java" ) ).thenReturn( "/path/from/toolchain" );
164 when( toolchain.getJavaHome() ).thenReturn( "/some/path" );
165 mojo.setToolchain( toolchain );
166
167 assertThat( mojo.getEnvironmentVariables() ).isEmpty();
168 JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
169 assertThat( mojo.getEnvironmentVariables() ).includes( MapAssert.entry( "JAVA_HOME", "/some/path" ) );
170 assertThat( effectiveJvm.getJvmExecutable().getPath() )
171 .contains( "/path/from/toolchain".replace( '/', separatorChar ) );
172 }
173
174 @Test
175 public void shouldNotChangeJavaHomeFromToolchainIfAlreadySet() throws Exception
176 {
177 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
178 mojo.setEnvironmentVariables( singletonMap( "JAVA_HOME", "/already/set/path" ) );
179
180 DefaultJavaToolChain toolchain = mock( DefaultJavaToolChain.class );
181 when( toolchain.findTool( "java" ) ).thenReturn( "/path/from/toolchain" );
182 when( toolchain.getJavaHome() ).thenReturn( "/some/path" );
183 mojo.setToolchain( toolchain );
184
185 JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
186 assertThat( mojo.getEnvironmentVariables() ).includes( MapAssert.entry( "JAVA_HOME", "/already/set/path" ) );
187 assertThat( effectiveJvm.getJvmExecutable().getPath() )
188 .contains( "/path/from/toolchain".replace( '/', separatorChar ) );
189 }
190
191
192
193
194
195 @Test
196 public void shouldChangeJavaHomeFromJvm() throws Exception
197 {
198 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
199
200 File currentJdkHome = toJdkHomeFromJre();
201 String javaExecutablePath = FilenameUtils.concat(
202 currentJdkHome.getAbsolutePath(), "bin/java" );
203
204 mojo.setJvm( javaExecutablePath );
205
206 assertThat( mojo.getEnvironmentVariables() ).isEmpty();
207 JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
208 assertThat( mojo.getEnvironmentVariables() )
209 .includes( MapAssert.entry( "JAVA_HOME", currentJdkHome.getAbsolutePath() ) );
210 assertThat( effectiveJvm.getJvmExecutable().getPath() ).contains( javaExecutablePath );
211 }
212
213
214
215
216
217 @Test
218 public void shouldNotChangeJavaHomeFromJvmIfAlreadySet() throws Exception
219 {
220 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
221 mojo.setEnvironmentVariables( singletonMap( "JAVA_HOME", "/already/set/path" ) );
222
223 File currentJdkHome = toJdkHomeFromJre();
224 String javaExecutablePath = FilenameUtils.concat( currentJdkHome.getAbsolutePath(), "bin/java" );
225
226 mojo.setJvm( javaExecutablePath );
227
228 JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
229 assertThat( mojo.getEnvironmentVariables() )
230 .includes( MapAssert.entry( "JAVA_HOME", "/already/set/path" ) );
231 assertThat( effectiveJvm.getJvmExecutable().getPath() ).contains( javaExecutablePath );
232 }
233
234 @Test
235 public void withoutJvmAndToolchain() throws Exception
236 {
237 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
238 Logger logger = mock( Logger.class );
239 mojo.setLogger( logger );
240 ArgumentCaptor<String> argument = ArgumentCaptor.forClass( String.class );
241 JdkAttributes effectiveJvm = invokeMethod( mojo, "getEffectiveJvm" );
242
243 assertThat( mojo.getJvm() )
244 .isNull();
245
246 assertThat( mojo.getEnvironmentVariables() )
247 .isEmpty();
248
249 assertThat( effectiveJvm )
250 .isNotNull();
251
252 assertThat( effectiveJvm.getJvmExecutable() )
253 .isNotNull();
254
255 Path javaHome = Paths.get( System.getProperty( "java.home" ) ).normalize();
256 boolean isLocalJvm = effectiveJvm.getJvmExecutable().toPath().normalize().startsWith( javaHome );
257 assertThat( isLocalJvm )
258 .isTrue();
259
260 verify( logger, times( 1 ) )
261 .debug( argument.capture() );
262
263 assertThat( argument.getValue() )
264 .startsWith( "Using JVM: " + System.getProperty( "java.home" ) );
265 }
266
267 @Test
268 public void shouldFailWithWrongJvmExecPath() throws Exception
269 {
270 AbstractSurefireMojoTest.Mojo mojo = new AbstractSurefireMojoTest.Mojo();
271 mojo.setLogger( mock( Logger.class ) );
272 mojo.setJvm( System.getProperty( "user.dir" ) );
273
274 e.expect( MojoFailureException.class );
275 e.expectMessage( startsWith( "Given path does not end with java executor" ) );
276
277 invokeMethod( mojo, "getEffectiveJvm" );
278 }
279
280
281
282
283 public static final class MockToolchainManager extends MockToolchainManagerMaven32
284 {
285 private final Toolchain specToolchain;
286
287 public MockToolchainManager( Toolchain specToolchain, Toolchain buildContextToolchain )
288 {
289 super( buildContextToolchain );
290 this.specToolchain = specToolchain;
291 }
292
293 public List<Toolchain> getToolchains( MavenSession session, String type, Map<String, String> requirements )
294 {
295 return specToolchain == null ? Collections.<Toolchain>emptyList() : singletonList( specToolchain );
296 }
297 }
298
299
300
301
302
303 public static class MockToolchainManagerMaven32 implements ToolchainManager
304 {
305
306 private final Toolchain buildContextToolchain;
307
308 public MockToolchainManagerMaven32( Toolchain buildContextToolchain )
309 {
310 this.buildContextToolchain = buildContextToolchain;
311 }
312
313 @Override
314 public Toolchain getToolchainFromBuildContext( String type, MavenSession context )
315 {
316 return buildContextToolchain;
317 }
318 }
319 }