GroupOfOne.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 AsynchronousChannelGroup
27 */
28
29import java.nio.ByteBuffer;
30import java.nio.channels.*;
31import java.net.*;
32import java.util.concurrent.*;
33import java.io.IOException;
34
35/**
36 * This test verifies that a channel or channel group can be closed from a
37 * completion handler when there are no threads available to handle I/O events.
38 */
39
40public class GroupOfOne {
41
42    public static void main(String[] args) throws Exception {
43        // create listener to accept connections
44        final AsynchronousServerSocketChannel listener =
45            AsynchronousServerSocketChannel.open()
46                .bind(new InetSocketAddress(0));
47        listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
48            public void completed(AsynchronousSocketChannel ch, Void att) {
49                listener.accept(null, this);
50            }
51            public void failed(Throwable exc, Void att) {
52            }
53            public void cancelled(Void att) {
54            }
55        });
56
57        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
58        SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
59
60        test(sa, true, false);
61        test(sa, false, true);
62        test(sa, true, true);
63    }
64
65    static void test(SocketAddress sa,
66                     final boolean closeChannel,
67                     final boolean shutdownGroup)
68        throws Exception
69    {
70        // group with 1 thread
71        final AsynchronousChannelGroup group = AsynchronousChannelGroup
72            .withFixedThreadPool(1, new ThreadFactory() {
73                @Override
74                public Thread newThread(final Runnable r) {
75                    return new Thread(r);
76                }});
77        final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
78
79        // the latch counts down when:
80        // 1. The read operation fails (expected)
81        // 2. the close/shutdown completes
82        final CountDownLatch latch = new CountDownLatch(2);
83
84        ch.connect(sa, null, new CompletionHandler<Void,Void>() {
85            public void completed(Void result, Void att)  {
86                System.out.println("Connected");
87
88                // initiate I/O operation that does not complete (successfully)
89                ByteBuffer buf = ByteBuffer.allocate(100);
90                ch.read(buf, null, new CompletionHandler<Integer,Void>() {
91                    public void completed(Integer bytesRead, Void att)  {
92                        throw new RuntimeException();
93                    }
94                    public void failed(Throwable exc, Void att) {
95                        if (!(exc instanceof AsynchronousCloseException))
96                            throw new RuntimeException(exc);
97                        System.out.println("Read failed (expected)");
98                        latch.countDown();
99                    }
100                    public void cancelled(Void att) {
101                        throw new RuntimeException();
102                    }
103                });
104
105                // close channel or shutdown group
106                try {
107                    if (closeChannel) {
108                        System.out.print("Close channel ...");
109                        ch.close();
110                        System.out.println(" done.");
111                    }
112                    if (shutdownGroup) {
113                        System.out.print("Shutdown group ...");
114                        group.shutdownNow();
115                        System.out.println(" done.");
116                    }
117                    latch.countDown();
118                } catch (IOException e) {
119                    throw new RuntimeException();
120                }
121            }
122            public void failed(Throwable exc, Void att) {
123                throw new RuntimeException(exc);
124            }
125            public void cancelled(Void att) {
126                throw new RuntimeException();
127            }
128        });
129
130        latch.await();
131
132        // clean-up
133        group.shutdown();
134        boolean terminated = group.awaitTermination(5, TimeUnit.SECONDS);
135        if (!terminated)
136            throw new RuntimeException("Group did not terminate");
137
138        System.out.println("TEST OKAY");
139    }
140}
141