1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.java.nio.channels; 18 19 import org.junit.Rule; 20 21 import java.io.IOException; 22 import java.net.BindException; 23 import java.net.InetSocketAddress; 24 import java.net.ServerSocket; 25 import java.net.Socket; 26 import java.net.SocketOption; 27 import java.net.StandardSocketOptions; 28 import java.nio.channels.AlreadyBoundException; 29 import java.nio.channels.AsynchronousChannelGroup; 30 import java.nio.channels.AsynchronousCloseException; 31 import java.nio.channels.AsynchronousServerSocketChannel; 32 import java.nio.channels.AsynchronousSocketChannel; 33 import java.nio.channels.ClosedChannelException; 34 import java.nio.channels.NotYetBoundException; 35 import java.nio.channels.UnresolvedAddressException; 36 import java.nio.channels.spi.AsynchronousChannelProvider; 37 import java.util.Set; 38 import java.util.concurrent.ExecutionException; 39 import java.util.concurrent.Executors; 40 import java.util.concurrent.Future; 41 import java.util.concurrent.TimeUnit; 42 import java.util.concurrent.atomic.AtomicReference; 43 import libcore.junit.junit3.TestCaseWithRules; 44 import libcore.junit.util.ResourceLeakageDetector; 45 import libcore.junit.util.ResourceLeakageDetector.LeakageDetectorRule; 46 47 public class AsynchronousServerSocketChannelTest extends TestCaseWithRules { 48 49 @Rule 50 public LeakageDetectorRule leakageDetectorRule = ResourceLeakageDetector.getRule(); 51 52 public void test_bind() throws Throwable { 53 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 54 assertTrue(assc.isOpen()); 55 assertNull(assc.getLocalAddress()); 56 assc.bind(new InetSocketAddress(0)); 57 assertNotNull(assc.getLocalAddress()); 58 try { 59 assc.bind(new InetSocketAddress(0)); 60 fail(); 61 } catch (AlreadyBoundException expected) {} 62 63 assc.close(); 64 assertFalse(assc.isOpen()); 65 } 66 67 public void test_bind_null() throws Throwable { 68 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 69 assertTrue(assc.isOpen()); 70 assertNull(assc.getLocalAddress()); 71 assc.bind(null); 72 assertNotNull(assc.getLocalAddress()); 73 try { 74 assc.bind(null); 75 fail(); 76 } catch (AlreadyBoundException expected) {} 77 78 assc.close(); 79 assertFalse(assc.isOpen()); 80 } 81 82 public void test_bind_unresolvedAddress() throws Throwable { 83 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 84 try { 85 assc.bind(new InetSocketAddress("unresolvedname", 31415)); 86 fail(); 87 } catch (UnresolvedAddressException expected) {} 88 89 assertNull(assc.getLocalAddress()); 90 assertTrue(assc.isOpen()); 91 assc.close(); 92 } 93 94 public void test_bind_used() throws Throwable { 95 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 96 ServerSocket ss = new ServerSocket(0); 97 try { 98 assc.bind(ss.getLocalSocketAddress()); 99 fail(); 100 } catch (BindException expected) {} 101 assertNull(assc.getLocalAddress()); 102 103 ss.close(); 104 assc.close(); 105 } 106 107 public void test_futureAccept() throws Throwable { 108 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 109 assc.bind(new InetSocketAddress(0)); 110 111 Future<AsynchronousSocketChannel> acceptFuture = assc.accept(); 112 113 Socket s = new Socket(); 114 s.connect(assc.getLocalAddress()); 115 116 AsynchronousSocketChannel asc = acceptFuture.get(1000, TimeUnit.MILLISECONDS); 117 118 assertTrue(s.isConnected()); 119 assertNotNull(asc.getLocalAddress()); 120 assertEquals(asc.getLocalAddress(), s.getRemoteSocketAddress()); 121 assertNotNull(asc.getRemoteAddress()); 122 assertEquals(asc.getRemoteAddress(), s.getLocalSocketAddress()); 123 124 asc.close(); 125 s.close(); 126 assc.close(); 127 } 128 129 public void test_completionHandlerAccept() throws Throwable { 130 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 131 assc.bind(new InetSocketAddress(0)); 132 133 FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler = 134 new FutureLikeCompletionHandler<AsynchronousSocketChannel>(); 135 136 assc.accept(null /* attachment */, acceptCompletionHandler); 137 138 Socket s = new Socket(); 139 s.connect(assc.getLocalAddress()); 140 AsynchronousSocketChannel asc = acceptCompletionHandler.get(1000); 141 142 assertNotNull(asc); 143 assertTrue(s.isConnected()); 144 assertNotNull(asc.getLocalAddress()); 145 assertEquals(asc.getLocalAddress(), s.getRemoteSocketAddress()); 146 assertNotNull(asc.getRemoteAddress()); 147 assertEquals(asc.getRemoteAddress(), s.getLocalSocketAddress()); 148 149 assertNull(acceptCompletionHandler.getAttachment()); 150 151 asc.close(); 152 s.close(); 153 assc.close(); 154 } 155 156 public void test_completionHandlerAccept_attachment() throws Throwable { 157 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 158 assc.bind(new InetSocketAddress(0)); 159 160 FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler = 161 new FutureLikeCompletionHandler<AsynchronousSocketChannel>(); 162 163 Integer attachment = new Integer(123); 164 assc.accept(attachment, acceptCompletionHandler); 165 166 Socket s = new Socket(); 167 s.connect(assc.getLocalAddress()); 168 AsynchronousSocketChannel asc = acceptCompletionHandler.get(1000); 169 170 assertNotNull(asc); 171 assertTrue(s.isConnected()); 172 173 assertEquals(attachment, acceptCompletionHandler.getAttachment()); 174 175 asc.close(); 176 s.close(); 177 assc.close(); 178 } 179 180 public void test_completionHandlerAccept_nyb() throws Throwable { 181 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 182 183 FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler = 184 new FutureLikeCompletionHandler<AsynchronousSocketChannel>(); 185 try { 186 assc.accept(null /* attachment */, acceptCompletionHandler); 187 fail(); 188 } catch(NotYetBoundException expected) {} 189 190 assc.close(); 191 } 192 193 public void test_completionHandlerAccept_npe() throws Throwable { 194 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 195 assc.bind(new InetSocketAddress(0)); 196 197 try { 198 assc.accept(null /* attachment */, null /* completionHandler */); 199 fail(); 200 } catch(NullPointerException expected) {} 201 202 assc.close(); 203 } 204 205 206 public void test_options() throws Throwable { 207 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 208 209 assc.setOption(StandardSocketOptions.SO_RCVBUF, 5000); 210 assertEquals(5000, (long)assc.getOption(StandardSocketOptions.SO_RCVBUF)); 211 212 assc.setOption(StandardSocketOptions.SO_REUSEADDR, true); 213 assertTrue(assc.getOption(StandardSocketOptions.SO_REUSEADDR)); 214 215 assc.close(); 216 } 217 218 public void test_options_iae() throws Throwable { 219 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 220 221 try { 222 assc.setOption(StandardSocketOptions.SO_KEEPALIVE, true); 223 fail(); 224 } catch (UnsupportedOperationException expected) {} 225 226 assc.close(); 227 } 228 229 public void test_group() throws Throwable { 230 AsynchronousChannelProvider provider = 231 AsynchronousChannelProvider.provider(); 232 AsynchronousChannelGroup group = 233 provider.openAsynchronousChannelGroup(2, Executors.defaultThreadFactory()); 234 235 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(group); 236 assertNull(assc.getLocalAddress()); 237 assc.bind(new InetSocketAddress(0)); 238 assertNotNull(assc.getLocalAddress()); 239 assertEquals(provider, assc.provider()); 240 assc.close(); 241 } 242 243 public void test_close() throws Throwable { 244 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 245 assc.bind(new InetSocketAddress(0)); 246 assc.close(); 247 248 Future<AsynchronousSocketChannel> acceptFuture = assc.accept(); 249 try { 250 acceptFuture.get(1000, TimeUnit.MILLISECONDS); 251 fail(); 252 } catch(ExecutionException expected) { 253 assertTrue(expected.getCause() instanceof ClosedChannelException); 254 } 255 256 FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler = 257 new FutureLikeCompletionHandler<AsynchronousSocketChannel>(); 258 assc.accept(null /* attachment */, acceptCompletionHandler); 259 try { 260 acceptCompletionHandler.get(1000); 261 fail(); 262 } catch(ClosedChannelException expected) {} 263 264 try { 265 assc.bind(new InetSocketAddress(0)); 266 fail(); 267 } catch(ClosedChannelException expected) {} 268 269 try { 270 assc.setOption(StandardSocketOptions.SO_REUSEADDR, true); 271 fail(); 272 } catch(ClosedChannelException expected) {} 273 274 // Try second close 275 assc.close(); 276 } 277 278 public void test_future_concurrent_close() throws Throwable { 279 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 280 assc.bind(new InetSocketAddress(0)); 281 282 final AtomicReference<Exception> killerThreadException = 283 new AtomicReference<Exception>(null); 284 final Thread killer = new Thread(new Runnable() { 285 public void run() { 286 try { 287 Thread.sleep(2000); 288 assc.close(); 289 } catch (Exception ex) { 290 killerThreadException.set(ex); 291 } 292 } 293 }); 294 killer.start(); 295 Future<AsynchronousSocketChannel> acceptFuture = assc.accept(); 296 try { 297 // This may timeout on slow devices, they may need more time for the killer thread to 298 // do its thing. 299 acceptFuture.get(10000, TimeUnit.MILLISECONDS); 300 fail(); 301 } catch(ExecutionException expected) { 302 assertTrue(expected.getCause() instanceof ClosedChannelException); 303 } 304 305 assertNull(killerThreadException.get()); 306 } 307 308 public void test_completionHandler_concurrent_close() throws Throwable { 309 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 310 assc.bind(new InetSocketAddress(0)); 311 312 final AtomicReference<Exception> killerThreadException = 313 new AtomicReference<Exception>(null); 314 final Thread killer = new Thread(new Runnable() { 315 public void run() { 316 try { 317 Thread.sleep(2000); 318 assc.close(); 319 } catch (Exception ex) { 320 killerThreadException.set(ex); 321 } 322 } 323 }); 324 killer.start(); 325 326 FutureLikeCompletionHandler<AsynchronousSocketChannel> acceptCompletionHandler = 327 new FutureLikeCompletionHandler<AsynchronousSocketChannel>(); 328 329 assc.accept(null /* attachment */, acceptCompletionHandler); 330 331 try { 332 // This may timeout on slow devices, they may need more time for the killer thread to 333 // do its thing. 334 acceptCompletionHandler.get(10000); 335 fail(); 336 } catch(AsynchronousCloseException expected) {} 337 338 assertNull(killerThreadException.get()); 339 } 340 341 public void test_supportedOptions() throws Throwable { 342 AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(); 343 344 Set<SocketOption<?>> supportedOptions = assc.supportedOptions(); 345 assertEquals(2, supportedOptions.size()); 346 347 assertTrue(supportedOptions.contains(StandardSocketOptions.SO_REUSEADDR)); 348 assertTrue(supportedOptions.contains(StandardSocketOptions.SO_RCVBUF)); 349 350 // supportedOptions should work after close according to spec 351 assc.close(); 352 supportedOptions = assc.supportedOptions(); 353 assertEquals(2, supportedOptions.size()); 354 } 355 356 public void test_closeGuardSupport() throws IOException { 357 try (AsynchronousServerSocketChannel asc = AsynchronousServerSocketChannel.open()) { 358 leakageDetectorRule.assertUnreleasedResourceCount(asc, 1); 359 } 360 } 361 362 public void test_closeGuardSupport_group() throws IOException { 363 AsynchronousChannelProvider provider = 364 AsynchronousChannelProvider.provider(); 365 AsynchronousChannelGroup group = 366 provider.openAsynchronousChannelGroup(2, Executors.defaultThreadFactory()); 367 368 try (AsynchronousServerSocketChannel assc = AsynchronousServerSocketChannel.open(group)) { 369 leakageDetectorRule.assertUnreleasedResourceCount(assc, 1); 370 } 371 } 372 } 373