/* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test * @bug 4607272 6842687 * @summary Unit test for AsynchronousChannelGroup */ import java.nio.ByteBuffer; import java.nio.channels.*; import java.net.*; import java.util.*; 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)); final List<AsynchronousSocketChannel> accepted = new ArrayList<AsynchronousSocketChannel>(); listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() { public void completed(AsynchronousSocketChannel ch, Void att) { synchronized (accepted) { accepted.add(ch); } listener.accept((Void)null, this); } public void failed(Throwable exc, 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); // clean-up listener.close(); synchronized (accepted) { for (AsynchronousSocketChannel ch: accepted) { ch.close(); } } } 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, (Void)null, new CompletionHandler<Void,Void>() { 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, (Void)null, new CompletionHandler<Integer,Void>() { 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(); } }); // 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); } }); 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"); } }