1 /* 2 * Copyright (c) 2012, 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 7184932 26 * @summary Test asynchronous close and interrupt of timed socket adapter methods 27 * @key randomness 28 */ 29 30 import java.io.*; 31 import java.nio.*; 32 import java.nio.channels.*; 33 import java.nio.channels.spi.AbstractSelectableChannel; 34 import java.net.*; 35 import java.util.concurrent.Callable; 36 import java.util.concurrent.Executors; 37 import java.util.concurrent.ScheduledExecutorService; 38 import java.util.concurrent.TimeUnit; 39 import java.util.Random; 40 41 42 public class AdaptorCloseAndInterrupt { 43 private static final ScheduledExecutorService pool = 44 Executors.newScheduledThreadPool(1); 45 final ServerSocketChannel listener; 46 final DatagramChannel peer; 47 final int port; 48 49 public AdaptorCloseAndInterrupt() { 50 listener = null; 51 peer = null; 52 port = -1; 53 } 54 55 public AdaptorCloseAndInterrupt(ServerSocketChannel listener) { 56 this.listener = listener; 57 this.port = listener.socket().getLocalPort(); 58 this.peer = null; 59 } 60 61 public AdaptorCloseAndInterrupt(DatagramChannel listener) { 62 this.peer = listener; 63 this.port = peer.socket().getLocalPort(); 64 this.listener = null; 65 } 66 67 public static void main(String args[]) throws Exception { 68 try { 69 try (ServerSocketChannel listener = ServerSocketChannel.open()) { 70 listener.socket().bind(null); 71 new AdaptorCloseAndInterrupt(listener).scReadAsyncClose(); 72 new AdaptorCloseAndInterrupt(listener).scReadAsyncInterrupt(); 73 } 74 75 try (DatagramChannel peer = DatagramChannel.open()) { 76 peer.socket().bind(null); 77 new AdaptorCloseAndInterrupt(peer).dcReceiveAsyncClose(); 78 new AdaptorCloseAndInterrupt(peer).dcReceiveAsyncInterrupt(); 79 } 80 81 new AdaptorCloseAndInterrupt().ssAcceptAsyncClose(); 82 new AdaptorCloseAndInterrupt().ssAcceptAsyncInterrupt(); 83 } finally { 84 pool.shutdown(); 85 } 86 System.out.println("Test Passed"); 87 } 88 89 void scReadAsyncClose() throws IOException { 90 try { 91 SocketChannel sc = SocketChannel.open(new InetSocketAddress( 92 "127.0.0.1", port)); 93 sc.socket().setSoTimeout(30*1000); 94 95 doAsyncClose(sc); 96 97 try { 98 sc.socket().getInputStream().read(new byte[100]); 99 throw new RuntimeException("read should not have completed"); 100 } catch (ClosedChannelException expected) {} 101 102 if (!sc.socket().isClosed()) 103 throw new RuntimeException("socket is not closed"); 104 } finally { 105 // accept connection and close it. 106 listener.accept().close(); 107 } 108 } 109 110 void scReadAsyncInterrupt() throws IOException { 111 try { 112 final SocketChannel sc = SocketChannel.open(new InetSocketAddress( 113 "127.0.0.1", port)); 114 sc.socket().setSoTimeout(30*1000); 115 116 doAsyncInterrupt(); 117 118 try { 119 sc.socket().getInputStream().read(new byte[100]); 120 throw new RuntimeException("read should not have completed"); 121 } catch (ClosedByInterruptException expected) { 122 Thread.currentThread().interrupted(); 123 } 124 125 if (!sc.socket().isClosed()) 126 throw new RuntimeException("socket is not closed"); 127 } finally { 128 // accept connection and close it. 129 listener.accept().close(); 130 } 131 } 132 133 void dcReceiveAsyncClose() throws IOException { 134 DatagramChannel dc = DatagramChannel.open(); 135 dc.connect(new InetSocketAddress( 136 "127.0.0.1", port)); 137 dc.socket().setSoTimeout(30*1000); 138 139 doAsyncClose(dc); 140 141 try { 142 dc.socket().receive(new DatagramPacket(new byte[100], 100)); 143 throw new RuntimeException("receive should not have completed"); 144 } catch (ClosedChannelException expected) {} 145 146 if (!dc.socket().isClosed()) 147 throw new RuntimeException("socket is not closed"); 148 } 149 150 void dcReceiveAsyncInterrupt() throws IOException { 151 DatagramChannel dc = DatagramChannel.open(); 152 dc.connect(new InetSocketAddress( 153 "127.0.0.1", port)); 154 dc.socket().setSoTimeout(30*1000); 155 156 doAsyncInterrupt(); 157 158 try { 159 dc.socket().receive(new DatagramPacket(new byte[100], 100)); 160 throw new RuntimeException("receive should not have completed"); 161 } catch (ClosedByInterruptException expected) { 162 Thread.currentThread().interrupted(); 163 } 164 165 if (!dc.socket().isClosed()) 166 throw new RuntimeException("socket is not closed"); 167 } 168 169 void ssAcceptAsyncClose() throws IOException { 170 ServerSocketChannel ssc = ServerSocketChannel.open(); 171 ssc.socket().bind(null); 172 ssc.socket().setSoTimeout(30*1000); 173 174 doAsyncClose(ssc); 175 176 try { 177 ssc.socket().accept(); 178 throw new RuntimeException("accept should not have completed"); 179 } catch (ClosedChannelException expected) {} 180 181 if (!ssc.socket().isClosed()) 182 throw new RuntimeException("socket is not closed"); 183 } 184 185 void ssAcceptAsyncInterrupt() throws IOException { 186 ServerSocketChannel ssc = ServerSocketChannel.open(); 187 ssc.socket().bind(null); 188 ssc.socket().setSoTimeout(30*1000); 189 190 doAsyncInterrupt(); 191 192 try { 193 ssc.socket().accept(); 194 throw new RuntimeException("accept should not have completed"); 195 } catch (ClosedByInterruptException expected) { 196 Thread.currentThread().interrupted(); 197 } 198 199 if (!ssc.socket().isClosed()) 200 throw new RuntimeException("socket is not closed"); 201 } 202 203 void doAsyncClose(final AbstractSelectableChannel sc) { 204 AdaptorCloseAndInterrupt.pool.schedule(new Callable<Void>() { 205 public Void call() throws Exception { 206 sc.close(); 207 return null; 208 } 209 }, new Random().nextInt(1000), TimeUnit.MILLISECONDS); 210 } 211 212 void doAsyncInterrupt() { 213 final Thread current = Thread.currentThread(); 214 AdaptorCloseAndInterrupt.pool.schedule(new Callable<Void>() { 215 public Void call() throws Exception { 216 current.interrupt(); 217 return null; 218 } 219 }, new Random().nextInt(1000), TimeUnit.MILLISECONDS); 220 } 221 222 }