You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2023/02/26 16:59:41 UTC
[maven-surefire] 01/01: Test Indexes and Reporters
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch test-indexes-and-reporters
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit 8b7d32d4f872e48aaa6f32db2245debfc016ff95
Author: tibordigana <ti...@apache.org>
AuthorDate: Sun Feb 26 17:59:29 2023 +0100
Test Indexes and Reporters
---
.../surefire/report/DefaultReporterFactory.java | 2 +
.../plugin/surefire/report/ReportEntryType.java | 20 ++-
.../surefire/report/ReportersAggregator.java | 135 +++++++++++++++++++++
.../surefire/report/StatelessXmlReporter.java | 61 ++++++----
.../plugin/surefire/report/TestMethodCalls.java | 40 ++++++
.../plugin/surefire/report/TestSetRunListener.java | 70 +++++++----
.../plugin/surefire/report/TestStatsProcessor.java | 5 +
.../plugin/surefire/report/WrappedReportEntry.java | 6 +
.../maven/surefire/api/report/ReportEntry.java | 21 ++++
.../surefire/api/report/TestOutputReportEntry.java | 13 ++
.../apache/maven/surefire/api/report/UniqueID.java | 70 +++++++++++
.../api/util/internal/ReportEntryUtils.java | 79 ++++++++++++
.../maven/surefire/extensions/ReportData.java | 96 +++++++++++++++
.../extensions/StatelessReportEventListener.java | 12 +-
.../StatelessTestSetSummaryListener.java | 6 +
.../TestAssumptionFailureOperation.java | 22 ++++
.../testoperations/TestErrorOperation.java | 22 ++++
.../TestExecutionSkippedByUserOperation.java | 22 ++++
.../testoperations/TestFailedOperation.java | 22 ++++
.../extensions/testoperations/TestOperation.java | 15 +++
.../testoperations/TestSetCompletedOperation.java | 22 ++++
.../testoperations/TestSetStartingOperation.java | 22 ++++
.../testoperations/TestSkippedOperation.java | 22 ++++
.../testoperations/TestStartingOperation.java | 22 ++++
.../testoperations/TestSucceededOperation.java | 22 ++++
.../maven/surefire/report/ClassMethodIndexer.java | 11 +-
.../junitplatform/JUnitPlatformProvider.java | 9 +-
.../surefire/junitplatform/RunListenerAdapter.java | 8 +-
28 files changed, 804 insertions(+), 73 deletions(-)
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
index d45ae83cf..7a8a475fb 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java
@@ -291,6 +291,8 @@ public class DefaultReporterFactory
// Merge all the stats for tests from listeners
for ( TestSetRunListener listener : listeners )
{
+ // this method should not be here
+ // it should be centralized in one place in the state machine - processor
for ( TestMethodStats methodStats : listener.getTestMethodStats() )
{
List<TestMethodStats> currentMethodStats =
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportEntryType.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportEntryType.java
index ffdb70653..b785523ef 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportEntryType.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportEntryType.java
@@ -19,13 +19,18 @@ package org.apache.maven.plugin.surefire.report;
* under the License.
*/
+import static java.util.Objects.requireNonNull;
+
/**
- * Type of an entry in the report
+ * Type of entry in the report.
*
*/
public enum ReportEntryType
{
-
+ TEST_SET_STARTING(),
+ TEST_SET_COMPLETED(),
+ TEST_STARTING(),
+ TEST_ASSUMPTION_FAILURE(),
ERROR( "error", "flakyError", "rerunError" ),
FAILURE( "failure", "flakyFailure", "rerunFailure" ),
SKIPPED( "skipped", "", "" ),
@@ -37,6 +42,11 @@ public enum ReportEntryType
private final String rerunXmlTag;
+ ReportEntryType()
+ {
+ this( null, null, null );
+ }
+
ReportEntryType( String xmlTag, String flakyXmlTag, String rerunXmlTag )
{
this.xmlTag = xmlTag;
@@ -46,16 +56,16 @@ public enum ReportEntryType
public String getXmlTag()
{
- return xmlTag;
+ return requireNonNull( xmlTag );
}
public String getFlakyXmlTag()
{
- return flakyXmlTag;
+ return requireNonNull( flakyXmlTag );
}
public String getRerunXmlTag()
{
- return rerunXmlTag;
+ return requireNonNull( rerunXmlTag );
}
}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportersAggregator.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportersAggregator.java
new file mode 100644
index 000000000..90eabe858
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ReportersAggregator.java
@@ -0,0 +1,135 @@
+package org.apache.maven.plugin.surefire.report;
+
+/*
+ * 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 org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
+import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener;
+import org.apache.maven.surefire.extensions.StatelessReportEventListener;
+import org.apache.maven.surefire.extensions.StatelessTestSetSummaryListener;
+import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener;
+import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener;
+
+/**
+ *
+ */
+public final class ReportersAggregator
+{
+ private StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> consoleReporter;
+ private StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> fileReporter;
+ private StatelessReportEventListener<WrappedReportEntry, TestSetStats> simpleXMLReporter;
+ private ConsoleOutputReportEventListener testOutputReceiver;
+ private StatisticsReporter statisticsReporter;
+ private StatelessTestSetSummaryListener testSetSummaryReporter;
+ private boolean trimStackTrace;
+ private boolean isPlainFormat;
+ private boolean briefOrPlainFormat;
+
+ public StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> getConsoleReporter()
+ {
+ return consoleReporter;
+ }
+
+ public void setConsoleReporter(
+ StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> consoleReporter )
+ {
+ this.consoleReporter = consoleReporter;
+ }
+
+ public StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> getFileReporter()
+ {
+ return fileReporter;
+ }
+
+ public void setFileReporter(
+ StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> fileReporter )
+ {
+ this.fileReporter = fileReporter;
+ }
+
+ public StatelessReportEventListener<WrappedReportEntry, TestSetStats> getSimpleXMLReporter()
+ {
+ return simpleXMLReporter;
+ }
+
+ public void setSimpleXMLReporter( StatelessReportEventListener<WrappedReportEntry, TestSetStats> simpleXMLReporter )
+ {
+ this.simpleXMLReporter = simpleXMLReporter;
+ }
+
+ public ConsoleOutputReportEventListener getTestOutputReceiver()
+ {
+ return testOutputReceiver;
+ }
+
+ public void setTestOutputReceiver( ConsoleOutputReportEventListener testOutputReceiver )
+ {
+ this.testOutputReceiver = testOutputReceiver;
+ }
+
+ public StatisticsReporter getStatisticsReporter()
+ {
+ return statisticsReporter;
+ }
+
+ public void setStatisticsReporter( StatisticsReporter statisticsReporter )
+ {
+ this.statisticsReporter = statisticsReporter;
+ }
+
+ public StatelessTestSetSummaryListener getTestSetSummaryReporter()
+ {
+ return testSetSummaryReporter;
+ }
+
+ public void setTestSetSummaryReporter( StatelessTestSetSummaryListener testSetSummaryReporter )
+ {
+ this.testSetSummaryReporter = testSetSummaryReporter;
+ }
+
+ public boolean isTrimStackTrace()
+ {
+ return trimStackTrace;
+ }
+
+ public void setTrimStackTrace( boolean trimStackTrace )
+ {
+ this.trimStackTrace = trimStackTrace;
+ }
+
+ public boolean isPlainFormat()
+ {
+ return isPlainFormat;
+ }
+
+ public void setPlainFormat( boolean plainFormat )
+ {
+ isPlainFormat = plainFormat;
+ }
+
+ public boolean isBriefOrPlainFormat()
+ {
+ return briefOrPlainFormat;
+ }
+
+ public void setBriefOrPlainFormat( boolean briefOrPlainFormat )
+ {
+ this.briefOrPlainFormat = briefOrPlainFormat;
+ }
+}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
index 45f1c5003..007a43be5 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java
@@ -20,6 +20,8 @@ package org.apache.maven.plugin.surefire.report;
*/
import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
+import org.apache.maven.surefire.extensions.ReportData;
+import org.apache.maven.surefire.api.report.UniqueID;
import org.apache.maven.surefire.shared.utils.xml.PrettyPrintXMLWriter;
import org.apache.maven.surefire.shared.utils.xml.XMLWriter;
import org.apache.maven.surefire.extensions.StatelessReportEventListener;
@@ -27,7 +29,6 @@ import org.apache.maven.surefire.api.report.SafeThrowable;
import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -43,6 +44,7 @@ import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentLinkedDeque;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.file.Files.newOutputStream;
import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType;
import static org.apache.maven.plugin.surefire.report.FileReporterUtils.stripIllegalFilenameChars;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED;
@@ -134,10 +136,22 @@ public class StatelessXmlReporter
this.phrasedMethodName = phrasedMethodName;
}
+ @Override
+ public void testSetCompleted( UniqueID sourceId, ReportData testSetStats )
+ {
+ TestMethodCalls methodCalls = new TestMethodCalls();
+
+ testSetStats.filterOperations( sourceId )
+ .forEach( methodCalls::addOperation );
+
+ testSetStats.filterRerunOperations( sourceId )
+ .forEach( methodCalls::addRerunOperation );
+ }
+
@Override
public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStats testSetStats )
{
- Map<String, Map<String, List<WrappedReportEntry>>> classMethodStatistics =
+ Map<UniqueID, Map<UniqueID, List<WrappedReportEntry>>> classMethodStatistics =
arrangeMethodStatistics( testSetReportEntry, testSetStats );
// The Java Language Spec:
@@ -151,9 +165,9 @@ public class StatelessXmlReporter
showProperties( ppw, testSetReportEntry.getSystemProperties() );
- for ( Entry<String, Map<String, List<WrappedReportEntry>>> statistics : classMethodStatistics.entrySet() )
+ for ( Entry<UniqueID, Map<UniqueID, List<WrappedReportEntry>>> statistics : classMethodStatistics.entrySet() )
{
- for ( Entry<String, List<WrappedReportEntry>> thisMethodRuns : statistics.getValue().entrySet() )
+ for ( Entry<UniqueID, List<WrappedReportEntry>> thisMethodRuns : statistics.getValue().entrySet() )
{
serializeTestClass( outputStream, fw, ppw, thisMethodRuns.getValue() );
}
@@ -171,38 +185,33 @@ public class StatelessXmlReporter
}
}
- private Map<String, Map<String, List<WrappedReportEntry>>> arrangeMethodStatistics(
- WrappedReportEntry testSetReportEntry, TestSetStats testSetStats )
+ private Map<UniqueID, Map<UniqueID, List<WrappedReportEntry>>> arrangeMethodStatistics(
+ UniqueID sourceId, TestMethodCalls methodCalls )
{
- Map<String, Map<String, List<WrappedReportEntry>>> classMethodStatistics = new LinkedHashMap<>();
- for ( WrappedReportEntry methodEntry : aggregateCacheFromMultipleReruns( testSetReportEntry, testSetStats ) )
+ Map<UniqueID, TestMethodCalls> methodStatistics = new LinkedHashMap<>();
+
+ for ( WrappedReportEntry methodEntry : methodCalls )
{
- String testClassName = methodEntry.getSourceName();
- Map<String, List<WrappedReportEntry>> stats = classMethodStatistics.get( testClassName );
- if ( stats == null )
- {
- stats = new LinkedHashMap<>();
- classMethodStatistics.put( testClassName, stats );
- }
- String methodName = methodEntry.getName();
- List<WrappedReportEntry> methodRuns = stats.get( methodName );
- if ( methodRuns == null )
- {
- methodRuns = new ArrayList<>();
- stats.put( methodName, methodRuns );
- }
+ UniqueID methodId = methodEntry.getTestRunUniqueId();
+
+ Map<UniqueID, List<WrappedReportEntry>> stats =
+ classMethodStatistics.computeIfAbsent( methodId.toSourceUniqueId(), k -> new LinkedHashMap<>() );
+
+ List<WrappedReportEntry> methodRuns =
+ stats.computeIfAbsent( methodId, k -> new ArrayList<>() );
+
methodRuns.add( methodEntry );
}
return classMethodStatistics;
}
private Deque<WrappedReportEntry> aggregateCacheFromMultipleReruns( WrappedReportEntry testSetReportEntry,
- TestSetStats testSetStats )
+ TestSetStats testSetStats )
{
- String suiteClassName = testSetReportEntry.getSourceName();
+ /*String suiteClassName = testSetReportEntry.getSourceName();
Deque<WrappedReportEntry> methodRunHistory = getAddMethodRunHistoryMap( suiteClassName );
methodRunHistory.addAll( testSetStats.getReportEntries() );
- return methodRunHistory;
+ return methodRunHistory;*/
}
private void serializeTestClass( OutputStream outputStream, OutputStreamWriter fw, XMLWriter ppw,
@@ -364,7 +373,7 @@ public class StatelessXmlReporter
reportFile.delete();
//noinspection ResultOfMethodCallIgnored
reportDir.mkdirs();
- return new BufferedOutputStream( new FileOutputStream( reportFile ), 64 * 1024 );
+ return new BufferedOutputStream( newOutputStream( reportFile.toPath() ), 64 * 1024 );
}
private static OutputStreamWriter getWriter( OutputStream fos )
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestMethodCalls.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestMethodCalls.java
new file mode 100644
index 000000000..4a1c5dcc5
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestMethodCalls.java
@@ -0,0 +1,40 @@
+package org.apache.maven.plugin.surefire.report;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.maven.surefire.api.report.UniqueID;
+import org.apache.maven.surefire.extensions.ReportData;
+import org.apache.maven.surefire.extensions.testoperations.TestOperation;
+
+import static java.util.stream.Collectors.toMap;
+
+final class TestMethodCalls
+{
+ private final ReportData reportData = new ReportData();
+
+ void addOperation( TestOperation<?> op )
+ {
+ reportData.addOperation( op );
+ }
+
+ void addRerunOperation( TestOperation<?> op )
+ {
+ reportData.addRetryOperation( op );
+ }
+
+ Map<UniqueID, ReportData> mapTestStats()
+ {
+ return reportData.getIds()
+ .stream()
+ .collect( toMap(
+ id -> id,
+ id ->
+ {
+ ReportData rep = new ReportData();
+ reportData.filterOperations( id ).forEach( rep::addOperation );
+ reportData.filterRerunOperations( id ).forEach( rep::addRetryOperation );
+ return rep;
+ }, (u, v) -> { throw new IllegalStateException(); }, LinkedHashMap::new ) );
+ }
+}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
index 2884f68a5..8463d8533 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java
@@ -20,25 +20,36 @@ package org.apache.maven.plugin.surefire.report;
*/
import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.RunMode;
import org.apache.maven.surefire.api.report.TestOutputReportEntry;
import org.apache.maven.surefire.api.report.TestReportListener;
import org.apache.maven.surefire.api.report.TestSetReportEntry;
+import org.apache.maven.surefire.extensions.StatelessTestSetSummaryListener;
+import org.apache.maven.surefire.extensions.TestOutputReportOperation;
+import org.apache.maven.surefire.extensions.TestSetReportOperation;
import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener;
+import org.apache.maven.surefire.extensions.TestReportOperation;
import org.apache.maven.surefire.extensions.StatelessReportEventListener;
import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener;
import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener;
+import org.apache.maven.surefire.extensions.testoperations.TestOperation;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
+import static org.apache.maven.surefire.api.report.RunMode.RERUN_TEST_AFTER_FAILURE;
/**
* Reports data for a single test set.
@@ -49,9 +60,8 @@ import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
public class TestSetRunListener
implements TestReportListener<TestOutputReportEntry>
{
- private final Queue<TestMethodStats> testMethodStats = new ConcurrentLinkedQueue<>();
-
- private final TestSetStats detailsForThis;
+ private final Map<Integer, List<TestOperation<?>>> operationsPerSource = new HashMap<>();
+ private final Map<Integer, List<TestOperation<?>>> rerunOperationsPerSource = new HashMap<>();
private final ConsoleOutputReportEventListener testOutputReceiver;
@@ -65,29 +75,20 @@ public class TestSetRunListener
private final StatisticsReporter statisticsReporter;
- private final Object lock;
-
- private Utf8RecodingDeferredFileOutputStream testStdOut = initDeferred( "stdout" );
+ private final StatelessTestSetSummaryListener testSetSummaryReport;
- private Utf8RecodingDeferredFileOutputStream testStdErr = initDeferred( "stderr" );
+ private final Object lock;
- @SuppressWarnings( "checkstyle:parameternumber" )
- public TestSetRunListener( StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats>
- consoleReporter,
- StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats>
- fileReporter,
- StatelessReportEventListener<WrappedReportEntry, TestSetStats> simpleXMLReporter,
- ConsoleOutputReportEventListener testOutputReceiver,
- StatisticsReporter statisticsReporter, boolean trimStackTrace,
- boolean isPlainFormat, boolean briefOrPlainFormat, Object lock )
+ public TestSetRunListener( ReportersAggregator reporters, Object lock )
{
- this.consoleReporter = consoleReporter;
- this.fileReporter = fileReporter;
- this.statisticsReporter = statisticsReporter;
- this.simpleXMLReporter = simpleXMLReporter;
- this.testOutputReceiver = testOutputReceiver;
- this.briefOrPlainFormat = briefOrPlainFormat;
- detailsForThis = new TestSetStats( trimStackTrace, isPlainFormat );
+ consoleReporter = reporters.getConsoleReporter();
+ fileReporter = reporters.getFileReporter();
+ statisticsReporter = reporters.getStatisticsReporter();
+ simpleXMLReporter = reporters.getSimpleXMLReporter();
+ testOutputReceiver = reporters.getTestOutputReceiver();
+ briefOrPlainFormat = reporters.isBriefOrPlainFormat();
+ testSetSummaryReport = reporters.getTestSetSummaryReporter();
+ detailsForThis = new TestSetStats( reporters.isTrimStackTrace(), reporters.isPlainFormat() );
this.lock = lock;
}
@@ -176,6 +177,7 @@ public class TestSetRunListener
{
synchronized ( lock )
{
+ addEntry( reportEntry.getSourceId(), reportEntry.getRunMode(), new TestOutputReportOperation( reportEntry ) );
Utf8RecodingDeferredFileOutputStream stream = reportEntry.isStdOut() ? testStdOut : testStdErr;
stream.write( reportEntry.getLog(), reportEntry.isNewLine() );
testOutputReceiver.writeTestOutput( reportEntry );
@@ -183,13 +185,14 @@ public class TestSetRunListener
}
catch ( IOException e )
{
- throw new RuntimeException( e );
+ throw new UncheckedIOException( e );
}
}
@Override
public void testSetStarting( TestSetReportEntry report )
{
+ addEntry( report.getSourceId(), report.getRunMode(), new TestSetReportOperation( report ) );
detailsForThis.testSetStart();
consoleReporter.testSetStarting( report );
testOutputReceiver.testSetStarting( report );
@@ -204,6 +207,7 @@ public class TestSetRunListener
@Override
public void testSetCompleted( TestSetReportEntry report )
{
+ addEntry( report.getSourceId(), report.getRunMode(), new TestSetReportOperation( report ) );
final WrappedReportEntry wrap = wrapTestSet( report );
final List<String> testResults =
briefOrPlainFormat ? detailsForThis.getTestResults() : Collections.<String>emptyList();
@@ -229,12 +233,14 @@ public class TestSetRunListener
@Override
public void testStarting( ReportEntry report )
{
+ addEntry( report.getSourceId(), report.getRunMode(), new TestReportOperation( report ) );
detailsForThis.testStart();
}
@Override
public void testSucceeded( ReportEntry reportEntry )
{
+ addEntry( reportEntry.getSourceId(), reportEntry.getRunMode(), new TestReportOperation( reportEntry ) );
WrappedReportEntry wrapped = wrap( reportEntry, SUCCESS );
detailsForThis.testSucceeded( wrapped );
statisticsReporter.testSucceeded( reportEntry );
@@ -244,6 +250,7 @@ public class TestSetRunListener
@Override
public void testError( ReportEntry reportEntry )
{
+ addEntry( reportEntry.getSourceId(), reportEntry.getRunMode(), new TestReportOperation( reportEntry ) );
WrappedReportEntry wrapped = wrap( reportEntry, ERROR );
detailsForThis.testError( wrapped );
statisticsReporter.testError( reportEntry );
@@ -253,6 +260,7 @@ public class TestSetRunListener
@Override
public void testFailed( ReportEntry reportEntry )
{
+ addEntry( reportEntry.getSourceId(), reportEntry.getRunMode(), new TestReportOperation( reportEntry ) );
WrappedReportEntry wrapped = wrap( reportEntry, FAILURE );
detailsForThis.testFailure( wrapped );
statisticsReporter.testFailed( reportEntry );
@@ -266,6 +274,7 @@ public class TestSetRunListener
@Override
public void testSkipped( ReportEntry reportEntry )
{
+ addEntry( reportEntry.getSourceId(), reportEntry.getRunMode(), new TestReportOperation( reportEntry ) );
WrappedReportEntry wrapped = wrap( reportEntry, SKIPPED );
detailsForThis.testSkipped( wrapped );
statisticsReporter.testSkipped( reportEntry );
@@ -280,6 +289,7 @@ public class TestSetRunListener
@Override
public void testAssumptionFailure( ReportEntry report )
{
+ addEntry( report.getSourceId(), report.getRunMode(), new TestReportOperation( report ) );
testSkipped( report );
}
@@ -323,6 +333,18 @@ public class TestSetRunListener
return testMethodStats;
}
+ private void addEntry( Integer source, RunMode runMode, TestOperation<?> operation )
+ {
+ Map<Integer, List<TestOperation<?>>> sourceOperations =
+ runMode == RERUN_TEST_AFTER_FAILURE ? rerunOperationsPerSource : operationsPerSource;
+ sourceOperations.compute( source, ( k, v ) ->
+ {
+ List<TestOperation<?>> operations = v == null ? new ArrayList<>() : v;
+ operations.add( operation );
+ return operations;
+ } );
+ }
+
private static String trimTrailingNewLine( final String message )
{
final int e = message == null ? 0 : lineBoundSymbolWidth( message );
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestStatsProcessor.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestStatsProcessor.java
new file mode 100644
index 000000000..1c7ec99da
--- /dev/null
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestStatsProcessor.java
@@ -0,0 +1,5 @@
+package org.apache.maven.plugin.surefire.report;
+
+public class TestStatsProcessor
+{
+}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
index bc2fca0c5..5e360b8eb 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java
@@ -23,6 +23,7 @@ import org.apache.maven.surefire.api.report.ReportEntry;
import org.apache.maven.surefire.api.report.RunMode;
import org.apache.maven.surefire.api.report.StackTraceWriter;
import org.apache.maven.surefire.api.report.TestSetReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
import javax.annotation.Nonnull;
import java.util.Collections;
@@ -239,6 +240,11 @@ public class WrappedReportEntry
return original.getTestRunId();
}
+ public UniqueID getTestRunUniqueId()
+ {
+ return getTestRunId() == null ? null : new UniqueID( getTestRunId() );
+ }
+
@Override
public Map<String, String> getSystemProperties()
{
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/ReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/ReportEntry.java
index ed3fdc5a1..3c2a9b983 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/ReportEntry.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/ReportEntry.java
@@ -21,6 +21,9 @@ package org.apache.maven.surefire.api.report;
import javax.annotation.Nonnull;
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toNameId;
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toSourceId;
+
/**
* Describes a single entry for a test report
*
@@ -41,6 +44,12 @@ public interface ReportEntry
*/
String getSourceText();
+ default Integer getSourceId()
+ {
+ Long id = getTestRunId();
+ return id == null ? null : toSourceId( id );
+ }
+
/**
* The name of the test case
*
@@ -55,6 +64,12 @@ public interface ReportEntry
*/
String getNameText();
+ default Integer getNameId()
+ {
+ Long id = getTestRunId();
+ return id == null ? null : toNameId( id );
+ }
+
/**
* The group/category of the testcase
*
@@ -123,4 +138,10 @@ public interface ReportEntry
* @return id
*/
Long getTestRunId();
+
+ default UniqueID getUniqueId()
+ {
+ Long id = getTestRunId();
+ return id == null ? null : new UniqueID( id );
+ }
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/TestOutputReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/TestOutputReportEntry.java
index 3610f85c2..411956f6b 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/TestOutputReportEntry.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/TestOutputReportEntry.java
@@ -19,6 +19,9 @@ package org.apache.maven.surefire.api.report;
* under the License.
*/
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toNameId;
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toSourceId;
+
/**
* This report entry should be used in {@link TestOutputReceiver#writeTestOutput(OutputReportEntry)}.
*
@@ -118,4 +121,14 @@ public final class TestOutputReportEntry implements OutputReportEntry
{
return new TestOutputReportEntry( log, false, true );
}
+
+ public Integer getSourceId()
+ {
+ return toSourceId( getTestRunId() );
+ }
+
+ public Integer getNameId()
+ {
+ return toNameId( getTestRunId() );
+ }
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/UniqueID.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/UniqueID.java
new file mode 100644
index 000000000..d9d58e1b6
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/UniqueID.java
@@ -0,0 +1,70 @@
+package org.apache.maven.surefire.api.report;
+
+/*
+ * 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.util.Objects;
+
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toSourceId;
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toTestRunId;
+
+/**
+ *
+ */
+public final class UniqueID
+{
+ private final Long id;
+
+ public UniqueID( int sourceId, Integer testId )
+ {
+ this( testId == null ? toTestRunId( sourceId ) : toTestRunId( sourceId, testId ) );
+ }
+
+ public UniqueID( Long id )
+ {
+ this.id = id;
+
+ }
+
+ public UniqueID toSourceUniqueId()
+ {
+ return new UniqueID( id == null ? null : toTestRunId( toSourceId( id ) ) );
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+ UniqueID uniqueID = (UniqueID) o;
+ return Objects.equals( id, uniqueID.id );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash( id );
+ }
+}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/ReportEntryUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/ReportEntryUtils.java
new file mode 100644
index 000000000..423c4af38
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/ReportEntryUtils.java
@@ -0,0 +1,79 @@
+package org.apache.maven.surefire.api.util.internal;
+
+/*
+ * 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.
+ */
+
+/**
+ * Utility class for {@link org.apache.maven.surefire.api.report.ReportEntry}.
+ */
+public final class ReportEntryUtils
+{
+ private ReportEntryUtils()
+ {
+ throw new IllegalStateException( "no instantiable constructor" );
+ }
+
+ /**
+ * @param sourceId class id or source id (parent)
+ * @param testId test child
+ * @return shifts {@code sourceId} to 32-bit MSB of long and encodes {@code testId} to LSB
+ */
+ public static long toTestRunId( int sourceId, int testId )
+ {
+ return toTestRunId( sourceId ) | testId;
+ }
+
+ /**
+ * @param sourceId class id or source id (parent)
+ * @return shifts in 32 bits
+ */
+ public static long toTestRunId( int sourceId )
+ {
+ return ( (long) sourceId ) << 32;
+ }
+
+ /**
+ * @param testRunId encoded 32-bit MSB source and 32-bit LSB name in 64-bit value
+ * @return shifts {@code testRunId} in 32 bits right
+ */
+ public static int toSourceId( long testRunId )
+ {
+ return (int) ( 0x00000000ffffffffL & ( testRunId >>> 32 ) );
+ }
+
+ public static boolean existsSourceId( Long testRunId )
+ {
+ return testRunId != null && toSourceId( testRunId ) != 0;
+ }
+
+ /**
+ *
+ * @param testRunId encoded 32-bit MSB source and 32-bit LSB name in 64-bit value
+ * @return 32-bit LSB of {@code testRunId}
+ */
+ public static int toNameId( long testRunId )
+ {
+ return (int) ( 0x00000000ffffffffL & testRunId );
+ }
+
+ public static boolean existsNameId( Long testRunId )
+ {
+ return testRunId != null && toNameId( testRunId ) != 0;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ReportData.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ReportData.java
new file mode 100644
index 000000000..52f38edc3
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ReportData.java
@@ -0,0 +1,96 @@
+package org.apache.maven.surefire.extensions;
+
+/*
+ * 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.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.surefire.api.report.UniqueID;
+import org.apache.maven.surefire.extensions.testoperations.TestOperation;
+
+import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+
+/**
+ *
+ */
+public final class ReportData
+{
+ private final List<TestOperation<?>> operations = new ArrayList<>();
+ private final List<TestOperation<?>> rerunOperations = new ArrayList<>();
+
+ public void addOperation( TestOperation<?> op )
+ {
+ operations.add( requireNonNull( op ) );
+ }
+
+ public void addRetryOperation( TestOperation<?> op )
+ {
+ rerunOperations.add( requireNonNull( op ) );
+ }
+
+ public Set<UniqueID> getIds()
+ {
+ return operations.stream()
+ .map( TestOperation::getSourceId )
+ .collect( toCollection( LinkedHashSet::new ) );
+ }
+
+ public List<TestOperation<?>> filterOperations( UniqueID sourceId )
+ {
+ return filterBySourceId( sourceId, operations );
+ }
+
+ public List<TestOperation<?>> filterRerunOperations( UniqueID sourceId )
+ {
+ return filterBySourceId( sourceId, rerunOperations );
+ }
+
+ public void removeSourceId( UniqueID sourceId )
+ {
+ removeBySourceId( sourceId, operations.iterator() );
+ removeBySourceId( sourceId, rerunOperations.iterator() );
+ }
+
+ private List<TestOperation<?>> filterBySourceId( UniqueID sourceId, List<TestOperation<?>> sources )
+ {
+ return sources.stream()
+ .filter( op -> op.getSourceId().equals( sourceId ) )
+ .collect( toList() );
+ }
+
+ private void removeBySourceId( UniqueID sourceId, Iterator<TestOperation<?>> it )
+ {
+ for ( TestOperation<?> op; it.hasNext(); )
+ {
+ op = it.next();
+ if ( op.getSourceId().equals( sourceId ) )
+ {
+ it.remove();
+ }
+ }
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java
index 20eda3bdb..4eadc8c71 100644
--- a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java
@@ -19,7 +19,7 @@ package org.apache.maven.surefire.extensions;
* under the License.
*/
-import org.apache.maven.surefire.api.report.TestSetReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
/**
* Creates a report upon handled event "<em>testSetCompleted</em>".
@@ -28,16 +28,12 @@ import org.apache.maven.surefire.api.report.TestSetReportEntry;
*
* author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
* @since 3.0.0-M4
- * @param <R> report entry type, see <em>WrappedReportEntry</em> from module the <em>maven-surefire-common</em>
- * @param <S> test-set statistics, see <em>TestSetStats</em> from module the <em>maven-surefire-common</em>
*/
-public interface StatelessReportEventListener<R extends TestSetReportEntry, S>
+public interface StatelessReportEventListener
{
/**
* The callback is called after the test class has been completed and the state of report is final.
- *
- * @param report <em>WrappedReportEntry</em>
- * @param testSetStats <em>TestSetStats</em>
+ * @param testSetStats <em>StatelessReportData</em>
*/
- void testSetCompleted( R report, S testSetStats );
+ void testSetCompleted( UniqueID sourceId, ReportData testSetStats );
}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestSetSummaryListener.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestSetSummaryListener.java
new file mode 100644
index 000000000..9608440c7
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestSetSummaryListener.java
@@ -0,0 +1,6 @@
+package org.apache.maven.surefire.extensions;
+
+public interface StatelessTestSetSummaryListener
+{
+ void testSetCompleted( );
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestAssumptionFailureOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestAssumptionFailureOperation.java
new file mode 100644
index 000000000..61f9a5f91
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestAssumptionFailureOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestAssumptionFailureOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestAssumptionFailureOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestErrorOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestErrorOperation.java
new file mode 100644
index 000000000..b54e5c741
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestErrorOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestErrorOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestErrorOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestExecutionSkippedByUserOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestExecutionSkippedByUserOperation.java
new file mode 100644
index 000000000..9b51178d7
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestExecutionSkippedByUserOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestExecutionSkippedByUserOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestExecutionSkippedByUserOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestFailedOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestFailedOperation.java
new file mode 100644
index 000000000..971522a34
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestFailedOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestFailedOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestFailedOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestOperation.java
new file mode 100644
index 000000000..d6e43c7d4
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestOperation.java
@@ -0,0 +1,15 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public abstract class TestOperation<T extends ReportEntry>
+{
+ private final long createdAt = System.currentTimeMillis();
+ public abstract UniqueID getSourceId();
+
+ public final long createdAt()
+ {
+ return createdAt;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSetCompletedOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSetCompletedOperation.java
new file mode 100644
index 000000000..333bf21c6
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSetCompletedOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.TestSetReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestSetCompletedOperation extends TestOperation<TestSetReportEntry>
+{
+ private final TestSetReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestSetCompletedOperation( TestSetReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSetStartingOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSetStartingOperation.java
new file mode 100644
index 000000000..00fa1b5d9
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSetStartingOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.TestSetReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestSetStartingOperation extends TestOperation<TestSetReportEntry>
+{
+ private final TestSetReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestSetStartingOperation( TestSetReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSkippedOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSkippedOperation.java
new file mode 100644
index 000000000..36c3d70db
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSkippedOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestSkippedOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestSkippedOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestStartingOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestStartingOperation.java
new file mode 100644
index 000000000..a3250a254
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestStartingOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestStartingOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestStartingOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSucceededOperation.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSucceededOperation.java
new file mode 100644
index 000000000..65f28bc75
--- /dev/null
+++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/testoperations/TestSucceededOperation.java
@@ -0,0 +1,22 @@
+package org.apache.maven.surefire.extensions.testoperations;
+
+import org.apache.maven.surefire.api.report.ReportEntry;
+import org.apache.maven.surefire.api.report.UniqueID;
+
+public final class TestSucceededOperation extends TestOperation<ReportEntry>
+{
+ private final ReportEntry event;
+ private final UniqueID sourceId;
+
+ public TestSucceededOperation( ReportEntry event )
+ {
+ this.event = event;
+ sourceId = event.getUniqueId();
+ }
+
+ @Override
+ public UniqueID getSourceId()
+ {
+ return sourceId;
+ }
+}
diff --git a/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/ClassMethodIndexer.java b/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/ClassMethodIndexer.java
index 8e58d7a4c..d9818e460 100644
--- a/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/ClassMethodIndexer.java
+++ b/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/ClassMethodIndexer.java
@@ -26,6 +26,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Objects.requireNonNull;
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toSourceId;
+import static org.apache.maven.surefire.api.util.internal.ReportEntryUtils.toTestRunId;
/**
* Creates an index for class/method.
@@ -44,10 +46,10 @@ public final class ClassMethodIndexer
return testIdMapping.computeIfAbsent( key, cm ->
{
Long classId = testIdMapping.get( new ClassMethod( requireNonNull( clazz ), null ) );
- long c = classId == null ? ( ( (long) classIndex.getAndIncrement() ) << 32 ) : classId;
+ int c = classId == null ? classIndex.getAndIncrement() : toSourceId( classId );
int m = method == null ? 0 : methodIndex.getAndIncrement();
long id = c | m;
- testLocalMapping.set( id );
+ testLocalMapping.set( toTestRunId( c, m ) );
return id;
} );
}
@@ -61,4 +63,9 @@ public final class ClassMethodIndexer
{
return testLocalMapping.get();
}
+
+ public void removeLocalIndex()
+ {
+ testLocalMapping.remove();
+ }
}
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java
index ad2ec944d..23ddb83ce 100644
--- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java
@@ -180,10 +180,10 @@ public class JUnitPlatformProvider
}
// Rerun failing tests if requested
int count = parameters.getTestRequest().getRerunFailingTestsCount();
- if ( count > 0 && adapter.hasFailingTests() )
+ if ( count > 0 )
{
adapter.setRunMode( RERUN_TEST_AFTER_FAILURE );
- for ( int i = 0; i < count; i++ )
+ for ( int i = 0; i < count && adapter.hasFailingTests(); i++ )
{
try
{
@@ -193,11 +193,6 @@ public class JUnitPlatformProvider
// Reset adapter's recorded failures and invoke the failed tests again
adapter.reset();
launcher.execute( discoveryRequest, adapter );
- // If no tests fail in the rerun, we're done
- if ( !adapter.hasFailingTests() )
- {
- break;
- }
}
finally
{
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
index aeb24576e..14cf13bb7 100644
--- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
@@ -172,6 +172,7 @@ final class RunListenerAdapter
createReportEntry( testIdentifier, null, systemProps(), null, elapsed ) );
}
}
+ classMethodIndexer.removeLocalIndex();
}
runningTestIdentifiersByUniqueId.remove( testIdentifier.getUniqueId() );
@@ -234,9 +235,14 @@ final class RunListenerAdapter
{
methodText = null;
}
+
StackTraceWriter stw =
testExecutionResult == null ? null : toStackTraceWriter( className, methodName, testExecutionResult );
- return new SimpleReportEntry( runMode, classMethodIndexer.indexClassMethod( className, methodName ), className,
+
+ long uniqueId = classMethodIndexer.indexClassMethod(
+ testIdentifier.getParentId().orElse( className ), testIdentifier.getUniqueId() );
+
+ return new SimpleReportEntry( runMode, uniqueId, className,
classText, methodName, methodText, stw, elapsedTime, reason, systemProperties );
}