/*
* Copyright ( c ) 2021 , 2022 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*/
/*
* @ test
* @ bug 8268435 8274780
* @ summary Verify ChannelInputStream methods readAllBytes and readNBytes
* @ requires ( sun . arch . data . model = = " 64 " & os . maxMemory > = 16 g )
* @ library . .
* @ library / test / lib
* @ build jdk . test . lib . RandomFactory
* @ modules java . base / jdk . internal . util
* @ run testng / othervm / timeout = 900 - Xmx12G ReadXBytes
* @ key randomness
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Random;
import jdk.internal.util.ArraysSupport;
import static java.nio.file.StandardOpenOption.*;
import jdk.test.lib.RandomFactory;
import org.testng.Assert ;
import static org.testng.Assert .assertEquals;
import static org.testng.Assert .assertNotNull;
import static org.testng.Assert .assertThrows;
import static org.testng.Assert .assertFalse;
import static org.testng.Assert .assertTrue;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ReadXBytes {
private static final Random RAND = RandomFactory.getRandom();
// The largest source from which to read all bytes
private static final int BIG_LENGTH = ArraysSupport.SOFT_MAX_ARRAY_LENGTH;
// A length greater than a 32-bit integer can accommodate
private static final long HUGE_LENGTH = Integer.MAX_VALUE + 27 L;
// Current directory
private static final Path DIR = Path.of(System.getProperty("test.dir" , "." ));
// --- Framework ---
// Create a temporary file path
static Path createFilePath() {
String name = String.format("ReadXBytes%d.tmp" , System.nanoTime());
return DIR.resolve(name);
}
// Creates a temporary file of a specified length with undefined content
static Path createFile(long length) throws IOException {
Path path = createFilePath();
path.toFile().deleteOnExit();
try (FileChannel fc = FileChannel.open(path, CREATE_NEW, SPARSE, WRITE)) {
if (length > 0 ) {
fc.position(length - 1 );
fc.write(ByteBuffer.wrap(new byte [] {27 }));
}
}
return path;
}
// Creates a temporary file of a specified length with random content
static Path createFileWithRandomContent(long length) throws IOException {
Path file = createFile(length);
try (FileChannel fc = FileChannel.open(file, WRITE)) {
if (length < 65536 ) {
// if the length is less than 64k, write the entire file
byte [] buf = new byte [(int )length];
RAND.nextBytes(buf);
ByteBuffer bb = ByteBuffer.wrap(buf);
while (bb.hasRemaining()) {
fc.write(bb);
}
} else {
// write the first and the last 32k only
byte [] buf = new byte [32768 ];
RAND.nextBytes(buf);
ByteBuffer bb = ByteBuffer.wrap(buf);
while (bb.hasRemaining()) {
fc.write(bb);
}
bb.clear();
fc.position(length - buf.length);
RAND.nextBytes(buf);
while (bb.hasRemaining()) {
fc.write(bb);
}
}
}
return file;
}
// Creates a file of a specified length
@FunctionalInterface
interface FileCreator {
Path create(long length) throws IOException;
}
// Performs a test for checking edge cases
@FunctionalInterface
interface EdgeTest {
void test(long length, InputStream source) throws IOException;
}
// Performs a test for evaluating correctness of content
@FunctionalInterface
interface DataTest {
void test(long length, InputStream source, InputStream reference)
throws IOException;
}
// Construct for testing zero length, EOF, and IAE
public void edgeTest(long length, FileCreator c, EdgeTest f)
throws IOException {
Path file = c.create(length);
try (FileChannel fc = FileChannel.open(file, READ);
InputStream cis = Channels.newInputStream(fc)) {
f.test(length, cis);
} finally {
Files.delete (file);
}
}
// Construct for testing correctness of content
public void dataTest(long length, FileCreator c, DataTest f)
throws IOException {
Path file = c.create(length);
try {
for (boolean seekable : List.of(false , true )) {
try (FileInputStream fis = new FileInputStream(file.toFile())) {
ReadableByteChannel ch;
if (seekable) {
ch = FileChannel.open(file, READ);
} else {
InputStream fis2 = new FileInputStream(file.toFile());
ch = Channels.newChannel(new FilterInputStream(fis2) {});
assertFalse(ch instanceof SeekableByteChannel);
}
try (InputStream cis = Channels.newInputStream(ch)) {
f.test(length, cis, fis);
}
}
}
} finally {
Files.delete (file);
}
}
// --- readAllBytes tests ---
// Verifies readAllBytes() behavior for an empty file
@Test
public void readAllBytesFromEmptyFile() throws IOException {
edgeTest(0 L, (length) -> createFile(length),
(length, cis) -> {
byte [] bytes = cis.readAllBytes();
assertNotNull(bytes);
assertEquals(bytes.length, 0 L);
}
);
}
// Verifies readAllBytes() behavior at EOF
@Test
public void readAllBytesAtEOF() throws IOException {
edgeTest(RAND.nextInt(Short .MAX_VALUE), (length) -> createFile(length),
(length, cis) -> {
cis.skipNBytes(length);
byte [] bytes = cis.readAllBytes();
assertNotNull(bytes);
assertEquals(bytes.length, 0 );
}
);
}
// Verifies readAllBytes() behavior for a maximal length source
@Test
public void readAllBytesFromMaxLengthFile() throws IOException {
dataTest(BIG_LENGTH, (length) -> createFileWithRandomContent(length),
(length, cis, fis) -> {
byte [] cisBytes = cis.readAllBytes();
assertNotNull(cisBytes);
assertEquals(cisBytes.length, (long )length);
byte [] fisBytes = fis.readAllBytes();
assertEquals(cisBytes, fisBytes);
}
);
}
// Verifies readAllBytes() throws OOME if the source is too large
@Test
public void readAllBytesFromBeyondMaxLengthFile() throws IOException {
dataTest(HUGE_LENGTH, (length) -> createFile(length),
(length, cis, fis) -> {
assertThrows(OutOfMemoryError.class ,
() -> {cis.readAllBytes();});
}
);
}
// Provides an array of lengths
@DataProvider
public Object[][] lengthProvider() throws IOException {
return new Object[][] {
{1 + RAND.nextInt(1 )},
{1 + RAND.nextInt(Byte .MAX_VALUE)},
{1 + RAND.nextInt(Short .MAX_VALUE)},
{1 + RAND.nextInt(1 _000 _000 )},
{1 + RAND.nextInt(BIG_LENGTH)}
};
}
// Verifies readAllBytes() accuracy for random lengths and initial positions
@Test(dataProvider = "lengthProvider" )
public void readAllBytes(int len) throws IOException {
dataTest(len, (length) -> createFileWithRandomContent(length),
(length, cis, fis) -> {
long position = RAND.nextInt(Math.toIntExact(length));
cis.skipNBytes(position);
byte [] cisBytes = cis.readAllBytes();
assertNotNull(cisBytes);
assertEquals(cisBytes.length, length - position);
fis.skipNBytes(position);
byte [] fisBytes = fis.readAllBytes();
assertEquals(cisBytes, fisBytes);
}
);
}
// --- readNBytes tests ---
// Verifies readNBytes() behavior for a negative length
@Test
public void readNBytesWithNegativeLength() throws IOException {
edgeTest(0 L, (length) -> createFile(length),
(length, cis) -> {
assertThrows(IllegalArgumentException.class ,
() -> {cis.readNBytes(-1 );});
}
);
}
// Verifies readNBytes() for an empty file
@Test
public void readNBytesFromEmptyFile() throws IOException {
edgeTest(0 L, (length) -> createFile(length),
(length, cis) -> {
byte [] bytes = cis.readNBytes(1 );
assertNotNull(bytes);
assertEquals(bytes.length, 0 );
}
);
}
// Verifies readNBytes() behavior at EOF
@Test
public void readNBytesAtEOF() throws IOException {
edgeTest(RAND.nextInt(Short .MAX_VALUE), (length) -> createFile(length),
(length, cis) -> {
cis.skipNBytes(length);
byte [] bytes = cis.readNBytes(1 );
assertNotNull(bytes);
assertEquals(bytes.length, 0 );
}
);
}
// Verifies readNBytes() behavior for a maximal length source
@Test
public void readNBytesFromMaxLengthFile() throws IOException {
dataTest(BIG_LENGTH, (length) -> createFileWithRandomContent(length),
(length, cis, fis) -> {
byte [] cisBytes = cis.readNBytes(BIG_LENGTH);
assertNotNull(cisBytes);
assertEquals(cisBytes.length, (long )length);
byte [] fisBytes = fis.readNBytes(BIG_LENGTH);
assertEquals(cisBytes, fisBytes);
}
);
}
// Verifies readNBytes() beyond the maximum length source
@Test
public void readNBytesFromBeyondMaxLengthFile() throws IOException {
dataTest(HUGE_LENGTH, (length) -> createFileWithRandomContent(length),
(length, cis, fis) -> {
assertTrue(BIG_LENGTH < length, length + " >= " + HUGE_LENGTH);
int n = Math.toIntExact(length - BIG_LENGTH);
cis.skipNBytes(BIG_LENGTH);
byte [] cisBytes = cis.readNBytes(n);
assertNotNull(cisBytes);
assertEquals(cisBytes.length, n);
fis.skipNBytes(BIG_LENGTH);
byte [] fisBytes = fis.readNBytes(n);
assertEquals(cisBytes, fisBytes);
}
);
}
// Verifies readNBytes() accuracy for random lengths and initial positions
@Test(dataProvider = "lengthProvider" )
public void readNBytes(int len) throws IOException {
dataTest(len, (length) -> createFileWithRandomContent(length),
(length, cis, fis) -> {
int ilen = Math.toIntExact(len);
int position = RAND.nextInt(ilen);
int n = RAND.nextInt(ilen - position);
cis.skipNBytes(position);
byte [] cisBytes = cis.readNBytes(n);
assertNotNull(cisBytes);
assertEquals(cisBytes.length, n);
fis.skipNBytes(position);
byte [] fisBytes = fis.readNBytes(n);
assertEquals(cisBytes, fisBytes);
}
);
}
}
Messung V0.5 in Prozent C=94 H=90 G=91
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland