This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit a3d1c9837b64fc611546db38ed485da1e0553478 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Sun Jul 7 17:51:01 2024 -0400 InfiniteCircularInputStream.available() should return 0 when the stream is closed --- src/changes/changes.xml | 1 + .../commons/io/input/CircularInputStream.java | 5 ++- .../io/input/InfiniteCircularInputStreamTest.java | 46 ++++++++++++++++++++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2cea2bae5..b735c6121 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -67,6 +67,7 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="add" due-to="Gary Gregory">CharSequenceInputStream.available() should return 0 after the stream is closed.</action> <action dev="ggregory" type="add" due-to="Gary Gregory">BoundedInputStream.available() should return 0 when the stream is closed.</action> <action dev="ggregory" type="add" due-to="Gary Gregory">CircularInputStream.available() should return 0 when the stream is closed.</action> + <action dev="ggregory" type="add" due-to="Gary Gregory">InfiniteCircularInputStream.available() should return 0 when the stream is closed.</action> <!-- UPDATE --> <action dev="ggregory" type="update" due-to="Dependabot">Bump tests commons.bytebuddy.version from 1.14.13 to 1.14.17 #615, #621, #631, #635.</action> <action dev="ggregory" type="update" due-to="Dependabot">Bump tests commons-codec:commons-codec from 1.16.1 to 1.17.0.</action> diff --git a/src/main/java/org/apache/commons/io/input/CircularInputStream.java b/src/main/java/org/apache/commons/io/input/CircularInputStream.java index 1376e009d..d508675b1 100644 --- a/src/main/java/org/apache/commons/io/input/CircularInputStream.java +++ b/src/main/java/org/apache/commons/io/input/CircularInputStream.java @@ -72,7 +72,8 @@ public class CircularInputStream extends InputStream { @Override public int available() throws IOException { - return closed ? 0 : targetByteCount <= Integer.MAX_VALUE ? (int) targetByteCount : Integer.MAX_VALUE; + // A negative targetByteCount means an infinite target count. + return closed ? 0 : targetByteCount <= Integer.MAX_VALUE ? Math.max(Integer.MAX_VALUE, (int) targetByteCount) : Integer.MAX_VALUE; } @Override @@ -83,7 +84,7 @@ public class CircularInputStream extends InputStream { @Override public int read() { - if (targetByteCount >= 0) { + if (targetByteCount >= 0 || closed) { if (byteCount == targetByteCount) { return IOUtils.EOF; } diff --git a/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.java b/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.java index 67baacaa0..451d289ef 100644 --- a/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.java +++ b/src/test/java/org/apache/commons/io/input/InfiniteCircularInputStreamTest.java @@ -19,6 +19,7 @@ package org.apache.commons.io.input; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.InputStream; @@ -34,10 +35,8 @@ public class InfiniteCircularInputStreamTest { private void assertStreamOutput(final byte[] toCycle, final byte[] expected) throws IOException { final byte[] actual = new byte[expected.length]; - try (InputStream infStream = new InfiniteCircularInputStream(toCycle)) { final int actualReadBytes = infStream.read(actual); - assertArrayEquals(expected, actual); assertEquals(expected.length, actualReadBytes); } @@ -47,6 +46,33 @@ public class InfiniteCircularInputStreamTest { return new InfiniteCircularInputStream(repeatContent); } + @SuppressWarnings("resource") + @Test + public void testAvailableAfterClose() throws Exception { + final InputStream shadow; + try (InputStream in = createInputStream(new byte[] { 1, 2 })) { + assertTrue(in.available() > 0); + assertEquals(1, in.read()); + assertEquals(2, in.read()); + assertEquals(1, in.read()); + shadow = in; + } + assertEquals(0, shadow.available()); + } + + @Test + public void testAvailableAfterOpen() throws Exception { + try (InputStream in = createInputStream(new byte[] { 1, 2 })) { + assertTrue(in.available() > 0); + assertEquals(1, in.read()); + assertTrue(in.available() > 0); + assertEquals(2, in.read()); + assertTrue(in.available() > 0); + assertEquals(1, in.read()); + assertTrue(in.available() > 0); + } + } + @Test public void testContainsEofInputSize0() { assertThrows(IllegalArgumentException.class, () -> createInputStream(new byte[] { -1 })); @@ -85,6 +111,20 @@ public class InfiniteCircularInputStreamTest { assertThrows(NullPointerException.class, () -> createInputStream(null)); } + @SuppressWarnings("resource") + @Test + public void testReadAfterClose() throws Exception { + final InputStream shadow; + try (InputStream in = createInputStream(new byte[] { 1, 2 })) { + assertTrue(in.available() > 0); + assertEquals(1, in.read()); + assertEquals(2, in.read()); + assertEquals(1, in.read()); + shadow = in; + } + assertEquals(IOUtils.EOF, shadow.read()); + } + @Test public void testWholeRangeOfBytes() throws IOException { final int size = Byte.MAX_VALUE - Byte.MIN_VALUE + 1; @@ -94,9 +134,7 @@ public class InfiniteCircularInputStreamTest { contentToCycle[i] = value == IOUtils.EOF ? 0 : value; value++; } - final byte[] expectedOutput = Arrays.copyOf(contentToCycle, size); - assertStreamOutput(contentToCycle, expectedOutput); }