1580N/A/*
2362N/A * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
1580N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1580N/A *
1580N/A * This code is free software; you can redistribute it and/or modify it
1580N/A * under the terms of the GNU General Public License version 2 only, as
1580N/A * published by the Free Software Foundation.
1580N/A *
1580N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1580N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1580N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1580N/A * version 2 for more details (a copy is included in the LICENSE file that
1580N/A * accompanied this code).
1580N/A *
1580N/A * You should have received a copy of the GNU General Public License version
1580N/A * 2 along with this work; if not, write to the Free Software Foundation,
1580N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1580N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
1580N/A */
1580N/A
1580N/A/* @test
1580N/A * @bug 6842687
1580N/A * @summary Unit test for AsynchronousSocketChannel/AsynchronousServerSocketChannel
1580N/A */
1580N/Aimport java.nio.ByteBuffer;
1580N/Aimport java.nio.channels.*;
1580N/Aimport java.net.*;
1580N/Aimport java.util.concurrent.*;
1580N/Aimport java.util.concurrent.atomic.AtomicReference;
1580N/A
1580N/A/**
1580N/A * Initiates I/O operation on a thread that terminates before the I/O completes.
1580N/A */
1580N/A
1580N/Apublic class DieBeforeComplete {
1580N/A
1580N/A public static void main(String[] args) throws Exception {
1580N/A final AsynchronousServerSocketChannel listener =
1580N/A AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
1580N/A
1580N/A InetAddress lh = InetAddress.getLocalHost();
1580N/A int port = ((InetSocketAddress) (listener.getLocalAddress())).getPort();
1580N/A final SocketAddress sa = new InetSocketAddress(lh, port);
1580N/A
1580N/A // -- accept --
1580N/A
1580N/A // initiate accept in a thread that dies before connection is established
1580N/A Future<AsynchronousSocketChannel> r1 =
1580N/A initiateAndDie(new Task<AsynchronousSocketChannel>() {
1580N/A public Future<AsynchronousSocketChannel> run() {
1580N/A return listener.accept();
1580N/A }});
1580N/A
1580N/A // establish and accept connection
1580N/A SocketChannel peer = SocketChannel.open(sa);
1580N/A final AsynchronousSocketChannel channel = r1.get();
1580N/A
1580N/A // --- read --
1580N/A
1580N/A // initiate read in a thread that dies befores bytes are available
1580N/A final ByteBuffer dst = ByteBuffer.allocate(100);
1580N/A Future<Integer> r2 = initiateAndDie(new Task<Integer>() {
1580N/A public Future<Integer> run() {
1580N/A return channel.read(dst);
1580N/A }});
1580N/A
1580N/A // send bytes
1580N/A peer.write(ByteBuffer.wrap("hello".getBytes()));
1580N/A int nread = r2.get();
1580N/A if (nread <= 0)
1580N/A throw new RuntimeException("Should have read at least one byte");
1580N/A
1580N/A // -- write --
1580N/A
1580N/A // initiate writes in threads that dies
1580N/A boolean completedImmediately;
1580N/A Future<Integer> r3;
1580N/A do {
1580N/A final ByteBuffer src = ByteBuffer.wrap(new byte[10000]);
1580N/A r3 = initiateAndDie(new Task<Integer>() {
1580N/A public Future<Integer> run() {
1580N/A return channel.write(src);
1580N/A }});
1580N/A try {
1580N/A int nsent = r3.get(5, TimeUnit.SECONDS);
1580N/A if (nsent <= 0)
1580N/A throw new RuntimeException("Should have wrote at least one byte");
1580N/A completedImmediately = true;
1580N/A } catch (TimeoutException x) {
1580N/A completedImmediately = false;
1580N/A }
1580N/A } while (completedImmediately);
1580N/A
1580N/A // drain connection
1580N/A peer.configureBlocking(false);
1580N/A ByteBuffer src = ByteBuffer.allocateDirect(10000);
1580N/A do {
1580N/A src.clear();
1580N/A nread = peer.read(src);
1580N/A if (nread == 0) {
1580N/A Thread.sleep(100);
1580N/A nread = peer.read(src);
1580N/A }
1580N/A } while (nread > 0);
1580N/A
1580N/A // write should complete now
1580N/A int nsent = r3.get();
1580N/A if (nsent <= 0)
1580N/A throw new RuntimeException("Should have wrote at least one byte");
1580N/A }
1580N/A
1580N/A static interface Task<T> {
1580N/A Future<T> run();
1580N/A }
1580N/A
1580N/A static <T> Future<T> initiateAndDie(final Task<T> task) {
1580N/A final AtomicReference<Future<T>> result = new AtomicReference<Future<T>>();
1580N/A Runnable r = new Runnable() {
1580N/A public void run() {
1580N/A result.set(task.run());
1580N/A }
1580N/A };
1580N/A Thread t = new Thread(r);
1580N/A t.start();
1580N/A while (t.isAlive()) {
1580N/A try {
1580N/A t.join();
1580N/A } catch (InterruptedException x) {
1580N/A }
1580N/A }
1580N/A return result.get();
1580N/A }
1580N/A}