1 /* 2 * Copyright (c) 2008, 2016, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4607272 26 * @summary Unit test for AsynchronousChannelGroup 27 * @key randomness 28 */ 29 30 import java.nio.ByteBuffer; 31 import java.nio.channels.*; 32 import java.net.*; 33 import java.util.*; 34 import java.util.concurrent.*; 35 import java.io.IOException; 36 37 public class Basic { 38 static final Random rand = new Random(); 39 static final ThreadFactory threadFactory = (Runnable r) -> { 40 return new Thread(r); 41 }; 42 main(String[] args)43 public static void main(String[] args) throws Exception { 44 shutdownTests(); 45 shutdownNowTests(); 46 afterShutdownTests(); 47 miscTests(); 48 } 49 awaitTermination(AsynchronousChannelGroup group)50 static void awaitTermination(AsynchronousChannelGroup group) throws InterruptedException { 51 boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS); 52 if (!terminated) 53 throw new RuntimeException("Group should have terminated"); 54 } 55 testShutdownWithNoChannels(ExecutorService pool, AsynchronousChannelGroup group)56 static void testShutdownWithNoChannels(ExecutorService pool, 57 AsynchronousChannelGroup group) 58 throws Exception 59 { 60 group.shutdown(); 61 if (!group.isShutdown()) 62 throw new RuntimeException("Group should be shutdown"); 63 // group should terminate quickly 64 awaitTermination(group); 65 if (pool != null && !pool.isTerminated()) 66 throw new RuntimeException("Executor should have terminated"); 67 } 68 testShutdownWithChannels(ExecutorService pool, AsynchronousChannelGroup group)69 static void testShutdownWithChannels(ExecutorService pool, 70 AsynchronousChannelGroup group) 71 throws Exception 72 { 73 74 // create channel that is bound to group 75 AsynchronousChannel ch; 76 switch (rand.nextInt(2)) { 77 case 0 : ch = AsynchronousSocketChannel.open(group); break; 78 case 1 : ch = AsynchronousServerSocketChannel.open(group); break; 79 default : throw new AssertionError(); 80 } 81 group.shutdown(); 82 if (!group.isShutdown()) 83 throw new RuntimeException("Group should be shutdown"); 84 85 // last channel so should terminate after this channel is closed 86 ch.close(); 87 88 // group should terminate quickly 89 awaitTermination(group); 90 if (pool != null && !pool.isTerminated()) 91 throw new RuntimeException("Executor should have terminated"); 92 } 93 shutdownTests()94 static void shutdownTests() throws Exception { 95 System.out.println("-- test shutdown --"); 96 97 // test shutdown with no channels in groups 98 for (int i = 0; i < 100; i++) { 99 ExecutorService pool = Executors.newCachedThreadPool(); 100 AsynchronousChannelGroup group = AsynchronousChannelGroup 101 .withCachedThreadPool(pool, rand.nextInt(5)); 102 testShutdownWithNoChannels(pool, group); 103 } 104 for (int i = 0; i < 100; i++) { 105 int nThreads = 1 + rand.nextInt(8); 106 AsynchronousChannelGroup group = AsynchronousChannelGroup 107 .withFixedThreadPool(nThreads, threadFactory); 108 testShutdownWithNoChannels(null, group); 109 } 110 for (int i = 0; i < 100; i++) { 111 ExecutorService pool = Executors.newCachedThreadPool(); 112 AsynchronousChannelGroup group = AsynchronousChannelGroup 113 .withThreadPool(pool); 114 testShutdownWithNoChannels(pool, group); 115 } 116 117 // test shutdown with channel in group 118 for (int i = 0; i < 100; i++) { 119 ExecutorService pool = Executors.newCachedThreadPool(); 120 AsynchronousChannelGroup group = AsynchronousChannelGroup 121 .withCachedThreadPool(pool, rand.nextInt(10)); 122 try { 123 testShutdownWithChannels(pool, group); 124 } finally { 125 group.shutdown(); 126 } 127 } 128 for (int i = 0; i < 100; i++) { 129 int nThreads = 1 + rand.nextInt(8); 130 AsynchronousChannelGroup group = AsynchronousChannelGroup 131 .withFixedThreadPool(nThreads, threadFactory); 132 try { 133 testShutdownWithChannels(null, group); 134 } finally { 135 group.shutdown(); 136 } 137 } 138 for (int i = 0; i < 100; i++) { 139 ExecutorService pool = Executors.newCachedThreadPool(); 140 AsynchronousChannelGroup group = AsynchronousChannelGroup 141 .withThreadPool(pool); 142 try { 143 testShutdownWithChannels(pool, group); 144 } finally { 145 group.shutdown(); 146 } 147 } 148 } 149 testShutdownNow(ExecutorService pool, AsynchronousChannelGroup group)150 static void testShutdownNow(ExecutorService pool, 151 AsynchronousChannelGroup group) 152 throws Exception 153 { 154 // I/O in progress 155 AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel 156 .open(group).bind(new InetSocketAddress(0)); 157 ch.accept(); 158 159 // forceful shutdown 160 group.shutdownNow(); 161 162 // shutdownNow is required to close all channels 163 if (ch.isOpen()) 164 throw new RuntimeException("Channel should be closed"); 165 166 awaitTermination(group); 167 168 if (pool != null && !pool.isTerminated()) 169 throw new RuntimeException("Executor should have terminated"); 170 } 171 shutdownNowTests()172 static void shutdownNowTests() throws Exception { 173 System.out.println("-- test shutdownNow --"); 174 175 for (int i = 0; i < 10; i++) { 176 ExecutorService pool = pool = Executors.newCachedThreadPool(); 177 AsynchronousChannelGroup group = AsynchronousChannelGroup 178 .withCachedThreadPool(pool, rand.nextInt(5)); 179 try { 180 testShutdownNow(pool, group); 181 } finally { 182 group.shutdown(); 183 } 184 } 185 for (int i = 0; i < 10; i++) { 186 int nThreads = 1 + rand.nextInt(8); 187 AsynchronousChannelGroup group = AsynchronousChannelGroup 188 .withFixedThreadPool(nThreads, threadFactory); 189 try { 190 testShutdownNow(null, group); 191 } finally { 192 group.shutdown(); 193 } 194 } 195 for (int i = 0; i < 10; i++) { 196 ExecutorService pool = Executors.newCachedThreadPool(); 197 AsynchronousChannelGroup group = AsynchronousChannelGroup 198 .withThreadPool(pool); 199 try { 200 testShutdownNow(pool, group); 201 } finally { 202 group.shutdown(); 203 } 204 } 205 } 206 207 // test creating channels in group after group is shutdown afterShutdownTests()208 static void afterShutdownTests() throws Exception { 209 System.out.println("-- test operations after group is shutdown --"); 210 AsynchronousChannelGroup group = 211 AsynchronousChannelGroup.withFixedThreadPool(1, threadFactory); 212 213 try (AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); 214 AsynchronousServerSocketChannel listener = 215 AsynchronousServerSocketChannel.open(group)) { 216 217 // initiate accept 218 listener.bind(new InetSocketAddress(0)); 219 Future<AsynchronousSocketChannel> result = listener.accept(); 220 221 // shutdown group 222 group.shutdown(); 223 if (!group.isShutdown()) 224 throw new RuntimeException("Group should be shutdown"); 225 226 // attempt to create another channel 227 try { 228 AsynchronousSocketChannel.open(group); 229 throw new RuntimeException("ShutdownChannelGroupException expected"); 230 } catch (ShutdownChannelGroupException x) { 231 } 232 try { 233 AsynchronousServerSocketChannel.open(group); 234 throw new RuntimeException("ShutdownChannelGroupException expected"); 235 } catch (ShutdownChannelGroupException x) { 236 } 237 238 // attempt to create another channel by connecting. This should cause 239 // the accept operation to fail. 240 InetAddress lh = InetAddress.getLocalHost(); 241 int port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); 242 InetSocketAddress isa = new InetSocketAddress(lh, port); 243 ch.connect(isa).get(); 244 try { 245 result.get(); 246 throw new RuntimeException("Connection was accepted"); 247 } catch (ExecutionException x) { 248 Throwable cause = x.getCause(); 249 if (!(cause instanceof IOException)) 250 throw new RuntimeException("Cause should be IOException"); 251 cause = cause.getCause(); 252 if (!(cause instanceof ShutdownChannelGroupException)) 253 throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); 254 } 255 256 // initiate another accept even though channel group is shutdown. 257 Future<AsynchronousSocketChannel> res = listener.accept(); 258 try { 259 res.get(3, TimeUnit.SECONDS); 260 throw new RuntimeException("TimeoutException expected"); 261 } catch (TimeoutException x) { 262 } 263 // connect to the listener which should cause the accept to complete 264 AsynchronousSocketChannel.open().connect(isa); 265 try { 266 res.get(); 267 throw new RuntimeException("Connection was accepted"); 268 } catch (ExecutionException x) { 269 Throwable cause = x.getCause(); 270 if (!(cause instanceof IOException)) 271 throw new RuntimeException("Cause should be IOException"); 272 cause = cause.getCause(); 273 if (!(cause instanceof ShutdownChannelGroupException)) 274 throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); 275 } 276 277 // group should *not* terminate as channels are open 278 boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); 279 if (terminated) { 280 throw new RuntimeException("Group should not have terminated"); 281 } 282 } finally { 283 group.shutdown(); 284 } 285 } 286 miscTests()287 static void miscTests() throws Exception { 288 System.out.println("-- miscellenous tests --"); 289 try { 290 AsynchronousChannelGroup.withFixedThreadPool(1, null); 291 throw new RuntimeException("NPE expected"); 292 } catch (NullPointerException x) { 293 } 294 try { 295 AsynchronousChannelGroup.withFixedThreadPool(0, threadFactory); 296 throw new RuntimeException("IAE expected"); 297 } catch (IllegalArgumentException e) { 298 } 299 try { 300 AsynchronousChannelGroup.withCachedThreadPool(null, 0); 301 throw new RuntimeException("NPE expected"); 302 } catch (NullPointerException x) { 303 } 304 try { 305 AsynchronousChannelGroup.withThreadPool(null); 306 throw new RuntimeException("NPE expected"); 307 } catch (NullPointerException e) { 308 } 309 } 310 } 311