This is an automated email from the ASF dual-hosted git repository.
slawekjaranowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new 794866cb40 In failed build limit reactor summary to only failed
modules (#12330)
794866cb40 is described below
commit 794866cb40e793b0ef0db67b4a78149c5dfbd4da
Author: Slawomir Jaranowski <[email protected]>
AuthorDate: Sat Jul 11 18:34:31 2026 +0200
In failed build limit reactor summary to only failed modules (#12330)
* In failed build limit reactor summary to only failed modules
When build fail in multimodule project we need scroll many lines to see
whats is wrong
based on: https://github.com/apache/maven/pull/11977
---
.../maven/cli/event/ExecutionEventLogger.java | 72 ++--
.../maven/cli/event/ExecutionEventLoggerTest.java | 227 +++++++++-
.../maven/cling/event/ExecutionEventLogger.java | 72 ++--
.../cling/event/ExecutionEventLoggerTest.java | 460 +++++++++++++++++++++
4 files changed, 764 insertions(+), 67 deletions(-)
diff --git
a/compat/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java
b/compat/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java
index 2aea29d6cb..ead9d732fd 100644
---
a/compat/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java
+++
b/compat/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java
@@ -201,7 +201,37 @@ private void logReactorSummary(MavenSession session) {
StringBuilder buffer = new StringBuilder(128);
+ String skippedMessage = builder().warning("SKIPPED").build();
+ String successMessage = builder().success("SUCCESS").build();
+ String failureMessage = builder().failure("FAILURE").build();
+ String unknownMessage = builder().warning("UNKNOWN").build();
+
+ boolean lastWasSkipped = false;
for (MavenProject project : projects) {
+ BuildSummary buildSummary = result.getBuildSummary(project);
+
+ String statusMessage;
+ boolean shouldSkip = result.hasExceptions();
+ if (buildSummary == null) {
+ statusMessage = skippedMessage;
+ } else if (buildSummary instanceof BuildSuccess) {
+ statusMessage = successMessage;
+ } else if (buildSummary instanceof BuildFailure) {
+ statusMessage = failureMessage;
+ shouldSkip = false;
+ } else {
+ statusMessage = unknownMessage;
+ }
+
+ if (shouldSkip) {
+ lastWasSkipped = true;
+ continue;
+ }
+ if (lastWasSkipped) {
+ logger.info("...");
+ lastWasSkipped = false;
+ }
+
buffer.append(project.getName());
buffer.append(' ');
@@ -217,35 +247,29 @@ private void logReactorSummary(MavenSession session) {
buffer.append(' ');
}
- BuildSummary buildSummary = result.getBuildSummary(project);
-
- if (buildSummary == null) {
- buffer.append(builder().warning("SKIPPED"));
- } else if (buildSummary instanceof BuildSuccess) {
- buffer.append(builder().success("SUCCESS"));
- buffer.append(" [");
- String buildTimeDuration =
formatDuration(buildSummary.getTime());
- int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH -
buildTimeDuration.length();
- if (padSize > 0) {
- buffer.append(chars(' ', padSize));
- }
- buffer.append(buildTimeDuration);
- buffer.append(']');
- } else if (buildSummary instanceof BuildFailure) {
- buffer.append(builder().failure("FAILURE"));
- buffer.append(" [");
- String buildTimeDuration =
formatDuration(buildSummary.getTime());
- int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH -
buildTimeDuration.length();
- if (padSize > 0) {
- buffer.append(chars(' ', padSize));
- }
- buffer.append(buildTimeDuration);
- buffer.append(']');
+ buffer.append(statusMessage);
+ if (buildSummary != null) {
+ formatBuildTime(buffer, buildSummary);
}
logger.info(buffer.toString());
buffer.setLength(0);
}
+
+ if (lastWasSkipped) {
+ logger.info("...");
+ }
+ }
+
+ private void formatBuildTime(StringBuilder buffer, BuildSummary
buildSummary) {
+ buffer.append(" [");
+ String buildTimeDuration = formatDuration(buildSummary.getTime());
+ int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH -
buildTimeDuration.length();
+ if (padSize > 0) {
+ buffer.append(chars(' ', padSize));
+ }
+ buffer.append(buildTimeDuration);
+ buffer.append(']');
}
private void logResult(MavenSession session) {
diff --git
a/compat/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java
b/compat/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java
index 9d9a8f19c0..1f7bd60aa6 100644
---
a/compat/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java
+++
b/compat/maven-embedder/src/test/java/org/apache/maven/cli/event/ExecutionEventLoggerTest.java
@@ -19,33 +19,49 @@
package org.apache.maven.cli.event;
import java.io.File;
+import java.util.Arrays;
import java.util.List;
+import org.apache.maven.execution.BuildFailure;
+import org.apache.maven.execution.BuildSuccess;
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.DefaultMavenExecutionResult;
import org.apache.maven.execution.ExecutionEvent;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
+import org.apache.maven.execution.ProjectDependencyGraph;
import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.apache.maven.jline.MessageUtils;
import org.apache.maven.project.MavenProject;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;
+import org.mockito.MockitoSession;
import org.slf4j.Logger;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@Deprecated
class ExecutionEventLoggerTest {
+ private MockitoSession mockitoSession;
+
private Logger logger;
private ExecutionEventLogger executionEventLogger;
- private JLineMessageBuilderFactory messageBuilderFactory = new
JLineMessageBuilderFactory();
+ private final JLineMessageBuilderFactory messageBuilderFactory = new
JLineMessageBuilderFactory();
@BeforeAll
static void setUp() {
@@ -59,11 +75,17 @@ static void tearDown() {
@BeforeEach
void beforeEach() {
+ mockitoSession = Mockito.mockitoSession().startMocking();
logger = mock(Logger.class);
when(logger.isInfoEnabled()).thenReturn(true);
executionEventLogger = new ExecutionEventLogger(messageBuilderFactory,
logger);
}
+ @AfterEach
+ void afterEach() {
+ mockitoSession.finishMocking();
+ }
+
@Test
void testProjectStarted() {
// prepare
@@ -78,10 +100,7 @@ void testProjectStarted() {
when(project.getFile()).thenReturn(new File(basedir,
"maven-embedder/pom.xml"));
when(event.getProject()).thenReturn(project);
- MavenProject rootProject = mock(MavenProject.class);
- when(rootProject.getBasedir()).thenReturn(basedir);
MavenSession session = mock(MavenSession.class);
- when(session.getTopLevelProject()).thenReturn(rootProject);
when(session.getTopDirectory()).thenReturn(basedir.toPath());
when(event.getSession()).thenReturn(session);
@@ -110,10 +129,8 @@ void testProjectStartedOverflow() {
when(project.getVersion()).thenReturn("3.0.0-SNAPSHOT");
when(event.getProject()).thenReturn(project);
when(project.getFile()).thenReturn(new File(basedir, "pom.xml"));
- when(project.getBasedir()).thenReturn(basedir);
MavenSession session = mock(MavenSession.class);
- when(session.getTopLevelProject()).thenReturn(project);
when(event.getSession()).thenReturn(session);
when(session.getTopDirectory()).thenReturn(basedir.toPath());
@@ -132,9 +149,6 @@ void testProjectStartedOverflow() {
@Test
void testTerminalWidth() {
// prepare
- Logger logger = mock(Logger.class);
- when(logger.isInfoEnabled()).thenReturn(true);
-
ExecutionEvent event = mock(ExecutionEvent.class);
MavenProject project = mock(MavenProject.class);
when(project.getGroupId()).thenReturn("org.apache.maven.plugins.overflow");
@@ -146,25 +160,25 @@ void testTerminalWidth() {
// default width
new ExecutionEventLogger(messageBuilderFactory, logger,
-1).projectStarted(event);
- Mockito.verify(logger).info("----------------------------[
maven-plugin ]----------------------------");
+ verify(logger).info("----------------------------[ maven-plugin
]----------------------------");
// terminal width: 30
new ExecutionEventLogger(messageBuilderFactory, logger,
30).projectStarted(event);
- Mockito.verify(logger).info("------------------[ maven-plugin
]------------------");
+ verify(logger).info("------------------[ maven-plugin
]------------------");
// terminal width: 70
new ExecutionEventLogger(messageBuilderFactory, logger,
70).projectStarted(event);
- Mockito.verify(logger).info("-----------------------[ maven-plugin
]-----------------------");
+ verify(logger).info("-----------------------[ maven-plugin
]-----------------------");
// terminal width: 110
new ExecutionEventLogger(messageBuilderFactory, logger,
110).projectStarted(event);
- Mockito.verify(logger)
+ verify(logger)
.info(
"-------------------------------------------[
maven-plugin ]-------------------------------------------");
// terminal width: 200
new ExecutionEventLogger(messageBuilderFactory, logger,
200).projectStarted(event);
- Mockito.verify(logger)
+ verify(logger)
.info(
"-----------------------------------------------------[ maven-plugin
]-----------------------------------------------------");
}
@@ -172,7 +186,6 @@ void testTerminalWidth() {
@Test
void testProjectStartedNoPom() {
// prepare
- File basedir = new File("").getAbsoluteFile();
ExecutionEvent event = mock(ExecutionEvent.class);
MavenProject project = mock(MavenProject.class);
when(project.getGroupId()).thenReturn("org.apache.maven");
@@ -182,7 +195,6 @@ void testProjectStartedNoPom() {
when(project.getVersion()).thenReturn("1");
when(event.getProject()).thenReturn(project);
when(project.getFile()).thenReturn(null);
- when(project.getBasedir()).thenReturn(basedir);
// execute
executionEventLogger.projectStarted(event);
@@ -258,11 +270,188 @@ void testMultiModuleProjectResumeFromProgress() {
inOrder.verify(logger).info(matches(".*Apache Maven Embedder
3.*\\[3\\/3\\]"));
}
+ @Test
+ void testSessionEndedSingleProject() {
+ // prepare
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD SUCCESS");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ @Test
+ void testSessionEndedSuccessMultimodule() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Maven Project
artifact1");
+ MavenProject project2 = generateMavenProject("Maven Project
artifact2");
+ MavenProject project3 = generateMavenProject("Maven Project
artifact3");
+
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+ executionResult.addBuildSummary(new BuildSuccess(project1, 1000));
+ executionResult.addBuildSummary(new BuildSuccess(project2, 2000));
+ executionResult.addBuildSummary(new BuildSuccess(project3, 3000));
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ ProjectDependencyGraph projectDependencyGraph =
mock(ProjectDependencyGraph.class);
+
when(projectDependencyGraph.getSortedProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+ when(mavenSession.getProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+ when(mavenSession.getTopLevelProject()).thenReturn(project1);
+
when(mavenSession.getProjectDependencyGraph()).thenReturn(projectDependencyGraph);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("Reactor Summary for Maven Project
artifact1 3.5.4-SNAPSHOT:");
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("Maven Project artifact1
............................ SUCCESS [ 1.000 s]");
+ inOrder.verify(logger).info("Maven Project artifact2
............................ SUCCESS [ 2.000 s]");
+ inOrder.verify(logger).info("Maven Project artifact3
............................ SUCCESS [ 3.000 s]");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD SUCCESS");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ @Test
+ void testSessionEndedFailureMultimodule() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Maven Project
artifact1");
+
+ MavenProject project2 = generateMavenProject("Maven Project
artifact2");
+ MavenProject project3 = generateMavenProject("Maven Project
artifact3");
+
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+ executionResult.addBuildSummary(new BuildSuccess(project1, 1000));
+ executionResult.addBuildSummary(new BuildFailure(project2, 2000, new
Exception("Failure")));
+ executionResult.addException(new Exception("Failure"));
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ ProjectDependencyGraph projectDependencyGraph =
mock(ProjectDependencyGraph.class);
+
when(projectDependencyGraph.getSortedProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+ when(mavenSession.getProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+ when(mavenSession.getTopLevelProject()).thenReturn(project1);
+
when(mavenSession.getProjectDependencyGraph()).thenReturn(projectDependencyGraph);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("Reactor Summary for Maven Project
artifact1 3.5.4-SNAPSHOT:");
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("...");
+ inOrder.verify(logger).info("Maven Project artifact2
............................ FAILURE [ 2.000 s]");
+ inOrder.verify(logger).info("...");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD FAILURE");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ @Test
+ void testSessionEndedFailureMultimoduleWithSeparatedFailures() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Maven Project
artifact1");
+ MavenProject project2 = generateMavenProject("Maven Project
artifact2");
+ MavenProject project3 = generateMavenProject("Maven Project
artifact3");
+ MavenProject project4 = generateMavenProject("Maven Project
artifact4");
+ MavenProject project5 = generateMavenProject("Maven Project
artifact5");
+ MavenProject project6 = generateMavenProject("Maven Project
artifact6");
+
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+ executionResult.addBuildSummary(new BuildSuccess(project1, 1000));
+ executionResult.addBuildSummary(new BuildFailure(project2, 2000, new
Exception("Failure 1")));
+ executionResult.addBuildSummary(new BuildSuccess(project3, 3000));
+ executionResult.addBuildSummary(new BuildSuccess(project4, 4000));
+ executionResult.addBuildSummary(new BuildFailure(project5, 5000, new
Exception("Failure 2")));
+ executionResult.addException(new Exception("Failure 1"));
+ executionResult.addException(new Exception("Failure 2"));
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ ProjectDependencyGraph projectDependencyGraph =
mock(ProjectDependencyGraph.class);
+ when(projectDependencyGraph.getSortedProjects())
+ .thenReturn(Arrays.asList(project1, project2, project3,
project4, project5, project6));
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+ when(mavenSession.getProjects())
+ .thenReturn(Arrays.asList(project1, project2, project3,
project4, project5, project6));
+ when(mavenSession.getTopLevelProject()).thenReturn(project1);
+
when(mavenSession.getProjectDependencyGraph()).thenReturn(projectDependencyGraph);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("Reactor Summary for Maven Project
artifact1 3.5.4-SNAPSHOT:");
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("...");
+ inOrder.verify(logger).info("Maven Project artifact2
............................ FAILURE [ 2.000 s]");
+ inOrder.verify(logger).info("...");
+ inOrder.verify(logger).info("Maven Project artifact5
............................ FAILURE [ 5.000 s]");
+ inOrder.verify(logger).info("...");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD FAILURE");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
private static MavenProject generateMavenProject(String projectName) {
MavenProject project = mock(MavenProject.class);
- when(project.getPackaging()).thenReturn("jar");
- when(project.getVersion()).thenReturn("3.5.4-SNAPSHOT");
- when(project.getName()).thenReturn(projectName);
+ lenient().when(project.getPackaging()).thenReturn("jar");
+ lenient().when(project.getVersion()).thenReturn("3.5.4-SNAPSHOT");
+ lenient().when(project.getName()).thenReturn(projectName);
return project;
}
diff --git
a/impl/maven-cli/src/main/java/org/apache/maven/cling/event/ExecutionEventLogger.java
b/impl/maven-cli/src/main/java/org/apache/maven/cling/event/ExecutionEventLogger.java
index 3d506a6050..d85cc71884 100644
---
a/impl/maven-cli/src/main/java/org/apache/maven/cling/event/ExecutionEventLogger.java
+++
b/impl/maven-cli/src/main/java/org/apache/maven/cling/event/ExecutionEventLogger.java
@@ -206,7 +206,37 @@ private void logReactorSummary(MavenSession session) {
StringBuilder buffer = new StringBuilder(128);
+ String skippedMessage = builder().warning("SKIPPED").build();
+ String successMessage = builder().success("SUCCESS").build();
+ String failureMessage = builder().failure("FAILURE").build();
+ String unknownMessage = builder().warning("UNKNOWN").build();
+
+ boolean lastWasSkipped = false;
for (MavenProject project : projects) {
+ BuildSummary buildSummary = result.getBuildSummary(project);
+
+ String statusMessage;
+ boolean shouldSkip = result.hasExceptions();
+ if (buildSummary == null) {
+ statusMessage = skippedMessage;
+ } else if (buildSummary instanceof BuildSuccess) {
+ statusMessage = successMessage;
+ } else if (buildSummary instanceof BuildFailure) {
+ statusMessage = failureMessage;
+ shouldSkip = false;
+ } else {
+ statusMessage = unknownMessage;
+ }
+
+ if (shouldSkip) {
+ lastWasSkipped = true;
+ continue;
+ }
+ if (lastWasSkipped) {
+ logger.info("...");
+ lastWasSkipped = false;
+ }
+
buffer.append(project.getName());
buffer.append(' ');
@@ -222,35 +252,29 @@ private void logReactorSummary(MavenSession session) {
buffer.append(' ');
}
- BuildSummary buildSummary = result.getBuildSummary(project);
-
- if (buildSummary == null) {
- buffer.append(builder().warning("SKIPPED"));
- } else if (buildSummary instanceof BuildSuccess) {
- buffer.append(builder().success("SUCCESS"));
- buffer.append(" [");
- String buildTimeDuration =
formatDuration(buildSummary.getExecTime());
- int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH -
buildTimeDuration.length();
- if (padSize > 0) {
- buffer.append(chars(' ', padSize));
- }
- buffer.append(buildTimeDuration);
- buffer.append(']');
- } else if (buildSummary instanceof BuildFailure) {
- buffer.append(builder().failure("FAILURE"));
- buffer.append(" [");
- String buildTimeDuration =
formatDuration(buildSummary.getExecTime());
- int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH -
buildTimeDuration.length();
- if (padSize > 0) {
- buffer.append(chars(' ', padSize));
- }
- buffer.append(buildTimeDuration);
- buffer.append(']');
+ buffer.append(statusMessage);
+ if (buildSummary != null) {
+ formatBuildTime(buffer, buildSummary);
}
logger.info(buffer.toString());
buffer.setLength(0);
}
+
+ if (lastWasSkipped) {
+ logger.info("...");
+ }
+ }
+
+ private void formatBuildTime(StringBuilder buffer, BuildSummary
buildSummary) {
+ buffer.append(" [");
+ String buildTimeDuration = formatDuration(buildSummary.getExecTime());
+ int padSize = MAX_PADDED_BUILD_TIME_DURATION_LENGTH -
buildTimeDuration.length();
+ if (padSize > 0) {
+ buffer.append(chars(' ', padSize));
+ }
+ buffer.append(buildTimeDuration);
+ buffer.append(']');
}
private void logResult(MavenSession session) {
diff --git
a/impl/maven-cli/src/test/java/org/apache/maven/cling/event/ExecutionEventLoggerTest.java
b/impl/maven-cli/src/test/java/org/apache/maven/cling/event/ExecutionEventLoggerTest.java
new file mode 100644
index 0000000000..8113dc614c
--- /dev/null
+++
b/impl/maven-cli/src/test/java/org/apache/maven/cling/event/ExecutionEventLoggerTest.java
@@ -0,0 +1,460 @@
+/*
+ * 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.cling.event;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.maven.execution.BuildFailure;
+import org.apache.maven.execution.BuildSuccess;
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.DefaultMavenExecutionResult;
+import org.apache.maven.execution.ExecutionEvent;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionResult;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.execution.ProjectDependencyGraph;
+import org.apache.maven.jline.JLineMessageBuilderFactory;
+import org.apache.maven.jline.MessageUtils;
+import org.apache.maven.project.MavenProject;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.slf4j.Logger;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.matches;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class ExecutionEventLoggerTest {
+
+ private MockitoSession mockitoSession;
+
+ private Logger logger;
+ private ExecutionEventLogger executionEventLogger;
+ private final JLineMessageBuilderFactory messageBuilderFactory = new
JLineMessageBuilderFactory();
+
+ @BeforeAll
+ static void setUp() {
+ MessageUtils.setColorEnabled(false);
+ }
+
+ @AfterAll
+ static void tearDown() {
+ MessageUtils.setColorEnabled(true);
+ }
+
+ @BeforeEach
+ void beforeEach() {
+ mockitoSession = Mockito.mockitoSession().startMocking();
+ logger = mock(Logger.class);
+ when(logger.isInfoEnabled()).thenReturn(true);
+ executionEventLogger = new ExecutionEventLogger(messageBuilderFactory,
logger);
+ }
+
+ @AfterEach
+ void afterEach() {
+ mockitoSession.finishMocking();
+ }
+
+ @Test
+ void testProjectStarted() {
+ // prepare
+ File basedir = new File("").getAbsoluteFile();
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ MavenProject project = mock(MavenProject.class);
+ when(project.getGroupId()).thenReturn("org.apache.maven");
+ when(project.getArtifactId()).thenReturn("maven-embedder");
+ when(project.getPackaging()).thenReturn("jar");
+ when(project.getName()).thenReturn("Apache Maven Embedder");
+ when(project.getVersion()).thenReturn("3.5.4-SNAPSHOT");
+ when(project.getFile()).thenReturn(new File(basedir,
"maven-embedder/pom.xml"));
+ when(event.getProject()).thenReturn(project);
+
+ MavenSession session = mock(MavenSession.class);
+ when(session.getTopDirectory()).thenReturn(basedir.toPath());
+ when(event.getSession()).thenReturn(session);
+
+ // execute
+ executionEventLogger.projectStarted(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("------------------<
org.apache.maven:maven-embedder >-------------------");
+ inOrder.verify(logger).info("Building Apache Maven Embedder
3.5.4-SNAPSHOT");
+ inOrder.verify(logger).info(adaptDirSeparator(" from
maven-embedder/pom.xml"));
+ inOrder.verify(logger).info("--------------------------------[ jar
]---------------------------------");
+ }
+
+ @Test
+ void testProjectStartedOverflow() {
+ // prepare
+ File basedir = new File("").getAbsoluteFile();
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ MavenProject project = mock(MavenProject.class);
+
when(project.getGroupId()).thenReturn("org.apache.maven.plugins.overflow");
+
when(project.getArtifactId()).thenReturn("maven-project-info-reports-plugin");
+ when(project.getPackaging()).thenReturn("maven-plugin");
+ when(project.getName()).thenReturn("Apache Maven Project Info Reports
Plugin");
+ when(project.getVersion()).thenReturn("3.0.0-SNAPSHOT");
+ when(event.getProject()).thenReturn(project);
+ when(project.getFile()).thenReturn(new File(basedir, "pom.xml"));
+
+ MavenSession session = mock(MavenSession.class);
+ when(event.getSession()).thenReturn(session);
+ when(session.getTopDirectory()).thenReturn(basedir.toPath());
+
+ // execute
+ executionEventLogger.projectStarted(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("--<
org.apache.maven.plugins.overflow:maven-project-info-reports-plugin >--");
+ inOrder.verify(logger).info("Building Apache Maven Project Info
Reports Plugin 3.0.0-SNAPSHOT");
+ inOrder.verify(logger).info(adaptDirSeparator(" from pom.xml"));
+ inOrder.verify(logger).info("----------------------------[
maven-plugin ]----------------------------");
+ }
+
+ @Test
+ void testTerminalWidth() {
+ // prepare
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ MavenProject project = mock(MavenProject.class);
+
when(project.getGroupId()).thenReturn("org.apache.maven.plugins.overflow");
+
when(project.getArtifactId()).thenReturn("maven-project-info-reports-plugin");
+ when(project.getPackaging()).thenReturn("maven-plugin");
+ when(project.getName()).thenReturn("Apache Maven Project Info Reports
Plugin");
+ when(project.getVersion()).thenReturn("3.0.0-SNAPSHOT");
+ when(event.getProject()).thenReturn(project);
+
+ // default width
+ new ExecutionEventLogger(messageBuilderFactory, logger,
-1).projectStarted(event);
+ verify(logger).info("----------------------------[ maven-plugin
]----------------------------");
+
+ // terminal width: 30
+ new ExecutionEventLogger(messageBuilderFactory, logger,
30).projectStarted(event);
+ verify(logger).info("------------------[ maven-plugin
]------------------");
+
+ // terminal width: 70
+ new ExecutionEventLogger(messageBuilderFactory, logger,
70).projectStarted(event);
+ verify(logger).info("-----------------------[ maven-plugin
]-----------------------");
+
+ // terminal width: 110
+ new ExecutionEventLogger(messageBuilderFactory, logger,
110).projectStarted(event);
+ verify(logger)
+ .info(
+ "-------------------------------------------[
maven-plugin ]-------------------------------------------");
+
+ // terminal width: 200
+ new ExecutionEventLogger(messageBuilderFactory, logger,
200).projectStarted(event);
+ verify(logger)
+ .info(
+
"-----------------------------------------------------[ maven-plugin
]-----------------------------------------------------");
+ }
+
+ @Test
+ void testProjectStartedNoPom() {
+ // prepare
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ MavenProject project = mock(MavenProject.class);
+ when(project.getGroupId()).thenReturn("org.apache.maven");
+ when(project.getArtifactId()).thenReturn("standalone-pom");
+ when(project.getPackaging()).thenReturn("pom");
+ when(project.getName()).thenReturn("Maven Stub Project (No POM)");
+ when(project.getVersion()).thenReturn("1");
+ when(event.getProject()).thenReturn(project);
+ when(project.getFile()).thenReturn(null);
+
+ // execute
+ executionEventLogger.projectStarted(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("------------------<
org.apache.maven:standalone-pom >-------------------");
+ inOrder.verify(logger).info("Building Maven Stub Project (No POM) 1");
+ inOrder.verify(logger).info("--------------------------------[ pom
]---------------------------------");
+ }
+
+ @Test
+ void testMultiModuleProjectProgress() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Apache Maven Embedder
1");
+ MavenProject project2 = generateMavenProject("Apache Maven Embedder
2");
+ MavenProject project3 = generateMavenProject("Apache Maven Embedder
3");
+
+ MavenSession session = mock(MavenSession.class);
+ when(session.getProjects()).thenReturn(List.of(project1, project2,
project3));
+ when(session.getAllProjects()).thenReturn(List.of(project1, project2,
project3));
+
+ ExecutionEvent sessionStartedEvent = mock(ExecutionEvent.class);
+ when(sessionStartedEvent.getSession()).thenReturn(session);
+ ExecutionEvent projectStartedEvent1 = mock(ExecutionEvent.class);
+ when(projectStartedEvent1.getProject()).thenReturn(project1);
+ ExecutionEvent projectStartedEvent2 = mock(ExecutionEvent.class);
+ when(projectStartedEvent2.getProject()).thenReturn(project2);
+ ExecutionEvent projectStartedEvent3 = mock(ExecutionEvent.class);
+ when(projectStartedEvent3.getProject()).thenReturn(project3);
+
+ // execute
+ executionEventLogger.sessionStarted(sessionStartedEvent);
+ executionEventLogger.projectStarted(projectStartedEvent1);
+ executionEventLogger.projectStarted(projectStartedEvent2);
+ executionEventLogger.projectStarted(projectStartedEvent3);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+ inOrder.verify(logger).info(matches(".*Apache Maven Embedder
1.*\\[1\\/3\\]"));
+ inOrder.verify(logger).info(matches(".*Apache Maven Embedder
2.*\\[2\\/3\\]"));
+ inOrder.verify(logger).info(matches(".*Apache Maven Embedder
3.*\\[3\\/3\\]"));
+ }
+
+ @Test
+ void testMultiModuleProjectResumeFromProgress() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Apache Maven Embedder
1");
+ MavenProject project2 = generateMavenProject("Apache Maven Embedder
2");
+ MavenProject project3 = generateMavenProject("Apache Maven Embedder
3");
+
+ MavenSession session = mock(MavenSession.class);
+ when(session.getProjects()).thenReturn(List.of(project2, project3));
+ when(session.getAllProjects()).thenReturn(List.of(project1, project2,
project3));
+
+ ExecutionEvent sessionStartedEvent = mock(ExecutionEvent.class);
+ when(sessionStartedEvent.getSession()).thenReturn(session);
+ ExecutionEvent projectStartedEvent2 = mock(ExecutionEvent.class);
+ when(projectStartedEvent2.getProject()).thenReturn(project2);
+ ExecutionEvent projectStartedEvent3 = mock(ExecutionEvent.class);
+ when(projectStartedEvent3.getProject()).thenReturn(project3);
+
+ // execute
+ executionEventLogger.sessionStarted(sessionStartedEvent);
+ executionEventLogger.projectStarted(projectStartedEvent2);
+ executionEventLogger.projectStarted(projectStartedEvent3);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+ inOrder.verify(logger, never()).info(matches(".*Apache Maven Embedder
1.*\\[1\\/3\\]"));
+ inOrder.verify(logger).info(matches(".*Apache Maven Embedder
2.*\\[2\\/3\\]"));
+ inOrder.verify(logger).info(matches(".*Apache Maven Embedder
3.*\\[3\\/3\\]"));
+ }
+
+ @Test
+ void testSessionEndedSingleProject() {
+ // prepare
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD SUCCESS");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ @Test
+ void testSessionEndedSuccessMultimodule() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Maven Project
artifact1");
+ MavenProject project2 = generateMavenProject("Maven Project
artifact2");
+ MavenProject project3 = generateMavenProject("Maven Project
artifact3");
+
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+ executionResult.addBuildSummary(new BuildSuccess(project1, 1000));
+ executionResult.addBuildSummary(new BuildSuccess(project2, 2000));
+ executionResult.addBuildSummary(new BuildSuccess(project3, 3000));
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ ProjectDependencyGraph projectDependencyGraph =
mock(ProjectDependencyGraph.class);
+
when(projectDependencyGraph.getSortedProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+ when(mavenSession.getProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+ when(mavenSession.getTopLevelProject()).thenReturn(project1);
+
when(mavenSession.getProjectDependencyGraph()).thenReturn(projectDependencyGraph);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("Reactor Summary for Maven Project
artifact1 3.5.4-SNAPSHOT:");
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("Maven Project artifact1
............................ SUCCESS [ 1.000 s]");
+ inOrder.verify(logger).info("Maven Project artifact2
............................ SUCCESS [ 2.000 s]");
+ inOrder.verify(logger).info("Maven Project artifact3
............................ SUCCESS [ 3.000 s]");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD SUCCESS");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ @Test
+ void testSessionEndedFailureMultimodule() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Maven Project
artifact1");
+
+ MavenProject project2 = generateMavenProject("Maven Project
artifact2");
+ MavenProject project3 = generateMavenProject("Maven Project
artifact3");
+
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+ executionResult.addBuildSummary(new BuildSuccess(project1, 1000));
+ executionResult.addBuildSummary(new BuildFailure(project2, 2000, new
Exception("Failure")));
+ executionResult.addException(new Exception("Failure"));
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ ProjectDependencyGraph projectDependencyGraph =
mock(ProjectDependencyGraph.class);
+
when(projectDependencyGraph.getSortedProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+ when(mavenSession.getProjects()).thenReturn(Arrays.asList(project1,
project2, project3));
+ when(mavenSession.getTopLevelProject()).thenReturn(project1);
+
when(mavenSession.getProjectDependencyGraph()).thenReturn(projectDependencyGraph);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("Reactor Summary for Maven Project
artifact1 3.5.4-SNAPSHOT:");
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("...");
+ inOrder.verify(logger).info("Maven Project artifact2
............................ FAILURE [ 2.000 s]");
+ inOrder.verify(logger).info("...");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD FAILURE");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ @Test
+ void testSessionEndedFailureMultimoduleWithSeparatedFailures() {
+ // prepare
+ MavenProject project1 = generateMavenProject("Maven Project
artifact1");
+ MavenProject project2 = generateMavenProject("Maven Project
artifact2");
+ MavenProject project3 = generateMavenProject("Maven Project
artifact3");
+ MavenProject project4 = generateMavenProject("Maven Project
artifact4");
+ MavenProject project5 = generateMavenProject("Maven Project
artifact5");
+ MavenProject project6 = generateMavenProject("Maven Project
artifact6");
+
+ MavenExecutionResult executionResult = new
DefaultMavenExecutionResult();
+ executionResult.addBuildSummary(new BuildSuccess(project1, 1000));
+ executionResult.addBuildSummary(new BuildFailure(project2, 2000, new
Exception("Failure 1")));
+ executionResult.addBuildSummary(new BuildSuccess(project3, 3000));
+ executionResult.addBuildSummary(new BuildSuccess(project4, 4000));
+ executionResult.addBuildSummary(new BuildFailure(project5, 5000, new
Exception("Failure 2")));
+ executionResult.addException(new Exception("Failure 1"));
+ executionResult.addException(new Exception("Failure 2"));
+
+ MavenExecutionRequest executionRequest = new
DefaultMavenExecutionRequest();
+
+ ProjectDependencyGraph projectDependencyGraph =
mock(ProjectDependencyGraph.class);
+ when(projectDependencyGraph.getSortedProjects())
+ .thenReturn(Arrays.asList(project1, project2, project3,
project4, project5, project6));
+
+ MavenSession mavenSession = mock(MavenSession.class);
+ when(mavenSession.getResult()).thenReturn(executionResult);
+ when(mavenSession.getRequest()).thenReturn(executionRequest);
+ when(mavenSession.getProjects())
+ .thenReturn(Arrays.asList(project1, project2, project3,
project4, project5, project6));
+ when(mavenSession.getTopLevelProject()).thenReturn(project1);
+
when(mavenSession.getProjectDependencyGraph()).thenReturn(projectDependencyGraph);
+
+ ExecutionEvent event = mock(ExecutionEvent.class);
+ when(event.getSession()).thenReturn(mavenSession);
+
+ // execute
+ executionEventLogger.sessionEnded(event);
+
+ // verify
+ InOrder inOrder = inOrder(logger);
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("Reactor Summary for Maven Project
artifact1 3.5.4-SNAPSHOT:");
+ inOrder.verify(logger).info("");
+ inOrder.verify(logger).info("...");
+ inOrder.verify(logger).info("Maven Project artifact2
............................ FAILURE [ 2.000 s]");
+ inOrder.verify(logger).info("...");
+ inOrder.verify(logger).info("Maven Project artifact5
............................ FAILURE [ 5.000 s]");
+ inOrder.verify(logger).info("...");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info("BUILD FAILURE");
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ inOrder.verify(logger).info(eq("Total time: {}{}"), anyString(),
anyString());
+ inOrder.verify(logger).info(eq("Finished at: {}"), anyString());
+
inOrder.verify(logger).info("------------------------------------------------------------------------");
+ }
+
+ private static MavenProject generateMavenProject(String projectName) {
+ MavenProject project = mock(MavenProject.class);
+ lenient().when(project.getPackaging()).thenReturn("jar");
+ lenient().when(project.getVersion()).thenReturn("3.5.4-SNAPSHOT");
+ lenient().when(project.getName()).thenReturn(projectName);
+ return project;
+ }
+
+ private static String adaptDirSeparator(String path) {
+ return path.replace('/', File.separatorChar).replace('\\',
File.separatorChar);
+ }
+}