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 6842687 26 * @summary Unit test for AsynchronousServerSocketChannel 27 * @run main/timeout=180 Basic 28 */ 29 30import java.nio.channels.*; 31import java.net.*; 32import static java.net.StandardSocketOptions.*; 33import java.io.IOException; 34import java.util.Set; 35import java.util.concurrent.ExecutionException; 36import java.util.concurrent.Future; 37import java.util.concurrent.atomic.AtomicReference; 38 39public class Basic { 40 41 public static void main(String[] args) throws Exception { 42 testBind(); 43 testAccept(); 44 testSocketOptions(); 45 } 46 47 static void testBind() throws Exception { 48 System.out.println("-- bind --"); 49 50 AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open(); 51 if (ch.getLocalAddress() != null) 52 throw new RuntimeException("Local address should be 'null'"); 53 ch.bind(new InetSocketAddress(0), 20); 54 55 // check local address after binding 56 InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress(); 57 if (local.getPort() == 0) 58 throw new RuntimeException("Unexpected port"); 59 if (!local.getAddress().isAnyLocalAddress()) 60 throw new RuntimeException("Not bound to a wildcard address"); 61 62 // try to re-bind 63 try { 64 ch.bind(new InetSocketAddress(0)); 65 throw new RuntimeException("AlreadyBoundException expected"); 66 } catch (AlreadyBoundException x) { 67 } 68 ch.close(); 69 70 // check ClosedChannelException 71 ch = AsynchronousServerSocketChannel.open(); 72 ch.close(); 73 try { 74 ch.bind(new InetSocketAddress(0)); 75 throw new RuntimeException("ClosedChannelException expected"); 76 } catch (ClosedChannelException x) { 77 } 78 } 79 80 static void testAccept() throws Exception { 81 System.out.println("-- accept --"); 82 83 final AsynchronousServerSocketChannel listener = 84 AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0)); 85 86 InetAddress lh = InetAddress.getLocalHost(); 87 int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); 88 final InetSocketAddress isa = new InetSocketAddress(lh, port); 89 90 // establish a few loopback connections 91 for (int i=0; i<100; i++) { 92 SocketChannel sc = SocketChannel.open(isa); 93 AsynchronousSocketChannel ch = listener.accept().get(); 94 sc.close(); 95 ch.close(); 96 } 97 98 final AtomicReference<Throwable> exception = new AtomicReference<Throwable>(); 99 100 // start accepting 101 listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() { 102 public void completed(AsynchronousSocketChannel ch, Void att) { 103 try { 104 ch.close(); 105 } catch (IOException ignore) { } 106 } 107 public void failed(Throwable exc, Void att) { 108 exception.set(exc); 109 } 110 }); 111 112 // check AcceptPendingException 113 try { 114 listener.accept(); 115 throw new RuntimeException("AcceptPendingException expected"); 116 } catch (AcceptPendingException x) { 117 } 118 119 // asynchronous close 120 listener.close(); 121 while (exception.get() == null) 122 Thread.sleep(100); 123 if (!(exception.get() instanceof AsynchronousCloseException)) 124 throw new RuntimeException("AsynchronousCloseException expected"); 125 126 // once closed when a further attemt should throw ClosedChannelException 127 try { 128 listener.accept().get(); 129 throw new RuntimeException("ExecutionException expected"); 130 } catch (ExecutionException x) { 131 if (!(x.getCause() instanceof ClosedChannelException)) 132 throw new RuntimeException("Cause of ClosedChannelException expected"); 133 } catch (InterruptedException x) { 134 } 135 136 } 137 138 static void testSocketOptions() throws Exception { 139 System.out.println("-- socket options --"); 140 AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open(); 141 try { 142 // check supported options 143 Set<SocketOption<?>> options = ch.supportedOptions(); 144 boolean reuseport = options.contains(SO_REUSEPORT); 145 if (!options.contains(SO_REUSEADDR)) 146 throw new RuntimeException("SO_REUSEADDR should be supported"); 147 if (!options.contains(SO_REUSEPORT) && reuseport) 148 throw new RuntimeException("SO_REUSEPORT should be supported"); 149 if (!options.contains(SO_RCVBUF)) 150 throw new RuntimeException("SO_RCVBUF should be supported"); 151 152 // allowed to change when not bound 153 ch.setOption(SO_RCVBUF, 256*1024); // can't check 154 int before = ch.getOption(SO_RCVBUF); 155 int after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); 156 if (after < before) 157 throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); 158 ch.setOption(SO_REUSEADDR, true); 159 checkOption(ch, SO_REUSEADDR, true); 160 ch.setOption(SO_REUSEADDR, false); 161 checkOption(ch, SO_REUSEADDR, false); 162 163 if (reuseport) { 164 ch.setOption(SO_REUSEPORT, true); 165 checkOption(ch, SO_REUSEPORT, true); 166 ch.setOption(SO_REUSEPORT, false); 167 checkOption(ch, SO_REUSEPORT, false); 168 } 169 } finally { 170 ch.close(); 171 } 172 } 173 174 static void checkOption(AsynchronousServerSocketChannel ch, 175 SocketOption name, Object expectedValue) 176 throws IOException 177 { 178 Object value = ch.getOption(name); 179 if (!value.equals(expectedValue)) 180 throw new RuntimeException("value not as expected"); 181 } 182} 183