1 /* 2 * Copyright (C) 2010 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.io.InputStream; 23 import java.io.OutputStream; 24 import java.lang.reflect.Field; 25 import java.net.BindException; 26 import java.net.ConnectException; 27 import java.net.Inet4Address; 28 import java.net.InetAddress; 29 import java.net.InetSocketAddress; 30 import java.net.ServerSocket; 31 import java.net.Socket; 32 import java.net.SocketImpl; 33 import java.net.StandardSocketOptions; 34 import java.nio.ByteBuffer; 35 import java.nio.channels.AlreadyBoundException; 36 import java.nio.channels.ClosedChannelException; 37 import java.nio.channels.NotYetConnectedException; 38 import java.nio.channels.SelectionKey; 39 import java.nio.channels.Selector; 40 import java.nio.channels.SocketChannel; 41 import libcore.junit.junit3.TestCaseWithRules; 42 import libcore.junit.util.ResourceLeakageDetector; 43 import libcore.junit.util.ResourceLeakageDetector.LeakageDetectorRule; 44 45 public class SocketChannelTest extends TestCaseWithRules { 46 47 @Rule 48 public LeakageDetectorRule guardRule = ResourceLeakageDetector.getRule(); 49 50 public void test_read_intoReadOnlyByteArrays() throws Exception { 51 try (ServerSocket ss = new ServerSocket(0); 52 SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress())) { 53 ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer(); 54 ss.setReuseAddress(true); 55 try { 56 sc.read(readOnly); 57 fail(); 58 } catch (IllegalArgumentException expected) { 59 } 60 try { 61 sc.read(new ByteBuffer[] { readOnly }); 62 fail(); 63 } catch (IllegalArgumentException expected) { 64 } 65 try { 66 sc.read(new ByteBuffer[] { readOnly }, 0, 1); 67 fail(); 68 } catch (IllegalArgumentException expected) { 69 } 70 } 71 } 72 73 // https://code.google.com/p/android/issues/detail?id=56684 74 public void test_56684() throws Exception { 75 SocketChannel sc = SocketChannel.open(); 76 sc.configureBlocking(false); 77 78 Selector selector = Selector.open(); 79 SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT); 80 81 try { 82 // This test originally mocked the connect syscall to return ENETUNREACH. 83 // This is not easily doable in openJdk libcore, but a connect to broadcast 84 // address (255.255.255.255) for a TCP connection produces ENETUNREACH 85 // Kernel code that does it is at 86 // http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.18#L182 87 sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] { 88 (byte) 255, (byte) 255, (byte) 255, (byte) 255 }), 0)); 89 fail(); 90 } catch (ConnectException ex) { 91 } 92 93 try { 94 sc.finishConnect(); 95 fail(); 96 } catch (ClosedChannelException expected) { 97 } 98 } 99 100 /** Checks that closing a Socket's output stream also closes the Socket and SocketChannel. */ 101 public void test_channelSocketOutputStreamClosureState() throws Exception { 102 ServerSocket ss = new ServerSocket(0); 103 104 SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress()); 105 sc.configureBlocking(true); 106 107 Socket scSocket = sc.socket(); 108 OutputStream os = scSocket.getOutputStream(); 109 110 assertTrue(sc.isOpen()); 111 assertFalse(scSocket.isClosed()); 112 113 os.close(); 114 115 assertFalse(sc.isOpen()); 116 assertTrue(scSocket.isClosed()); 117 118 ss.close(); 119 } 120 121 /** Checks that closing a Socket's input stream also closes the Socket and SocketChannel. */ 122 public void test_channelSocketInputStreamClosureState() throws Exception { 123 ServerSocket ss = new ServerSocket(0); 124 125 SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress()); 126 sc.configureBlocking(true); 127 128 Socket scSocket = sc.socket(); 129 InputStream is = scSocket.getInputStream(); 130 131 assertTrue(sc.isOpen()); 132 assertFalse(scSocket.isClosed()); 133 134 is.close(); 135 136 assertFalse(sc.isOpen()); 137 assertTrue(scSocket.isClosed()); 138 139 ss.close(); 140 } 141 142 /** Checks the state of the SocketChannel and associated Socket after open() */ 143 public void test_open_initialState() throws Exception { 144 SocketChannel sc = SocketChannel.open(); 145 try { 146 assertNull(sc.socket().getLocalSocketAddress()); 147 148 Socket socket = sc.socket(); 149 assertFalse(socket.isBound()); 150 assertFalse(socket.isClosed()); 151 assertFalse(socket.isConnected()); 152 assertEquals(-1, socket.getLocalPort()); 153 assertTrue(socket.getLocalAddress().isAnyLocalAddress()); 154 assertNull(socket.getLocalSocketAddress()); 155 assertNull(socket.getInetAddress()); 156 assertEquals(0, socket.getPort()); 157 assertNull(socket.getRemoteSocketAddress()); 158 assertFalse(socket.getReuseAddress()); 159 160 assertSame(sc, socket.getChannel()); 161 } finally { 162 sc.close(); 163 } 164 } 165 166 public void test_bind_unresolvedAddress() throws IOException { 167 SocketChannel sc = SocketChannel.open(); 168 try { 169 sc.socket().bind(new InetSocketAddress("unresolvedname", 31415)); 170 fail(); 171 } catch (IOException expected) { 172 } 173 174 assertNull(sc.socket().getLocalSocketAddress()); 175 assertTrue(sc.isOpen()); 176 assertFalse(sc.isConnected()); 177 178 sc.close(); 179 } 180 181 /** Checks that the SocketChannel and associated Socket agree on the socket state. */ 182 public void test_bind_socketStateSync() throws IOException { 183 SocketChannel sc = SocketChannel.open(); 184 assertNull(sc.socket().getLocalSocketAddress()); 185 186 Socket socket = sc.socket(); 187 assertNull(socket.getLocalSocketAddress()); 188 assertFalse(socket.isBound()); 189 190 InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0); 191 sc.socket().bind(bindAddr); 192 193 InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress(); 194 assertEquals(actualAddr, socket.getLocalSocketAddress()); 195 assertEquals(bindAddr.getHostName(), actualAddr.getHostName()); 196 assertTrue(socket.isBound()); 197 assertFalse(socket.isConnected()); 198 assertFalse(socket.isClosed()); 199 200 sc.close(); 201 202 assertFalse(sc.isOpen()); 203 assertTrue(socket.isClosed()); 204 } 205 206 /** 207 * Checks that the SocketChannel and associated Socket agree on the socket state, even if 208 * the Socket object is requested/created after bind(). 209 */ 210 public void test_bind_socketObjectCreationAfterBind() throws IOException { 211 SocketChannel sc = SocketChannel.open(); 212 assertNull(sc.socket().getLocalSocketAddress()); 213 214 InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0); 215 sc.socket().bind(bindAddr); 216 217 // Socket object creation after bind(). 218 Socket socket = sc.socket(); 219 InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress(); 220 assertEquals(actualAddr, socket.getLocalSocketAddress()); 221 assertEquals(bindAddr.getHostName(), actualAddr.getHostName()); 222 assertTrue(socket.isBound()); 223 assertFalse(socket.isConnected()); 224 assertFalse(socket.isClosed()); 225 226 sc.close(); 227 228 assertFalse(sc.isOpen()); 229 assertTrue(socket.isClosed()); 230 } 231 232 /** 233 * Tests connect() and object state for a blocking SocketChannel. Blocking mode is the default. 234 */ 235 public void test_connect_blocking() throws Exception { 236 ServerSocket ss = new ServerSocket(0); 237 238 SocketChannel sc = SocketChannel.open(); 239 assertTrue(sc.isBlocking()); 240 241 assertTrue(sc.connect(ss.getLocalSocketAddress())); 242 243 assertTrue(sc.socket().isBound()); 244 assertTrue(sc.isConnected()); 245 assertTrue(sc.socket().isConnected()); 246 assertFalse(sc.socket().isClosed()); 247 assertTrue(sc.isBlocking()); 248 249 ss.close(); 250 sc.close(); 251 } 252 253 /** Tests connect() and object state for a non-blocking SocketChannel. */ 254 public void test_connect_nonBlocking() throws Exception { 255 ServerSocket ss = new ServerSocket(0); 256 257 SocketChannel sc = SocketChannel.open(); 258 assertTrue(sc.isBlocking()); 259 sc.configureBlocking(false); 260 assertFalse(sc.isBlocking()); 261 262 if (!sc.connect(ss.getLocalSocketAddress())) { 263 do { 264 assertTrue(sc.socket().isBound()); 265 assertFalse(sc.isConnected()); 266 assertFalse(sc.socket().isConnected()); 267 assertFalse(sc.socket().isClosed()); 268 } while (!sc.finishConnect()); 269 } 270 assertTrue(sc.socket().isBound()); 271 assertTrue(sc.isConnected()); 272 assertTrue(sc.socket().isConnected()); 273 assertFalse(sc.socket().isClosed()); 274 assertFalse(sc.isBlocking()); 275 276 ss.close(); 277 sc.close(); 278 } 279 280 public void test_Socket_impl_notNull() throws Exception { 281 try (SocketChannel sc = SocketChannel.open(); 282 Socket socket = sc.socket()) { 283 Field f_impl = Socket.class.getDeclaredField("impl"); 284 f_impl.setAccessible(true); 285 Object implFieldValue = f_impl.get(socket); 286 assertNotNull(implFieldValue); 287 assertTrue(implFieldValue instanceof SocketImpl); 288 } 289 } 290 291 public void test_setOption() throws Exception { 292 SocketChannel sc = SocketChannel.open(); 293 sc.setOption(StandardSocketOptions.SO_LINGER, 1000); 294 295 // Assert that we can read back the option from the channel... 296 assertEquals(1000, (int) sc.<Integer>getOption(StandardSocketOptions.SO_LINGER)); 297 // ... and its socket adaptor. 298 assertEquals(1000, sc.socket().getSoLinger()); 299 300 sc.close(); 301 try { 302 sc.setOption(StandardSocketOptions.SO_LINGER, 2000); 303 fail(); 304 } catch (ClosedChannelException expected) { 305 } 306 } 307 308 public void test_bind() throws IOException { 309 InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); 310 SocketChannel sc = SocketChannel.open(); 311 sc.bind(socketAddress); 312 assertEquals(socketAddress.getAddress(), 313 ((InetSocketAddress) (sc.getLocalAddress())).getAddress()); 314 assertTrue(((InetSocketAddress) (sc.getLocalAddress())).getPort() > 0); 315 316 try { 317 sc.bind(socketAddress); 318 fail(); 319 } catch (AlreadyBoundException expected) { 320 } 321 322 socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 323 ((InetSocketAddress) (sc.getLocalAddress())).getPort()); 324 try (SocketChannel sc1 = SocketChannel.open()){ 325 sc1.bind(socketAddress); 326 fail(); 327 } catch (BindException expected) { 328 } 329 330 sc.close(); 331 socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0); 332 try { 333 sc.bind(socketAddress); 334 fail(); 335 } catch (ClosedChannelException expected) { 336 } 337 } 338 339 public void test_getRemoteAddress() throws IOException { 340 try (SocketChannel sc = SocketChannel.open(); 341 ServerSocket ss = new ServerSocket(0)) { 342 assertNull(sc.getRemoteAddress()); 343 344 sc.connect(ss.getLocalSocketAddress()); 345 assertEquals(sc.getRemoteAddress(), ss.getLocalSocketAddress()); 346 } 347 } 348 349 public void test_shutdownInput() throws IOException { 350 try (SocketChannel channel1 = SocketChannel.open(); 351 ServerSocket server1 = new ServerSocket(0)) { 352 InetSocketAddress localAddr1 = new InetSocketAddress("127.0.0.1", 353 server1.getLocalPort()); 354 355 // initialize write content 356 byte[] writeContent = new byte[10]; 357 for (int i = 0; i < writeContent.length; i++) { 358 writeContent[i] = (byte) i; 359 } 360 361 // establish connection 362 channel1.connect(localAddr1); 363 Socket acceptedSocket = server1.accept(); 364 // use OutputStream.write to write bytes data. 365 OutputStream out = acceptedSocket.getOutputStream(); 366 out.write(writeContent); 367 // use close to guarantee all data is sent 368 acceptedSocket.close(); 369 370 channel1.configureBlocking(false); 371 ByteBuffer readContent = ByteBuffer.allocate(10 + 1); 372 channel1.shutdownInput(); 373 assertEquals(-1, channel1.read(readContent)); 374 } 375 } 376 377 public void test_shutdownOutput() throws IOException { 378 try (SocketChannel channel1 = SocketChannel.open(); 379 ServerSocket server1 = new ServerSocket(0)) { 380 InetSocketAddress localAddr1 = new InetSocketAddress( 381 "127.0.0.1", server1.getLocalPort()); 382 383 // initialize write content 384 ByteBuffer writeContent = ByteBuffer.allocate(10); 385 for (int i = 0; i < 10; i++) { 386 writeContent.put((byte) i); 387 } 388 writeContent.flip(); 389 390 try { 391 channel1.shutdownOutput(); 392 fail(); 393 } catch (NotYetConnectedException expected) { 394 } 395 396 // establish connection 397 channel1.connect(localAddr1); 398 channel1.shutdownOutput(); 399 400 try { 401 channel1.write(writeContent); 402 fail(); 403 } catch (ClosedChannelException expected) { 404 } 405 406 // Closing the channel early to verify that is CloseChannelException thrown by 407 // #shutdownOutput. 408 channel1.close(); 409 410 try { 411 channel1.shutdownOutput(); 412 fail(); 413 } catch (ClosedChannelException expected) { 414 } 415 } 416 } 417 } 418