Basic.java revision 893:f06f30b29f36
1/* 2 * Copyright 2008-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24/* @test 25 * @bug 4607272 26 * @summary Unit test for AsynchronousSocketChannel 27 * @run main/timeout=600 Basic 28 */ 29 30import java.nio.ByteBuffer; 31import java.nio.channels.*; 32import static java.net.StandardSocketOption.*; 33import java.net.*; 34import java.util.Random; 35import java.util.concurrent.*; 36import java.util.concurrent.atomic.*; 37import java.io.IOException; 38 39public class Basic { 40 static final Random rand = new Random(); 41 42 public static void main(String[] args) throws Exception { 43 testBind(); 44 testSocketOptions(); 45 testConnect(); 46 testCloseWhenPending(); 47 testCancel(); 48 testRead1(); 49 testRead2(); 50 testRead3(); 51 testWrite1(); 52 testWrite2(); 53 testTimeout(); 54 testShutdown(); 55 } 56 57 static class Server { 58 private final ServerSocketChannel ssc; 59 private final InetSocketAddress address; 60 61 Server() throws IOException { 62 ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0)); 63 64 InetAddress lh = InetAddress.getLocalHost(); 65 int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); 66 address = new InetSocketAddress(lh, port); 67 } 68 69 InetSocketAddress address() { 70 return address; 71 } 72 73 SocketChannel accept() throws IOException { 74 return ssc.accept(); 75 } 76 77 void close() { 78 try { 79 ssc.close(); 80 } catch (IOException ignore) { } 81 } 82 83 } 84 85 static void testBind() throws Exception { 86 System.out.println("-- bind --"); 87 88 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 89 if (ch.getLocalAddress() != null) 90 throw new RuntimeException("Local address should be 'null'"); 91 ch.bind(new InetSocketAddress(0)); 92 93 // check local address after binding 94 InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress(); 95 if (local.getPort() == 0) 96 throw new RuntimeException("Unexpected port"); 97 if (!local.getAddress().isAnyLocalAddress()) 98 throw new RuntimeException("Not bound to a wildcard address"); 99 100 // try to re-bind 101 try { 102 ch.bind(new InetSocketAddress(0)); 103 throw new RuntimeException("AlreadyBoundException expected"); 104 } catch (AlreadyBoundException x) { 105 } 106 ch.close(); 107 108 // check ClosedChannelException 109 ch = AsynchronousSocketChannel.open(); 110 ch.close(); 111 try { 112 ch.bind(new InetSocketAddress(0)); 113 throw new RuntimeException("ClosedChannelException expected"); 114 } catch (ClosedChannelException x) { 115 } 116 } 117 118 static void testSocketOptions() throws Exception { 119 System.out.println("-- socket options --"); 120 121 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open() 122 .setOption(SO_RCVBUF, 128*1024) 123 .setOption(SO_SNDBUF, 128*1024) 124 .setOption(SO_REUSEADDR, true) 125 .bind(new InetSocketAddress(0)); 126 127 // default values 128 if ((Boolean)ch.getOption(SO_KEEPALIVE)) 129 throw new RuntimeException("Default of SO_KEEPALIVE should be 'false'"); 130 if ((Boolean)ch.getOption(TCP_NODELAY)) 131 throw new RuntimeException("Default of TCP_NODELAY should be 'false'"); 132 133 // set and check 134 if (!(Boolean)ch.setOption(SO_KEEPALIVE, true).getOption(SO_KEEPALIVE)) 135 throw new RuntimeException("SO_KEEPALIVE did not change"); 136 if (!(Boolean)ch.setOption(TCP_NODELAY, true).getOption(TCP_NODELAY)) 137 throw new RuntimeException("SO_KEEPALIVE did not change"); 138 139 // read others (can't check as actual value is implementation dependent) 140 ch.getOption(SO_RCVBUF); 141 ch.getOption(SO_SNDBUF); 142 143 ch.close(); 144 } 145 146 static void testConnect() throws Exception { 147 System.out.println("-- connect --"); 148 149 Server server = new Server(); 150 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 151 ch.connect(server.address()).get(); 152 153 // check local address 154 if (ch.getLocalAddress() == null) 155 throw new RuntimeException("Not bound to local address"); 156 157 // check remote address 158 InetSocketAddress remote = (InetSocketAddress)ch.getRemoteAddress(); 159 if (remote.getPort() != server.address().getPort()) 160 throw new RuntimeException("Connected to unexpected port"); 161 if (!remote.getAddress().equals(server.address().getAddress())) 162 throw new RuntimeException("Connected to unexpected address"); 163 164 // try to connect again 165 try { 166 ch.connect(server.address()).get(); 167 throw new RuntimeException("AlreadyConnectedException expected"); 168 } catch (AlreadyConnectedException x) { 169 } 170 ch.close(); 171 172 // check that connect fails with ClosedChannelException) 173 ch = AsynchronousSocketChannel.open(); 174 ch.close(); 175 try { 176 ch.connect(server.address()).get(); 177 throw new RuntimeException("ExecutionException expected"); 178 } catch (ExecutionException x) { 179 if (!(x.getCause() instanceof ClosedChannelException)) 180 throw new RuntimeException("Cause of ClosedChannelException expected"); 181 } 182 final AtomicReference<Throwable> connectException = 183 new AtomicReference<Throwable>(); 184 ch.connect(server.address(), null, new CompletionHandler<Void,Void>() { 185 public void completed(Void result, Void att) { 186 } 187 public void failed(Throwable exc, Void att) { 188 connectException.set(exc); 189 } 190 public void cancelled(Void att) { 191 } 192 }); 193 while (connectException.get() == null) { 194 Thread.sleep(100); 195 } 196 if (!(connectException.get() instanceof ClosedChannelException)) 197 throw new RuntimeException("ClosedChannelException expected"); 198 199 System.out.println("-- connect to non-existent host --"); 200 201 // test failure 202 InetAddress badHost = InetAddress.getByName("1.2.3.4"); 203 if (!badHost.isReachable(10*1000)) { 204 205 ch = AsynchronousSocketChannel.open(); 206 try { 207 ch.connect(new InetSocketAddress(badHost, 9876)).get(); 208 throw new RuntimeException("Connection should not be established"); 209 } catch (ExecutionException x) { 210 } 211 if (ch.isOpen()) 212 throw new RuntimeException("Channel should be closed"); 213 } 214 215 server.close(); 216 } 217 218 static void testCloseWhenPending() throws Exception { 219 System.out.println("-- asynchronous close when connecting --"); 220 221 AsynchronousSocketChannel ch; 222 223 // asynchronous close while connecting 224 InetAddress rh = InetAddress.getByName("1.2.3.4"); 225 if (!rh.isReachable(3000)) { 226 InetSocketAddress isa = new InetSocketAddress(rh, 1234); 227 228 ch = AsynchronousSocketChannel.open(); 229 Future<Void> result = ch.connect(isa); 230 231 // give time to initiate the connect (SYN) 232 Thread.sleep(50); 233 234 // close 235 ch.close(); 236 237 // check that AsynchronousCloseException is thrown 238 try { 239 result.get(); 240 throw new RuntimeException("Should not connect"); 241 } catch (ExecutionException x) { 242 if (!(x.getCause() instanceof AsynchronousCloseException)) 243 throw new RuntimeException(x); 244 } 245 } 246 247 System.out.println("-- asynchronous close when reading --"); 248 249 Server server = new Server(); 250 ch = AsynchronousSocketChannel.open(); 251 ch.connect(server.address()).get(); 252 253 ByteBuffer dst = ByteBuffer.allocateDirect(100); 254 Future<Integer> result = ch.read(dst); 255 256 // attempt a second read - should fail with ReadPendingException 257 ByteBuffer buf = ByteBuffer.allocateDirect(100); 258 try { 259 ch.read(buf); 260 throw new RuntimeException("ReadPendingException expected"); 261 } catch (ReadPendingException x) { 262 } 263 264 // close channel (should cause initial read to complete) 265 ch.close(); 266 267 // check that AsynchronousCloseException is thrown 268 try { 269 result.get(); 270 throw new RuntimeException("Should not read"); 271 } catch (ExecutionException x) { 272 if (!(x.getCause() instanceof AsynchronousCloseException)) 273 throw new RuntimeException(x); 274 } 275 276 System.out.println("-- asynchronous close when writing --"); 277 278 ch = AsynchronousSocketChannel.open(); 279 ch.connect(server.address()).get(); 280 281 final AtomicReference<Throwable> writeException = 282 new AtomicReference<Throwable>(); 283 284 // write bytes to fill socket buffer 285 ch.write(genBuffer(), ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() { 286 public void completed(Integer result, AsynchronousSocketChannel ch) { 287 ch.write(genBuffer(), ch, this); 288 } 289 public void failed(Throwable x, AsynchronousSocketChannel ch) { 290 writeException.set(x); 291 } 292 public void cancelled(AsynchronousSocketChannel ch) { 293 } 294 }); 295 296 // give time for socket buffer to fill up. 297 Thread.sleep(5*1000); 298 299 // attempt a concurrent write - should fail with WritePendingException 300 try { 301 ch.write(genBuffer()); 302 throw new RuntimeException("WritePendingException expected"); 303 } catch (WritePendingException x) { 304 } 305 306 // close channel - should cause initial write to complete 307 ch.close(); 308 309 // wait for exception 310 while (writeException.get() == null) { 311 Thread.sleep(100); 312 } 313 if (!(writeException.get() instanceof AsynchronousCloseException)) 314 throw new RuntimeException("AsynchronousCloseException expected"); 315 316 server.close(); 317 } 318 319 static void testCancel() throws Exception { 320 System.out.println("-- cancel --"); 321 322 Server server = new Server(); 323 324 for (int i=0; i<2; i++) { 325 boolean mayInterruptIfRunning = (i == 0) ? false : true; 326 327 // establish loopback connection 328 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 329 ch.connect(server.address()).get(); 330 SocketChannel peer = server.accept(); 331 332 // start read operation 333 final CountDownLatch latch = new CountDownLatch(1); 334 ByteBuffer buf = ByteBuffer.allocate(1); 335 Future<Integer> res = ch.read(buf, null, 336 new CompletionHandler<Integer,Void>() { 337 public void completed(Integer result, Void att) { 338 } 339 public void failed(Throwable exc, Void att) { 340 } 341 public void cancelled(Void att) { 342 latch.countDown(); 343 } 344 }); 345 346 // cancel operation 347 boolean cancelled = res.cancel(mayInterruptIfRunning); 348 349 // check post-conditions 350 if (!res.isDone()) 351 throw new RuntimeException("isDone should return true"); 352 if (res.isCancelled() != cancelled) 353 throw new RuntimeException("isCancelled not consistent"); 354 try { 355 res.get(); 356 throw new RuntimeException("CancellationException expected"); 357 } catch (CancellationException x) { 358 } 359 try { 360 res.get(1, TimeUnit.SECONDS); 361 throw new RuntimeException("CancellationException expected"); 362 } catch (CancellationException x) { 363 } 364 365 // check that completion handler executed. 366 latch.await(); 367 368 ch.close(); 369 peer.close(); 370 } 371 372 server.close(); 373 } 374 375 static void testRead1() throws Exception { 376 System.out.println("-- read (1) --"); 377 378 Server server = new Server(); 379 final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 380 ch.connect(server.address()).get(); 381 382 // read with 0 bytes remaining should complete immediately 383 ByteBuffer buf = ByteBuffer.allocate(1); 384 buf.put((byte)0); 385 int n = ch.read(buf).get(); 386 if (n != 0) 387 throw new RuntimeException("0 expected"); 388 389 // write bytes and close connection 390 SocketChannel sc = server.accept(); 391 ByteBuffer src = genBuffer(); 392 sc.setOption(StandardSocketOption.SO_SNDBUF, src.remaining()); 393 while (src.hasRemaining()) 394 sc.write(src); 395 sc.close(); 396 397 // reads should complete immediately 398 final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100); 399 final CountDownLatch latch = new CountDownLatch(1); 400 ch.read(dst, null, new CompletionHandler<Integer,Void>() { 401 public void completed(Integer result, Void att) { 402 int n = result; 403 if (n > 0) { 404 ch.read(dst, null, this); 405 } else { 406 latch.countDown(); 407 } 408 } 409 public void failed(Throwable exc, Void att) { 410 } 411 public void cancelled(Void att) { 412 } 413 }); 414 415 latch.await(); 416 417 // check buffers 418 src.flip(); 419 dst.flip(); 420 if (!src.equals(dst)) { 421 throw new RuntimeException("Contents differ"); 422 } 423 424 // close channel 425 ch.close(); 426 427 // check read fails with ClosedChannelException 428 try { 429 ch.read(dst).get(); 430 throw new RuntimeException("ExecutionException expected"); 431 } catch (ExecutionException x) { 432 if (!(x.getCause() instanceof ClosedChannelException)) 433 throw new RuntimeException("Cause of ClosedChannelException expected"); 434 } 435 436 server.close(); 437 } 438 439 static void testRead2() throws Exception { 440 System.out.println("-- read (2) --"); 441 442 Server server = new Server(); 443 444 final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 445 ch.connect(server.address()).get(); 446 SocketChannel sc = server.accept(); 447 448 ByteBuffer src = genBuffer(); 449 450 // read until the buffer is full 451 final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity()); 452 final CountDownLatch latch = new CountDownLatch(1); 453 ch.read(dst, null, new CompletionHandler<Integer,Void>() { 454 public void completed(Integer result, Void att) { 455 if (dst.hasRemaining()) { 456 ch.read(dst, null, this); 457 } else { 458 latch.countDown(); 459 } 460 } 461 public void failed(Throwable exc, Void att) { 462 } 463 public void cancelled(Void att) { 464 } 465 }); 466 467 // trickle the writing 468 do { 469 int rem = src.remaining(); 470 int size = (rem <= 100) ? rem : 50 + rand.nextInt(rem - 100); 471 ByteBuffer buf = ByteBuffer.allocate(size); 472 for (int i=0; i<size; i++) 473 buf.put(src.get()); 474 buf.flip(); 475 Thread.sleep(50 + rand.nextInt(1500)); 476 while (buf.hasRemaining()) 477 sc.write(buf); 478 } while (src.hasRemaining()); 479 480 // wait until ascynrhonous reading has completed 481 latch.await(); 482 483 // check buffers 484 src.flip(); 485 dst.flip(); 486 if (!src.equals(dst)) { 487 throw new RuntimeException("Contents differ"); 488 } 489 490 sc.close(); 491 ch.close(); 492 server.close(); 493 } 494 495 // exercise scattering read 496 static void testRead3() throws Exception { 497 System.out.println("-- read (3) --"); 498 499 Server server = new Server(); 500 final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 501 ch.connect(server.address()).get(); 502 SocketChannel sc = server.accept(); 503 504 ByteBuffer[] dsts = new ByteBuffer[3]; 505 for (int i=0; i<dsts.length; i++) { 506 dsts[i] = ByteBuffer.allocateDirect(100); 507 } 508 509 // scattering read that completes ascynhronously 510 final CountDownLatch latch = new CountDownLatch(1); 511 ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, null, 512 new CompletionHandler<Long,Void>() { 513 public void completed(Long result, Void att) { 514 long n = result; 515 if (n <= 0) 516 throw new RuntimeException("No bytes read"); 517 latch.countDown(); 518 } 519 public void failed(Throwable exc, Void att) { 520 } 521 public void cancelled(Void att) { 522 } 523 }); 524 525 // write some bytes 526 sc.write(genBuffer()); 527 528 // read should now complete 529 latch.await(); 530 531 // write more bytes 532 sc.write(genBuffer()); 533 534 // read should complete immediately 535 for (int i=0; i<dsts.length; i++) { 536 dsts[i].rewind(); 537 } 538 long n = ch 539 .read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, null, null).get(); 540 if (n <= 0) 541 throw new RuntimeException("No bytes read"); 542 543 ch.close(); 544 sc.close(); 545 server.close(); 546 } 547 548 static void testWrite1() throws Exception { 549 System.out.println("-- write (1) --"); 550 551 Server server = new Server(); 552 final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 553 ch.connect(server.address()).get(); 554 SocketChannel sc = server.accept(); 555 556 // write with 0 bytes remaining should complete immediately 557 ByteBuffer buf = ByteBuffer.allocate(1); 558 buf.put((byte)0); 559 int n = ch.write(buf).get(); 560 if (n != 0) 561 throw new RuntimeException("0 expected"); 562 563 // write all bytes and close connection when done 564 final ByteBuffer src = genBuffer(); 565 ch.write(src, null, new CompletionHandler<Integer,Void>() { 566 public void completed(Integer result, Void att) { 567 if (src.hasRemaining()) { 568 ch.write(src, null, this); 569 } else { 570 try { 571 ch.close(); 572 } catch (IOException ignore) { } 573 } 574 } 575 public void failed(Throwable exc, Void att) { 576 } 577 public void cancelled(Void att) { 578 } 579 }); 580 581 // read to EOF or buffer full 582 ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100); 583 do { 584 n = sc.read(dst); 585 } while (n > 0); 586 sc.close(); 587 588 // check buffers 589 src.flip(); 590 dst.flip(); 591 if (!src.equals(dst)) { 592 throw new RuntimeException("Contents differ"); 593 } 594 595 // check write fails with ClosedChannelException 596 try { 597 ch.read(dst).get(); 598 throw new RuntimeException("ExecutionException expected"); 599 } catch (ExecutionException x) { 600 if (!(x.getCause() instanceof ClosedChannelException)) 601 throw new RuntimeException("Cause of ClosedChannelException expected"); 602 } 603 604 server.close(); 605 } 606 607 // exercise gathering write 608 static void testWrite2() throws Exception { 609 System.out.println("-- write (2) --"); 610 611 Server server = new Server(); 612 final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 613 ch.connect(server.address()).get(); 614 SocketChannel sc = server.accept(); 615 616 // write buffers (should complete immediately) 617 ByteBuffer[] srcs = genBuffers(1); 618 long n = ch 619 .write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, null, null).get(); 620 if (n <= 0) 621 throw new RuntimeException("No bytes written"); 622 623 // set to true to signal that no more buffers should be written 624 final AtomicBoolean continueWriting = new AtomicBoolean(true); 625 626 // number of bytes written 627 final AtomicLong bytesWritten = new AtomicLong(n); 628 629 // write until socket buffer is full so as to create the conditions 630 // for when a write does not complete immediately 631 srcs = genBuffers(1); 632 ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, null, 633 new CompletionHandler<Long,Void>() { 634 public void completed(Long result, Void att) { 635 long n = result; 636 if (n <= 0) 637 throw new RuntimeException("No bytes written"); 638 bytesWritten.addAndGet(n); 639 if (continueWriting.get()) { 640 ByteBuffer[] srcs = genBuffers(8); 641 ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, 642 null, this); 643 } 644 } 645 public void failed(Throwable exc, Void att) { 646 } 647 public void cancelled(Void att) { 648 } 649 }); 650 651 // give time for socket buffer to fill up. 652 Thread.sleep(5*1000); 653 654 // signal handler to stop further writing 655 continueWriting.set(false); 656 657 // read until done 658 ByteBuffer buf = ByteBuffer.allocateDirect(4096); 659 long total = 0L; 660 do { 661 n = sc.read(buf); 662 if (n <= 0) 663 throw new RuntimeException("No bytes read"); 664 buf.rewind(); 665 total += n; 666 } while (total < bytesWritten.get()); 667 668 ch.close(); 669 sc.close(); 670 server.close(); 671 } 672 673 static void testShutdown() throws Exception { 674 System.out.println("-- shutdown--"); 675 676 Server server = new Server(); 677 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 678 ch.connect(server.address()).get(); 679 SocketChannel sc = server.accept(); 680 681 ByteBuffer buf = ByteBuffer.allocateDirect(1000); 682 int n; 683 684 // check read 685 ch.shutdownInput(); 686 n = ch.read(buf).get(); 687 if (n != -1) 688 throw new RuntimeException("-1 expected"); 689 // check full with full buffer 690 buf.put(new byte[100]); 691 n = ch.read(buf).get(); 692 if (n != -1) 693 throw new RuntimeException("-1 expected"); 694 695 // check write 696 ch.shutdownOutput(); 697 try { 698 ch.write(buf).get(); 699 throw new RuntimeException("ClosedChannelException expected"); 700 } catch (ExecutionException x) { 701 if (!(x.getCause() instanceof ClosedChannelException)) 702 throw new RuntimeException("ClosedChannelException expected"); 703 } 704 705 sc.close(); 706 ch.close(); 707 server.close(); 708 } 709 710 static void testTimeout() throws Exception { 711 Server server = new Server(); 712 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 713 ch.connect(server.address()).get(); 714 715 System.out.println("-- timeout when reading --"); 716 717 // this read should timeout 718 ByteBuffer dst = ByteBuffer.allocate(512); 719 try { 720 ch.read(dst, 3, TimeUnit.SECONDS, null, null).get(); 721 throw new RuntimeException("Read did not timeout"); 722 } catch (ExecutionException x) { 723 if (!(x.getCause() instanceof InterruptedByTimeoutException)) 724 throw new RuntimeException("InterruptedByTimeoutException expected"); 725 } 726 727 // after a timeout then further reading should throw unspecified runtime exception 728 boolean exceptionThrown = false; 729 try { 730 ch.read(dst); 731 } catch (RuntimeException x) { 732 exceptionThrown = true; 733 } 734 if (!exceptionThrown) 735 throw new RuntimeException("RuntimeException expected after timeout."); 736 737 738 System.out.println("-- timeout when writing --"); 739 740 final AtomicReference<Throwable> writeException = new AtomicReference<Throwable>(); 741 742 final long timeout = 5; 743 final TimeUnit unit = TimeUnit.SECONDS; 744 745 // write bytes to fill socket buffer 746 ch.write(genBuffer(), timeout, unit, ch, 747 new CompletionHandler<Integer,AsynchronousSocketChannel>() 748 { 749 public void completed(Integer result, AsynchronousSocketChannel ch) { 750 ch.write(genBuffer(), timeout, unit, ch, this); 751 } 752 public void failed(Throwable exc, AsynchronousSocketChannel ch) { 753 writeException.set(exc); 754 } 755 public void cancelled(AsynchronousSocketChannel ch) { 756 } 757 }); 758 759 // wait for exception 760 while (writeException.get() == null) { 761 Thread.sleep(100); 762 } 763 if (!(writeException.get() instanceof InterruptedByTimeoutException)) 764 throw new RuntimeException("InterruptedByTimeoutException expected"); 765 766 // after a timeout then further writing should throw unspecified runtime exception 767 exceptionThrown = false; 768 try { 769 ch.write(genBuffer()); 770 } catch (RuntimeException x) { 771 exceptionThrown = true; 772 } 773 if (!exceptionThrown) 774 throw new RuntimeException("RuntimeException expected after timeout."); 775 776 ch.close(); 777 } 778 779 // returns ByteBuffer with random bytes 780 static ByteBuffer genBuffer() { 781 int size = 1024 + rand.nextInt(16000); 782 byte[] buf = new byte[size]; 783 rand.nextBytes(buf); 784 boolean useDirect = rand.nextBoolean(); 785 if (useDirect) { 786 ByteBuffer bb = ByteBuffer.allocateDirect(buf.length); 787 bb.put(buf); 788 bb.flip(); 789 return bb; 790 } else { 791 return ByteBuffer.wrap(buf); 792 } 793 } 794 795 // return ByteBuffer[] with random bytes 796 static ByteBuffer[] genBuffers(int max) { 797 int len = 1; 798 if (max > 1) 799 len += rand.nextInt(max); 800 ByteBuffer[] bufs = new ByteBuffer[len]; 801 for (int i=0; i<len; i++) 802 bufs[i] = genBuffer(); 803 return bufs; 804 } 805} 806