Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java
38828 views
1
/*
2
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/* @test
25
* @bug 4607272 6842687 6878369 6944810 7023403
26
* @summary Unit test for AsynchronousSocketChannel
27
* @run main Basic -skipSlowConnectTest
28
* @key randomness
29
*/
30
31
import java.nio.ByteBuffer;
32
import java.nio.channels.*;
33
import java.net.*;
34
import java.util.Arrays;
35
import java.util.Random;
36
import java.util.Set;
37
import java.util.List;
38
import java.util.concurrent.*;
39
import java.util.concurrent.atomic.*;
40
import java.io.Closeable;
41
import java.io.IOException;
42
import static java.net.StandardSocketOptions.*;
43
import static jdk.net.ExtendedSocketOptions.*;
44
45
public class Basic {
46
static final Random rand = new Random();
47
48
static boolean skipSlowConnectTest = false;
49
50
public static void main(String[] args) throws Exception {
51
for (String arg: args) {
52
switch (arg) {
53
case "-skipSlowConnectTest" :
54
skipSlowConnectTest = true;
55
break;
56
default:
57
throw new RuntimeException("Unrecognized argument: " + arg);
58
}
59
}
60
61
testBind();
62
testSocketOptions();
63
testConnect();
64
testCloseWhenPending();
65
testCancel();
66
testRead1();
67
testRead2();
68
testRead3();
69
testWrite1();
70
testWrite2();
71
// skip timeout tests until 7052549 is fixed
72
if (!System.getProperty("os.name").startsWith("Windows"))
73
testTimeout();
74
testShutdown();
75
}
76
77
static class Server implements Closeable {
78
private final ServerSocketChannel ssc;
79
private final InetSocketAddress address;
80
81
Server() throws IOException {
82
ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
83
84
InetAddress lh = InetAddress.getLocalHost();
85
int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
86
address = new InetSocketAddress(lh, port);
87
}
88
89
InetSocketAddress address() {
90
return address;
91
}
92
93
SocketChannel accept() throws IOException {
94
return ssc.accept();
95
}
96
97
public void close() throws IOException {
98
ssc.close();
99
}
100
101
}
102
103
static void testBind() throws Exception {
104
System.out.println("-- bind --");
105
106
try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
107
if (ch.getLocalAddress() != null)
108
throw new RuntimeException("Local address should be 'null'");
109
ch.bind(new InetSocketAddress(0));
110
111
// check local address after binding
112
InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress();
113
if (local.getPort() == 0)
114
throw new RuntimeException("Unexpected port");
115
if (!local.getAddress().isAnyLocalAddress())
116
throw new RuntimeException("Not bound to a wildcard address");
117
118
// try to re-bind
119
try {
120
ch.bind(new InetSocketAddress(0));
121
throw new RuntimeException("AlreadyBoundException expected");
122
} catch (AlreadyBoundException x) {
123
}
124
}
125
126
// check ClosedChannelException
127
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
128
ch.close();
129
try {
130
ch.bind(new InetSocketAddress(0));
131
throw new RuntimeException("ClosedChannelException expected");
132
} catch (ClosedChannelException x) {
133
}
134
}
135
136
static void testSocketOptions() throws Exception {
137
System.out.println("-- socket options --");
138
139
try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
140
ch.setOption(SO_RCVBUF, 128*1024)
141
.setOption(SO_SNDBUF, 128*1024)
142
.setOption(SO_REUSEADDR, true);
143
144
// check SO_SNDBUF/SO_RCVBUF limits
145
int before, after;
146
before = ch.getOption(SO_SNDBUF);
147
after = ch.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
148
if (after < before)
149
throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
150
before = ch.getOption(SO_RCVBUF);
151
after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
152
if (after < before)
153
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
154
155
ch.bind(new InetSocketAddress(0));
156
157
// default values
158
if (ch.getOption(SO_KEEPALIVE))
159
throw new RuntimeException("Default of SO_KEEPALIVE should be 'false'");
160
if (ch.getOption(TCP_NODELAY))
161
throw new RuntimeException("Default of TCP_NODELAY should be 'false'");
162
163
// set and check
164
if (!ch.setOption(SO_KEEPALIVE, true).getOption(SO_KEEPALIVE))
165
throw new RuntimeException("SO_KEEPALIVE did not change");
166
if (!ch.setOption(TCP_NODELAY, true).getOption(TCP_NODELAY))
167
throw new RuntimeException("SO_KEEPALIVE did not change");
168
169
// read others (can't check as actual value is implementation dependent)
170
ch.getOption(SO_RCVBUF);
171
ch.getOption(SO_SNDBUF);
172
Set<SocketOption<?>> options = ch.supportedOptions();
173
List<SocketOption<?>> extOptions = Arrays.asList(TCP_KEEPCOUNT,
174
TCP_KEEPIDLE, TCP_KEEPINTERVAL);
175
if (options.containsAll(extOptions)) {
176
ch.setOption(TCP_KEEPIDLE, 1234);
177
checkOption(ch, TCP_KEEPIDLE, 1234);
178
ch.setOption(TCP_KEEPINTERVAL, 123);
179
checkOption(ch, TCP_KEEPINTERVAL, 123);
180
ch.setOption(TCP_KEEPCOUNT, 7);
181
checkOption(ch, TCP_KEEPCOUNT, 7);
182
}
183
}
184
}
185
186
static void checkOption(AsynchronousSocketChannel sc, SocketOption name, Object expectedValue)
187
throws IOException {
188
Object value = sc.getOption(name);
189
if (!value.equals(expectedValue)) {
190
throw new RuntimeException("value not as expected");
191
}
192
}
193
194
static void testConnect() throws Exception {
195
System.out.println("-- connect --");
196
197
SocketAddress address;
198
199
try (Server server = new Server()) {
200
address = server.address();
201
202
// connect to server and check local/remote addresses
203
try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
204
ch.connect(address).get();
205
// check local address
206
if (ch.getLocalAddress() == null)
207
throw new RuntimeException("Not bound to local address");
208
209
// check remote address
210
InetSocketAddress remote = (InetSocketAddress)ch.getRemoteAddress();
211
if (remote.getPort() != server.address().getPort())
212
throw new RuntimeException("Connected to unexpected port");
213
if (!remote.getAddress().equals(server.address().getAddress()))
214
throw new RuntimeException("Connected to unexpected address");
215
216
// try to connect again
217
try {
218
ch.connect(server.address()).get();
219
throw new RuntimeException("AlreadyConnectedException expected");
220
} catch (AlreadyConnectedException x) {
221
}
222
223
// clean-up
224
server.accept().close();
225
}
226
227
// check that connect fails with ClosedChannelException
228
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
229
ch.close();
230
try {
231
ch.connect(server.address()).get();
232
throw new RuntimeException("ExecutionException expected");
233
} catch (ExecutionException x) {
234
if (!(x.getCause() instanceof ClosedChannelException))
235
throw new RuntimeException("Cause of ClosedChannelException expected");
236
}
237
final AtomicReference<Throwable> connectException = new AtomicReference<>();
238
ch.connect(server.address(), (Void)null, new CompletionHandler<Void,Void>() {
239
public void completed(Void result, Void att) {
240
}
241
public void failed(Throwable exc, Void att) {
242
connectException.set(exc);
243
}
244
});
245
while (connectException.get() == null) {
246
Thread.sleep(100);
247
}
248
if (!(connectException.get() instanceof ClosedChannelException))
249
throw new RuntimeException("ClosedChannelException expected");
250
}
251
252
// test that failure to connect closes the channel
253
try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
254
try {
255
ch.connect(address).get();
256
} catch (ExecutionException x) {
257
// failed to establish connection
258
if (ch.isOpen())
259
throw new RuntimeException("Channel should be closed");
260
}
261
}
262
263
// repeat test by connecting to a (probably) non-existent host. This
264
// improves the chance that the connect will not fail immediately.
265
if (!skipSlowConnectTest) {
266
try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()) {
267
try {
268
ch.connect(genSocketAddress()).get();
269
} catch (ExecutionException x) {
270
// failed to establish connection
271
if (ch.isOpen())
272
throw new RuntimeException("Channel should be closed");
273
}
274
}
275
}
276
}
277
278
static void testCloseWhenPending() throws Exception {
279
System.out.println("-- asynchronous close when connecting --");
280
281
AsynchronousSocketChannel ch;
282
283
// asynchronous close while connecting
284
ch = AsynchronousSocketChannel.open();
285
Future<Void> connectResult = ch.connect(genSocketAddress());
286
287
// give time to initiate the connect (SYN)
288
Thread.sleep(50);
289
290
// close
291
ch.close();
292
293
// check that exception is thrown in timely manner
294
try {
295
connectResult.get(5, TimeUnit.SECONDS);
296
} catch (TimeoutException x) {
297
throw new RuntimeException("AsynchronousCloseException not thrown");
298
} catch (ExecutionException x) {
299
// expected
300
}
301
302
System.out.println("-- asynchronous close when reading --");
303
304
try (Server server = new Server()) {
305
ch = AsynchronousSocketChannel.open();
306
ch.connect(server.address()).get();
307
308
ByteBuffer dst = ByteBuffer.allocateDirect(100);
309
Future<Integer> result = ch.read(dst);
310
311
// attempt a second read - should fail with ReadPendingException
312
ByteBuffer buf = ByteBuffer.allocateDirect(100);
313
try {
314
ch.read(buf);
315
throw new RuntimeException("ReadPendingException expected");
316
} catch (ReadPendingException x) {
317
}
318
319
// close channel (should cause initial read to complete)
320
ch.close();
321
server.accept().close();
322
323
// check that AsynchronousCloseException is thrown
324
try {
325
result.get();
326
throw new RuntimeException("Should not read");
327
} catch (ExecutionException x) {
328
if (!(x.getCause() instanceof AsynchronousCloseException))
329
throw new RuntimeException(x);
330
}
331
332
System.out.println("-- asynchronous close when writing --");
333
334
ch = AsynchronousSocketChannel.open();
335
ch.connect(server.address()).get();
336
337
final AtomicReference<Throwable> writeException =
338
new AtomicReference<Throwable>();
339
340
// write bytes to fill socket buffer
341
ch.write(genBuffer(), ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
342
public void completed(Integer result, AsynchronousSocketChannel ch) {
343
ch.write(genBuffer(), ch, this);
344
}
345
public void failed(Throwable x, AsynchronousSocketChannel ch) {
346
writeException.set(x);
347
}
348
});
349
350
// give time for socket buffer to fill up.
351
Thread.sleep(5*1000);
352
353
// attempt a concurrent write - should fail with WritePendingException
354
try {
355
ch.write(genBuffer());
356
throw new RuntimeException("WritePendingException expected");
357
} catch (WritePendingException x) {
358
}
359
360
// close channel - should cause initial write to complete
361
ch.close();
362
server.accept().close();
363
364
// wait for exception
365
while (writeException.get() == null) {
366
Thread.sleep(100);
367
}
368
if (!(writeException.get() instanceof AsynchronousCloseException))
369
throw new RuntimeException("AsynchronousCloseException expected");
370
}
371
}
372
373
static void testCancel() throws Exception {
374
System.out.println("-- cancel --");
375
376
try (Server server = new Server()) {
377
for (int i=0; i<2; i++) {
378
boolean mayInterruptIfRunning = (i == 0) ? false : true;
379
380
// establish loopback connection
381
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
382
ch.connect(server.address()).get();
383
SocketChannel peer = server.accept();
384
385
// start read operation
386
ByteBuffer buf = ByteBuffer.allocate(1);
387
Future<Integer> res = ch.read(buf);
388
389
// cancel operation
390
boolean cancelled = res.cancel(mayInterruptIfRunning);
391
392
// check post-conditions
393
if (!res.isDone())
394
throw new RuntimeException("isDone should return true");
395
if (res.isCancelled() != cancelled)
396
throw new RuntimeException("isCancelled not consistent");
397
try {
398
res.get();
399
throw new RuntimeException("CancellationException expected");
400
} catch (CancellationException x) {
401
}
402
try {
403
res.get(1, TimeUnit.SECONDS);
404
throw new RuntimeException("CancellationException expected");
405
} catch (CancellationException x) {
406
}
407
408
// check that the cancel doesn't impact writing to the channel
409
if (!mayInterruptIfRunning) {
410
buf = ByteBuffer.wrap("a".getBytes());
411
ch.write(buf).get();
412
}
413
414
ch.close();
415
peer.close();
416
}
417
}
418
}
419
420
static void testRead1() throws Exception {
421
System.out.println("-- read (1) --");
422
423
try (Server server = new Server()) {
424
final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
425
ch.connect(server.address()).get();
426
427
// read with 0 bytes remaining should complete immediately
428
ByteBuffer buf = ByteBuffer.allocate(1);
429
buf.put((byte)0);
430
int n = ch.read(buf).get();
431
if (n != 0)
432
throw new RuntimeException("0 expected");
433
434
// write bytes and close connection
435
ByteBuffer src = genBuffer();
436
try (SocketChannel sc = server.accept()) {
437
sc.setOption(SO_SNDBUF, src.remaining());
438
while (src.hasRemaining())
439
sc.write(src);
440
}
441
442
// reads should complete immediately
443
final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100);
444
final CountDownLatch latch = new CountDownLatch(1);
445
ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
446
public void completed(Integer result, Void att) {
447
int n = result;
448
if (n > 0) {
449
ch.read(dst, (Void)null, this);
450
} else {
451
latch.countDown();
452
}
453
}
454
public void failed(Throwable exc, Void att) {
455
}
456
});
457
458
latch.await();
459
460
// check buffers
461
src.flip();
462
dst.flip();
463
if (!src.equals(dst)) {
464
throw new RuntimeException("Contents differ");
465
}
466
467
// close channel
468
ch.close();
469
470
// check read fails with ClosedChannelException
471
try {
472
ch.read(dst).get();
473
throw new RuntimeException("ExecutionException expected");
474
} catch (ExecutionException x) {
475
if (!(x.getCause() instanceof ClosedChannelException))
476
throw new RuntimeException("Cause of ClosedChannelException expected");
477
}
478
}
479
}
480
481
static void testRead2() throws Exception {
482
System.out.println("-- read (2) --");
483
484
try (Server server = new Server()) {
485
final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
486
ch.connect(server.address()).get();
487
SocketChannel sc = server.accept();
488
489
ByteBuffer src = genBuffer();
490
491
// read until the buffer is full
492
final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity());
493
final CountDownLatch latch = new CountDownLatch(1);
494
ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
495
public void completed(Integer result, Void att) {
496
if (dst.hasRemaining()) {
497
ch.read(dst, (Void)null, this);
498
} else {
499
latch.countDown();
500
}
501
}
502
public void failed(Throwable exc, Void att) {
503
}
504
});
505
506
// trickle the writing
507
do {
508
int rem = src.remaining();
509
int size = (rem <= 100) ? rem : 50 + rand.nextInt(rem - 100);
510
ByteBuffer buf = ByteBuffer.allocate(size);
511
for (int i=0; i<size; i++)
512
buf.put(src.get());
513
buf.flip();
514
Thread.sleep(50 + rand.nextInt(1500));
515
while (buf.hasRemaining())
516
sc.write(buf);
517
} while (src.hasRemaining());
518
519
// wait until ascynrhonous reading has completed
520
latch.await();
521
522
// check buffers
523
src.flip();
524
dst.flip();
525
if (!src.equals(dst)) {
526
throw new RuntimeException("Contents differ");
527
}
528
529
sc.close();
530
ch.close();
531
}
532
}
533
534
// exercise scattering read
535
static void testRead3() throws Exception {
536
System.out.println("-- read (3) --");
537
538
try (Server server = new Server()) {
539
final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
540
ch.connect(server.address()).get();
541
SocketChannel sc = server.accept();
542
543
ByteBuffer[] dsts = new ByteBuffer[3];
544
for (int i=0; i<dsts.length; i++) {
545
dsts[i] = ByteBuffer.allocateDirect(100);
546
}
547
548
// scattering read that completes ascynhronously
549
final CountDownLatch l1 = new CountDownLatch(1);
550
ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null,
551
new CompletionHandler<Long,Void>() {
552
public void completed(Long result, Void att) {
553
long n = result;
554
if (n <= 0)
555
throw new RuntimeException("No bytes read");
556
l1.countDown();
557
}
558
public void failed(Throwable exc, Void att) {
559
}
560
});
561
562
// write some bytes
563
sc.write(genBuffer());
564
565
// read should now complete
566
l1.await();
567
568
// write more bytes
569
sc.write(genBuffer());
570
571
// read should complete immediately
572
for (int i=0; i<dsts.length; i++) {
573
dsts[i].rewind();
574
}
575
576
final CountDownLatch l2 = new CountDownLatch(1);
577
ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null,
578
new CompletionHandler<Long,Void>() {
579
public void completed(Long result, Void att) {
580
long n = result;
581
if (n <= 0)
582
throw new RuntimeException("No bytes read");
583
l2.countDown();
584
}
585
public void failed(Throwable exc, Void att) {
586
}
587
});
588
l2.await();
589
590
ch.close();
591
sc.close();
592
}
593
}
594
595
static void testWrite1() throws Exception {
596
System.out.println("-- write (1) --");
597
598
try (Server server = new Server()) {
599
final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
600
ch.connect(server.address()).get();
601
SocketChannel sc = server.accept();
602
603
// write with 0 bytes remaining should complete immediately
604
ByteBuffer buf = ByteBuffer.allocate(1);
605
buf.put((byte)0);
606
int n = ch.write(buf).get();
607
if (n != 0)
608
throw new RuntimeException("0 expected");
609
610
// write all bytes and close connection when done
611
final ByteBuffer src = genBuffer();
612
ch.write(src, (Void)null, new CompletionHandler<Integer,Void>() {
613
public void completed(Integer result, Void att) {
614
if (src.hasRemaining()) {
615
ch.write(src, (Void)null, this);
616
} else {
617
try {
618
ch.close();
619
} catch (IOException ignore) { }
620
}
621
}
622
public void failed(Throwable exc, Void att) {
623
}
624
});
625
626
// read to EOF or buffer full
627
ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100);
628
do {
629
n = sc.read(dst);
630
} while (n > 0);
631
sc.close();
632
633
// check buffers
634
src.flip();
635
dst.flip();
636
if (!src.equals(dst)) {
637
throw new RuntimeException("Contents differ");
638
}
639
640
// check write fails with ClosedChannelException
641
try {
642
ch.read(dst).get();
643
throw new RuntimeException("ExecutionException expected");
644
} catch (ExecutionException x) {
645
if (!(x.getCause() instanceof ClosedChannelException))
646
throw new RuntimeException("Cause of ClosedChannelException expected");
647
}
648
}
649
}
650
651
// exercise gathering write
652
static void testWrite2() throws Exception {
653
System.out.println("-- write (2) --");
654
655
try (Server server = new Server()) {
656
final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
657
ch.connect(server.address()).get();
658
SocketChannel sc = server.accept();
659
660
// number of bytes written
661
final AtomicLong bytesWritten = new AtomicLong(0);
662
663
// write buffers (should complete immediately)
664
ByteBuffer[] srcs = genBuffers(1);
665
final CountDownLatch l1 = new CountDownLatch(1);
666
ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, (Void)null,
667
new CompletionHandler<Long,Void>() {
668
public void completed(Long result, Void att) {
669
long n = result;
670
if (n <= 0)
671
throw new RuntimeException("No bytes read");
672
bytesWritten.addAndGet(n);
673
l1.countDown();
674
}
675
public void failed(Throwable exc, Void att) {
676
}
677
});
678
l1.await();
679
680
// set to true to signal that no more buffers should be written
681
final AtomicBoolean continueWriting = new AtomicBoolean(true);
682
683
// write until socket buffer is full so as to create the conditions
684
// for when a write does not complete immediately
685
srcs = genBuffers(1);
686
ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, (Void)null,
687
new CompletionHandler<Long,Void>() {
688
public void completed(Long result, Void att) {
689
long n = result;
690
if (n <= 0)
691
throw new RuntimeException("No bytes written");
692
bytesWritten.addAndGet(n);
693
if (continueWriting.get()) {
694
ByteBuffer[] srcs = genBuffers(8);
695
ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS,
696
(Void)null, this);
697
}
698
}
699
public void failed(Throwable exc, Void att) {
700
}
701
});
702
703
// give time for socket buffer to fill up.
704
Thread.sleep(5*1000);
705
706
// signal handler to stop further writing
707
continueWriting.set(false);
708
709
// read until done
710
ByteBuffer buf = ByteBuffer.allocateDirect(4096);
711
long total = 0L;
712
do {
713
int n = sc.read(buf);
714
if (n <= 0)
715
throw new RuntimeException("No bytes read");
716
buf.rewind();
717
total += n;
718
} while (total < bytesWritten.get());
719
720
ch.close();
721
sc.close();
722
}
723
}
724
725
static void testShutdown() throws Exception {
726
System.out.println("-- shutdown--");
727
728
try (Server server = new Server();
729
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open())
730
{
731
ch.connect(server.address()).get();
732
try (SocketChannel peer = server.accept()) {
733
ByteBuffer buf = ByteBuffer.allocateDirect(1000);
734
int n;
735
736
// check read
737
ch.shutdownInput();
738
n = ch.read(buf).get();
739
if (n != -1)
740
throw new RuntimeException("-1 expected");
741
// check full with full buffer
742
buf.put(new byte[100]);
743
n = ch.read(buf).get();
744
if (n != -1)
745
throw new RuntimeException("-1 expected");
746
747
// check write
748
ch.shutdownOutput();
749
try {
750
ch.write(buf).get();
751
throw new RuntimeException("ClosedChannelException expected");
752
} catch (ExecutionException x) {
753
if (!(x.getCause() instanceof ClosedChannelException))
754
throw new RuntimeException("ClosedChannelException expected");
755
}
756
}
757
}
758
}
759
760
static void testTimeout() throws Exception {
761
System.out.println("-- timeouts --");
762
testTimeout(Integer.MIN_VALUE, TimeUnit.SECONDS);
763
testTimeout(-1L, TimeUnit.SECONDS);
764
testTimeout(0L, TimeUnit.SECONDS);
765
testTimeout(2L, TimeUnit.SECONDS);
766
}
767
768
static void testTimeout(final long timeout, final TimeUnit unit) throws Exception {
769
try (Server server = new Server()) {
770
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
771
ch.connect(server.address()).get();
772
773
ByteBuffer dst = ByteBuffer.allocate(512);
774
775
final AtomicReference<Throwable> readException = new AtomicReference<Throwable>();
776
777
// this read should timeout if value is > 0
778
ch.read(dst, timeout, unit, null, new CompletionHandler<Integer,Void>() {
779
public void completed(Integer result, Void att) {
780
readException.set(new RuntimeException("Should not complete"));
781
}
782
public void failed(Throwable exc, Void att) {
783
readException.set(exc);
784
}
785
});
786
if (timeout > 0L) {
787
// wait for exception
788
while (readException.get() == null) {
789
Thread.sleep(100);
790
}
791
if (!(readException.get() instanceof InterruptedByTimeoutException))
792
throw new RuntimeException("InterruptedByTimeoutException expected");
793
794
// after a timeout then further reading should throw unspecified runtime exception
795
boolean exceptionThrown = false;
796
try {
797
ch.read(dst);
798
} catch (RuntimeException x) {
799
exceptionThrown = true;
800
}
801
if (!exceptionThrown)
802
throw new RuntimeException("RuntimeException expected after timeout.");
803
} else {
804
Thread.sleep(1000);
805
Throwable exc = readException.get();
806
if (exc != null)
807
throw new RuntimeException(exc);
808
}
809
810
final AtomicReference<Throwable> writeException = new AtomicReference<Throwable>();
811
812
// write bytes to fill socket buffer
813
ch.write(genBuffer(), timeout, unit, ch,
814
new CompletionHandler<Integer,AsynchronousSocketChannel>()
815
{
816
public void completed(Integer result, AsynchronousSocketChannel ch) {
817
ch.write(genBuffer(), timeout, unit, ch, this);
818
}
819
public void failed(Throwable exc, AsynchronousSocketChannel ch) {
820
writeException.set(exc);
821
}
822
});
823
if (timeout > 0) {
824
// wait for exception
825
while (writeException.get() == null) {
826
Thread.sleep(100);
827
}
828
if (!(writeException.get() instanceof InterruptedByTimeoutException))
829
throw new RuntimeException("InterruptedByTimeoutException expected");
830
831
// after a timeout then further writing should throw unspecified runtime exception
832
boolean exceptionThrown = false;
833
try {
834
ch.write(genBuffer());
835
} catch (RuntimeException x) {
836
exceptionThrown = true;
837
}
838
if (!exceptionThrown)
839
throw new RuntimeException("RuntimeException expected after timeout.");
840
} else {
841
Thread.sleep(1000);
842
Throwable exc = writeException.get();
843
if (exc != null)
844
throw new RuntimeException(exc);
845
}
846
847
// clean-up
848
server.accept().close();
849
ch.close();
850
}
851
}
852
853
// returns ByteBuffer with random bytes
854
static ByteBuffer genBuffer() {
855
int size = 1024 + rand.nextInt(16000);
856
byte[] buf = new byte[size];
857
rand.nextBytes(buf);
858
boolean useDirect = rand.nextBoolean();
859
if (useDirect) {
860
ByteBuffer bb = ByteBuffer.allocateDirect(buf.length);
861
bb.put(buf);
862
bb.flip();
863
return bb;
864
} else {
865
return ByteBuffer.wrap(buf);
866
}
867
}
868
869
// return ByteBuffer[] with random bytes
870
static ByteBuffer[] genBuffers(int max) {
871
int len = 1;
872
if (max > 1)
873
len += rand.nextInt(max);
874
ByteBuffer[] bufs = new ByteBuffer[len];
875
for (int i=0; i<len; i++)
876
bufs[i] = genBuffer();
877
return bufs;
878
}
879
880
// return random SocketAddress
881
static SocketAddress genSocketAddress() {
882
StringBuilder sb = new StringBuilder("10.");
883
sb.append(rand.nextInt(256));
884
sb.append('.');
885
sb.append(rand.nextInt(256));
886
sb.append('.');
887
sb.append(rand.nextInt(256));
888
InetAddress rh;
889
try {
890
rh = InetAddress.getByName(sb.toString());
891
} catch (UnknownHostException x) {
892
throw new InternalError("Should not happen");
893
}
894
return new InetSocketAddress(rh, rand.nextInt(65535)+1);
895
}
896
}
897
898