Skip to content

Commit 13caf16

Browse files
committed
Issue #3166: STDOUT and STDERR are auto closed after test execution
1 parent 55ea1ba commit 13caf16

File tree

7 files changed

+99
-63
lines changed

7 files changed

+99
-63
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0-M1.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ repository on GitHub.
2727
==== New Features and Improvements
2828

2929
* New optional CLI options `--redirect-stdout` and `--redirect-stderr` to redirect stdout
30-
and stderr outputs to a file.
30+
and stderr outputs to a file.
3131

3232

3333
[[release-notes-5.13.0-M1-junit-jupiter]]

documentation/src/docs/asciidoc/user-guide/advanced-topics/junit-platform-reporting.adoc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,13 @@ $ java -jar junit-platform-console-standalone-{platform-version}.jar <OPTIONS> \
154154
--config-resource=configuration.properties
155155
----
156156

157-
You can redirect standard output and standard error using the --redirect-stdout and --redirect-stderr options:
157+
You can redirect standard output and standard error using the `--redirect-stdout` and
158+
`--redirect-stderr` options:
158159

159160
[source,console,subs=attributes+]
160161
----
161162
$ java -jar junit-platform-console-standalone-{platform-version}.jar <OPTIONS> \
162-
--redirect-stdout=foo.txt
163+
--redirect-stdout=foo.txt \
163164
--redirect-stderr=bar.txt
164165
----
165166

junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ static class ConsoleOutputOptions {
5151
@Option(names = "-details-theme", hidden = true)
5252
private final Theme theme2 = DEFAULT_THEME;
5353

54-
@Option(names = "--redirect-stdout", paramLabel = "FILE", description = "Redirect tests stdout to a file.")
54+
@Option(names = "--redirect-stdout", paramLabel = "FILE", description = "Redirect test output to stdout to a file.")
5555
private Path stdout;
5656

57-
@Option(names = "--redirect-stderr", paramLabel = "FILE", description = "Redirect tests stderr to a file.")
57+
@Option(names = "--redirect-stderr", paramLabel = "FILE", description = "Redirect test output to stderr to a file.")
5858
private Path stderr;
5959

6060
private void applyTo(TestConsoleOutputOptions result) {

junit-platform-console/src/main/java/org/junit/platform/console/tasks/ConsoleTestExecutor.java

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
import static org.junit.platform.console.tasks.DiscoveryRequestCreator.toDiscoveryRequestBuilder;
1515
import static org.junit.platform.launcher.LauncherConstants.OUTPUT_DIR_PROPERTY_NAME;
1616

17-
import java.io.IOException;
1817
import java.io.PrintStream;
1918
import java.io.PrintWriter;
2019
import java.net.URL;
2120
import java.net.URLClassLoader;
22-
import java.nio.file.Files;
2321
import java.nio.file.Path;
2422
import java.util.EnumSet;
2523
import java.util.List;
@@ -106,8 +104,8 @@ private TestExecutionSummary executeTests(PrintWriter out, Optional<Path> report
106104

107105
PrintStream originalOut = System.out;
108106
PrintStream originalErr = System.err;
109-
try {
110-
redirectStdStreams(outputOptions.getStdoutPath(), outputOptions.getStderrPath());
107+
try (StdStreamHandler stdStreamHandler = new StdStreamHandler()) {
108+
stdStreamHandler.redirectStdStreams(outputOptions.getStdoutPath(), outputOptions.getStderrPath());
111109
launchTests(launcher, reportsDir);
112110
}
113111
finally {
@@ -206,47 +204,6 @@ private void printSummary(TestExecutionSummary summary, PrintWriter out) {
206204
summary.printTo(out);
207205
}
208206

209-
@API(status = INTERNAL, since = "5.12")
210-
private boolean isSameFile(Path path1, Path path2) {
211-
if (path1 == null || path2 == null)
212-
return false;
213-
return (path1.normalize().toAbsolutePath().equals(path2.normalize().toAbsolutePath()));
214-
}
215-
216-
private void redirectStdStreams(Path stdoutPath, Path stderrPath) {
217-
if (isSameFile(stdoutPath, stderrPath)) {
218-
try {
219-
PrintStream commonStream = new PrintStream(Files.newOutputStream(stdoutPath), true);
220-
System.setOut(commonStream);
221-
System.setErr(commonStream);
222-
}
223-
catch (IOException e) {
224-
throw new JUnitException("Error setting up stream for Stdout and Stderr at path: " + stdoutPath, e);
225-
}
226-
}
227-
else {
228-
if (stdoutPath != null) {
229-
try {
230-
PrintStream outStream = new PrintStream(Files.newOutputStream(stdoutPath), true);
231-
System.setOut(outStream);
232-
}
233-
catch (IOException e) {
234-
throw new JUnitException("Error setting up stream for Stdout at path: " + stdoutPath, e);
235-
}
236-
}
237-
238-
if (stderrPath != null) {
239-
try {
240-
PrintStream errStream = new PrintStream(Files.newOutputStream(stderrPath), true);
241-
System.setErr(errStream);
242-
}
243-
catch (IOException e) {
244-
throw new JUnitException("Error setting up stream for Stderr at path: " + stderrPath, e);
245-
}
246-
}
247-
}
248-
}
249-
250207
@FunctionalInterface
251208
public interface Factory {
252209
ConsoleTestExecutor create(TestDiscoveryOptions discoveryOptions, TestConsoleOutputOptions outputOptions);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2015-2025 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.platform.console.tasks;
12+
13+
import java.io.IOException;
14+
import java.io.PrintStream;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
18+
import org.junit.platform.commons.JUnitException;
19+
20+
class StdStreamHandler implements AutoCloseable {
21+
private PrintStream stdout;
22+
private PrintStream stderr;
23+
24+
public StdStreamHandler() {
25+
}
26+
27+
private boolean isSameFile(Path path1, Path path2) {
28+
if (path1 == null || path2 == null)
29+
return false;
30+
return (path1.normalize().toAbsolutePath().equals(path2.normalize().toAbsolutePath()));
31+
}
32+
33+
public void redirectStdStreams(Path stdoutPath, Path stderrPath) {
34+
if (isSameFile(stdoutPath, stderrPath)) {
35+
try {
36+
PrintStream commonStream = new PrintStream(Files.newOutputStream(stdoutPath), true);
37+
this.stdout = commonStream;
38+
this.stderr = commonStream;
39+
}
40+
catch (IOException e) {
41+
throw new JUnitException("Error setting up stream for Stdout and Stderr at path: " + stdoutPath, e);
42+
}
43+
}
44+
else {
45+
if (stdoutPath != null) {
46+
try {
47+
this.stdout = new PrintStream(Files.newOutputStream(stdoutPath), true);
48+
}
49+
catch (IOException e) {
50+
throw new JUnitException("Error setting up stream for Stdout at path: " + stdoutPath, e);
51+
}
52+
}
53+
54+
if (stderrPath != null) {
55+
try {
56+
this.stderr = new PrintStream(Files.newOutputStream(stderrPath), true);
57+
}
58+
catch (IOException e) {
59+
throw new JUnitException("Error setting up stream for Stderr at path: " + stderrPath, e);
60+
}
61+
}
62+
}
63+
64+
if (stdout != null) {
65+
System.setOut(stdout);
66+
}
67+
if (stderr != null) {
68+
System.setErr(stderr);
69+
}
70+
}
71+
72+
@Override
73+
public void close() {
74+
if (stdout != null) {
75+
stdout.close();
76+
}
77+
if (stderr != null) {
78+
stderr.close();
79+
}
80+
}
81+
}

platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
package org.junit.platform.console;
1212

13-
import static java.nio.file.Files.deleteIfExists;
1413
import static org.assertj.core.api.Assertions.assertThat;
1514
import static org.junit.jupiter.api.Assertions.assertAll;
1615
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
@@ -22,6 +21,7 @@
2221
import java.nio.file.Path;
2322

2423
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.io.TempDir;
2525
import org.junit.jupiter.params.ParameterizedTest;
2626
import org.junit.jupiter.params.provider.ValueSource;
2727

@@ -100,33 +100,30 @@ void executeScanModules(final String line) {
100100

101101
@ParameterizedTest
102102
@ValueSource(strings = { "--redirect-stdout", "--redirect-stderr" })
103-
void executeWithRedirectedStdStream(String redirectedStream) throws IOException {
104-
105-
Path outputFile = Path.of("foo.txt");
103+
void executeWithRedirectedStdStream(String redirectedStream, @TempDir Path tempDir) throws IOException {
104+
Path outputFile = tempDir.resolve("output.txt");
106105
var line = String.format(
107-
"execute -e junit-jupiter --select-method org.junit.platform.console.options.StdStreamTest#printTest "
106+
"execute -e junit-jupiter --select-method org.junit.platform.console.options.StdStreamTestCase#printTest "
108107
+ "%s %s",
109108
redirectedStream, outputFile);
110109
var args = line.split(" ");
111110
new ConsoleLauncherWrapper().execute(args);
112111

113112
assertTrue(Files.exists(outputFile), "File does not exist.");
114-
assertEquals(Files.size(outputFile), 20, "Invalid file size.");
115-
deleteIfExists(outputFile);
113+
assertEquals(20, Files.size(outputFile), "Invalid file size.");
116114
}
117115

118116
@Test
119-
void executeWithRedirectedStdStreamsToSameFile() throws IOException {
120-
Path outputFile = Path.of("foo.txt");
117+
void executeWithRedirectedStdStreamsToSameFile(@TempDir Path tempDir) throws IOException {
118+
Path outputFile = tempDir.resolve("output.txt");
121119
var line = String.format(
122-
"execute -e junit-jupiter --select-method org.junit.platform.console.options.StdStreamTest#printTest "
120+
"execute -e junit-jupiter --select-method org.junit.platform.console.options.StdStreamTestCase#printTest "
123121
+ "--redirect-stdout %s --redirect-stderr %s",
124122
outputFile, outputFile);
125123
var args = line.split(" ");
126124
new ConsoleLauncherWrapper().execute(args);
127125

128126
assertTrue(Files.exists(outputFile), "File does not exist.");
129-
assertEquals(Files.size(outputFile), 40, "Invalid file size.");
130-
deleteIfExists(outputFile);
127+
assertEquals(40, Files.size(outputFile), "Invalid file size.");
131128
}
132129
}

platform-tests/src/test/java/org/junit/platform/console/options/StdStreamTest.java renamed to platform-tests/src/test/java/org/junit/platform/console/options/StdStreamTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import org.junit.jupiter.api.Test;
1414

15-
public class StdStreamTest {
15+
public class StdStreamTestCase {
1616

1717
@Test
1818
void printTest() {

0 commit comments

Comments
 (0)