|
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 * @build Basic |
|
28 * @run main/othervm -XX:-UseVMInterruptibleIO Basic |
|
29 */ |
|
30 |
|
31 import java.nio.ByteBuffer; |
|
32 import java.nio.channels.*; |
|
33 import java.net.*; |
|
34 import java.util.*; |
|
35 import java.util.concurrent.*; |
|
36 import java.io.IOException; |
|
37 |
|
38 public class Basic { |
|
39 static final Random rand = new Random(); |
|
40 static final ThreadFactory threadFactory = new ThreadFactory() { |
|
41 @Override |
|
42 public Thread newThread(final Runnable r) { |
|
43 return new Thread(r); |
|
44 }}; |
|
45 |
|
46 |
|
47 public static void main(String[] args) throws Exception { |
|
48 shutdownTests(); |
|
49 shutdownNowTests(); |
|
50 afterShutdownTests(); |
|
51 miscTests(); |
|
52 } |
|
53 |
|
54 static void shutdownTests() throws Exception { |
|
55 System.out.println("-- test shutdown --"); |
|
56 |
|
57 // test shutdown with no channels in groups |
|
58 for (int i=0; i<500; i++) { |
|
59 ExecutorService pool = null; |
|
60 AsynchronousChannelGroup group; |
|
61 if (rand.nextBoolean()) { |
|
62 pool = Executors.newCachedThreadPool(); |
|
63 group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5)); |
|
64 } else { |
|
65 int nThreads = 1 + rand.nextInt(8); |
|
66 group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, threadFactory); |
|
67 } |
|
68 group.shutdown(); |
|
69 if (!group.isShutdown()) |
|
70 throw new RuntimeException("Group should be shutdown"); |
|
71 // group should terminate quickly |
|
72 boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); |
|
73 if (!terminated) |
|
74 throw new RuntimeException("Group should have terminated"); |
|
75 if (pool != null && !pool.isTerminated()) |
|
76 throw new RuntimeException("Executor should have terminated"); |
|
77 } |
|
78 |
|
79 // shutdown with channel in group |
|
80 for (int i=0; i<500; i++) { |
|
81 ExecutorService pool = null; |
|
82 AsynchronousChannelGroup group; |
|
83 if (rand.nextBoolean()) { |
|
84 pool = Executors.newCachedThreadPool(); |
|
85 group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(10)); |
|
86 } else { |
|
87 int nThreads = 1 + rand.nextInt(8); |
|
88 group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, threadFactory); |
|
89 } |
|
90 // create channel that is bound to group |
|
91 AsynchronousChannel ch; |
|
92 switch (rand.nextInt(3)) { |
|
93 case 0 : ch = AsynchronousSocketChannel.open(group); break; |
|
94 case 1 : ch = AsynchronousServerSocketChannel.open(group); break; |
|
95 case 2 : ch = AsynchronousDatagramChannel.open(null, group); break; |
|
96 default : throw new AssertionError(); |
|
97 } |
|
98 group.shutdown(); |
|
99 if (!group.isShutdown()) |
|
100 throw new RuntimeException("Group should be shutdown"); |
|
101 |
|
102 // last channel so should terminate after this channel is closed |
|
103 ch.close(); |
|
104 |
|
105 // group should terminate quickly |
|
106 boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); |
|
107 if (!terminated) |
|
108 throw new RuntimeException("Group should have terminated"); |
|
109 if (pool != null && !pool.isTerminated()) |
|
110 throw new RuntimeException("Executor should have terminated"); |
|
111 } |
|
112 } |
|
113 |
|
114 static void shutdownNowTests() throws Exception { |
|
115 System.out.println("-- test shutdownNow --"); |
|
116 |
|
117 for (int i=0; i< 10; i++) { |
|
118 ExecutorService pool = null; |
|
119 AsynchronousChannelGroup group; |
|
120 if (rand.nextBoolean()) { |
|
121 pool = Executors.newCachedThreadPool(); |
|
122 group = AsynchronousChannelGroup |
|
123 .withCachedThreadPool(pool, rand.nextInt(5)); |
|
124 } else { |
|
125 int nThreads = 1 + rand.nextInt(8); |
|
126 group = AsynchronousChannelGroup |
|
127 .withFixedThreadPool(nThreads, threadFactory); |
|
128 } |
|
129 |
|
130 // I/O in progress |
|
131 AsynchronousChannel ch; |
|
132 if (rand.nextBoolean()) { |
|
133 AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel |
|
134 .open(group).bind(new InetSocketAddress(0)); |
|
135 listener.accept(); |
|
136 ch = listener; |
|
137 } else { |
|
138 AsynchronousDatagramChannel adc = |
|
139 AsynchronousDatagramChannel.open(null, group); |
|
140 adc.receive(ByteBuffer.allocate(100)); |
|
141 ch = adc; |
|
142 } |
|
143 |
|
144 // forceful shutdown |
|
145 group.shutdownNow(); |
|
146 |
|
147 // shutdownNow is required to close all channels |
|
148 if (ch.isOpen()) |
|
149 throw new RuntimeException("Channel should be closed"); |
|
150 |
|
151 boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); |
|
152 if (!terminated) |
|
153 throw new RuntimeException("Group should have terminated"); |
|
154 if (pool != null && !pool.isTerminated()) |
|
155 throw new RuntimeException("Executor should have terminated"); |
|
156 } |
|
157 } |
|
158 |
|
159 // test creating channels in group after group is shutdown |
|
160 static void afterShutdownTests() throws Exception { |
|
161 System.out.println("-- test operations after group is shutdown --"); |
|
162 AsynchronousChannelGroup group = |
|
163 AsynchronousChannelGroup.withFixedThreadPool(1, threadFactory); |
|
164 |
|
165 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); |
|
166 AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(group); |
|
167 |
|
168 // initiate accept |
|
169 listener.bind(new InetSocketAddress(0)); |
|
170 Future<AsynchronousSocketChannel> result = listener.accept(); |
|
171 |
|
172 // shutdown group |
|
173 group.shutdown(); |
|
174 if (!group.isShutdown()) |
|
175 throw new RuntimeException("Group should be shutdown"); |
|
176 |
|
177 // attempt to create another channel |
|
178 try { |
|
179 AsynchronousSocketChannel.open(group); |
|
180 throw new RuntimeException("ShutdownChannelGroupException expected"); |
|
181 } catch (ShutdownChannelGroupException x) { |
|
182 } |
|
183 try { |
|
184 AsynchronousServerSocketChannel.open(group); |
|
185 throw new RuntimeException("ShutdownChannelGroupException expected"); |
|
186 } catch (ShutdownChannelGroupException x) { |
|
187 } |
|
188 |
|
189 // attempt to create another channel by connecting. This should cause |
|
190 // the accept operation to fail. |
|
191 InetAddress lh = InetAddress.getLocalHost(); |
|
192 int port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); |
|
193 InetSocketAddress isa = new InetSocketAddress(lh, port); |
|
194 ch.connect(isa).get(); |
|
195 try { |
|
196 result.get(); |
|
197 throw new RuntimeException("Connection was accepted"); |
|
198 } catch (ExecutionException x) { |
|
199 Throwable cause = x.getCause(); |
|
200 if (!(cause instanceof IOException)) |
|
201 throw new RuntimeException("Cause should be IOException"); |
|
202 cause = cause.getCause(); |
|
203 if (!(cause instanceof ShutdownChannelGroupException)) |
|
204 throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); |
|
205 } |
|
206 |
|
207 // initiate another accept even though channel group is shutdown. |
|
208 Future<AsynchronousSocketChannel> res = listener.accept(); |
|
209 try { |
|
210 res.get(3, TimeUnit.SECONDS); |
|
211 throw new RuntimeException("TimeoutException expected"); |
|
212 } catch (TimeoutException x) { |
|
213 } |
|
214 // connect to the listener which should cause the accept to complete |
|
215 AsynchronousSocketChannel.open().connect(isa); |
|
216 try { |
|
217 res.get(); |
|
218 throw new RuntimeException("Connection was accepted"); |
|
219 } catch (ExecutionException x) { |
|
220 Throwable cause = x.getCause(); |
|
221 if (!(cause instanceof IOException)) |
|
222 throw new RuntimeException("Cause should be IOException"); |
|
223 cause = cause.getCause(); |
|
224 if (!(cause instanceof ShutdownChannelGroupException)) |
|
225 throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); |
|
226 } |
|
227 |
|
228 // group should *not* terminate as channels are open |
|
229 boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); |
|
230 if (terminated) |
|
231 throw new RuntimeException("Group should not have terminated"); |
|
232 |
|
233 // close channel; group should terminate quickly |
|
234 ch.close(); |
|
235 listener.close(); |
|
236 terminated = group.awaitTermination(3, TimeUnit.SECONDS); |
|
237 if (!terminated) |
|
238 throw new RuntimeException("Group should have terminated"); |
|
239 } |
|
240 |
|
241 static void miscTests() throws Exception { |
|
242 System.out.println("-- miscellenous tests --"); |
|
243 try { |
|
244 AsynchronousChannelGroup.withFixedThreadPool(1, null); |
|
245 throw new RuntimeException("NPE expected"); |
|
246 } catch (NullPointerException x) { |
|
247 } |
|
248 try { |
|
249 AsynchronousChannelGroup.withFixedThreadPool(0, threadFactory); |
|
250 throw new RuntimeException("IAE expected"); |
|
251 } catch (IllegalArgumentException e) { |
|
252 } |
|
253 try { |
|
254 AsynchronousChannelGroup.withCachedThreadPool(null, 0); |
|
255 throw new RuntimeException("NPE expected"); |
|
256 } catch (NullPointerException x) { |
|
257 } |
|
258 } |
|
259 } |