mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +02:00
8322141: SequenceInputStream.transferTo should not return as soon as Long.MAX_VALUE bytes have been transferred
Reviewed-by: vsitnikov, bpb, jpai
This commit is contained in:
parent
e0bad5153b
commit
2d609557ff
2 changed files with 50 additions and 2 deletions
|
@ -242,11 +242,14 @@ public class SequenceInputStream extends InputStream {
|
||||||
if (getClass() == SequenceInputStream.class) {
|
if (getClass() == SequenceInputStream.class) {
|
||||||
long transferred = 0;
|
long transferred = 0;
|
||||||
while (in != null) {
|
while (in != null) {
|
||||||
|
long numTransferred = in.transferTo(out);
|
||||||
|
// increment the total transferred byte count
|
||||||
|
// only if we haven't already reached the Long.MAX_VALUE
|
||||||
if (transferred < Long.MAX_VALUE) {
|
if (transferred < Long.MAX_VALUE) {
|
||||||
try {
|
try {
|
||||||
transferred = Math.addExact(transferred, in.transferTo(out));
|
transferred = Math.addExact(transferred, numTransferred);
|
||||||
} catch (ArithmeticException ignore) {
|
} catch (ArithmeticException ignore) {
|
||||||
return Long.MAX_VALUE;
|
transferred = Long.MAX_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextStream();
|
nextStream();
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.SequenceInputStream;
|
import java.io.SequenceInputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -39,6 +40,7 @@ import jdk.test.lib.RandomFactory;
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotEquals;
|
||||||
import static org.testng.Assert.assertThrows;
|
import static org.testng.Assert.assertThrows;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -126,6 +128,49 @@ public class TransferTo {
|
||||||
outputStreamProvider, createRandomBytes(4096, 0), 0, 4096);
|
outputStreamProvider, createRandomBytes(4096, 0), 0, 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special case: Assert subsequent input stream is read when preceding stream already was MAX_VALUE long.
|
||||||
|
* Note: Not testing actual content as it requires multiple GBs of memory and long time.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testHugeStream() throws Exception {
|
||||||
|
InputStream is1 = repeat(0, Long.MAX_VALUE);
|
||||||
|
InputStream is2 = repeat(0, 1);
|
||||||
|
assertNotEquals(is1.available(), 0);
|
||||||
|
assertNotEquals(is2.available(), 0);
|
||||||
|
SequenceInputStream sis = new SequenceInputStream(is1, is2);
|
||||||
|
OutputStream nos = OutputStream.nullOutputStream();
|
||||||
|
sis.transferTo(nos);
|
||||||
|
assertEquals(is1.available(), 0);
|
||||||
|
assertEquals(is2.available(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Produces an input stream that returns b count times.
|
||||||
|
* Builds a dysfunctional mock that solely implements
|
||||||
|
* available() and transferTo() particually,
|
||||||
|
* but fails with any other operation.
|
||||||
|
*/
|
||||||
|
private static InputStream repeat(int b, long count) {
|
||||||
|
return new InputStream() {
|
||||||
|
private long pos;
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return (int) Math.min(count - pos, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public long transferTo(OutputStream os) throws IOException {
|
||||||
|
// skipping actual writing to os to spare time
|
||||||
|
pos += count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Asserts that the transferred content is correct, i.e., compares the bytes
|
* Asserts that the transferred content is correct, i.e., compares the bytes
|
||||||
* actually transferred to those expected. The position of the input and
|
* actually transferred to those expected. The position of the input and
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue