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