You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ol...@apache.org on 2025/12/26 09:05:07 UTC
(maven-surefire) branch test-junit-platform-runner-junit4-parallel-stack created (now d1cc77af8)
This is an automated email from the ASF dual-hosted git repository.
olamy pushed a change to branch test-junit-platform-runner-junit4-parallel-stack
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
at d1cc77af8 remove now useless code
This branch includes the following new commits:
new e266e3c74 Bump org.htmlunit:htmlunit from 4.18.0 to 4.19.0 (#3224)
new a41be8995 use stack trace to locate current test class in use
new d1cc77af8 remove now useless code
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(maven-surefire) 01/03: Bump org.htmlunit:htmlunit from 4.18.0 to 4.19.0 (#3224)
Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
olamy pushed a commit to branch test-junit-platform-runner-junit4-parallel-stack
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit e266e3c74ec2e5991e3f4e2aae19d4bdaf1ee3fd
Author: dependabot[bot] <49...@users.noreply.github.com>
AuthorDate: Tue Nov 25 05:59:54 2025 +0100
Bump org.htmlunit:htmlunit from 4.18.0 to 4.19.0 (#3224)
Bumps [org.htmlunit:htmlunit](https://github.com/HtmlUnit/htmlunit) from 4.18.0 to 4.19.0.
- [Release notes](https://github.com/HtmlUnit/htmlunit/releases)
- [Commits](https://github.com/HtmlUnit/htmlunit/compare/4.18.0...4.19.0)
---
updated-dependencies:
- dependency-name: org.htmlunit:htmlunit
dependency-version: 4.19.0
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <su...@github.com>
Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 7ae05daef..26ef3a3de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -207,7 +207,7 @@
<dependency>
<groupId>org.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
- <version>4.18.0</version>
+ <version>4.19.0</version>
</dependency>
<dependency>
<!-- used in the unit tests and maven-shared-utils:3.3.4 -->
(maven-surefire) 02/03: use stack trace to locate current test class in use
Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
olamy pushed a commit to branch test-junit-platform-runner-junit4-parallel-stack
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit a41be8995b4c085e8a7d5ee4ccdb1be35eff5e33
Author: Olivier Lamy <ol...@cloudbees.com>
AuthorDate: Tue Dec 16 22:05:29 2025 +1000
use stack trace to locate current test class in use
Signed-off-by: Olivier Lamy <ol...@cloudbees.com>
---
.../surefire/booterclient/output/ForkClient.java | 13 +--
.../output/ForkedProcessEventNotifier.java | 3 +-
.../ForkedProcessStandardOutErrEventListener.java | 2 +-
.../surefire/report/ConsoleOutputFileReporter.java | 96 ++++++++++++++++++----
.../apache/maven/surefire/stream/EventDecoder.java | 20 +++--
.../booterclient/ForkingRunListenerTest.java | 2 -
.../booterclient/output/ForkClientTest.java | 8 +-
.../output/ThreadedStreamConsumerTest.java | 2 +-
.../extensions/ForkedProcessEventNotifierTest.java | 3 +-
.../maven/surefire/stream/EventDecoderTest.java | 36 ++++----
.../api/event/AbstractStandardStreamEvent.java | 8 +-
.../surefire/api/event/StandardStreamErrEvent.java | 4 +-
.../event/StandardStreamErrWithNewLineEvent.java | 4 +-
.../surefire/api/event/StandardStreamOutEvent.java | 4 +-
.../event/StandardStreamOutWithNewLineEvent.java | 4 +-
.../surefire/api/report/OutputReportEntry.java | 6 ++
.../surefire/api/report/StackTraceProvider.java | 55 +++++++++++++
.../surefire/api/report/TestOutputReportEntry.java | 35 +++++++-
.../surefire/api/stream/AbstractStreamDecoder.java | 72 ++++++++--------
.../surefire/booter/spi/EventChannelEncoder.java | 15 ++--
.../booter/spi/EventChannelEncoderTest.java | 24 +++---
.../surefire/its/JUnit47RedirectOutputIT.java | 3 -
22 files changed, 290 insertions(+), 129 deletions(-)
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
index cecc271c6..4ab96d6da 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java
@@ -201,15 +201,15 @@ public void handle(String key, String value, RunMode runMode, Long testRunId) {
private final class StdOutListener implements ForkedProcessStandardOutErrEventListener {
@Override
- public void handle(String output, boolean newLine, RunMode runMode, Long testRunId) {
- writeTestOutput(output, true, newLine, runMode, testRunId);
+ public void handle(String output, boolean newLine, RunMode runMode, Long testRunId, String stack) {
+ writeTestOutput(output, true, newLine, runMode, testRunId, stack);
}
}
private final class StdErrListener implements ForkedProcessStandardOutErrEventListener {
@Override
- public void handle(String output, boolean newLine, RunMode runMode, Long testRunId) {
- writeTestOutput(output, false, newLine, runMode, testRunId);
+ public void handle(String output, boolean newLine, RunMode runMode, Long testRunId, String stack) {
+ writeTestOutput(output, false, newLine, runMode, testRunId, stack);
}
}
@@ -336,9 +336,10 @@ void dumpToLoFile(String msg) {
util.dumpStreamText(msg, reportsDir, forkNumber);
}
- private void writeTestOutput(String output, boolean isStdout, boolean newLine, RunMode runMode, Long testRunId) {
+ private void writeTestOutput(
+ String output, boolean isStdout, boolean newLine, RunMode runMode, Long testRunId, String stack) {
getConsoleOutputReceiver()
- .writeTestOutput(new TestOutputReportEntry(output, isStdout, newLine, runMode, testRunId));
+ .writeTestOutput(new TestOutputReportEntry(output, isStdout, newLine, runMode, testRunId, stack));
}
public Map<String, String> getTestVmSystemProperties() {
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventNotifier.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventNotifier.java
index a3cedd035..e20131d70 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventNotifier.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventNotifier.java
@@ -178,7 +178,8 @@ public void notifyEvent(Event event) {
standardStreamEvent.getMessage(),
newLine,
standardStreamEvent.getRunMode(),
- standardStreamEvent.getTestRunId());
+ standardStreamEvent.getTestRunId(),
+ standardStreamEvent.getStack());
}
} else if (event.isSysPropCategory()) {
SystemPropertyEvent systemPropertyEvent = (SystemPropertyEvent) event;
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java
index fc966cd95..bff039ff5 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java
@@ -25,5 +25,5 @@
* @since 3.0.0-M4
*/
public interface ForkedProcessStandardOutErrEventListener {
- void handle(String output, boolean newLine, RunMode runMode, Long testRunId);
+ void handle(String output, boolean newLine, RunMode runMode, Long testRunId, String stack);
}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
index 19a11ae77..556c35c18 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
@@ -20,11 +20,13 @@
import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicStampedReference;
import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
@@ -56,6 +58,8 @@ public class ConsoleOutputFileReporter implements TestcycleConsoleOutputReceiver
private final AtomicStampedReference<FilterOutputStream> fileOutputStream =
new AtomicStampedReference<>(null, OPEN);
+ private final Map<String, FilterOutputStream> outputStreams = new ConcurrentHashMap<>();
+
private volatile String reportEntryName;
public ConsoleOutputFileReporter(
@@ -91,26 +95,44 @@ public synchronized void writeTestOutput(TestOutputReportEntry reportEntry) {
// This method is called in single thread T1 per fork JVM (see ThreadedStreamConsumer).
// The close() method is called in main Thread T2.
int[] status = new int[1];
- FilterOutputStream os = fileOutputStream.get(status);
- if (status[0] != CLOSED) {
- if (os == null) {
+ fileOutputStream.get(status);
+ if (status[0] == CLOSED) {
+ return;
+ }
+
+ // Determine the target class name based on stack trace or reportEntryName
+ String targetClassName = extractTestClassFromStack(reportEntry.getStack());
+ if (targetClassName == null) {
+ targetClassName = reportEntryName;
+ }
+ // If still null, use "null" as the file name (for output before any test starts)
+ if (targetClassName == null) {
+ targetClassName = "null";
+ }
+
+ // Get or create output stream for this test class
+ FilterOutputStream os = outputStreams.computeIfAbsent(targetClassName, className -> {
+ try {
if (!reportsDirectory.exists()) {
//noinspection ResultOfMethodCallIgnored
reportsDirectory.mkdirs();
}
- File file = getReportFile(reportsDirectory, reportEntryName, reportNameSuffix, "-output.txt");
- os = new BufferedOutputStream(new FileOutputStream(file), STREAM_BUFFER_SIZE);
- fileOutputStream.set(os, OPEN);
- }
- String output = reportEntry.getLog();
- if (output == null) {
- output = "null";
- }
- Charset charset = Charset.forName(encoding);
- os.write(output.getBytes(charset));
- if (reportEntry.isNewLine()) {
- os.write(NL.getBytes(charset));
+ File file = getReportFile(reportsDirectory, className, reportNameSuffix, "-output.txt");
+ return new BufferedOutputStream(Files.newOutputStream(file.toPath()), STREAM_BUFFER_SIZE);
+ } catch (IOException e) {
+ dumpException(e);
+ throw new UncheckedIOException(e);
}
+ });
+
+ String output = reportEntry.getLog();
+ if (output == null) {
+ output = "null";
+ }
+ Charset charset = Charset.forName(encoding);
+ os.write(output.getBytes(charset));
+ if (reportEntry.isNewLine()) {
+ os.write(NL.getBytes(charset));
}
} catch (IOException e) {
dumpException(e);
@@ -118,6 +140,37 @@ public synchronized void writeTestOutput(TestOutputReportEntry reportEntry) {
}
}
+ /**
+ * Extracts the test class name from the stack trace.
+ * Stack format: className#method;className#method;...
+ * Returns the first class name that looks like a test class.
+ */
+ private String extractTestClassFromStack(String stack) {
+ if (stack == null || stack.isEmpty()) {
+ return null;
+ }
+ // The stack contains entries like "className#method;className#method;..."
+ // We look for the test class which typically is the first entry or an entry with "Test" in the name
+ String[] entries = stack.split(";");
+ for (String entry : entries) {
+ int hashIndex = entry.indexOf('#');
+ if (hashIndex > 0) {
+ String className = entry.substring(0, hashIndex);
+ // Skip JDK classes and known framework classes
+ if (!className.startsWith("java.")
+ && !className.startsWith("sun.")
+ && !className.startsWith("jdk.")
+ && !className.startsWith("org.junit.")
+ && !className.startsWith("junit.")
+ && !className.startsWith("org.apache.maven.surefire.")
+ && !className.startsWith("org.apache.maven.shadefire.")) {
+ return className;
+ }
+ }
+ }
+ return null;
+ }
+
@SuppressWarnings("checkstyle:emptyblock")
private void closeNullReportFile(ReportEntry reportEntry) {
try {
@@ -148,6 +201,17 @@ private void close(boolean closeReattempt) throws IOException {
if (os != null && status[0] == OPEN) {
os.close();
}
+ // Close all output streams in the map
+ for (FilterOutputStream stream : outputStreams.values()) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ dumpException(e);
+ }
+ }
+ if (!closeReattempt) {
+ outputStreams.clear();
+ }
}
}
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/surefire/stream/EventDecoder.java b/maven-surefire-common/src/main/java/org/apache/maven/surefire/stream/EventDecoder.java
index 0bfc1e26b..ba5bd7c45 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/surefire/stream/EventDecoder.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/surefire/stream/EventDecoder.java
@@ -208,7 +208,7 @@ protected final SegmentType[] nextSegmentType(@Nonnull ForkedProcessEventType ev
case BOOTERCODE_STDOUT_NEW_LINE:
case BOOTERCODE_STDERR:
case BOOTERCODE_STDERR_NEW_LINE:
- return EVENT_WITH_RUNMODE_TID_AND_ONE_STRING;
+ return EVENT_WITH_RUNMODE_TID_AND_TWO_STRINGS;
case BOOTERCODE_SYSPROPS:
return EVENT_WITH_RUNMODE_TID_AND_TWO_STRINGS;
case BOOTERCODE_TESTSET_STARTING:
@@ -255,19 +255,21 @@ protected final Event toMessage(@Nonnull ForkedProcessEventType eventType, @Nonn
checkArguments(memento, 1);
return new ConsoleWarningEvent((String) memento.getData().get(0));
case BOOTERCODE_STDOUT:
- checkArguments(memento, 3);
- return new StandardStreamOutEvent(memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2));
+ checkArguments(memento, 4);
+ return new StandardStreamOutEvent(
+ memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2), memento.ofDataAt(3));
case BOOTERCODE_STDOUT_NEW_LINE:
- checkArguments(memento, 3);
+ checkArguments(memento, 4);
return new StandardStreamOutWithNewLineEvent(
- memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2));
+ memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2), memento.ofDataAt(3));
case BOOTERCODE_STDERR:
- checkArguments(memento, 3);
- return new StandardStreamErrEvent(memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2));
+ checkArguments(memento, 4);
+ return new StandardStreamErrEvent(
+ memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2), memento.ofDataAt(3));
case BOOTERCODE_STDERR_NEW_LINE:
- checkArguments(memento, 3);
+ checkArguments(memento, 4);
return new StandardStreamErrWithNewLineEvent(
- memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2));
+ memento.ofDataAt(0), memento.ofDataAt(1), memento.ofDataAt(2), memento.ofDataAt(3));
case BOOTERCODE_SYSPROPS:
checkArguments(memento, 4);
return new SystemPropertyEvent(
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
index d25e9b4ae..4a5c58141 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java
@@ -65,7 +65,6 @@
import static org.apache.maven.surefire.api.util.internal.Channels.newChannel;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
/**
* @author Kristian Rosenvold
@@ -277,7 +276,6 @@ private static List<Event> streamToEvent(byte[] stream) throws Exception {
try (EventConsumerThread t = new EventConsumerThread("t", channel, handler, countdown, arguments)) {
t.start();
countdown.awaitClosed();
- verifyZeroInteractions(logger);
assertThat(arguments.isCalled()).isFalse();
for (int i = 0, size = handler.countEventsInCache(); i < size; i++) {
events.add(handler.pullEvent());
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java
index 4013cb074..b4317e9f0 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java
@@ -384,7 +384,7 @@ public void shouldReceiveStdOut() {
when(factory.createTestReportListener()).thenReturn(receiver);
NotifiableTestStream notifiableTestStream = mock(NotifiableTestStream.class);
ForkClient client = new ForkClient(factory, notifiableTestStream, 0);
- client.handleEvent(new StandardStreamOutEvent(NORMAL_RUN, 1L, "msg"));
+ client.handleEvent(new StandardStreamOutEvent(NORMAL_RUN, 1L, "msg", null));
verifyZeroInteractions(notifiableTestStream);
verify(factory, times(1)).createTestReportListener();
verifyNoMoreInteractions(factory);
@@ -410,7 +410,7 @@ public void shouldReceiveStdOutNewLine() {
when(factory.createTestReportListener()).thenReturn(receiver);
NotifiableTestStream notifiableTestStream = mock(NotifiableTestStream.class);
ForkClient client = new ForkClient(factory, notifiableTestStream, 0);
- client.handleEvent(new StandardStreamOutWithNewLineEvent(NORMAL_RUN, 1L, "msg"));
+ client.handleEvent(new StandardStreamOutWithNewLineEvent(NORMAL_RUN, 1L, "msg", null));
verifyZeroInteractions(notifiableTestStream);
verify(factory, times(1)).createTestReportListener();
verifyNoMoreInteractions(factory);
@@ -436,7 +436,7 @@ public void shouldReceiveStdErr() {
when(factory.createTestReportListener()).thenReturn(receiver);
NotifiableTestStream notifiableTestStream = mock(NotifiableTestStream.class);
ForkClient client = new ForkClient(factory, notifiableTestStream, 0);
- client.handleEvent(new StandardStreamErrEvent(NORMAL_RUN, 1L, "msg"));
+ client.handleEvent(new StandardStreamErrEvent(NORMAL_RUN, 1L, "msg", null));
verifyZeroInteractions(notifiableTestStream);
verify(factory, times(1)).createTestReportListener();
verifyNoMoreInteractions(factory);
@@ -462,7 +462,7 @@ public void shouldReceiveStdErrNewLine() {
when(factory.createTestReportListener()).thenReturn(receiver);
NotifiableTestStream notifiableTestStream = mock(NotifiableTestStream.class);
ForkClient client = new ForkClient(factory, notifiableTestStream, 0);
- client.handleEvent(new StandardStreamErrWithNewLineEvent(NORMAL_RUN, 1L, "msg"));
+ client.handleEvent(new StandardStreamErrWithNewLineEvent(NORMAL_RUN, 1L, "msg", null));
verifyZeroInteractions(notifiableTestStream);
verify(factory, times(1)).createTestReportListener();
verifyNoMoreInteractions(factory);
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumerTest.java
index 1672f5857..12492ffe6 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumerTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumerTest.java
@@ -94,7 +94,7 @@ public void handleEvent(@Nonnull Event event) {
long t1 = System.currentTimeMillis();
- Event event = new StandardStreamOutWithNewLineEvent(NORMAL_RUN, 1L, "");
+ Event event = new StandardStreamOutWithNewLineEvent(NORMAL_RUN, 1L, "", null);
for (int i = 0; i < 5_000_000; i++) {
streamConsumer.handleEvent(event);
}
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/ForkedProcessEventNotifierTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/ForkedProcessEventNotifierTest.java
index 26237831a..2a0cf7802 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/ForkedProcessEventNotifierTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/extensions/ForkedProcessEventNotifierTest.java
@@ -956,7 +956,8 @@ private static class StandardOutErrEventAssertionListener implements ForkedProce
this.newLine = newLine;
}
- public void handle(String output, boolean newLine, RunMode runMode, Long testRunId) {
+ @Override
+ public void handle(String output, boolean newLine, RunMode runMode, Long testRunId, String stack) {
called.set(true);
assertThat(runMode).isEqualTo(this.runMode);
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/stream/EventDecoderTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/stream/EventDecoderTest.java
index a49d7c739..c1659fea9 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/stream/EventDecoderTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/stream/EventDecoderTest.java
@@ -158,24 +158,24 @@ public void shouldMapEventTypeToSegmentType() {
assertThat(segmentTypes).hasSize(3).isEqualTo(new SegmentType[] {STRING_ENCODING, DATA_STRING, END_OF_FRAME});
segmentTypes = decoder.nextSegmentType(BOOTERCODE_STDOUT);
- assertThat(segmentTypes)
- .hasSize(5)
- .isEqualTo(new SegmentType[] {RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, END_OF_FRAME});
+ assertThat(segmentTypes).hasSize(6).isEqualTo(new SegmentType[] {
+ RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, DATA_STRING, END_OF_FRAME
+ });
segmentTypes = decoder.nextSegmentType(ForkedProcessEventType.BOOTERCODE_STDOUT_NEW_LINE);
- assertThat(segmentTypes)
- .hasSize(5)
- .isEqualTo(new SegmentType[] {RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, END_OF_FRAME});
+ assertThat(segmentTypes).hasSize(6).isEqualTo(new SegmentType[] {
+ RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, DATA_STRING, END_OF_FRAME
+ });
segmentTypes = decoder.nextSegmentType(ForkedProcessEventType.BOOTERCODE_STDERR);
- assertThat(segmentTypes)
- .hasSize(5)
- .isEqualTo(new SegmentType[] {RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, END_OF_FRAME});
+ assertThat(segmentTypes).hasSize(6).isEqualTo(new SegmentType[] {
+ RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, DATA_STRING, END_OF_FRAME
+ });
segmentTypes = decoder.nextSegmentType(ForkedProcessEventType.BOOTERCODE_STDERR_NEW_LINE);
- assertThat(segmentTypes)
- .hasSize(5)
- .isEqualTo(new SegmentType[] {RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, END_OF_FRAME});
+ assertThat(segmentTypes).hasSize(6).isEqualTo(new SegmentType[] {
+ RUN_MODE, TEST_RUN_ID, STRING_ENCODING, DATA_STRING, DATA_STRING, END_OF_FRAME
+ });
segmentTypes = decoder.nextSegmentType(BOOTERCODE_SYSPROPS);
assertThat(segmentTypes).hasSize(6).isEqualTo(new SegmentType[] {
@@ -397,36 +397,40 @@ public void shouldCreateEvent() throws Exception {
assertThat(((ConsoleDebugEvent) event).getMessage()).isNull();
memento = decoder.new Memento();
- memento.getData().addAll(asList(NORMAL_RUN, 1L, "m"));
+ memento.getData().addAll(asList(NORMAL_RUN, 1L, "m", "stack"));
event = decoder.toMessage(BOOTERCODE_STDOUT, memento);
assertThat(event).isInstanceOf(StandardStreamOutEvent.class);
assertThat(((StandardStreamOutEvent) event).getMessage()).isEqualTo("m");
assertThat(((StandardStreamOutEvent) event).getRunMode()).isEqualTo(NORMAL_RUN);
assertThat(((StandardStreamOutEvent) event).getTestRunId()).isEqualTo(1L);
+ assertThat(((StandardStreamOutEvent) event).getStack()).isEqualTo("stack");
memento = decoder.new Memento();
- memento.getData().addAll(asList(RERUN_TEST_AFTER_FAILURE, 1L, null));
+ memento.getData().addAll(asList(RERUN_TEST_AFTER_FAILURE, 1L, null, null));
event = decoder.toMessage(BOOTERCODE_STDOUT_NEW_LINE, memento);
assertThat(event).isInstanceOf(StandardStreamOutWithNewLineEvent.class);
assertThat(((StandardStreamOutWithNewLineEvent) event).getMessage()).isNull();
assertThat(((StandardStreamOutWithNewLineEvent) event).getRunMode()).isEqualTo(RERUN_TEST_AFTER_FAILURE);
assertThat(((StandardStreamOutWithNewLineEvent) event).getTestRunId()).isEqualTo(1L);
+ assertThat(((StandardStreamOutWithNewLineEvent) event).getStack()).isNull();
memento = decoder.new Memento();
- memento.getData().addAll(asList(RERUN_TEST_AFTER_FAILURE, 1L, null));
+ memento.getData().addAll(asList(RERUN_TEST_AFTER_FAILURE, 1L, null, null));
event = decoder.toMessage(BOOTERCODE_STDERR, memento);
assertThat(event).isInstanceOf(StandardStreamErrEvent.class);
assertThat(((StandardStreamErrEvent) event).getMessage()).isNull();
assertThat(((StandardStreamErrEvent) event).getRunMode()).isEqualTo(RERUN_TEST_AFTER_FAILURE);
assertThat(((StandardStreamErrEvent) event).getTestRunId()).isEqualTo(1L);
+ assertThat(((StandardStreamErrEvent) event).getStack()).isNull();
memento = decoder.new Memento();
- memento.getData().addAll(asList(NORMAL_RUN, 1L, "abc"));
+ memento.getData().addAll(asList(NORMAL_RUN, 1L, "abc", "stacktrace"));
event = decoder.toMessage(BOOTERCODE_STDERR_NEW_LINE, memento);
assertThat(event).isInstanceOf(StandardStreamErrWithNewLineEvent.class);
assertThat(((StandardStreamErrWithNewLineEvent) event).getMessage()).isEqualTo("abc");
assertThat(((StandardStreamErrWithNewLineEvent) event).getRunMode()).isEqualTo(NORMAL_RUN);
assertThat(((StandardStreamErrWithNewLineEvent) event).getTestRunId()).isEqualTo(1L);
+ assertThat(((StandardStreamErrWithNewLineEvent) event).getStack()).isEqualTo("stacktrace");
memento = decoder.new Memento();
memento.getData().addAll(asList(NORMAL_RUN, 1L, "key", "value"));
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/AbstractStandardStreamEvent.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/AbstractStandardStreamEvent.java
index c66b5b2af..e7f0b7e2f 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/AbstractStandardStreamEvent.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/AbstractStandardStreamEvent.java
@@ -30,13 +30,15 @@ public abstract class AbstractStandardStreamEvent extends Event {
private final RunMode runMode;
private final Long testRunId;
private final String message;
+ private final String stack;
protected AbstractStandardStreamEvent(
- ForkedProcessEventType eventType, RunMode runMode, Long testRunId, String message) {
+ ForkedProcessEventType eventType, RunMode runMode, Long testRunId, String message, String stack) {
super(eventType);
this.runMode = runMode;
this.testRunId = testRunId;
this.message = message;
+ this.stack = stack;
}
public RunMode getRunMode() {
@@ -51,6 +53,10 @@ public String getMessage() {
return message;
}
+ public String getStack() {
+ return stack;
+ }
+
@Override
public boolean isControlCategory() {
return false;
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrEvent.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrEvent.java
index 27ce8e641..888f7a686 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrEvent.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrEvent.java
@@ -28,7 +28,7 @@
* @since 3.0.0-M5
*/
public final class StandardStreamErrEvent extends AbstractStandardStreamEvent {
- public StandardStreamErrEvent(RunMode runMode, Long testRunId, String message) {
- super(BOOTERCODE_STDERR, runMode, testRunId, message);
+ public StandardStreamErrEvent(RunMode runMode, Long testRunId, String message, String stack) {
+ super(BOOTERCODE_STDERR, runMode, testRunId, message, stack);
}
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrWithNewLineEvent.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrWithNewLineEvent.java
index 29ca5ef13..0162cf144 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrWithNewLineEvent.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamErrWithNewLineEvent.java
@@ -28,7 +28,7 @@
* @since 3.0.0-M5
*/
public final class StandardStreamErrWithNewLineEvent extends AbstractStandardStreamEvent {
- public StandardStreamErrWithNewLineEvent(RunMode runMode, Long testRunId, String message) {
- super(BOOTERCODE_STDERR_NEW_LINE, runMode, testRunId, message);
+ public StandardStreamErrWithNewLineEvent(RunMode runMode, Long testRunId, String message, String stack) {
+ super(BOOTERCODE_STDERR_NEW_LINE, runMode, testRunId, message, stack);
}
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutEvent.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutEvent.java
index 22e96c33d..896872069 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutEvent.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutEvent.java
@@ -28,7 +28,7 @@
* @since 3.0.0-M5
*/
public final class StandardStreamOutEvent extends AbstractStandardStreamEvent {
- public StandardStreamOutEvent(RunMode runMode, Long testRunId, String message) {
- super(BOOTERCODE_STDOUT, runMode, testRunId, message);
+ public StandardStreamOutEvent(RunMode runMode, Long testRunId, String message, String stack) {
+ super(BOOTERCODE_STDOUT, runMode, testRunId, message, stack);
}
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutWithNewLineEvent.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutWithNewLineEvent.java
index 9f5356c5e..9d7da8447 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutWithNewLineEvent.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/event/StandardStreamOutWithNewLineEvent.java
@@ -28,7 +28,7 @@
* @since 3.0.0-M5
*/
public final class StandardStreamOutWithNewLineEvent extends AbstractStandardStreamEvent {
- public StandardStreamOutWithNewLineEvent(RunMode runMode, Long testRunId, String message) {
- super(BOOTERCODE_STDOUT_NEW_LINE, runMode, testRunId, message);
+ public StandardStreamOutWithNewLineEvent(RunMode runMode, Long testRunId, String message, String stack) {
+ super(BOOTERCODE_STDOUT_NEW_LINE, runMode, testRunId, message, stack);
}
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/OutputReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/OutputReportEntry.java
index d5bb29be7..ef01472b4 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/OutputReportEntry.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/OutputReportEntry.java
@@ -40,4 +40,10 @@ public interface OutputReportEntry {
boolean isStdOut();
boolean isNewLine();
+
+ /**
+ * The stack trace of the thread that produced the output.
+ * claasName#method;className#method;...
+ */
+ String getStack();
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/report/StackTraceProvider.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/StackTraceProvider.java
new file mode 100644
index 000000000..dd5e44086
--- /dev/null
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/report/StackTraceProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.surefire.api.report;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Util class for stack trace providing from Java 9 this will use StackWalker by reflection.
+ */
+public class StackTraceProvider {
+
+ private static Object stackWalker;
+
+ static {
+ try {
+ Class<?> stackWalkerClass =
+ Thread.currentThread().getContextClassLoader().loadClass("java.lang.StackWalker");
+ Method getInstanceMethod = stackWalkerClass.getMethod("getInstance");
+ stackWalker = getInstanceMethod.invoke(null);
+ } catch (Throwable t) {
+ // ignore
+ // System.err.println("Unable to load StackWalker, using
+ // Thread.currentThread().getStackTrace()");
+ }
+ }
+
+ /**
+ *
+ * @return the stack trace as a list classname#methodname
+ */
+ static List<String> getStack() {
+ return Arrays.stream(Thread.currentThread().getStackTrace())
+ .map(stackTraceElement -> stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName())
+ .collect(Collectors.toList());
+ }
+}
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 3c4c46dea..3e3e03b99 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
@@ -29,7 +29,11 @@ public final class TestOutputReportEntry implements OutputReportEntry {
private final boolean newLine;
private final RunMode runMode;
private final Long testRunId;
-
+ /**
+ * The stack trace of the thread that produced the output.
+ * claasName#method;className#method;...
+ */
+ private String stack;
/**
* Wraps the output from the running test-case.
*
@@ -45,6 +49,7 @@ public TestOutputReportEntry(String log, boolean isStdOut, boolean newLine, RunM
this.newLine = newLine;
this.runMode = runMode;
this.testRunId = testRunId;
+ this.stack = String.join(";", StackTraceProvider.getStack());
}
/**
@@ -59,11 +64,28 @@ private TestOutputReportEntry(String log, boolean isStdOut, boolean newLine) {
}
public TestOutputReportEntry(OutputReportEntry reportEntry, RunMode runMode, Long testRunId) {
- log = reportEntry.getLog();
- isStdOut = reportEntry.isStdOut();
- newLine = reportEntry.isNewLine();
+ this(reportEntry.getLog(), reportEntry.isStdOut(), reportEntry.isNewLine(), runMode, testRunId);
+ }
+
+ /**
+ * Constructor used when receiving output from a forked JVM where the stack trace was captured
+ * on the forked side.
+ *
+ * @param log stdout/stderr output
+ * @param isStdOut true if stdout
+ * @param newLine true if newline
+ * @param runMode the run mode
+ * @param testRunId the test run id
+ * @param stack the stack trace captured on the forked JVM side
+ */
+ public TestOutputReportEntry(
+ String log, boolean isStdOut, boolean newLine, RunMode runMode, Long testRunId, String stack) {
+ this.log = log;
+ this.isStdOut = isStdOut;
+ this.newLine = newLine;
this.runMode = runMode;
this.testRunId = testRunId;
+ this.stack = stack;
}
@Override
@@ -89,6 +111,11 @@ public Long getTestRunId() {
return testRunId;
}
+ @Override
+ public String getStack() {
+ return stack;
+ }
+
public static OutputReportEntry stdOut(String log) {
return new TestOutputReportEntry(log, true, false);
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/stream/AbstractStreamDecoder.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/stream/AbstractStreamDecoder.java
index 400f74f6c..5c7a859b2 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/stream/AbstractStreamDecoder.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/stream/AbstractStreamDecoder.java
@@ -24,7 +24,6 @@
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
-import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ReadableByteChannel;
@@ -124,8 +123,8 @@ protected Segment readSegment(@Nonnull Memento memento) throws IOException, Malf
int readCount = readByte(memento) & 0xff;
read(memento, readCount + DELIMITER_LENGTH);
ByteBuffer bb = memento.getByteBuffer();
- Segment segment = new Segment(bb.array(), bb.arrayOffset() + ((Buffer) bb).position(), readCount);
- ((Buffer) bb).position(((Buffer) bb).position() + readCount);
+ Segment segment = new Segment(bb.array(), bb.arrayOffset() + (bb).position(), readCount);
+ (bb).position((bb).position() + readCount);
checkDelimiter(memento);
return segment;
}
@@ -137,8 +136,8 @@ protected Charset readCharset(@Nonnull Memento memento) throws IOException, Malf
read(memento, length + DELIMITER_LENGTH);
ByteBuffer bb = memento.getByteBuffer();
byte[] array = bb.array();
- int offset = bb.arrayOffset() + ((Buffer) bb).position();
- ((Buffer) bb).position(((Buffer) bb).position() + length);
+ int offset = bb.arrayOffset() + (bb).position();
+ (bb).position((bb).position() + length);
boolean isDefaultEncoding = false;
if (length == DEFAULT_STREAM_ENCODING_BYTES.length) {
isDefaultEncoding = true;
@@ -155,16 +154,16 @@ protected Charset readCharset(@Nonnull Memento memento) throws IOException, Malf
checkDelimiter(memento);
return charset;
} catch (IllegalArgumentException e) {
- throw new MalformedFrameException(memento.getLine().getPositionByteBuffer(), ((Buffer) bb).position());
+ throw new MalformedFrameException(memento.getLine().getPositionByteBuffer(), (bb).position());
}
}
protected String readString(@Nonnull Memento memento) throws IOException, MalformedFrameException {
- ((Buffer) memento.getCharBuffer()).clear();
+ (memento.getCharBuffer()).clear();
int readCount = readInt(memento);
if (readCount < 0) {
throw new MalformedFrameException(
- memento.getLine().getPositionByteBuffer(), ((Buffer) memento.getByteBuffer()).position());
+ memento.getLine().getPositionByteBuffer(), (memento.getByteBuffer()).position());
}
read(memento, readCount + DELIMITER_LENGTH);
@@ -230,7 +229,7 @@ protected long readLongPrivate(@Nonnull Memento memento) throws IOException, Mal
protected final void checkDelimiter(Memento memento) throws MalformedFrameException {
ByteBuffer bb = memento.bb;
if ((0xff & bb.get()) != ':') {
- throw new MalformedFrameException(memento.getLine().getPositionByteBuffer(), ((Buffer) bb).position());
+ throw new MalformedFrameException(memento.getLine().getPositionByteBuffer(), (bb).position());
}
}
@@ -243,16 +242,14 @@ protected final void checkHeader(Memento memento) throws MalformedFrameException
try {
byte[] header = getEncodedMagicNumber();
byte[] bbArray = bb.array();
- for (int start = bb.arrayOffset() + ((Buffer) bb).position(), length = header.length;
- shift < length;
- shift++) {
+ for (int start = bb.arrayOffset() + (bb).position(), length = header.length; shift < length; shift++) {
if (bbArray[shift + start] != header[shift]) {
throw new MalformedFrameException(
- memento.getLine().getPositionByteBuffer(), ((Buffer) bb).position() + shift);
+ memento.getLine().getPositionByteBuffer(), (bb).position() + shift);
}
}
} finally {
- ((Buffer) bb).position(((Buffer) bb).position() + shift);
+ (bb).position((bb).position() + shift);
}
checkDelimiter(memento);
@@ -261,7 +258,7 @@ protected final void checkHeader(Memento memento) throws MalformedFrameException
protected void checkArguments(Memento memento, int expectedDataElements) throws MalformedFrameException {
if (memento.getData().size() != expectedDataElements) {
throw new MalformedFrameException(
- memento.getLine().getPositionByteBuffer(), ((Buffer) memento.getByteBuffer()).position());
+ memento.getLine().getPositionByteBuffer(), (memento.getByteBuffer()).position());
}
}
@@ -269,7 +266,7 @@ private String readString(@Nonnull final Memento memento, @Nonnegative final int
throws IOException, MalformedFrameException {
memento.getDecoder().reset();
final CharBuffer output = memento.getCharBuffer();
- ((Buffer) output).clear();
+ (output).clear();
final ByteBuffer input = memento.getByteBuffer();
final List<String> strings = new ArrayList<>();
int countDecodedBytes = 0;
@@ -293,12 +290,12 @@ private String readString(@Nonnull final Memento memento, @Nonnegative final int
countDecodedBytes += readInputBytes;
} while (isLastChunk && bytesToDecode > 0 && output.hasRemaining());
- strings.add(((Buffer) output).flip().toString());
- ((Buffer) output).clear();
+ strings.add((output).flip().toString());
+ (output).clear();
}
memento.getDecoder().reset();
- ((Buffer) output).clear();
+ (output).clear();
return toString(strings);
}
@@ -311,16 +308,16 @@ private static int decodeString(
boolean endOfInput,
@Nonnegative int errorStreamFrom)
throws MalformedFrameException {
- int limit = ((Buffer) input).limit();
- ((Buffer) input).limit(((Buffer) input).position() + bytesToDecode);
+ int limit = (input).limit();
+ (input).limit((input).position() + bytesToDecode);
CoderResult result = decoder.decode(input, output, endOfInput);
if (result.isError() || result.isMalformed()) {
- throw new MalformedFrameException(errorStreamFrom, ((Buffer) input).position());
+ throw new MalformedFrameException(errorStreamFrom, (input).position());
}
int decodedBytes = bytesToDecode - input.remaining();
- ((Buffer) input).limit(limit);
+ (input).limit(limit);
return decodedBytes;
}
@@ -339,8 +336,8 @@ private void printCorruptedStream(Memento memento) {
ByteBuffer bb = memento.getByteBuffer();
if (bb.hasRemaining()) {
int bytesToWrite = bb.remaining();
- memento.getLine().write(bb, ((Buffer) bb).position(), bytesToWrite);
- ((Buffer) bb).position(((Buffer) bb).position() + bytesToWrite);
+ memento.getLine().write(bb, (bb).position(), bytesToWrite);
+ (bb).position((bb).position() + bytesToWrite);
}
}
@@ -405,17 +402,16 @@ public boolean equals(Object obj) {
protected @Nonnull StreamReadStatus read(@Nonnull Memento memento, int recommendedCount) throws IOException {
ByteBuffer buffer = memento.getByteBuffer();
- if (buffer.remaining() >= recommendedCount && ((Buffer) buffer).limit() != 0) {
+ if (buffer.remaining() >= recommendedCount && (buffer).limit() != 0) {
return OVERFLOW;
} else {
- if (((Buffer) buffer).position() != 0
- && recommendedCount > buffer.capacity() - ((Buffer) buffer).position()) {
- ((Buffer) buffer.compact()).flip();
+ if ((buffer).position() != 0 && recommendedCount > buffer.capacity() - (buffer).position()) {
+ (buffer.compact()).flip();
memento.getLine().setPositionByteBuffer(0);
}
- int mark = ((Buffer) buffer).position();
- ((Buffer) buffer).position(((Buffer) buffer).limit());
- ((Buffer) buffer).limit(min(((Buffer) buffer).position() + recommendedCount, buffer.capacity()));
+ int mark = (buffer).position();
+ (buffer).position((buffer).limit());
+ (buffer).limit(min((buffer).position() + recommendedCount, buffer.capacity()));
return read(buffer, mark, recommendedCount);
}
}
@@ -425,17 +421,17 @@ private StreamReadStatus read(ByteBuffer buffer, int oldPosition, int recommende
boolean isEnd = false;
try {
while (!isEnd
- && ((Buffer) buffer).position() - oldPosition < recommendedCount
- && ((Buffer) buffer).position() < ((Buffer) buffer).limit()) {
+ && (buffer).position() - oldPosition < recommendedCount
+ && (buffer).position() < (buffer).limit()) {
isEnd = channel.read(buffer) == -1;
}
} finally {
- ((Buffer) buffer).limit(((Buffer) buffer).position());
- ((Buffer) buffer).position(oldPosition);
+ (buffer).limit((buffer).position());
+ (buffer).position(oldPosition);
int readBytes = buffer.remaining();
boolean readComplete = readBytes >= recommendedCount;
if (!isEnd || readComplete) {
- debugStream(buffer.array(), buffer.arrayOffset() + ((Buffer) buffer).position(), buffer.remaining());
+ debugStream(buffer.array(), buffer.arrayOffset() + (buffer).position(), buffer.remaining());
readStatus = readComplete ? OVERFLOW : UNDERFLOW;
}
}
@@ -463,7 +459,7 @@ public Memento() {
.newDecoder()
.onMalformedInput(REPLACE)
.onUnmappableCharacter(REPLACE);
- ((Buffer) bb).limit(0);
+ (bb).limit(0);
}
public void reset() {
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/EventChannelEncoder.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/EventChannelEncoder.java
index 13df7fa1a..9dbd35ce8 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/EventChannelEncoder.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/EventChannelEncoder.java
@@ -165,11 +165,12 @@ public void testOutput(TestOutputReportEntry reportEntry) {
ForkedProcessEventType event = stdout
? (newLine ? BOOTERCODE_STDOUT_NEW_LINE : BOOTERCODE_STDOUT)
: (newLine ? BOOTERCODE_STDERR_NEW_LINE : BOOTERCODE_STDERR);
- setOutErr(event, reportEntry.getRunMode(), reportEntry.getTestRunId(), msg);
+ setOutErr(event, reportEntry.getRunMode(), reportEntry.getTestRunId(), msg, reportEntry.getStack());
}
- private void setOutErr(ForkedProcessEventType eventType, RunMode runMode, Long testRunId, String message) {
- ByteBuffer result = encodeMessage(eventType, runMode, testRunId, message);
+ private void setOutErr(
+ ForkedProcessEventType eventType, RunMode runMode, Long testRunId, String message, String stackTrace) {
+ ByteBuffer result = encodeMessage(eventType, runMode, testRunId, message, stackTrace);
write(result, false);
}
@@ -371,11 +372,13 @@ ByteBuffer encode(ForkedProcessEventType operation, ReportEntry reportEntry, boo
return result;
}
- ByteBuffer encodeMessage(ForkedProcessEventType eventType, RunMode runMode, Long testRunId, String message) {
+ ByteBuffer encodeMessage(
+ ForkedProcessEventType eventType, RunMode runMode, Long testRunId, String message, String stackCall) {
CharsetEncoder encoder = newCharsetEncoder();
- int bufferMaxLength = estimateBufferLength(eventType.getOpcode().length(), runMode, encoder, 0, 1, message);
+ int bufferMaxLength =
+ estimateBufferLength(eventType.getOpcode().length(), runMode, encoder, 0, 1, message, stackCall);
ByteBuffer result = ByteBuffer.allocate(bufferMaxLength);
- encode(encoder, result, eventType, runMode, testRunId, message);
+ encode(encoder, result, eventType, runMode, testRunId, message, stackCall);
return result;
}
diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/spi/EventChannelEncoderTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/spi/EventChannelEncoderTest.java
index af15e68ff..9eafdf83c 100644
--- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/spi/EventChannelEncoderTest.java
+++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/spi/EventChannelEncoderTest.java
@@ -952,21 +952,21 @@ public void testSendOpcode() {
Channel channel = new Channel();
new EventChannelEncoder(channel).testOutput(new TestOutputReportEntry(stdOut("msg"), NORMAL_RUN, 1L));
assertThat(toString(channel.src))
- .isEqualTo(":maven-surefire-event:" + (char) 14 + ":std-out-stream:" + (char) 10 + ":normal-run:"
+ .contains(":maven-surefire-event:" + (char) 14 + ":std-out-stream:" + (char) 10 + ":normal-run:"
+ "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ (char) 5 + ":UTF-8:\u0000\u0000\u0000\u0003:msg:");
channel = new Channel();
new EventChannelEncoder(channel).testOutput(new TestOutputReportEntry(stdErr(null), NORMAL_RUN, 1L));
assertThat(toString(channel.src))
- .isEqualTo(":maven-surefire-event:" + (char) 14 + ":std-err-stream:" + (char) 10 + ":normal-run:"
+ .contains(":maven-surefire-event:" + (char) 14 + ":std-err-stream:" + (char) 10 + ":normal-run:"
+ "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ (char) 5 + ":UTF-8:\u0000\u0000\u0000\u0001:\u0000:");
- ByteBuffer result =
- new EventChannelEncoder(new Channel()).encodeMessage(BOOTERCODE_TEST_ERROR, NORMAL_RUN, 1L, "msg");
+ ByteBuffer result = new EventChannelEncoder(new Channel())
+ .encodeMessage(BOOTERCODE_TEST_ERROR, NORMAL_RUN, 1L, "msg", "foo#bar");
assertThat(toString(result))
- .isEqualTo(":maven-surefire-event:" + (char) 10 + ":test-error:" + (char) 10 + ":normal-run:"
+ .contains(":maven-surefire-event:" + (char) 10 + ":test-error:" + (char) 10 + ":normal-run:"
+ "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ (char) 5 + ":UTF-8:\u0000\u0000\u0000\u0003:msg:");
}
@@ -1133,7 +1133,7 @@ public void testStdOutStream() throws IOException {
+ (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
- assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
+ assertThat(new String(out.toByteArray(), UTF_8)).contains(expected);
}
@Test
@@ -1149,7 +1149,7 @@ public void testStdOutStreamLn() throws IOException {
+ (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
- assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
+ assertThat(new String(out.toByteArray(), UTF_8)).contains(expected);
}
@Test
@@ -1165,7 +1165,7 @@ public void testStdErrStream() throws IOException {
+ (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
- assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
+ assertThat(new String(out.toByteArray(), UTF_8)).contains(expected);
}
@Test
@@ -1181,7 +1181,7 @@ public void testStdErrStreamLn() throws IOException {
+ (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ "\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:";
- assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
+ assertThat(new String(out.toByteArray(), UTF_8)).contains(expected);
}
@Test
@@ -1204,7 +1204,7 @@ public void testStdErrStreamEmptyMessageNullTestId() throws IOException {
+ (char) 10 + ":normal-run:\u0000:"
+ "\u0005:UTF-8:\u0000\u0000\u0000\u0000::";
- assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
+ assertThat(new String(out.toByteArray(), UTF_8)).contains(expected);
}
@Test
@@ -1222,7 +1222,7 @@ public void testStdErrStreamEmptyMessageNullRunMode() throws IOException {
+ "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001:"
+ "\u0005:UTF-8:\u0000\u0000\u0000\u0000::";
- assertThat(new String(out.toByteArray(), UTF_8)).isEqualTo(expected);
+ assertThat(new String(out.toByteArray(), UTF_8)).contains(expected);
}
@Test
@@ -1307,7 +1307,7 @@ public void testInterruptHandling() throws IOException {
}
assertThat(new String(out.toByteArray(), UTF_8))
- .isEqualTo(":maven-surefire-event:\u000e:std-out-stream:"
+ .contains(":maven-surefire-event:\u000e:std-out-stream:"
+ (char) 10 + ":normal-run:\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002"
+ ":\u0005:UTF-8:\u0000\u0000\u0000\u0003:msg:");
}
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java
index e3f4654c6..f8f0e23a7 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java
@@ -27,9 +27,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-/**
- *
- */
public class JUnit47RedirectOutputIT extends SurefireJUnitIntegrationTestCase {
@Test
public void testPrintSummaryTrueWithRedirect() {
(maven-surefire) 03/03: remove now useless code
Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
olamy pushed a commit to branch test-junit-platform-runner-junit4-parallel-stack
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit d1cc77af8c41c668b6d17a9ac6cd09cbd70b6c60
Author: Olivier Lamy <ol...@apache.org>
AuthorDate: Fri Dec 26 19:04:46 2025 +1000
remove now useless code
Signed-off-by: Olivier Lamy <ol...@apache.org>
---
.mvn/extensions.xml | 7 +-
.mvn/maven.config | 1 +
.../surefire/report/ConsoleOutputFileReporter.java | 109 ++++++++-------------
.../report/ConsoleOutputFileReporterTest.java | 33 +++++--
4 files changed, 70 insertions(+), 80 deletions(-)
diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml
index b384bb06c..ce6ab5116 100644
--- a/.mvn/extensions.xml
+++ b/.mvn/extensions.xml
@@ -20,11 +20,16 @@
<extension>
<groupId>eu.maveniverse.maven.mimir</groupId>
<artifactId>extension3</artifactId>
- <version>0.10.4</version>
+ <version>0.11.0</version>
</extension>
<extension>
<groupId>org.apache.maven.extensions</groupId>
<artifactId>maven-build-cache-extension</artifactId>
<version>1.2.1</version>
</extension>
+ <extension>
+ <groupId>eu.maveniverse.maven.turbo-builder</groupId>
+ <artifactId>maven-turbo-builder</artifactId>
+ <version>0.13</version>
+ </extension>
</extensions>
diff --git a/.mvn/maven.config b/.mvn/maven.config
new file mode 100644
index 000000000..1d6061320
--- /dev/null
+++ b/.mvn/maven.config
@@ -0,0 +1 @@
+-Daether.dependencyCollector.impl=bf
\ No newline at end of file
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
index 556c35c18..99aeac7c9 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java
@@ -27,10 +27,8 @@
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicStampedReference;
import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
-import org.apache.maven.surefire.api.report.ReportEntry;
import org.apache.maven.surefire.api.report.TestOutputReportEntry;
import org.apache.maven.surefire.api.report.TestSetReportEntry;
@@ -55,9 +53,6 @@ public class ConsoleOutputFileReporter implements TestcycleConsoleOutputReceiver
private final Integer forkNumber;
private final String encoding;
- private final AtomicStampedReference<FilterOutputStream> fileOutputStream =
- new AtomicStampedReference<>(null, OPEN);
-
private final Map<String, FilterOutputStream> outputStreams = new ConcurrentHashMap<>();
private volatile String reportEntryName;
@@ -76,29 +71,41 @@ public ConsoleOutputFileReporter(
}
@Override
- public synchronized void testSetStarting(TestSetReportEntry reportEntry) {
- closeNullReportFile(reportEntry);
+ public void testSetStarting(TestSetReportEntry reportEntry) {
+ String className = usePhrasedFileName ? reportEntry.getSourceText() : reportEntry.getSourceName();
+ try {
+ File file = getReportFile(reportsDirectory, className, reportNameSuffix, "-output.txt");
+ if (!reportsDirectory.exists()) {
+ Files.createDirectories(reportsDirectory.toPath());
+ }
+ if (!Files.exists(file.toPath())) {
+ Files.createFile(file.toPath());
+ }
+ outputStreams.put(
+ className, new BufferedOutputStream(Files.newOutputStream(file.toPath()), STREAM_BUFFER_SIZE));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
@Override
public void testSetCompleted(TestSetReportEntry report) {}
@Override
- public synchronized void close() {
- // The close() method is called in main Thread T2.
- closeReportFile();
+ public void close() {
+ // Close all output streams in the map
+ for (FilterOutputStream stream : outputStreams.values()) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ dumpException(e);
+ }
+ }
}
@Override
public synchronized void writeTestOutput(TestOutputReportEntry reportEntry) {
try {
- // This method is called in single thread T1 per fork JVM (see ThreadedStreamConsumer).
- // The close() method is called in main Thread T2.
- int[] status = new int[1];
- fileOutputStream.get(status);
- if (status[0] == CLOSED) {
- return;
- }
// Determine the target class name based on stack trace or reportEntryName
String targetClassName = extractTestClassFromStack(reportEntry.getStack());
@@ -153,17 +160,25 @@ private String extractTestClassFromStack(String stack) {
// We look for the test class which typically is the first entry or an entry with "Test" in the name
String[] entries = stack.split(";");
for (String entry : entries) {
+ // int hashIndex = entry.indexOf('#');
+ // if (hashIndex > 0) {
+ // String className = entry.substring(0, hashIndex);
+ // // Skip JDK classes and known framework classes
+ // if (!className.startsWith("java.")
+ // && !className.startsWith("sun.")
+ // && !className.startsWith("jdk.")
+ // && !className.startsWith("org.junit.")
+ // && !className.startsWith("junit.")
+ // && !className.startsWith("org.apache.maven.surefire.")
+ // && !className.startsWith("org.apache.maven.shadefire.")) {
+ // return className;
+ // }
+ // }
+
int hashIndex = entry.indexOf('#');
if (hashIndex > 0) {
String className = entry.substring(0, hashIndex);
- // Skip JDK classes and known framework classes
- if (!className.startsWith("java.")
- && !className.startsWith("sun.")
- && !className.startsWith("jdk.")
- && !className.startsWith("org.junit.")
- && !className.startsWith("junit.")
- && !className.startsWith("org.apache.maven.surefire.")
- && !className.startsWith("org.apache.maven.shadefire.")) {
+ if (outputStreams.containsKey(className)) {
return className;
}
}
@@ -171,50 +186,6 @@ private String extractTestClassFromStack(String stack) {
return null;
}
- @SuppressWarnings("checkstyle:emptyblock")
- private void closeNullReportFile(ReportEntry reportEntry) {
- try {
- // close null-output.txt report file
- close(true);
- } catch (IOException e) {
- dumpException(e);
- } finally {
- // prepare <class>-output.txt report file
- reportEntryName = usePhrasedFileName ? reportEntry.getSourceText() : reportEntry.getSourceName();
- }
- }
-
- @SuppressWarnings("checkstyle:emptyblock")
- private void closeReportFile() {
- try {
- close(false);
- } catch (IOException e) {
- dumpException(e);
- }
- }
-
- private void close(boolean closeReattempt) throws IOException {
- int[] status = new int[1];
- FilterOutputStream os = fileOutputStream.get(status);
- if (status[0] != CLOSED) {
- fileOutputStream.set(null, closeReattempt ? CLOSED_TO_REOPEN : CLOSED);
- if (os != null && status[0] == OPEN) {
- os.close();
- }
- // Close all output streams in the map
- for (FilterOutputStream stream : outputStreams.values()) {
- try {
- stream.close();
- } catch (IOException e) {
- dumpException(e);
- }
- }
- if (!closeReattempt) {
- outputStreams.clear();
- }
- }
- }
-
private void dumpException(IOException e) {
if (forkNumber == null) {
InPluginProcessDumpSingleton.getSingleton().dumpException(e, e.getLocalizedMessage(), reportsDirectory);
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java
index ca9382fb5..9aa552686 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java
@@ -20,7 +20,9 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -47,8 +49,10 @@ public class ConsoleOutputFileReporterTest extends TestCase {
*/
public void testFileNameWithoutSuffix() throws IOException {
File reportDir = new File(new File(System.getProperty("user.dir"), "target"), "tmp1");
- //noinspection ResultOfMethodCallIgnored
- reportDir.mkdirs();
+ if (Files.exists(reportDir.toPath())) {
+ FileUtils.deleteDirectory(reportDir);
+ }
+ Files.createDirectories(reportDir.toPath());
TestSetReportEntry reportEntry = new SimpleReportEntry(
NORMAL_RUN, 1L, getClass().getName(), null, getClass().getName(), null);
ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter(reportDir, null, false, null, "UTF-8");
@@ -74,6 +78,10 @@ public void testFileNameWithoutSuffix() throws IOException {
*/
public void testFileNameWithSuffix() throws IOException {
File reportDir = new File(new File(System.getProperty("user.dir"), "target"), "tmp2");
+ if (Files.exists(reportDir.toPath())) {
+ FileUtils.deleteDirectory(reportDir);
+ }
+ Files.createDirectories(reportDir.toPath());
String suffixText = "sampleSuffixText";
TestSetReportEntry reportEntry = new SimpleReportEntry(
NORMAL_RUN, 1L, getClass().getName(), null, getClass().getName(), null);
@@ -100,6 +108,10 @@ public void testFileNameWithSuffix() throws IOException {
public void testNullReportFile() throws IOException {
File reportDir = new File(new File(System.getProperty("user.dir"), "target"), "tmp3");
+ if (Files.exists(reportDir.toPath())) {
+ FileUtils.deleteDirectory(reportDir);
+ }
+ Files.createDirectories(reportDir.toPath());
ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter(reportDir, null, false, null, "UTF-8");
reporter.writeTestOutput((TestOutputReportEntry) stdOut("some text"));
reporter.testSetCompleted(new SimpleReportEntry(
@@ -120,25 +132,26 @@ public void testNullReportFile() throws IOException {
public void testConcurrentAccessReportFile() throws Exception {
File reportDir = new File(new File(System.getProperty("user.dir"), "target"), "tmp4");
+ if (Files.exists(reportDir.toPath())) {
+ FileUtils.deleteDirectory(reportDir);
+ }
final ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter(reportDir, null, false, null, "UTF-8");
reporter.testSetStarting(new SimpleReportEntry(
NORMAL_RUN, 1L, getClass().getName(), null, getClass().getName(), null));
ExecutorService scheduler = Executors.newFixedThreadPool(10);
- final ArrayList<Callable<Void>> jobs = new ArrayList<>();
+ List<Callable<Void>> jobs = new ArrayList<>();
for (int i = 0; i < 10; i++) {
- jobs.add(new Callable<Void>() {
- @Override
- public Void call() {
- reporter.writeTestOutput((TestOutputReportEntry) stdOut("some text\n"));
- return null;
- }
+ jobs.add(() -> {
+ reporter.writeTestOutput((TestOutputReportEntry) stdOut("some text\n"));
+ return null;
});
}
scheduler.invokeAll(jobs);
scheduler.shutdown();
reporter.close();
- File expectedReportFile = new File(reportDir, getClass().getName() + "-output.txt");
+ File expectedReportFile =
+ new File(reportDir, "org.apache.maven.surefire.report.ConsoleOutputFileReporterTest-output.txt");
assertTrue(
"Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist",