From ebbd7e29c8432228bdd209fca004e3f85b7bf99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Verh=C3=A1s?= Date: Thu, 11 Aug 2022 08:50:01 +0200 Subject: [PATCH] Revert "Add StdErr to StdIoExtension (#650 / #653)" This reverts commit 9fa2a20ccd1b73dbfe6898fc44d12c3c091143b6. --- docs/standard-input-output.adoc | 12 ++-- .../jupiter/StdInOutExtensionDemo.java | 12 +++- .../org/junitpioneer/jupiter/ReadsStdIo.java | 5 +- .../java/org/junitpioneer/jupiter/StdErr.java | 21 ------ .../junitpioneer/jupiter/StdIoExtension.java | 24 +------ .../java/org/junitpioneer/jupiter/StdOut.java | 30 ++++++++- .../junitpioneer/jupiter/StdOutputStream.java | 42 ------------ .../org/junitpioneer/jupiter/WritesStdIo.java | 4 +- .../jupiter/StdIoExtensionTests.java | 65 ++----------------- 9 files changed, 55 insertions(+), 160 deletions(-) delete mode 100644 src/main/java/org/junitpioneer/jupiter/StdErr.java delete mode 100644 src/main/java/org/junitpioneer/jupiter/StdOutputStream.java diff --git a/docs/standard-input-output.adoc b/docs/standard-input-output.adoc index 611275648..d35a4921e 100644 --- a/docs/standard-input-output.adoc +++ b/docs/standard-input-output.adoc @@ -3,9 +3,9 @@ :xp-demo-dir: ../src/demo/java :demo: {xp-demo-dir}/org/junitpioneer/jupiter/StdInOutExtensionDemo.java -The standard IO extension adds a simple way to test classes that read from the standard input (`System.in`) or write to the standard output (`System.out` or `System.err`). +The standard IO extension adds a simple way to test classes that read from the standard input (`System.in`) or write to the standard output (`System.out`). -WARNING: Depending on the configuration, the extension redirects the standard input and/or output, in which case nothing gets forwarded to the original `System.in` and/or `System.out` / `System.err`. +WARNING: Depending on the configuration, the extension redirects the standard input and/or output, in which case nothing gets forwarded to the original `System.in` and/or `System.out`. This becomes particularly important when running tests in parallel, where other tests may interfere with tests annotated with `@StdIo`. == Basic use @@ -13,8 +13,8 @@ This becomes particularly important when running tests in parallel, where other The extension consists of two parts: * The annotation `@StdIo`. It allows defining input that is read from `System.in` without having to wait for user input. -* Parameters `StdIn`, `StdOut`, and `StdErr`, which you can have injected into your test. - Their `capturedLines()` methods allow you to access lines read from `System.in` or written to `System.out` or `System.err`, so you can verify them with common assertions. +* Parameters `StdIn` and `StdOut`, which you can have injected into your test. + Their `capturedLines()` methods allow you to access lines read from `System.in` or written to `System.out`, so you can verify them with common assertions. For example, after calling `System.out.println("Hello")` and `System.out.println("World")`, the `StdOut::capturedLines` method would return an array ["Hello", "World"]. With `System.out.print("Hello")` and `System.out.println("World")` (note that the first method does not print a line break), it would return `["HelloWorld"]`. @@ -61,9 +61,7 @@ A combination of the two previous cases - `System.in` and `System.out` get repla include::{demo}[tag=stdio_both_replaced_and_verify] ---- -NOTE: Omitted from these examples is `StdErr` which behaves exactly the same way as `StdOut` and works in combination with it. - -The remaining combinations of the annotation, its values, and `StdIn`/`StdOut`/`StdErr` are considered misconfigurations and lead to exceptions. +The remaining combinations of the annotation, its values, and `StdIn`/`StdOut` are considered misconfigurations and lead to exceptions. == Thread-Safety diff --git a/src/demo/java/org/junitpioneer/jupiter/StdInOutExtensionDemo.java b/src/demo/java/org/junitpioneer/jupiter/StdInOutExtensionDemo.java index e5f46777e..72fa16b20 100644 --- a/src/demo/java/org/junitpioneer/jupiter/StdInOutExtensionDemo.java +++ b/src/demo/java/org/junitpioneer/jupiter/StdInOutExtensionDemo.java @@ -70,7 +70,7 @@ void bothReplaceAndVerify(StdIn in, StdOut out) { // end::stdio_both_replaced_and_verify[] // tag::stdio_edge_cases_ExampleConsoleReader[] - class ConsoleReader { + class ExampleConsoleReader { private List lines = new ArrayList<>(); @@ -91,7 +91,7 @@ class ConsoleReaderTest { @Test @StdIo({ "line1", "line2", "line3" }) - void testReadLines(StdIn in) throws IOException { + void testReadLines(StdIn in) { ConsoleReader consoleReader = new ConsoleReader(); consoleReader.readLines(); @@ -108,4 +108,12 @@ void testReadLines(StdIn in) throws IOException { } // end::stdio_edge_cases_ConsoleReaderTest[] + class ConsoleReader { + + public void readLines() { + // demo stuff + } + + } + } diff --git a/src/main/java/org/junitpioneer/jupiter/ReadsStdIo.java b/src/main/java/org/junitpioneer/jupiter/ReadsStdIo.java index d37ce7209..132d6a94e 100644 --- a/src/main/java/org/junitpioneer/jupiter/ReadsStdIo.java +++ b/src/main/java/org/junitpioneer/jupiter/ReadsStdIo.java @@ -21,8 +21,8 @@ import org.junit.jupiter.api.parallel.Resources; /** - * Marks tests that read the static fields {@code System.in}, {@code System.out} or {@code System.err} - * but don't call {@code System.setIn()}, {@code System.setOut()} or {@code System.setErr()}. + * Marks tests that read the static fields {@code System.in} or {@code System.out} + * but don't call {@code System.setIn()} or {@code System.setOut()}. * *

During * parallel test execution, @@ -41,6 +41,5 @@ @Inherited @ResourceLock(value = "java.lang.System.in", mode = ResourceAccessMode.READ) @ResourceLock(value = Resources.SYSTEM_OUT, mode = ResourceAccessMode.READ) -@ResourceLock(value = Resources.SYSTEM_ERR, mode = ResourceAccessMode.READ) public @interface ReadsStdIo { } diff --git a/src/main/java/org/junitpioneer/jupiter/StdErr.java b/src/main/java/org/junitpioneer/jupiter/StdErr.java deleted file mode 100644 index a7a9f0db7..000000000 --- a/src/main/java/org/junitpioneer/jupiter/StdErr.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2016-2022 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * http://www.eclipse.org/legal/epl-v20.html - */ - -package org.junitpioneer.jupiter; - -/** - *

For details and examples, see - * the documentation on Standard input/output - *

- * - * @see StdIo - */ -public class StdErr extends StdOutputStream { -} diff --git a/src/main/java/org/junitpioneer/jupiter/StdIoExtension.java b/src/main/java/org/junitpioneer/jupiter/StdIoExtension.java index 4abb59f33..f9b545ea1 100644 --- a/src/main/java/org/junitpioneer/jupiter/StdIoExtension.java +++ b/src/main/java/org/junitpioneer/jupiter/StdIoExtension.java @@ -33,13 +33,12 @@ class StdIoExtension implements ParameterResolver, BeforeEachCallback, AfterEach private static final String SYSTEM_IN_KEY = "StdIo_System_In"; private static final String SYSTEM_OUT_KEY = "StdIo_System_Out"; - private static final String SYSTEM_ERR_KEY = "StdIo_System_Err"; private static final String STD_IN_KEY = "StdIo_Std_In"; @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Class type = parameterContext.getParameter().getType(); - return (type == StdIn.class || type == StdOut.class || type == StdErr.class); + return (type == StdIn.class || type == StdOut.class); } @Override @@ -47,8 +46,6 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte Class parameterType = parameterContext.getParameter().getType(); if (parameterType == StdOut.class) return prepareStdOut(extensionContext); - if (parameterType == StdErr.class) - return prepareStdErr(extensionContext); if (parameterType == StdIn.class) { String[] source = extensionContext.getRequiredTestMethod().getAnnotation(StdIo.class).value(); if (source.length == 0) @@ -95,21 +92,6 @@ private void swapAndStoreIn(ExtensionContext context, StdIn stdIn) { System.setIn(stdIn); //NOSONAR required to redirect output } - private StdErr prepareStdErr(ExtensionContext context) { - storeStdErr(context); - return createErr(); - } - - private void storeStdErr(ExtensionContext context) { - context.getStore(NAMESPACE).put(SYSTEM_ERR_KEY, System.err); //NOSONAR never writing to System.err, only storing it - } - - private StdErr createErr() { - StdErr err = new StdErr(); - System.setErr(new PrintStream(err)); - return err; - } - @Override public void beforeEach(ExtensionContext context) { String[] source = findClosestEnclosingAnnotation(context, StdIo.class) @@ -137,10 +119,6 @@ public void afterEach(ExtensionContext context) { PrintStream storedSystemOut = context.getStore(NAMESPACE).get(SYSTEM_OUT_KEY, PrintStream.class); if (storedSystemOut != null) System.setOut(storedSystemOut); //NOSONAR resetting input - - PrintStream storedSystemErr = context.getStore(NAMESPACE).get(SYSTEM_ERR_KEY, PrintStream.class); - if (storedSystemErr != null) - System.setErr(storedSystemErr); //NOSONAR resetting input } } diff --git a/src/main/java/org/junitpioneer/jupiter/StdOut.java b/src/main/java/org/junitpioneer/jupiter/StdOut.java index e4a845330..a035eb99f 100644 --- a/src/main/java/org/junitpioneer/jupiter/StdOut.java +++ b/src/main/java/org/junitpioneer/jupiter/StdOut.java @@ -10,6 +10,10 @@ package org.junitpioneer.jupiter; +import java.io.OutputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; + /** *

For details and examples, see * the documentation on Standard input/output @@ -17,5 +21,29 @@ * * @see StdIo */ -public class StdOut extends StdOutputStream { +public class StdOut extends OutputStream { + + private final StringWriter writer = new StringWriter(); + + public StdOut() { + // recreate default constructor to prevent compiler warning + } + + @Override + public void write(int i) { + writer.write(i); + } + + @Override + public final void write(byte[] b, int off, int len) { + writer.write(new String(b, Charset.defaultCharset()), off, len); + } + + /** + * @return the lines that were written to {@code System.out} + */ + public String[] capturedLines() { + return writer.toString().split(StdIoExtension.SEPARATOR); + } + } diff --git a/src/main/java/org/junitpioneer/jupiter/StdOutputStream.java b/src/main/java/org/junitpioneer/jupiter/StdOutputStream.java deleted file mode 100644 index 153d4606f..000000000 --- a/src/main/java/org/junitpioneer/jupiter/StdOutputStream.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2016-2022 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * http://www.eclipse.org/legal/epl-v20.html - */ - -package org.junitpioneer.jupiter; - -import java.io.OutputStream; -import java.io.StringWriter; -import java.nio.charset.Charset; - -abstract class StdOutputStream extends OutputStream { - - private final StringWriter writer = new StringWriter(); - - public StdOutputStream() { - // recreate default constructor to prevent compiler warning - } - - @Override - public void write(int i) { - writer.write(i); - } - - @Override - public final void write(byte[] b, int off, int len) { - writer.write(new String(b, Charset.defaultCharset()), off, len); - } - - /** - * @return the lines that were written to {@code System.out} or {@code System.err} - */ - public String[] capturedLines() { - return writer.toString().split(StdIoExtension.SEPARATOR); - } - -} diff --git a/src/main/java/org/junitpioneer/jupiter/WritesStdIo.java b/src/main/java/org/junitpioneer/jupiter/WritesStdIo.java index 70ecc057d..149d5dd49 100644 --- a/src/main/java/org/junitpioneer/jupiter/WritesStdIo.java +++ b/src/main/java/org/junitpioneer/jupiter/WritesStdIo.java @@ -21,8 +21,7 @@ import org.junit.jupiter.api.parallel.Resources; /** - * Marks tests that call {@code System.setIn()}, {@code System.setOut()} or {@code System.setErr()} to - * set the static fields {@code System.in}/{@code System.out}/{@code System.err}. + * Marks tests that call {@code System.setIn()} or {@code System.setOut()} to set the static fields {@code System.in}/{@code System.out}. * *

During * parallel test execution, @@ -41,6 +40,5 @@ @Inherited @ResourceLock(value = "java.lang.System.in", mode = ResourceAccessMode.READ_WRITE) @ResourceLock(value = Resources.SYSTEM_OUT, mode = ResourceAccessMode.READ_WRITE) -@ResourceLock(value = Resources.SYSTEM_ERR, mode = ResourceAccessMode.READ_WRITE) public @interface WritesStdIo { } diff --git a/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java b/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java index d749829d7..5c419e883 100644 --- a/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java +++ b/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java @@ -43,7 +43,6 @@ public class StdIoExtensionTests { private final BasicCommandLineApp app = new BasicCommandLineApp(); private final static PrintStream STDOUT = System.out; - private final static PrintStream STDERR = System.err; private final static InputStream STDIN = System.in; @Nested @@ -61,17 +60,6 @@ void catchesOut(StdOut out) { "Lifts up his burning head, each under eye"); } - @Test - @StdIo - @DisplayName("catches the output on the standard err as lines") - void catchesErr(StdErr err) { - app.writeErr(); - - assertThat(err.capturedLines()) - .containsExactly("Lo! in the orient when the gracious light", - "Lifts up his burning head, each under eye"); - } - @Test @StdIo({ "Doth homage to his new-appearing sight", "Serving with looks his sacred majesty;" }) @DisplayName("catches the input from the standard in") @@ -112,7 +100,7 @@ void catchesInWithoutParameter() throws IOException { app.read(); assertThat(app.lines) - .containsExactly("But when from highmost pitch, with weary car,", + .containsExactlyInAnyOrder("But when from highmost pitch, with weary car,", "Like feeble age, he reeleth from the day,"); } @@ -134,23 +122,21 @@ class ResettingTests { @Test @ReadsStdIo @Order(1) - @DisplayName("1: System.in, System.out and System.err is untouched") + @DisplayName("1: System.in and System.out is untouched") void untouched() { assertThat(System.in).isEqualTo(STDIN); assertThat(System.out).isEqualTo(STDOUT); - assertThat(System.err).isEqualTo(STDERR); } @Test @StdIo({ "From his low tract, and look another way:", "So thou, thyself outgoing in thy noon" }) @Order(2) - @DisplayName("2: System.in, System.out and System.err is redirected") - void redirected(StdIn in, StdOut out, StdErr err) throws IOException { + @DisplayName("2: System.in and System.out is redirected") + void redirected(StdIn in, StdOut out) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String line = reader.readLine(); System.out.println(line); - System.err.println(line); // even though `BufferedReader::readLine` was called just once, // both lines were read because the reader buffers @@ -158,21 +144,18 @@ void redirected(StdIn in, StdOut out, StdErr err) throws IOException { .containsExactlyInAnyOrder("From his low tract, and look another way:", "So thou, thyself outgoing in thy noon"); assertThat(out.capturedLines()).containsExactlyInAnyOrder("From his low tract, and look another way:"); - assertThat(err.capturedLines()).containsExactlyInAnyOrder("From his low tract, and look another way:"); assertThat(System.in).isNotEqualTo(STDIN); assertThat(System.out).isNotEqualTo(STDOUT); - assertThat(System.err).isNotEqualTo(STDERR); } @Test @ReadsStdIo @Order(3) - @DisplayName("3: System.in, System.out and System.err is reset to their original value") + @DisplayName("3: System.in and System.out is reset to their original value") void reset() { assertThat(System.in).isEqualTo(STDIN); assertThat(System.out).isEqualTo(STDOUT); - assertThat(System.err).isEqualTo(STDERR); } @Test @@ -193,11 +176,10 @@ void redirected_single_in(StdIn in) throws IOException { @Test @ReadsStdIo @Order(5) - @DisplayName("5: System.in is reset, System.out and System.err is unaffected.") + @DisplayName("5: System.in is reset, System.out is unaffected.") void reset_single_in() { assertThat(System.in).isEqualTo(STDIN); assertThat(System.out).isEqualTo(STDOUT); - assertThat(System.err).isEqualTo(STDERR); } @Test @@ -211,43 +193,16 @@ void redirected_single_out(StdOut out) { assertThat(out.capturedLines()).containsExactlyInAnyOrder("Shakespeare", "Sonnet VII"); assertThat(System.in).isEqualTo(STDIN); - assertThat(System.err).isEqualTo(STDERR); assertThat(System.out).isNotEqualTo(STDOUT); } @Test @ReadsStdIo @Order(7) - @DisplayName("7: System.out is reset, System.in and System.err is unaffected.") + @DisplayName("7: System.out is reset, System.in is unaffected.") void reset_single_out() { assertThat(System.in).isEqualTo(STDIN); assertThat(System.out).isEqualTo(STDOUT); - assertThat(System.err).isEqualTo(STDERR); - } - - @Test - @StdIo - @Order(6) - @DisplayName("6: Only System.err is redirected.") - void redirected_single_err(StdErr err) { - System.err.println("Mortal beauty"); - System.err.println("Gracious light"); - - assertThat(err.capturedLines()).containsExactlyInAnyOrder("Mortal beauty", "Gracious light"); - - assertThat(System.in).isEqualTo(STDIN); - assertThat(System.out).isEqualTo(STDOUT); - assertThat(System.err).isNotEqualTo(STDERR); - } - - @Test - @ReadsStdIo - @Order(7) - @DisplayName("7: System.err is reset, System.in and System.out is unaffected.") - void reset_single_err() { - assertThat(System.in).isEqualTo(STDIN); - assertThat(System.out).isEqualTo(STDOUT); - assertThat(System.err).isEqualTo(STDERR); } } @@ -330,12 +285,6 @@ public void write() { System.out.println("Lifts up his burning head, each under eye"); } - public void writeErr() { - System.err.print("Lo! in the orient "); - System.err.println("when the gracious light"); - System.err.println("Lifts up his burning head, each under eye"); - } - public void read() throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); lines.add(reader.readLine());