blob: 6a112e8dbe7660d5482efc008b8dcffcaa696d02 [file] [log] [blame]
package org.apache.maven.lifecycle;
/*
* 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 java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.apache.maven.AbstractCoreMavenComponentTestCase;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.MojoExecutionEvent;
import org.apache.maven.execution.MojoExecutionListener;
import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.execution.ProjectExecutionEvent;
import org.apache.maven.execution.ProjectExecutionListener;
import org.apache.maven.lifecycle.internal.DefaultLifecycleTaskSegmentCalculator;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
import org.apache.maven.lifecycle.internal.LifecycleTask;
import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
import org.apache.maven.lifecycle.internal.TaskSegment;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import javax.inject.Inject;
public class LifecycleExecutorTest
extends AbstractCoreMavenComponentTestCase
{
@Inject
private DefaultLifecycleExecutor lifecycleExecutor;
@Inject
private DefaultLifecycleTaskSegmentCalculator lifeCycleTaskSegmentCalculator;
@Inject
private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
@Inject
private MojoDescriptorCreator mojoDescriptorCreator;
protected String getProjectsDirectory()
{
return "src/test/projects/lifecycle-executor";
}
// -----------------------------------------------------------------------------------------------
// Tests which exercise the lifecycle executor when it is dealing with default lifecycle phases.
// -----------------------------------------------------------------------------------------------
@Test
public void testCalculationOfBuildPlanWithIndividualTaskWherePluginIsSpecifiedInThePom()
throws Exception
{
// We are doing something like "mvn resources:resources" where no version is specified but this
// project we are working on has the version specified in the POM so the version should come from there.
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-basic", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "resources:resources" ) );
assertEquals( 1, executionPlan.size() );
MojoExecution mojoExecution = executionPlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-resources-plugin",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
@Test
public void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanLifecycle()
throws Exception
{
// We are doing something like "mvn clean:clean" where no version is specified but this
// project we are working on has the version specified in the POM so the version should come from there.
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-basic", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "clean" ) );
assertEquals( 1, executionPlan.size() );
MojoExecution mojoExecution = executionPlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-clean-plugin", mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
@Test
public void testCalculationOfBuildPlanWithIndividualTaskOfTheCleanCleanGoal()
throws Exception
{
// We are doing something like "mvn clean:clean" where no version is specified but this
// project we are working on has the version specified in the POM so the version should come from there.
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-basic", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "clean:clean" ) );
assertEquals( 1, executionPlan.size() );
MojoExecution mojoExecution = executionPlan.get( 0 );
assertNotNull( mojoExecution );
assertEquals( "org.apache.maven.plugins",
mojoExecution.getMojoDescriptor().getPluginDescriptor().getGroupId() );
assertEquals( "maven-clean-plugin", mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifactId() );
assertEquals( "0.1", mojoExecution.getMojoDescriptor().getPluginDescriptor().getVersion() );
}
List<MojoExecution> getExecutions( MavenExecutionPlan mavenExecutionPlan )
{
List<MojoExecution> result = new ArrayList<>();
for ( ExecutionPlanItem executionPlanItem : mavenExecutionPlan )
{
result.add( executionPlanItem.getMojoExecution() );
}
return result;
}
// We need to take in multiple lifecycles
public void testCalculationOfBuildPlanTasksOfTheCleanLifecycleAndTheInstallLifecycle()
throws Exception
{
File pom = getProject( "project-with-additional-lifecycle-elements" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-additional-lifecycle-elements", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "clean", "install" ) );
//[01] clean:clean
//[02] resources:resources
//[03] compiler:compile
//[04] it:generate-metadata
//[05] resources:testResources
//[06] compiler:testCompile
//[07] it:generate-test-metadata
//[08] surefire:test
//[09] jar:jar
//[10] install:install
//
assertEquals( 10, executionPlan.size() );
assertEquals( "clean:clean", executionPlan.get( 0 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "resources:resources", executionPlan.get( 1 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:compile", executionPlan.get( 2 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-metadata", executionPlan.get( 3 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "resources:testResources", executionPlan.get( 4 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:testCompile", executionPlan.get( 5 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-test-metadata", executionPlan.get( 6 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "surefire:test", executionPlan.get( 7 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executionPlan.get( 8 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "install:install", executionPlan.get( 9 ).getMojoDescriptor().getFullGoalName() );
}
// We need to take in multiple lifecycles
public void testCalculationOfBuildPlanWithMultipleExecutionsOfModello()
throws Exception
{
File pom = getProject( "project-with-multiple-executions" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-multiple-executions", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0.1", session.getCurrentProject().getVersion() );
MavenExecutionPlan plan = calculateExecutionPlan( session, "clean", "install" );
List<MojoExecution> executions = getExecutions( plan );
//[01] clean:clean
//[02] modello:xpp3-writer
//[03] modello:java
//[04] modello:xpp3-reader
//[05] modello:xpp3-writer
//[06] modello:java
//[07] modello:xpp3-reader
//[08] plugin:descriptor
//[09] resources:resources
//[10] compiler:compile
//[11] resources:testResources
//[12] compiler:testCompile
//[13] surefire:test
//[14] jar:jar
//[15] plugin:addPluginArtifactMetadata
//[16] install:install
//
assertEquals( 16, executions.size() );
assertEquals( "clean:clean", executions.get( 0 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:xpp3-writer", executions.get( 1 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:java", executions.get( 2 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:xpp3-reader", executions.get( 3 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:xpp3-writer", executions.get( 4 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:java", executions.get( 5 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:xpp3-reader", executions.get( 6 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "resources:resources", executions.get( 7 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:compile", executions.get( 8 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "plugin:descriptor", executions.get( 9 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "resources:testResources", executions.get( 10 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:testCompile", executions.get( 11 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "surefire:test", executions.get( 12 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executions.get( 13 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "plugin:addPluginArtifactMetadata", executions.get( 14 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "install:install", executions.get( 15 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "src/main/mdo/remote-resources.mdo",
new MojoExecutionXPathContainer( executions.get( 1 ) ).getValue(
"configuration/models[1]/model" ) );
assertEquals( "src/main/mdo/supplemental-model.mdo",
new MojoExecutionXPathContainer( executions.get( 4 ) ).getValue(
"configuration/models[1]/model" ) );
}
@Test
public void testLifecycleQueryingUsingADefaultLifecyclePhase()
throws Exception
{
File pom = getProject( "project-with-additional-lifecycle-elements" );
MavenSession session = createMavenSession( pom );
assertEquals( "project-with-additional-lifecycle-elements", session.getCurrentProject().getArtifactId() );
assertEquals( "1.0", session.getCurrentProject().getVersion() );
List<MojoExecution> executionPlan = getExecutions( calculateExecutionPlan( session, "package" ) );
//[01] resources:resources
//[02] compiler:compile
//[03] it:generate-metadata
//[04] resources:testResources
//[05] compiler:testCompile
//[06] plexus-component-metadata:generate-test-metadata
//[07] surefire:test
//[08] jar:jar
//
assertEquals( 8, executionPlan.size() );
assertEquals( "resources:resources", executionPlan.get( 0 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:compile", executionPlan.get( 1 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-metadata", executionPlan.get( 2 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "resources:testResources", executionPlan.get( 3 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "compiler:testCompile", executionPlan.get( 4 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "it:generate-test-metadata", executionPlan.get( 5 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "surefire:test", executionPlan.get( 6 ).getMojoDescriptor().getFullGoalName() );
assertEquals( "jar:jar", executionPlan.get( 7 ).getMojoDescriptor().getFullGoalName() );
}
@Test
public void testLifecyclePluginsRetrievalForDefaultLifecycle()
throws Exception
{
List<Plugin> plugins =
new ArrayList<>( lifecycleExecutor.getPluginsBoundByDefaultToAllLifecycles( "jar" ) );
assertThat( plugins.toString(), plugins, hasSize( 9 ) );
}
@Test
public void testPluginConfigurationCreation()
throws Exception
{
File pom = getProject( "project-with-additional-lifecycle-elements" );
MavenSession session = createMavenSession( pom );
MojoDescriptor mojoDescriptor =
mojoDescriptorCreator.getMojoDescriptor( "org.apache.maven.its.plugins:maven-it-plugin:0.1:java", session,
session.getCurrentProject() );
Xpp3Dom dom = MojoDescriptorCreator.convert( mojoDescriptor );
System.out.println( dom );
}
MavenExecutionPlan calculateExecutionPlan( MavenSession session, String... tasks )
throws Exception
{
List<TaskSegment> taskSegments =
lifeCycleTaskSegmentCalculator.calculateTaskSegments( session, Arrays.asList( tasks ) );
TaskSegment mergedSegment = new TaskSegment( false );
for ( TaskSegment taskSegment : taskSegments )
{
mergedSegment.getTasks().addAll( taskSegment.getTasks() );
}
return lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, session.getCurrentProject(),
mergedSegment.getTasks() );
}
@Test
public void testInvalidGoalName()
throws Exception
{
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
MojoNotFoundException e = assertThrows(
MojoNotFoundException.class,
() -> getExecutions( calculateExecutionPlan( session, "resources:" ) ),
"expected a MojoNotFoundException" );
assertEquals( "", e.getGoal() );
e = assertThrows(
MojoNotFoundException.class,
() -> getExecutions( calculateExecutionPlan( session, "org.apache.maven.plugins:maven-resources-plugin:0.1:resources:toomany" ) ),
"expected a MojoNotFoundException" );
assertEquals( "resources:toomany", e.getGoal() );
}
@Test
public void testPluginPrefixRetrieval()
throws Exception
{
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
Plugin plugin = mojoDescriptorCreator.findPluginForPrefix( "resources", session );
assertEquals( "org.apache.maven.plugins", plugin.getGroupId() );
assertEquals( "maven-resources-plugin", plugin.getArtifactId() );
}
// Prefixes
@Test
public void testFindingPluginPrefixforCleanClean()
throws Exception
{
File pom = getProject( "project-basic" );
MavenSession session = createMavenSession( pom );
Plugin plugin = mojoDescriptorCreator.findPluginForPrefix( "clean", session );
assertNotNull( plugin );
}
@Test
public void testSetupMojoExecution()
throws Exception
{
File pom = getProject( "mojo-configuration" );
MavenSession session = createMavenSession( pom );
LifecycleTask task = new LifecycleTask( "generate-sources" );
MavenExecutionPlan executionPlan =
lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, session.getCurrentProject(),
Arrays.asList( (Object) task ), false );
MojoExecution execution = executionPlan.getMojoExecutions().get(0);
assertEquals( "maven-it-plugin", execution.getArtifactId(), execution.toString() );
assertNull(execution.getConfiguration());
lifeCycleExecutionPlanCalculator.setupMojoExecution( session, session.getCurrentProject(), execution,
new HashSet<>() );
assertNotNull(execution.getConfiguration());
assertEquals("1.0", execution.getConfiguration().getChild( "version" ).getAttribute( "default-value" ));
}
@Test
public void testExecutionListeners()
throws Exception
{
final File pom = getProject( "project-basic" );
final MavenSession session = createMavenSession( pom );
session.setProjectDependencyGraph( new ProjectDependencyGraph()
{
@Override
public List<MavenProject> getUpstreamProjects( MavenProject project, boolean transitive )
{
return Collections.emptyList();
}
@Override
public List<MavenProject> getAllProjects()
{
return session.getAllProjects();
}
@Override
public List<MavenProject> getSortedProjects()
{
return Collections.singletonList( session.getCurrentProject() );
}
@Override
public List<MavenProject> getDownstreamProjects( MavenProject project, boolean transitive )
{
return Collections.emptyList();
}
} );
final List<String> log = new ArrayList<>();
MojoExecutionListener mojoListener = new MojoExecutionListener()
{
public void beforeMojoExecution( MojoExecutionEvent event )
throws MojoExecutionException
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNotNull( event.getExecution() );
assertNotNull( event.getMojo() );
assertNull( event.getCause() );
log.add( "beforeMojoExecution " + event.getProject().getArtifactId() + ":"
+ event.getExecution().getExecutionId() );
}
public void afterMojoExecutionSuccess( MojoExecutionEvent event )
throws MojoExecutionException
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNotNull( event.getExecution() );
assertNotNull( event.getMojo() );
assertNull( event.getCause() );
log.add( "afterMojoExecutionSuccess " + event.getProject().getArtifactId() + ":"
+ event.getExecution().getExecutionId() );
}
public void afterExecutionFailure( MojoExecutionEvent event )
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNotNull( event.getExecution() );
assertNotNull( event.getMojo() );
assertNotNull( event.getCause() );
log.add( "afterExecutionFailure " + event.getProject().getArtifactId() + ":"
+ event.getExecution().getExecutionId() );
}
};
ProjectExecutionListener projectListener = new ProjectExecutionListener()
{
public void beforeProjectExecution( ProjectExecutionEvent event )
throws LifecycleExecutionException
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNull( event.getExecutionPlan() );
assertNull( event.getCause() );
log.add( "beforeProjectExecution " + event.getProject().getArtifactId() );
}
public void beforeProjectLifecycleExecution( ProjectExecutionEvent event )
throws LifecycleExecutionException
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNotNull( event.getExecutionPlan() );
assertNull( event.getCause() );
log.add( "beforeProjectLifecycleExecution " + event.getProject().getArtifactId() );
}
public void afterProjectExecutionSuccess( ProjectExecutionEvent event )
throws LifecycleExecutionException
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNotNull( event.getExecutionPlan() );
assertNull( event.getCause() );
log.add( "afterProjectExecutionSuccess " + event.getProject().getArtifactId() );
}
public void afterProjectExecutionFailure( ProjectExecutionEvent event )
{
assertNotNull( event.getSession() );
assertNotNull( event.getProject() );
assertNull( event.getExecutionPlan() );
assertNotNull( event.getCause() );
log.add( "afterProjectExecutionFailure " + event.getProject().getArtifactId() );
}
};
getContainer().lookup( DelegatingProjectExecutionListener.class ).addProjectExecutionListener( projectListener );
getContainer().lookup( DelegatingMojoExecutionListener.class ).addMojoExecutionListener( mojoListener );
try
{
lifecycleExecutor.execute( session );
}
finally
{
getContainer().lookup( DelegatingProjectExecutionListener.class ).removeProjectExecutionListener( projectListener );
getContainer().lookup( DelegatingMojoExecutionListener.class ).removeMojoExecutionListener( mojoListener );
}
List<String> expectedLog = Arrays.asList( "beforeProjectExecution project-basic", //
"beforeProjectLifecycleExecution project-basic", //
"beforeMojoExecution project-basic:default-resources", //
"afterMojoExecutionSuccess project-basic:default-resources", //
"beforeMojoExecution project-basic:default-compile", //
"afterMojoExecutionSuccess project-basic:default-compile", //
"beforeMojoExecution project-basic:default-testResources", //
"afterMojoExecutionSuccess project-basic:default-testResources", //
"beforeMojoExecution project-basic:default-testCompile", //
"afterMojoExecutionSuccess project-basic:default-testCompile", //
"beforeMojoExecution project-basic:default-test", //
"afterMojoExecutionSuccess project-basic:default-test", //
"beforeMojoExecution project-basic:default-jar", //
"afterMojoExecutionSuccess project-basic:default-jar", //
"afterProjectExecutionSuccess project-basic" //
);
assertEventLog( expectedLog, log );
}
private static void assertEventLog( List<String> expectedList, List<String> actualList )
{
assertEquals( toString( expectedList ), toString( actualList ) );
}
private static String toString( List<String> lines )
{
StringBuilder sb = new StringBuilder();
for ( String line : lines )
{
sb.append( line ).append( '\n' );
}
return sb.toString();
}
}