You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2024/08/07 02:11:42 UTC
(commons-io) 03/04: Revert *InputStream.read() should return -1 (EOF) after the stream is closed
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 cc62ff74731a880cd7b5f9cec8f011d20b3e9af3
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Aug 6 22:11:24 2024 -0400
Revert *InputStream.read() should return -1 (EOF) after the stream is
closed
- The InputStream#read(*) Javadocs suggests we should throw an
IOException in that case
- BOMInputStream
- ProxyInputStream
- BufferedFileChannelInputStream
- MemoryMappedFileInputStream
- RandomAccessFileInputStream
---
src/changes/changes.xml | 8 +----
.../commons/io/input/AbstractInputStream.java | 21 +++++++++++++
.../apache/commons/io/input/BOMInputStream.java | 4 +--
.../io/input/BufferedFileChannelInputStream.java | 4 +--
.../io/input/MemoryMappedFileInputStream.java | 10 +------
.../apache/commons/io/input/ProxyInputStream.java | 13 ++++++--
.../io/input/RandomAccessFileInputStream.java | 3 +-
.../apache/commons/io/input/ReaderInputStream.java | 4 +--
.../commons/io/input/BOMInputStreamTest.java | 6 ++--
.../input/BufferedFileChannelInputStreamTest.java | 4 +--
.../io/input/MemoryMappedFileInputStreamTest.java | 7 ++---
.../MessageDigestCalculatingInputStreamTest.java | 31 ++++++++++++++-----
.../io/input/MessageDigestInputStreamTest.java | 28 ++++++++++++-----
.../io/input/ObservableInputStreamTest.java | 29 +++++++++++++-----
.../commons/io/input/ProxyInputStreamTest.java | 35 ++++++++++++++++------
.../io/input/RandomAccessFileInputStreamTest.java | 3 +-
.../commons/io/input/ReaderInputStreamTest.java | 16 +++++-----
17 files changed, 143 insertions(+), 83 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1fb4418cd..b07c67c63 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -74,20 +74,14 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="fix" due-to="Gary Gregory">CircularInputStream.available() should return 0 when the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">InfiniteCircularInputStream.available() should return 0 when the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">ChecksumInputStream(InputStream, Checksum, long, long) should fail-fast on null Checksum input.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">BufferedFileChannelInputStream.read() should return -1 (EOF) after the stream is closed.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">BOMInputStream.read() should return -1 (EOF) after the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">Deprecate NullInputStream.INSTANCE in favor of constructors.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">NullInputStream.available() should return 0 after the stream is closed.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">NullInputStream.read() should return -1 (EOF) after the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">MemoryMappedFileInputStream.available() should return 0 after the stream is closed.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">MemoryMappedFileInputStream.read() should return -1 (EOF) after the stream is closed.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">ProxyInputStream.read() should return -1 (EOF) after the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">RandomAccessFileInputStream.available() should return 0 after the stream is closed.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">RandomAccessFileInputStream.read() should return -1 (EOF) after the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">ReaderInputStream.available() should return 0 after the stream is closed.</action>
- <action dev="ggregory" type="fix" due-to="Gary Gregory">ReaderInputStream.read() should return -1 (EOF) after the stream is closed.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">AutoCloseInputStream does not call handleIOException() on close() when the proxied stream throws an IOException.</action>
<action dev="ggregory" type="fix" due-to="Gary Gregory">BoundedInputStream does not call handleIOException() on close() when the proxied stream throws an IOException.</action>
+ <action dev="ggregory" type="fix" due-to="Gary Gregory">NullInputStream.read() can be configured to return -1 (EOF) after 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.18 #615, #621, #631, #635, #642.</action>
<action dev="ggregory" type="update" due-to="Dependabot">Bump tests commons-codec:commons-codec from 1.16.1 to 1.17.1 #644.</action>
diff --git a/src/main/java/org/apache/commons/io/input/AbstractInputStream.java b/src/main/java/org/apache/commons/io/input/AbstractInputStream.java
index 5c71facd1..e7f3c20c3 100644
--- a/src/main/java/org/apache/commons/io/input/AbstractInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/AbstractInputStream.java
@@ -27,11 +27,32 @@ import java.io.InputStream;
*/
public abstract class AbstractInputStream extends InputStream {
+ /**
+ * Throws an IOException on false input.
+ *
+ * @param isOpen whether the stream is open or not.
+ * @throws IOException if this instance is closed.
+ */
+ static void checkOpen(final boolean isOpen) throws IOException {
+ if (!isOpen) {
+ throw new IOException("The stream is closed.");
+ }
+ }
+
/**
* Whether {@link #close()} completed successfully.
*/
private boolean closed;
+ /**
+ * Checks if this instance is closed and throws an IOException if so.
+ *
+ * @throws IOException if this instance is closed.
+ */
+ void checkOpen() throws IOException {
+ checkOpen(!isClosed());
+ }
+
@Override
public void close() throws IOException {
super.close();
diff --git a/src/main/java/org/apache/commons/io/input/BOMInputStream.java b/src/main/java/org/apache/commons/io/input/BOMInputStream.java
index 7bd305b70..73dadaa9a 100644
--- a/src/main/java/org/apache/commons/io/input/BOMInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BOMInputStream.java
@@ -419,9 +419,7 @@ public class BOMInputStream extends ProxyInputStream {
*/
@Override
public int read() throws IOException {
- if (isClosed()) {
- return EOF;
- }
+ checkOpen();
final int b = readFirstBytes();
return b >= 0 ? b : in.read();
}
diff --git a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
index e503912b7..70075e3af 100644
--- a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
@@ -243,9 +243,7 @@ public final class BufferedFileChannelInputStream extends InputStream {
* @throws IOException if an I/O error occurs.
*/
private boolean refill() throws IOException {
- if (!fileChannel.isOpen()) {
- return false;
- }
+ AbstractInputStream.checkOpen(fileChannel.isOpen());
if (!byteBuffer.hasRemaining()) {
byteBuffer.clear();
int nRead = 0;
diff --git a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
index 02c02a9dc..4363d9599 100644
--- a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
@@ -170,12 +170,6 @@ public final class MemoryMappedFileInputStream extends AbstractInputStream {
return buffer.remaining();
}
- private void checkOpen() throws IOException {
- if (isClosed()) {
- throw new IOException("Stream closed");
- }
- }
-
private void cleanBuffer() {
if (ByteBufferCleaner.isSupported() && buffer.isDirect()) {
ByteBufferCleaner.clean(buffer);
@@ -210,9 +204,7 @@ public final class MemoryMappedFileInputStream extends AbstractInputStream {
@Override
public int read() throws IOException {
- if (isClosed()) {
- return EOF;
- }
+ checkOpen();
if (!buffer.hasRemaining()) {
nextBuffer();
if (!buffer.hasRemaining()) {
diff --git a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
index fd43678e8..523d07ab5 100644
--- a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
@@ -143,6 +143,15 @@ public abstract class ProxyInputStream extends FilterInputStream {
// no-op default
}
+ /**
+ * Checks if this instance is closed and throws an IOException if so.
+ *
+ * @throws IOException if this instance is closed.
+ */
+ void checkOpen() throws IOException {
+ AbstractInputStream.checkOpen(!isClosed());
+ }
+
/**
* Invokes the delegate's {@link InputStream#close()} method.
*
@@ -210,9 +219,6 @@ public abstract class ProxyInputStream extends FilterInputStream {
*/
@Override
public int read() throws IOException {
- if (isClosed()) {
- return EOF;
- }
try {
beforeRead(1);
final int b = in.read();
@@ -328,4 +334,5 @@ public abstract class ProxyInputStream extends FilterInputStream {
public InputStream unwrap() {
return in;
}
+
}
diff --git a/src/main/java/org/apache/commons/io/input/RandomAccessFileInputStream.java b/src/main/java/org/apache/commons/io/input/RandomAccessFileInputStream.java
index 3bb10c93d..afeccb4d5 100644
--- a/src/main/java/org/apache/commons/io/input/RandomAccessFileInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/RandomAccessFileInputStream.java
@@ -22,7 +22,6 @@ import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Objects;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.io.RandomAccessFileMode;
import org.apache.commons.io.build.AbstractOrigin;
import org.apache.commons.io.build.AbstractStreamBuilder;
@@ -210,7 +209,7 @@ public class RandomAccessFileInputStream extends AbstractInputStream {
@Override
public int read() throws IOException {
- return isClosed() ? IOUtils.EOF : randomAccessFile.read();
+ return randomAccessFile.read();
}
@Override
diff --git a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java
index 1b0ad36ea..3767029b9 100644
--- a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java
@@ -408,9 +408,7 @@ public class ReaderInputStream extends AbstractInputStream {
*/
@Override
public int read() throws IOException {
- if (isClosed()) {
- return EOF;
- }
+ checkOpen();
for (;;) {
if (encoderOut.hasRemaining()) {
return encoderOut.get() & 0xFF;
diff --git a/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java b/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java
index c5d914414..350d099d4 100644
--- a/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/BOMInputStreamTest.java
@@ -37,7 +37,6 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.io.ByteOrderMark;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SystemProperties;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
@@ -429,12 +428,11 @@ public class BOMInputStreamTest {
@Test
public void testReadAfterClose() throws Exception {
final byte[] data = { 'A', 'B', 'C', 'D' };
- final InputStream shadow;
try (InputStream in = BOMInputStream.builder().setInputStream(createUtf8Input(data, true)).get()) {
assertEquals(7, in.available());
- shadow = in;
+ in.close();
+ assertThrows(IOException.class, in::read);
}
- assertEquals(IOUtils.EOF, shadow.read());
}
@Test
diff --git a/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.java b/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.java
index 7c8baf0fe..1e1f6f46d 100644
--- a/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/BufferedFileChannelInputStreamTest.java
@@ -16,7 +16,6 @@
*/
package org.apache.commons.io.input;
-import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -24,7 +23,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.StandardOpenOption;
-import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -71,7 +69,7 @@ public class BufferedFileChannelInputStreamTest extends AbstractInputStreamTest
public void testReadAfterClose() throws Exception {
for (final InputStream inputStream : inputStreams) {
inputStream.close();
- assertEquals(IOUtils.EOF, inputStream.read());
+ assertThrows(IOException.class, inputStream::read);
}
}
diff --git a/src/test/java/org/apache/commons/io/input/MemoryMappedFileInputStreamTest.java b/src/test/java/org/apache/commons/io/input/MemoryMappedFileInputStreamTest.java
index 690c56c7f..0687a8200 100644
--- a/src/test/java/org/apache/commons/io/input/MemoryMappedFileInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/MemoryMappedFileInputStreamTest.java
@@ -19,6 +19,7 @@ package org.apache.commons.io.input;
import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY;
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 java.io.IOException;
import java.io.InputStream;
@@ -146,16 +147,14 @@ public class MemoryMappedFileInputStreamTest {
}
}
- @SuppressWarnings("resource")
@ParameterizedTest
@MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
public void testReadAfterClose(final int len) throws Exception {
final Path file = createTestFile(len);
- final InputStream shadow;
try (InputStream inputStream = newInputStream(file, 1024)) {
- shadow = inputStream;
+ inputStream.close();
+ assertThrows(IOException.class, inputStream::read);
}
- assertEquals(IOUtils.EOF, shadow.read());
}
@Test
diff --git a/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java b/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java
index e1038678f..46ae17641 100644
--- a/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/MessageDigestCalculatingInputStreamTest.java
@@ -20,10 +20,13 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.security.MessageDigest;
import org.apache.commons.codec.digest.DigestUtils;
@@ -39,8 +42,12 @@ import org.junit.jupiter.api.Test;
public class MessageDigestCalculatingInputStreamTest {
private InputStream createInputStream() throws IOException {
- return MessageDigestCalculatingInputStream.builder()
- .setInputStream(new ByteArrayInputStream(MessageDigestInputStreamTest.generateRandomByteStream(256))).get();
+ final ByteArrayInputStream origin = new ByteArrayInputStream(MessageDigestInputStreamTest.generateRandomByteStream(256));
+ return createInputStream(origin);
+ }
+
+ private MessageDigestCalculatingInputStream createInputStream(final InputStream origin) throws IOException {
+ return MessageDigestCalculatingInputStream.builder().setInputStream(origin).get();
}
@SuppressWarnings("resource")
@@ -111,15 +118,23 @@ public class MessageDigestCalculatingInputStreamTest {
}
}
- @SuppressWarnings("resource")
@Test
- public void testReadAfterClose() throws Exception {
- final InputStream shadow;
+ public void testReadAfterClose_ByteArrayInputStream() throws Exception {
try (InputStream in = createInputStream()) {
- assertTrue(in.available() > 0);
- shadow = in;
+ in.close();
+ // ByteArrayInputStream does not throw on a closed stream.
+ assertNotEquals(IOUtils.EOF, in.read());
+ }
+ }
+
+ @SuppressWarnings("resource")
+ @Test
+ public void testReadAfterClose_ChannelInputStream() throws Exception {
+ try (InputStream in = createInputStream(Files.newInputStream(Paths.get("src/test/resources/org/apache/commons/io/abitmorethan16k.txt")))) {
+ in.close();
+ // ChannelInputStream throws when closed
+ assertThrows(IOException.class, in::read);
}
- assertEquals(IOUtils.EOF, shadow.read());
}
}
diff --git a/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java b/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java
index 3f6f263ff..8f7208e08 100644
--- a/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/MessageDigestInputStreamTest.java
@@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
@@ -47,10 +49,15 @@ public class MessageDigestInputStreamTest {
}
private InputStream createInputStream() throws IOException, NoSuchAlgorithmException {
+ return createInputStream(new ByteArrayInputStream(MessageDigestInputStreamTest.generateRandomByteStream(256)));
+ }
+
+ private InputStream createInputStream(final InputStream origin) throws IOException, NoSuchAlgorithmException {
// @formatter:off
return MessageDigestInputStream.builder()
.setMessageDigest(MessageDigest.getInstance(MessageDigestAlgorithms.SHA_512))
- .setInputStream(new ByteArrayInputStream(MessageDigestInputStreamTest.generateRandomByteStream(256))).get();
+ .setInputStream(origin)
+ .get();
// @formatter:on
}
@@ -98,15 +105,22 @@ public class MessageDigestInputStreamTest {
}
}
- @SuppressWarnings("resource")
@Test
- public void testReadAfterClose() throws Exception {
- final InputStream shadow;
+ public void testReadAfterClose_ByteArrayInputStream() throws Exception {
try (InputStream in = createInputStream()) {
- assertTrue(in.available() > 0);
- shadow = in;
+ in.close();
+ assertNotEquals(IOUtils.EOF, in.read());
+ }
+ }
+
+ @SuppressWarnings("resource")
+ @Test
+ public void testReadAfterClose_ChannelInputStream() throws Exception {
+ try (InputStream in = createInputStream(Files.newInputStream(Paths.get("src/test/resources/org/apache/commons/io/abitmorethan16k.txt")))) {
+ in.close();
+ // ChannelInputStream throws when closed
+ assertThrows(IOException.class, in::read);
}
- assertEquals(IOUtils.EOF, shadow.read());
}
}
diff --git a/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java b/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java
index 685cfd56d..f45861403 100644
--- a/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/ObservableInputStreamTest.java
@@ -25,6 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ObservableInputStream.Observer;
@@ -134,7 +136,11 @@ public class ObservableInputStreamTest {
private InputStream createInputStream() {
final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
- return new ObservableInputStream(new ByteArrayInputStream(buffer));
+ return createInputStream(new ByteArrayInputStream(buffer));
+ }
+
+ private ObservableInputStream createInputStream(final InputStream origin) {
+ return new ObservableInputStream(origin);
}
@SuppressWarnings("resource")
@@ -246,7 +252,7 @@ public class ObservableInputStreamTest {
public void testDataBytesCalled() throws Exception {
final byte[] buffer = MessageDigestInputStreamTest.generateRandomByteStream(IOUtils.DEFAULT_BUFFER_SIZE);
try (ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
- final ObservableInputStream ois = new ObservableInputStream(bais)) {
+ final ObservableInputStream ois = createInputStream(bais)) {
final DataViewObserver observer = new DataViewObserver();
final byte[] readBuffer = new byte[23];
assertNull(observer.buffer);
@@ -333,15 +339,22 @@ public class ObservableInputStreamTest {
testNotificationCallbacks(IOUtils.DEFAULT_BUFFER_SIZE);
}
- @SuppressWarnings("resource")
@Test
- public void testReadAfterClose() throws Exception {
- final InputStream shadow;
+ public void testReadAfterClose_ByteArrayInputStream() throws Exception {
try (InputStream in = createInputStream()) {
- assertTrue(in.available() > 0);
- shadow = in;
+ in.close();
+ assertNotEquals(IOUtils.EOF, in.read());
+ }
+ }
+
+ @SuppressWarnings("resource")
+ @Test
+ public void testReadAfterClose_ChannelInputStream() throws Exception {
+ try (InputStream in = createInputStream(Files.newInputStream(Paths.get("src/test/resources/org/apache/commons/io/abitmorethan16k.txt")))) {
+ in.close();
+ // ChannelInputStream throws when closed
+ assertThrows(IOException.class, in::read);
}
- assertEquals(IOUtils.EOF, shadow.read());
}
}
diff --git a/src/test/java/org/apache/commons/io/input/ProxyInputStreamTest.java b/src/test/java/org/apache/commons/io/input/ProxyInputStreamTest.java
index b6d44fdff..db047b1e0 100644
--- a/src/test/java/org/apache/commons/io/input/ProxyInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/ProxyInputStreamTest.java
@@ -20,6 +20,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.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -30,6 +31,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.Arrays;
import org.apache.commons.io.IOUtils;
@@ -188,18 +191,32 @@ public class ProxyInputStreamTest<T extends ProxyInputStream> {
}
}
- @SuppressWarnings("resource")
@Test
- public void testReadAfterClose() throws IOException {
- InputStream shadow;
- try (InputStream inputStream = createFixture()) {
- shadow = inputStream;
- }
- assertEquals(IOUtils.EOF, shadow.read());
+ public void testReadAfterClose_ByteArrayInputStream() throws IOException {
try (InputStream inputStream = new ProxyInputStreamFixture(new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8)))) {
- shadow = inputStream;
+ inputStream.close();
+ // ByteArrayInputStream does not throw on a closed stream.
+ assertNotEquals(IOUtils.EOF, inputStream.read());
+ }
+ }
+
+ @Test
+ public void testReadAfterClose_ChannelInputStream() throws IOException {
+ try (InputStream inputStream = new ProxyInputStreamFixture(
+ Files.newInputStream(Paths.get("src/test/resources/org/apache/commons/io/abitmorethan16k.txt")))) {
+ inputStream.close();
+ // ChannelInputStream throws when closed
+ assertThrows(IOException.class, inputStream::read);
+ }
+ }
+
+ @Test
+ public void testReadAfterClose_CharSequenceInputStream() throws IOException {
+ try (InputStream inputStream = createFixture()) {
+ inputStream.close();
+ // CharSequenceInputStream (like ByteArrayInputStream) does not throw on a closed stream.
+ assertEquals(IOUtils.EOF, inputStream.read());
}
- assertEquals(IOUtils.EOF, shadow.read());
}
@Test
diff --git a/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.java b/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.java
index 56880152a..08540914b 100644
--- a/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/RandomAccessFileInputStreamTest.java
@@ -33,7 +33,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.io.RandomAccessFileMode;
import org.junit.jupiter.api.Test;
@@ -205,7 +204,7 @@ public class RandomAccessFileInputStreamTest {
try (RandomAccessFileInputStream inputStream = new RandomAccessFileInputStream(createRandomAccessFile(),
true)) {
inputStream.close();
- assertEquals(IOUtils.EOF, inputStream.read());
+ assertThrows(IOException.class, inputStream::read);
}
}
diff --git a/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java b/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
index d89ac3a1b..b4322a368 100644
--- a/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/input/ReaderInputStreamTest.java
@@ -257,6 +257,14 @@ public class ReaderInputStreamTest {
testWithSingleByteRead(LARGE_TEST_STRING, UTF_8);
}
+ @Test
+ public void testReadAfterClose() throws IOException {
+ try (InputStream inputStream = createInputStream()) {
+ inputStream.close();
+ assertThrows(IOException.class, inputStream::read);
+ }
+ }
+
@Test
public void testReadEofTwice() throws IOException {
try (ReaderInputStream reader = ReaderInputStream.builder().setCharset(StandardCharsets.UTF_8).setReader(new StringReader("123")).get()) {
@@ -301,14 +309,6 @@ public class ReaderInputStreamTest {
}
}
- @Test
- public void testReadAfterClose() throws IOException {
- try (InputStream inputStream = createInputStream()) {
- inputStream.close();
- assertEquals(IOUtils.EOF, inputStream.read());
- }
- }
-
@Test
public void testResetCharset() {
assertNotNull(ReaderInputStream.builder().setReader(new StringReader("\uD800")).setCharset((Charset) null).getCharset());