1 package org.apache.maven.shared.release.exec;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static org.mockito.Matchers.endsWith;
23 import static org.mockito.Matchers.eq;
24 import static org.mockito.Matchers.isA;
25 import static org.mockito.Matchers.isNull;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.verifyNoMoreInteractions;
31 import static org.mockito.Mockito.when;
32
33 import java.io.File;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.io.Writer;
37
38 import org.apache.maven.settings.Proxy;
39 import org.apache.maven.settings.Server;
40 import org.apache.maven.settings.Settings;
41 import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
42 import org.apache.maven.shared.release.ReleaseResult;
43 import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
44 import org.apache.maven.shared.release.env.ReleaseEnvironment;
45 import org.codehaus.plexus.PlexusTestCase;
46 import org.codehaus.plexus.util.cli.Arg;
47 import org.codehaus.plexus.util.cli.CommandLineException;
48 import org.codehaus.plexus.util.cli.Commandline;
49 import org.mockito.ArgumentCaptor;
50 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
51
52
53
54
55
56
57 public class ForkedMavenExecutorTest
58 extends PlexusTestCase
59 {
60 private ForkedMavenExecutor executor;
61
62 private SecDispatcher secDispatcher;
63
64 protected void setUp()
65 throws Exception
66 {
67 super.setUp();
68
69 executor = (ForkedMavenExecutor) lookup( MavenExecutor.ROLE, "forked-path" );
70
71 secDispatcher = (SecDispatcher) lookup( SecDispatcher.ROLE, "mng-4384" );
72 }
73
74 public void testExecution()
75 throws Exception
76 {
77
78 File workingDirectory = getTestFile( "target/working-directory" );
79 Process mockProcess = mock( Process.class );
80 when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
81 when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
82 when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
83 when( mockProcess.waitFor() ).thenReturn( 0 );
84
85 Commandline commandLineMock = mock( Commandline.class );
86 when( commandLineMock.execute() ).thenReturn( mockProcess );
87
88 Arg valueArgument = mock( Arg.class );
89 when( commandLineMock.createArg() ).thenReturn( valueArgument );
90
91 CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
92 when( commandLineFactoryMock.createCommandLine( isA( String.class ) ) ).thenReturn( commandLineMock );
93
94 executor.setCommandLineFactory( commandLineFactoryMock );
95
96
97 executor.executeGoals( workingDirectory, "clean integration-test", false, null, new ReleaseResult() );
98
99
100 verify( mockProcess ).getInputStream();
101 verify( mockProcess ).getErrorStream();
102 verify( mockProcess ).getOutputStream();
103 verify( mockProcess ).waitFor();
104 verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
105 verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
106 verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
107 verify( commandLineMock ).execute();
108 verify( commandLineMock, times( 4 ) ).createArg();
109 verify( valueArgument ).setValue( "clean" );
110 verify( valueArgument ).setValue( "integration-test" );
111 verify( valueArgument ).setValue( "--no-plugin-updates" );
112 verify( valueArgument ).setValue( "--batch-mode" );
113 verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
114
115 verifyNoMoreInteractions( mockProcess, commandLineFactoryMock, commandLineMock, valueArgument );
116 }
117
118 public void testExecutionWithCustomPomFile()
119 throws Exception
120 {
121 File workingDirectory = getTestFile( "target/working-directory" );
122 Process mockProcess = mock( Process.class );
123 when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
124 when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
125 when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
126 when( mockProcess.waitFor() ).thenReturn( 0 );
127
128 Commandline commandLineMock = mock( Commandline.class );
129 when( commandLineMock.execute() ).thenReturn( mockProcess );
130
131 Arg argMock = mock( Arg.class );
132 when( commandLineMock.createArg() ).thenReturn( argMock );
133
134 CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
135 when( commandLineFactoryMock.createCommandLine( isA( String.class ) ) ).thenReturn( commandLineMock );
136
137 executor.setCommandLineFactory( commandLineFactoryMock );
138
139
140 executor.executeGoals( workingDirectory, "clean integration-test", false, null, "my-pom.xml",
141 new ReleaseResult() );
142
143 verify( mockProcess ).getInputStream();
144 verify( mockProcess ).getErrorStream();
145 verify( mockProcess ).getOutputStream();
146 verify( mockProcess ).waitFor();
147 verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
148 verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
149 verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
150 verify( commandLineMock ).execute();
151 verify( commandLineMock, times( 6 ) ).createArg();
152 verify( argMock ).setValue( "clean" );
153 verify( argMock ).setValue( "integration-test" );
154 verify( argMock ).setValue( "-f" );
155 verify( argMock ).setValue( "my-pom.xml" );
156 verify( argMock ).setValue( "--no-plugin-updates" );
157 verify( argMock ).setValue( "--batch-mode" );
158 verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
159
160 verifyNoMoreInteractions( mockProcess, commandLineMock, argMock, commandLineFactoryMock );
161 }
162
163 public void testExecutionWithArguments()
164 throws Exception
165 {
166 File workingDirectory = getTestFile( "target/working-directory" );
167 Process mockProcess = mock( Process.class );
168 when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
169 when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
170 when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
171 when( mockProcess.waitFor() ).thenReturn( 0 );
172
173 Commandline commandLineMock = mock( Commandline.class );
174 when( commandLineMock.execute() ).thenReturn( mockProcess );
175
176 Arg argMock = mock( Arg.class );
177 when( commandLineMock.createArg() ).thenReturn( argMock );
178
179 CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
180 when( commandLineFactoryMock.createCommandLine( endsWith( "mvn" ) ) ).thenReturn( commandLineMock );
181
182 executor.setCommandLineFactory( commandLineFactoryMock );
183
184
185 String arguments = "-DperformRelease=true -Dmaven.test.skip=true";
186 executor.executeGoals( workingDirectory, "clean integration-test", false, arguments, new ReleaseResult() );
187
188
189 verify( mockProcess ).getInputStream();
190 verify( mockProcess ).getErrorStream();
191 verify( mockProcess ).getOutputStream();
192 verify( mockProcess ).waitFor();
193 verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
194 verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
195 verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
196 verify( commandLineMock ).execute();
197 verify( commandLineMock, times( 5 ) ).createArg();
198 verify( argMock ).setValue( "clean" );
199 verify( argMock ).setValue( "integration-test" );
200 verify( argMock ).setValue( "--no-plugin-updates" );
201 verify( argMock ).setValue( "--batch-mode" );
202 verify( argMock ).setLine( "-DperformRelease=true -Dmaven.test.skip=true" );
203 verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
204
205 verifyNoMoreInteractions( mockProcess, commandLineMock, argMock, commandLineFactoryMock );
206 }
207
208 public void testExecutionWithNonZeroExitCode()
209 throws Exception
210 {
211
212 File workingDirectory = getTestFile( "target/working-directory" );
213 Process mockProcess = mock( Process.class );
214 when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
215 when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
216 when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
217 when( mockProcess.waitFor() ).thenReturn( 1 );
218 when( mockProcess.exitValue() ).thenReturn( 1 );
219
220 Commandline commandLineMock = mock( Commandline.class );
221 when( commandLineMock.execute() ).thenReturn( mockProcess );
222
223 Arg argMock = mock( Arg.class );
224 when( commandLineMock.createArg() ).thenReturn( argMock );
225
226 CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
227 when( commandLineFactoryMock.createCommandLine( endsWith( "mvn" ) ) ).thenReturn( commandLineMock );
228
229 executor.setCommandLineFactory( commandLineFactoryMock );
230
231
232 try
233 {
234 executor.executeGoals( workingDirectory, "clean integration-test", false, null, new ReleaseResult() );
235
236 fail( "Should have thrown an exception" );
237 }
238 catch ( MavenExecutorException e )
239 {
240 assertEquals( "Check exit code", 1, e.getExitCode() );
241 }
242
243
244 verify( mockProcess ).getInputStream();
245 verify( mockProcess ).getErrorStream();
246 verify( mockProcess ).getOutputStream();
247 verify( mockProcess ).waitFor();
248
249 verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
250 verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
251 verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
252 verify( commandLineMock ).execute();
253 verify( commandLineMock, times( 4 ) ).createArg();
254 verify( argMock ).setValue( "clean" );
255 verify( argMock ).setValue( "integration-test" );
256 verify( argMock ).setValue( "--no-plugin-updates" );
257 verify( argMock ).setValue( "--batch-mode" );
258 verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
259
260 verifyNoMoreInteractions( mockProcess, commandLineMock, argMock, commandLineFactoryMock );
261 }
262
263 public void testExecutionWithCommandLineException()
264 throws Exception
265 {
266
267 File workingDirectory = getTestFile( "target/working-directory" );
268
269 Commandline commandLineMock = mock( Commandline.class );
270 when( commandLineMock.execute() ).thenThrow( new CommandLineException( "..." ) );
271
272 Arg argMock = mock( Arg.class );
273 when ( commandLineMock.createArg() ).thenReturn( argMock );
274
275 CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
276 when( commandLineFactoryMock.createCommandLine( endsWith( "mvn" ) ) ).thenReturn( commandLineMock );
277
278 executor.setCommandLineFactory( commandLineFactoryMock );
279
280
281 try
282 {
283 executor.executeGoals( workingDirectory, "clean integration-test", false, null, new ReleaseResult() );
284
285 fail( "Should have thrown an exception" );
286 }
287 catch ( MavenExecutorException e )
288 {
289 assertEquals( "Check cause", CommandLineException.class, e.getCause().getClass() );
290 }
291
292
293 verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
294 verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
295 verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
296 verify( commandLineMock ).execute();
297 verify( commandLineMock, times( 4 ) ).createArg();
298 verify( argMock ).setValue( "clean" );
299 verify( argMock ).setValue( "integration-test" );
300 verify( argMock ).setValue( "--no-plugin-updates" );
301 verify( argMock ).setValue( "--batch-mode" );
302 verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
303
304 verifyNoMoreInteractions( commandLineMock, argMock, commandLineFactoryMock );
305 }
306
307 public void testEncryptSettings()
308 throws Exception
309 {
310
311 File workingDirectory = getTestFile( "target/working-directory" );
312 Process mockProcess = mock( Process.class );
313 when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
314 when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
315 when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
316 when( mockProcess.waitFor() ).thenReturn( 0 );
317
318 Commandline commandLineMock = mock( Commandline.class );
319 when( commandLineMock.execute() ).thenReturn( mockProcess );
320
321 Arg valueArgument = mock( Arg.class );
322 when( commandLineMock.createArg() ).thenReturn( valueArgument );
323
324 CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
325 when( commandLineFactoryMock.createCommandLine( isA( String.class ) ) ).thenReturn( commandLineMock );
326
327 executor.setCommandLineFactory( commandLineFactoryMock );
328
329 Settings settings = new Settings();
330 Server server = new Server();
331 server.setPassphrase( "server_passphrase" );
332 server.setPassword( "server_password" );
333 settings.addServer( server );
334 Proxy proxy = new Proxy();
335 proxy.setPassword( "proxy_password" );
336 settings.addProxy( proxy );
337
338 ReleaseEnvironment releaseEnvironment = new DefaultReleaseEnvironment();
339 releaseEnvironment.setSettings( settings );
340
341 AbstractMavenExecutor executorSpy = spy( executor );
342 SettingsXpp3Writer settingsWriter = mock( SettingsXpp3Writer.class );
343
344 ArgumentCaptor<Settings> encryptedSettings = ArgumentCaptor.forClass( Settings.class );
345
346 when( executorSpy.getSettingsWriter() ).thenReturn( settingsWriter );
347
348 executorSpy.executeGoals( workingDirectory, "validate", releaseEnvironment, false, null, new ReleaseResult() );
349
350 verify( settingsWriter ).write( isA( Writer.class ), encryptedSettings.capture() );
351
352 assertNotSame( settings, encryptedSettings.getValue() );
353
354 Server encryptedServer = encryptedSettings.getValue().getServers().get( 0 );
355 assertEquals( "server_passphrase", secDispatcher.decrypt( encryptedServer.getPassphrase() ) );
356 assertEquals( "server_password", secDispatcher.decrypt( encryptedServer.getPassword() ) );
357
358 Proxy encryptedProxy = encryptedSettings.getValue().getProxies().get( 0 );
359 assertEquals( "proxy_password", secDispatcher.decrypt( encryptedProxy.getPassword() ) );
360
361 File settingsSecurity = new File( System.getProperty( "user.home" ), ".m2/settings-security.xml" );
362 if ( settingsSecurity.exists() )
363 {
364 assertFalse( "server_passphrase".equals( encryptedServer.getPassphrase() ) );
365 assertFalse( "server_password".equals( encryptedServer.getPassword() ) );
366 assertFalse( "proxy_password".equals( encryptedProxy.getPassword() ) );
367 }
368 }
369 }