This is an automated email from the ASF dual-hosted git repository.
laskoviymishka pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/main by this push:
new 089434ba2b Core: Fix ByteBufferInputStream.read() to return -1 at EOF
(#16167)
089434ba2b is described below
commit 089434ba2b3881f0fbd31968cf763001ed324c7a
Author: Sachin Ranjalkar <[email protected]>
AuthorDate: Sun May 17 01:25:51 2026 +0530
Core: Fix ByteBufferInputStream.read() to return -1 at EOF (#16167)
* Core: Fix ByteBufferInputStream.read() to return -1 at EOF instead of
throwing EOFException (#16127)
* Core: Enhance EOF test coverage for ByteBufferInputStream
Add read(byte[]) assertion to assertAtEOF helper to pin both overloads,
and add testDrainedMultiBufferStream to explicitly exercise the
nextBuffer() -> return -1 code path in MultiBufferInputStream.
---
.../apache/iceberg/io/MultiBufferInputStream.java | 4 +--
.../apache/iceberg/io/SingleBufferInputStream.java | 2 +-
.../iceberg/io/TestByteBufferInputStreams.java | 34 +++++++++++++++++++---
3 files changed, 33 insertions(+), 7 deletions(-)
diff --git
a/core/src/main/java/org/apache/iceberg/io/MultiBufferInputStream.java
b/core/src/main/java/org/apache/iceberg/io/MultiBufferInputStream.java
index 6d38497d22..fae2e615ef 100644
--- a/core/src/main/java/org/apache/iceberg/io/MultiBufferInputStream.java
+++ b/core/src/main/java/org/apache/iceberg/io/MultiBufferInputStream.java
@@ -263,7 +263,7 @@ class MultiBufferInputStream extends ByteBufferInputStream {
@Override
public int read() throws IOException {
if (current == null) {
- throw new EOFException();
+ return -1;
}
while (true) {
@@ -272,7 +272,7 @@ class MultiBufferInputStream extends ByteBufferInputStream {
return current.get() & 0xFF; // as unsigned
} else if (!nextBuffer()) {
// there are no more buffers
- throw new EOFException();
+ return -1;
}
}
}
diff --git
a/core/src/main/java/org/apache/iceberg/io/SingleBufferInputStream.java
b/core/src/main/java/org/apache/iceberg/io/SingleBufferInputStream.java
index fef2f9164f..50431faf7e 100644
--- a/core/src/main/java/org/apache/iceberg/io/SingleBufferInputStream.java
+++ b/core/src/main/java/org/apache/iceberg/io/SingleBufferInputStream.java
@@ -58,7 +58,7 @@ class SingleBufferInputStream extends ByteBufferInputStream {
@Override
public int read() throws IOException {
if (!buffer.hasRemaining()) {
- throw new EOFException();
+ return -1;
}
return buffer.get() & 0xFF; // as unsigned
}
diff --git
a/core/src/test/java/org/apache/iceberg/io/TestByteBufferInputStreams.java
b/core/src/test/java/org/apache/iceberg/io/TestByteBufferInputStreams.java
index c0850d82fa..fd2bd6a9d3 100644
--- a/core/src/test/java/org/apache/iceberg/io/TestByteBufferInputStreams.java
+++ b/core/src/test/java/org/apache/iceberg/io/TestByteBufferInputStreams.java
@@ -35,6 +35,15 @@ public abstract class TestByteBufferInputStreams {
protected abstract void checkOriginalData();
+ private static void assertAtEOF(ByteBufferInputStream stream) throws
IOException {
+ long pos = stream.getPos();
+ assertThat(stream.read()).as("read() at EOF").isEqualTo(-1);
+ assertThat(stream.read()).as("read() should keep returning -1 at
EOF").isEqualTo(-1);
+ assertThat(stream.read(new byte[1])).as("read(byte[]) at
EOF").isEqualTo(-1);
+ assertThat(stream.getPos()).as("Position should not advance past
EOF").isEqualTo(pos);
+ assertThat(stream.available()).as("available() should be 0 at
EOF").isEqualTo(0);
+ }
+
@Test
public void testRead0() throws Exception {
byte[] bytes = new byte[0];
@@ -67,7 +76,7 @@ public abstract class TestByteBufferInputStreams {
assertThat(stream.read(bytes)).as("Should return -1 at end of
stream").isEqualTo(-1);
- assertThat(stream.available()).as("Should have no more remaining
content").isEqualTo(0);
+ assertAtEOF(stream);
checkOriginalData();
}
@@ -102,7 +111,7 @@ public abstract class TestByteBufferInputStreams {
assertThat(stream.read(bytes)).as("Should return -1 at end of
stream").isEqualTo(-1);
- assertThat(stream.available()).as("Should have no more remaining
content").isEqualTo(0);
+ assertAtEOF(stream);
}
checkOriginalData();
@@ -142,7 +151,7 @@ public abstract class TestByteBufferInputStreams {
assertThat(stream.read(bytes)).as("Should return -1 at end of
stream").isEqualTo(-1);
- assertThat(stream.available()).as("Should have no more remaining
content").isEqualTo(0);
+ assertAtEOF(stream);
}
checkOriginalData();
@@ -158,7 +167,7 @@ public abstract class TestByteBufferInputStreams {
assertThat(stream.read()).isEqualTo(i);
}
-
assertThatThrownBy(stream::read).isInstanceOf(EOFException.class).hasMessage(null);
+ assertAtEOF(stream);
checkOriginalData();
}
@@ -532,4 +541,21 @@ public abstract class TestByteBufferInputStreams {
.isInstanceOf(IOException.class)
.hasMessageStartingWith("No mark defined");
}
+
+ @Test
+ public void testEmptyStream() throws Exception {
+ assertAtEOF(ByteBufferInputStream.wrap(ByteBuffer.allocate(0)));
+ assertAtEOF(ByteBufferInputStream.wrap(ByteBuffer.allocate(0),
ByteBuffer.allocate(0)));
+ assertAtEOF(ByteBufferInputStream.wrap(Collections.emptyList()));
+ }
+
+ @Test
+ public void testDrainedMultiBufferStream() throws Exception {
+ ByteBufferInputStream stream =
+ ByteBufferInputStream.wrap(
+ ByteBuffer.wrap(new byte[] {1, 2, 3}), ByteBuffer.wrap(new byte[]
{4, 5}));
+ byte[] buf = new byte[5];
+ assertThat(stream.read(buf)).as("Should read all bytes").isEqualTo(5);
+ assertAtEOF(stream);
+ }
}