diff --git a/src/main/java/org/junitpioneer/jupiter/StdIn.java b/src/main/java/org/junitpioneer/jupiter/StdIn.java index 13e4d95d8..c3d38dfba 100644 --- a/src/main/java/org/junitpioneer/jupiter/StdIn.java +++ b/src/main/java/org/junitpioneer/jupiter/StdIn.java @@ -27,14 +27,27 @@ public class StdIn extends InputStream { private final StringReader reader; private final StringWriter writer = new StringWriter(); + /** + * Keeps track of number of bytes that are still available to {@link InputStream#read() read()}. + */ + private int availableBytes; + public StdIn(String[] values) { - reader = new StringReader(String.join(StdIoExtension.SEPARATOR, values)); + var mockedInput = String.join(StdIoExtension.SEPARATOR, values); + reader = new StringReader(mockedInput); + availableBytes = mockedInput.getBytes().length; + } + + @Override + public int available() throws IOException { + return availableBytes; } @Override public int read() throws IOException { int reading = reader.read(); if (reading != -1) { + availableBytes--; writer.write(reading); } return reading; diff --git a/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java b/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java index a2e581305..1c55ffb33 100644 --- a/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java +++ b/src/test/java/org/junitpioneer/jupiter/StdIoExtensionTests.java @@ -106,6 +106,34 @@ void catchesNothing(StdIn in) { assertThat(in.capturedLines()).containsExactly(""); } + @Test + @StdIo({ "Doth homage to his new-appearing sight", "Serving with looks his sacred majesty;" }) + @DisplayName("for non-empty input, available() reports input's number of bytes") + void everythingAvailableBeforeRead(StdIn in) throws IOException { + int inputLength = ("Doth homage to his new-appearing sight" + System.getProperty("line.separator") + + "Serving with looks his sacred majesty;").getBytes().length; + + assertThat(in.available()).isEqualTo(inputLength); + } + + @Test + @StdIo({ "Doth homage to his new-appearing sight" }) + @DisplayName("for non-empty input after partial read, available() reports correctly reduced number of bytes") + void somethingAvailableAfterRead(StdIn in) throws IOException { + int bytesToRead = 16; + app.read(bytesToRead); + int remainingLength = "Doth homage to his new-appearing sight".getBytes().length - bytesToRead; + + assertThat(in.available()).isEqualTo(remainingLength); + } + + @Test + @StdIo("") + @DisplayName("for empty input, available() returns 0 available bytes") + void nothingAvailableWhenEmpty(StdIn in) throws IOException { + assertThat(in.available()).isEqualTo(0); + } + @Test @StdIo({ "And having climbed the steep-up heavenly hill,", "Resembling strong youth in his middle age," }) @DisplayName("catches the input from the standard in and the output on the standard out") @@ -357,6 +385,12 @@ public void read() throws IOException { lines.add(reader.readLine()); } + public void read(int byteCount) throws IOException { + for (int i = 0; i < byteCount; i++) { + System.in.read(); + } + } + public void readAndWrite() throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); lines.add(reader.readLine());