/* * Copyright 2008-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ /* @test * @bug 4607272 * @summary Unit test for AsynchronousChannelGroup */ import java.nio.ByteBuffer; import java.nio.channels.*; import java.net.*; import java.util.concurrent.*; import java.io.IOException; /** * This test verifies that a channel or channel group can be closed from a * completion handler when there are no threads available to handle I/O events. */ public class GroupOfOne { public static void main(String[] args) throws Exception { // create listener to accept connections final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open() .bind(new InetSocketAddress(0)); listener.accept(null, new CompletionHandler() { public void completed(AsynchronousSocketChannel ch, Void att) { listener.accept(null, this); } public void failed(Throwable exc, Void att) { } public void cancelled(Void att) { } }); int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); test(sa, true, false); test(sa, false, true); test(sa, true, true); } static void test(SocketAddress sa, final boolean closeChannel, final boolean shutdownGroup) throws Exception { // group with 1 thread final AsynchronousChannelGroup group = AsynchronousChannelGroup .withFixedThreadPool(1, new ThreadFactory() { @Override public Thread newThread(final Runnable r) { return new Thread(r); }}); final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); // the latch counts down when: // 1. The read operation fails (expected) // 2. the close/shutdown completes final CountDownLatch latch = new CountDownLatch(2); ch.connect(sa, null, new CompletionHandler() { public void completed(Void result, Void att) { System.out.println("Connected"); // initiate I/O operation that does not complete (successfully) ByteBuffer buf = ByteBuffer.allocate(100); ch.read(buf, null, new CompletionHandler() { public void completed(Integer bytesRead, Void att) { throw new RuntimeException(); } public void failed(Throwable exc, Void att) { if (!(exc instanceof AsynchronousCloseException)) throw new RuntimeException(exc); System.out.println("Read failed (expected)"); latch.countDown(); } public void cancelled(Void att) { throw new RuntimeException(); } }); // close channel or shutdown group try { if (closeChannel) { System.out.print("Close channel ..."); ch.close(); System.out.println(" done."); } if (shutdownGroup) { System.out.print("Shutdown group ..."); group.shutdownNow(); System.out.println(" done."); } latch.countDown(); } catch (IOException e) { throw new RuntimeException(); } } public void failed(Throwable exc, Void att) { throw new RuntimeException(exc); } public void cancelled(Void att) { throw new RuntimeException(); } }); latch.await(); // clean-up group.shutdown(); boolean terminated = group.awaitTermination(5, TimeUnit.SECONDS); if (!terminated) throw new RuntimeException("Group did not terminate"); System.out.println("TEST OKAY"); } }