Skip to content

Commit 7ea4b19

Browse files
author
Brian Burkhalter
committed
8278166: java/nio/channels/Channels/TransferTo.java timed out
Reviewed-by: lancea, alanb
1 parent 543d1a8 commit 7ea4b19

File tree

1 file changed

+95
-53
lines changed

1 file changed

+95
-53
lines changed

test/jdk/java/nio/channels/Channels/TransferTo.java

Lines changed: 95 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323

2424
import java.io.ByteArrayInputStream;
2525
import java.io.ByteArrayOutputStream;
26-
import java.io.IOException;
2726
import java.io.InputStream;
27+
import java.io.IOException;
2828
import java.io.OutputStream;
29+
import java.nio.ByteBuffer;
2930
import java.nio.channels.Channels;
3031
import java.nio.channels.FileChannel;
3132
import java.nio.channels.IllegalBlockingModeException;
@@ -51,6 +52,7 @@
5152
import jdk.test.lib.RandomFactory;
5253

5354
import static java.lang.String.format;
55+
import static java.nio.file.StandardOpenOption.*;
5456

5557
import static org.testng.Assert.assertEquals;
5658
import static org.testng.Assert.assertThrows;
@@ -62,8 +64,8 @@
6264
* @build jdk.test.lib.RandomFactory
6365
* @run testng/othervm/timeout=180 TransferTo
6466
* @bug 8265891
65-
* @summary tests whether sun.nio.ChannelInputStream.transferTo conforms to the
66-
* InputStream.transferTo contract defined in the javadoc
67+
* @summary Tests whether sun.nio.ChannelInputStream.transferTo conforms to the
68+
* InputStream.transferTo specification
6769
* @key randomness
6870
*/
6971
public class TransferTo {
@@ -72,27 +74,30 @@ public class TransferTo {
7274

7375
private static final int ITERATIONS = 10;
7476

75-
private static final int NUM_WRITES = 3 * 1024;
76-
private static final int BYTES_PER_WRITE = 1024 * 1024;
77-
private static final long BYTES_WRITTEN = (long) NUM_WRITES * BYTES_PER_WRITE;
77+
private static final int NUM_WRITES = 3*1024;
78+
private static final int BYTES_PER_WRITE = 1024*1024;
79+
private static final long BYTES_WRITTEN = (long) NUM_WRITES*BYTES_PER_WRITE;
7880

7981
private static final Random RND = RandomFactory.getRandom();
8082

8183
private static final Path CWD = Path.of(".");
8284

8385
/*
84-
* Provides test scenarios, i. e. combinations of input and output streams to be tested.
86+
* Provides test scenarios, i.e., combinations of input and output streams
87+
* to be tested.
8588
*/
8689
@DataProvider
8790
public static Object[][] streamCombinations() throws Exception {
8891
return new Object[][] {
8992
// tests FileChannel.transferTo(FileChannel) optimized case
9093
{ fileChannelInput(), fileChannelOutput() },
9194

92-
// tests FileChannel.transferTo(SelectableChannelOutput) optimized case
95+
// tests FileChannel.transferTo(SelectableChannelOutput)
96+
// optimized case
9397
{ fileChannelInput(), selectableChannelOutput() },
9498

95-
// tests FileChannel.transferTo(WritableChannelOutput) optimized case
99+
// tests FileChannel.transferTo(WritableChannelOutput)
100+
// optimized case
96101
{ fileChannelInput(), writableByteChannelOutput() },
97102

98103
// tests InputStream.transferTo(OutputStream) default case
@@ -101,7 +106,8 @@ public static Object[][] streamCombinations() throws Exception {
101106
}
102107

103108
/*
104-
* Testing API compliance: Input stream must throw NullPointerException when parameter "out" is null.
109+
* Testing API compliance: input stream must throw NullPointerException
110+
* when parameter "out" is null.
105111
*/
106112
@Test(dataProvider = "streamCombinations")
107113
public void testNullPointerException(InputStreamProvider inputStreamProvider,
@@ -117,7 +123,8 @@ public void testNullPointerException(InputStreamProvider inputStreamProvider,
117123
}
118124

119125
/*
120-
* Testing API compliance: Complete content of input stream must be transferred to output stream.
126+
* Testing API compliance: complete content of input stream must be
127+
* transferred to output stream.
121128
*/
122129
@Test(dataProvider = "streamCombinations")
123130
public void testStreamContents(InputStreamProvider inputStreamProvider,
@@ -128,10 +135,12 @@ public void testStreamContents(InputStreamProvider inputStreamProvider,
128135
// tests input stream with a length between 1k and 4k
129136
checkTransferredContents(inputStreamProvider, outputStreamProvider, createRandomBytes(1024, 4096));
130137

131-
// tests input stream with several data chunks, as 16k is more than a single chunk can hold
138+
// tests input stream with several data chunks, as 16k is more than a
139+
// single chunk can hold
132140
checkTransferredContents(inputStreamProvider, outputStreamProvider, createRandomBytes(16384, 16384));
133141

134-
// tests randomly chosen starting positions within source and target stream
142+
// tests randomly chosen starting positions within source and
143+
// target stream
135144
for (int i = 0; i < ITERATIONS; i++) {
136145
byte[] inBytes = createRandomBytes(MIN_SIZE, MAX_SIZE_INCR);
137146
int posIn = RND.nextInt(inBytes.length);
@@ -147,34 +156,60 @@ public void testStreamContents(InputStreamProvider inputStreamProvider,
147156
}
148157

149158
/*
150-
* Special test for file-to-file transfer of more than two GB.
151-
* This test covers multiple iterations of FileChannel.transerTo(FileChannel),
152-
* which ChannelInputStream.transferTo() only applies in this particular case,
153-
* and cannot get tested using a single byte[] due to size limitation of arrays.
159+
* Special test for file-to-file transfer of more than 2 GB. This test
160+
* covers multiple iterations of FileChannel.transerTo(FileChannel),
161+
* which ChannelInputStream.transferTo() only applies in this particular
162+
* case, and cannot get tested using a single byte[] due to size limitation
163+
* of arrays.
154164
*/
155165
@Test
156166
public void testMoreThanTwoGB() throws IOException {
157-
Path sourceFile = Files.createTempFile(CWD, "test2GBSource", null);
167+
// prepare two temporary files to be compared at the end of the test
168+
// set the source file name
169+
String sourceName = String.format("test3GBSource%s.tmp",
170+
String.valueOf(RND.nextInt(Integer.MAX_VALUE)));
171+
Path sourceFile = CWD.resolve(sourceName);
172+
158173
try {
159-
// preparing two temporary files which will be compared at the end of the test
160-
Path targetFile = Files.createTempFile(CWD, "test2GBtarget", null);
174+
// set the target file name
175+
String targetName = String.format("test3GBTarget%s.tmp",
176+
String.valueOf(RND.nextInt(Integer.MAX_VALUE)));
177+
Path targetFile = CWD.resolve(targetName);
178+
161179
try {
162-
// writing 3 GB of random bytes into source file
163-
for (int i = 0; i < NUM_WRITES; i++)
164-
Files.write(sourceFile, createRandomBytes(BYTES_PER_WRITE, 0), StandardOpenOption.APPEND);
180+
// calculate initial position to be just short of 2GB
181+
final long initPos = 2047*BYTES_PER_WRITE;
182+
183+
// create the source file with a hint to be sparse
184+
try (FileChannel fc = FileChannel.open(sourceFile, CREATE_NEW, SPARSE, WRITE, APPEND);) {
185+
// set initial position to avoid writing nearly 2GB
186+
fc.position(initPos);
187+
188+
// fill the remainder of the file with random bytes
189+
int nw = (int)(NUM_WRITES - initPos/BYTES_PER_WRITE);
190+
for (int i = 0; i < nw; i++) {
191+
byte[] rndBytes = createRandomBytes(BYTES_PER_WRITE, 0);
192+
ByteBuffer src = ByteBuffer.wrap(rndBytes);
193+
fc.write(src);
194+
}
195+
}
165196

166-
// performing actual transfer, effectively by multiple invocations of Filechannel.transferTo(FileChannel)
167-
long count;
168-
try (InputStream inputStream = Channels.newInputStream(FileChannel.open(sourceFile));
169-
OutputStream outputStream = Channels
170-
.newOutputStream(FileChannel.open(targetFile, StandardOpenOption.WRITE))) {
171-
count = inputStream.transferTo(outputStream);
197+
// create the target file with a hint to be sparse
198+
try (FileChannel fc = FileChannel.open(targetFile, CREATE_NEW, WRITE, SPARSE);) {
172199
}
173200

174-
// comparing reported transferred bytes, must be 3 GB
175-
assertEquals(count, BYTES_WRITTEN);
201+
// perform actual transfer, effectively by multiple invocations
202+
// of Filechannel.transferTo(FileChannel)
203+
try (InputStream inputStream = Channels.newInputStream(FileChannel.open(sourceFile));
204+
OutputStream outputStream = Channels.newOutputStream(FileChannel.open(targetFile, WRITE))) {
205+
long count = inputStream.transferTo(outputStream);
206+
207+
// compare reported transferred bytes, must be 3 GB
208+
// less the value of the initial position
209+
assertEquals(count, BYTES_WRITTEN - initPos);
210+
}
176211

177-
// comparing content of both files, failing in case of any difference
212+
// compare content of both files, failing if different
178213
assertEquals(Files.mismatch(sourceFile, targetFile), -1);
179214

180215
} finally {
@@ -186,28 +221,33 @@ public void testMoreThanTwoGB() throws IOException {
186221
}
187222

188223
/*
189-
* Special test whether selectable channel based transfer throws blocking mode exception.
224+
* Special test of whether selectable channel based transfer throws blocking
225+
* mode exception.
190226
*/
191227
@Test
192228
public void testIllegalBlockingMode() throws IOException {
193229
Pipe pipe = Pipe.open();
194230
try {
195-
// testing arbitrary input (here: empty file) to non-blocking selectable output
231+
// testing arbitrary input (here: empty file) to non-blocking
232+
// selectable output
196233
try (FileChannel fc = FileChannel.open(Files.createTempFile(CWD, "testIllegalBlockingMode", null));
197-
InputStream is = Channels.newInputStream(fc);
198-
SelectableChannel sc = pipe.sink().configureBlocking(false);
199-
OutputStream os = Channels.newOutputStream((WritableByteChannel) sc)) {
234+
InputStream is = Channels.newInputStream(fc);
235+
SelectableChannel sc = pipe.sink().configureBlocking(false);
236+
OutputStream os = Channels.newOutputStream((WritableByteChannel) sc)) {
200237

201-
// IllegalBlockingMode must be thrown when trying to perform a transfer
238+
// IllegalBlockingMode must be thrown when trying to perform
239+
// a transfer
202240
assertThrows(IllegalBlockingModeException.class, () -> is.transferTo(os));
203241
}
204242

205-
// testing non-blocking selectable input to arbitrary output (here: byte array)
243+
// testing non-blocking selectable input to arbitrary output
244+
// (here: byte array)
206245
try (SelectableChannel sc = pipe.source().configureBlocking(false);
207-
InputStream is = Channels.newInputStream((ReadableByteChannel) sc);
208-
OutputStream os = new ByteArrayOutputStream()) {
246+
InputStream is = Channels.newInputStream((ReadableByteChannel) sc);
247+
OutputStream os = new ByteArrayOutputStream()) {
209248

210-
// IllegalBlockingMode must be thrown when trying to perform a transfer
249+
// IllegalBlockingMode must be thrown when trying to perform
250+
// a transfer
211251
assertThrows(IllegalBlockingModeException.class, () -> is.transferTo(os));
212252
}
213253
} finally {
@@ -217,26 +257,26 @@ public void testIllegalBlockingMode() throws IOException {
217257
}
218258

219259
/*
220-
* Asserts that the transferred content is correct, i. e. compares the actually transferred bytes
221-
* to the expected assumption. The position of the input and output stream before the transfer is
222-
* the start of stream (BOF).
260+
* Asserts that the transferred content is correct, i.e., compares the bytes
261+
* actually transferred to those expected. The position of the input and
262+
* output streams before the transfer are zero (BOF).
223263
*/
224264
private static void checkTransferredContents(InputStreamProvider inputStreamProvider,
225265
OutputStreamProvider outputStreamProvider, byte[] inBytes) throws Exception {
226266
checkTransferredContents(inputStreamProvider, outputStreamProvider, inBytes, 0, 0);
227267
}
228268

229269
/*
230-
* Asserts that the transferred content is correct, i. e. compares the actually transferred bytes
231-
* to the expected assumption. The position of the input and output stream before the transfer is
232-
* provided by the caller.
270+
* Asserts that the transferred content is correct, i. e. compares the bytes
271+
* actually transferred to those expected. The positions of the input and
272+
* output streams before the transfer are provided by the caller.
233273
*/
234274
private static void checkTransferredContents(InputStreamProvider inputStreamProvider,
235275
OutputStreamProvider outputStreamProvider, byte[] inBytes, int posIn, int posOut) throws Exception {
236276
AtomicReference<Supplier<byte[]>> recorder = new AtomicReference<>();
237277
try (InputStream in = inputStreamProvider.input(inBytes);
238-
OutputStream out = outputStreamProvider.output(recorder::set)) {
239-
// skip bytes till starting position
278+
OutputStream out = outputStreamProvider.output(recorder::set)) {
279+
// skip bytes until starting position
240280
in.skipNBytes(posIn);
241281
out.write(new byte[posOut]);
242282

@@ -252,7 +292,8 @@ private static void checkTransferredContents(InputStreamProvider inputStreamProv
252292
}
253293

254294
/*
255-
* Creates an array of random size (between min and min + maxRandomAdditive) filled with random bytes
295+
* Creates an array of random size (between min and min + maxRandomAdditive)
296+
* filled with random bytes
256297
*/
257298
private static byte[] createRandomBytes(int min, int maxRandomAdditive) {
258299
byte[] bytes = new byte[min + (maxRandomAdditive == 0 ? 0 : RND.nextInt(maxRandomAdditive))];
@@ -298,7 +339,8 @@ public InputStream input(byte... bytes) throws Exception {
298339
}
299340

300341
/*
301-
* Creates a provider for an input stream which wraps a readable byte channel but is not a file channel
342+
* Creates a provider for an input stream which wraps a readable byte
343+
* channel but is not a file channel
302344
*/
303345
private static InputStreamProvider readableByteChannelInput() {
304346
return new InputStreamProvider() {
@@ -316,7 +358,7 @@ private static OutputStreamProvider fileChannelOutput() {
316358
return new OutputStreamProvider() {
317359
public OutputStream output(Consumer<Supplier<byte[]>> spy) throws Exception {
318360
Path path = Files.createTempFile(CWD, "fileChannelOutput", null);
319-
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE);
361+
FileChannel fileChannel = FileChannel.open(path, WRITE);
320362
spy.accept(() -> {
321363
try {
322364
return Files.readAllBytes(path);

0 commit comments

Comments
 (0)