blob: d6cc66da005730ee700306f306e52ff4f95a497d [file] [log] [blame]
package org.apache.maven.shared.release.exec;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import static org.mockito.Matchers.endsWith;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
import org.apache.maven.shared.release.ReleaseResult;
import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
import org.apache.maven.shared.release.env.ReleaseEnvironment;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.util.cli.Arg;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.Commandline;
import org.mockito.ArgumentCaptor;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
/**
* Test the forked Maven executor.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class ForkedMavenExecutorTest
extends PlexusTestCase
{
private ForkedMavenExecutor executor;
private SecDispatcher secDispatcher;
@Override
protected void setUp()
throws Exception
{
super.setUp();
executor = (ForkedMavenExecutor) lookup( MavenExecutor.ROLE, "forked-path" );
secDispatcher = (SecDispatcher) lookup( SecDispatcher.ROLE, "mng-4384" );
}
public void testExecution()
throws Exception
{
// prepare
File workingDirectory = getTestFile( "target/working-directory" );
Process mockProcess = mock( Process.class );
when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
when( mockProcess.waitFor() ).thenReturn( 0 );
Commandline commandLineMock = mock( Commandline.class );
when( commandLineMock.execute() ).thenReturn( mockProcess );
Arg valueArgument = mock( Arg.class );
when( commandLineMock.createArg() ).thenReturn( valueArgument );
CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
when( commandLineFactoryMock.createCommandLine( isA( String.class ) /*"mvn"*/ ) ).thenReturn( commandLineMock );
executor.setCommandLineFactory( commandLineFactoryMock );
// execute
executor.executeGoals( workingDirectory, "clean integration-test", false, null, new ReleaseResult() );
// verify
verify( mockProcess ).getInputStream();
verify( mockProcess ).getErrorStream();
verify( mockProcess ).getOutputStream();
verify( mockProcess ).waitFor();
verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
verify( commandLineMock ).execute();
verify( commandLineMock, times( 3 ) ).createArg();
verify( valueArgument ).setValue( "clean" );
verify( valueArgument ).setValue( "integration-test" );
verify( valueArgument ).setValue( "--batch-mode" );
verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
verifyNoMoreInteractions( mockProcess, commandLineFactoryMock, commandLineMock, valueArgument );
}
public void testExecutionWithCustomPomFile()
throws Exception
{
File workingDirectory = getTestFile( "target/working-directory" );
Process mockProcess = mock( Process.class );
when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
when( mockProcess.waitFor() ).thenReturn( 0 );
Commandline commandLineMock = mock( Commandline.class );
when( commandLineMock.execute() ).thenReturn( mockProcess );
Arg argMock = mock( Arg.class );
when( commandLineMock.createArg() ).thenReturn( argMock );
CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
when( commandLineFactoryMock.createCommandLine( isA( String.class ) /* "mvn" */ ) ).thenReturn( commandLineMock );
executor.setCommandLineFactory( commandLineFactoryMock );
// execute
executor.executeGoals( workingDirectory, "clean integration-test", false, null, "my-pom.xml",
new ReleaseResult() );
// verify
verify( mockProcess ).getInputStream();
verify( mockProcess ).getErrorStream();
verify( mockProcess ).getOutputStream();
verify( mockProcess ).waitFor();
verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
verify( commandLineMock ).execute();
verify( commandLineMock, times( 5 ) ).createArg();
verify( argMock ).setValue( "clean" );
verify( argMock ).setValue( "integration-test" );
verify( argMock ).setValue( "-f" );
verify( argMock ).setValue( "my-pom.xml" );
verify( argMock ).setValue( "--batch-mode" );
verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
verifyNoMoreInteractions( mockProcess, commandLineMock, argMock, commandLineFactoryMock );
}
public void testExecutionWithArguments()
throws Exception
{
File workingDirectory = getTestFile( "target/working-directory" );
Process mockProcess = mock( Process.class );
when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
when( mockProcess.waitFor() ).thenReturn( 0 );
Commandline commandLineMock = mock( Commandline.class );
when( commandLineMock.execute() ).thenReturn( mockProcess );
Arg argMock = mock( Arg.class );
when( commandLineMock.createArg() ).thenReturn( argMock );
CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
when( commandLineFactoryMock.createCommandLine( endsWith( "mvn" ) ) ).thenReturn( commandLineMock );
executor.setCommandLineFactory( commandLineFactoryMock );
// execute
String arguments = "-DperformRelease=true -Dmaven.test.skip=true";
executor.executeGoals( workingDirectory, "clean integration-test", false, arguments, new ReleaseResult() );
// verify
verify( mockProcess ).getInputStream();
verify( mockProcess ).getErrorStream();
verify( mockProcess ).getOutputStream();
verify( mockProcess ).waitFor();
verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
verify( commandLineMock ).execute();
verify( commandLineMock, times( 4 ) ).createArg();
verify( argMock ).setValue( "clean" );
verify( argMock ).setValue( "integration-test" );
verify( argMock ).setValue( "--batch-mode" );
verify( argMock ).setLine( "-DperformRelease=true -Dmaven.test.skip=true" );
verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
verifyNoMoreInteractions( mockProcess, commandLineMock, argMock, commandLineFactoryMock );
}
public void testExecutionWithNonZeroExitCode()
throws Exception
{
// prepare
File workingDirectory = getTestFile( "target/working-directory" );
Process mockProcess = mock( Process.class );
when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
when( mockProcess.waitFor() ).thenReturn( 1 );
when( mockProcess.exitValue() ).thenReturn( 1 ); // why was this here in the original test?
Commandline commandLineMock = mock( Commandline.class );
when( commandLineMock.execute() ).thenReturn( mockProcess );
Arg argMock = mock( Arg.class );
when( commandLineMock.createArg() ).thenReturn( argMock );
CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
when( commandLineFactoryMock.createCommandLine( endsWith( "mvn" ) ) ).thenReturn( commandLineMock );
executor.setCommandLineFactory( commandLineFactoryMock );
// execute
try
{
executor.executeGoals( workingDirectory, "clean integration-test", false, null, new ReleaseResult() );
fail( "Should have thrown an exception" );
}
catch ( MavenExecutorException e )
{
assertEquals( "Check exit code", 1, e.getExitCode() );
}
// verify
verify( mockProcess ).getInputStream();
verify( mockProcess ).getErrorStream();
verify( mockProcess ).getOutputStream();
verify( mockProcess ).waitFor();
// verify( mockProcess ).exitValue();
verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
verify( commandLineMock ).execute();
verify( commandLineMock, times( 3 ) ).createArg();
verify( argMock ).setValue( "clean" );
verify( argMock ).setValue( "integration-test" );
verify( argMock ).setValue( "--batch-mode" );
verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
verifyNoMoreInteractions( mockProcess, commandLineMock, argMock, commandLineFactoryMock );
}
public void testExecutionWithCommandLineException()
throws Exception
{
// prepare
File workingDirectory = getTestFile( "target/working-directory" );
Commandline commandLineMock = mock( Commandline.class );
when( commandLineMock.execute() ).thenThrow( new CommandLineException( "..." ) );
Arg argMock = mock( Arg.class );
when ( commandLineMock.createArg() ).thenReturn( argMock );
CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
when( commandLineFactoryMock.createCommandLine( endsWith( "mvn" ) ) ).thenReturn( commandLineMock );
executor.setCommandLineFactory( commandLineFactoryMock );
// execute
try
{
executor.executeGoals( workingDirectory, "clean integration-test", false, null, new ReleaseResult() );
fail( "Should have thrown an exception" );
}
catch ( MavenExecutorException e )
{
assertEquals( "Check cause", CommandLineException.class, e.getCause().getClass() );
}
// verify
verify( commandLineMock ).setWorkingDirectory( workingDirectory.getAbsolutePath() );
verify( commandLineMock ).addEnvironment( "MAVEN_TERMINATE_CMD", "on" );
verify( commandLineMock ).addEnvironment( eq( "M2_HOME" ), isNull( String.class ) );
verify( commandLineMock ).execute();
verify( commandLineMock, times( 3 ) ).createArg();
verify( argMock ).setValue( "clean" );
verify( argMock ).setValue( "integration-test" );
verify( argMock ).setValue( "--batch-mode" );
verify( commandLineFactoryMock ).createCommandLine( endsWith( "mvn" ) );
verifyNoMoreInteractions( commandLineMock, argMock, commandLineFactoryMock );
}
public void testEncryptSettings()
throws Exception
{
// prepare
File workingDirectory = getTestFile( "target/working-directory" );
Process mockProcess = mock( Process.class );
when( mockProcess.getInputStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getErrorStream() ).thenReturn( mock( InputStream.class ) );
when( mockProcess.getOutputStream() ).thenReturn( mock( OutputStream.class ) );
when( mockProcess.waitFor() ).thenReturn( 0 );
Commandline commandLineMock = mock( Commandline.class );
when( commandLineMock.execute() ).thenReturn( mockProcess );
Arg valueArgument = mock( Arg.class );
when( commandLineMock.createArg() ).thenReturn( valueArgument );
CommandLineFactory commandLineFactoryMock = mock( CommandLineFactory.class );
when( commandLineFactoryMock.createCommandLine( isA( String.class ) /* "mvn" */) ).thenReturn( commandLineMock );
executor.setCommandLineFactory( commandLineFactoryMock );
Settings settings = new Settings();
Server server = new Server();
server.setPassphrase( "server_passphrase" );
server.setPassword( "server_password" );
settings.addServer( server );
Proxy proxy = new Proxy();
proxy.setPassword( "proxy_password" );
settings.addProxy( proxy );
ReleaseEnvironment releaseEnvironment = new DefaultReleaseEnvironment();
releaseEnvironment.setSettings( settings );
AbstractMavenExecutor executorSpy = spy( executor );
SettingsXpp3Writer settingsWriter = mock( SettingsXpp3Writer.class );
ArgumentCaptor<Settings> encryptedSettings = ArgumentCaptor.forClass( Settings.class );
when( executorSpy.getSettingsWriter() ).thenReturn( settingsWriter );
executorSpy.executeGoals( workingDirectory, "validate", releaseEnvironment, false, null, new ReleaseResult() );
verify( settingsWriter ).write( isA( Writer.class ), encryptedSettings.capture() );
assertNotSame( settings, encryptedSettings.getValue() );
Server encryptedServer = encryptedSettings.getValue().getServers().get( 0 );
assertEquals( "server_passphrase", secDispatcher.decrypt( encryptedServer.getPassphrase() ) );
assertEquals( "server_password", secDispatcher.decrypt( encryptedServer.getPassword() ) );
Proxy encryptedProxy = encryptedSettings.getValue().getProxies().get( 0 );
assertEquals( "proxy_password", secDispatcher.decrypt( encryptedProxy.getPassword() ) );
File settingsSecurity = new File( System.getProperty( "user.home" ), ".m2/settings-security.xml" );
if ( settingsSecurity.exists() )
{
assertFalse( "server_passphrase".equals( encryptedServer.getPassphrase() ) );
assertFalse( "server_password".equals( encryptedServer.getPassword() ) );
assertFalse( "proxy_password".equals( encryptedProxy.getPassword() ) );
}
}
}