blob: 2c742b4c87307750a7819c787dbe6e7ca32d16c1 [file] [log] [blame]
/*
* 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.
*/
package org.apache.maven.lifecycle;
import javax.inject.Inject;
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.api.xml.XmlNode;
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.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;
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
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
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
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
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
void testLifecyclePluginsRetrievalForDefaultLifecycle() throws Exception {
List<Plugin> plugins = new ArrayList<>(lifecycleExecutor.getPluginsBoundByDefaultToAllLifecycles("jar"));
assertThat(plugins.toString(), plugins, hasSize(9));
}
@Test
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());
XmlNode dom = MojoDescriptorCreator.convert(mojoDescriptor).getDom();
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
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
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
void testFindingPluginPrefixForCleanClean() throws Exception {
File pom = getProject("project-basic");
MavenSession session = createMavenSession(pom);
Plugin plugin = mojoDescriptorCreator.findPluginForPrefix("clean", session);
assertNotNull(plugin);
}
@Test
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
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();
}
}