1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package libcore.java.nio.channels; 19 20 import java.io.IOException; 21 import java.net.InetSocketAddress; 22 import java.net.ServerSocket; 23 import java.net.Socket; 24 import java.net.SocketAddress; 25 import java.net.SocketOption; 26 import java.net.SocketException; 27 import java.nio.ByteBuffer; 28 import java.nio.channels.NoConnectionPendingException; 29 import java.nio.channels.NotYetConnectedException; 30 import java.nio.channels.SelectionKey; 31 import java.nio.channels.ServerSocketChannel; 32 import java.nio.channels.SocketChannel; 33 import java.nio.channels.UnresolvedAddressException; 34 import java.nio.channels.UnsupportedAddressTypeException; 35 import java.nio.channels.spi.SelectorProvider; 36 import java.util.Set; 37 import junit.framework.TestCase; 38 39 public class OldSocketChannelTest extends TestCase { 40 41 private static final int CAPACITY_NORMAL = 200; 42 43 private static final int CAPACITY_HUGE = 512 * 1024; 44 45 private InetSocketAddress localAddr1; 46 47 private SocketChannel channel1; 48 49 private SocketChannel channel2; 50 51 private ServerSocket server1; 52 53 private final static int TIMEOUT = 60000; 54 setUp()55 protected void setUp() throws Exception { 56 super.setUp(); 57 this.channel1 = SocketChannel.open(); 58 this.channel2 = SocketChannel.open(); 59 this.server1 = new ServerSocket(0); 60 this.localAddr1 = (InetSocketAddress) server1.getLocalSocketAddress(); 61 } 62 tearDown()63 protected void tearDown() throws Exception { 64 super.tearDown(); 65 if (null != this.channel1) { 66 try { 67 this.channel1.close(); 68 } catch (Exception e) { 69 // ignore 70 } 71 } 72 if (null != this.channel2) { 73 try { 74 this.channel2.close(); 75 } catch (Exception e) { 76 // ignore 77 } 78 } 79 if (null != this.server1) { 80 try { 81 this.server1.close(); 82 } catch (Exception e) { 83 // ignore 84 } 85 } 86 } 87 88 // ------------------------------------------------------------------- 89 // Test for methods in abstract class. 90 // ------------------------------------------------------------------- testConstructor()91 public void testConstructor() throws IOException { 92 SocketChannel channel = 93 SelectorProvider.provider().openSocketChannel(); 94 assertNotNull(channel); 95 assertSame(SelectorProvider.provider(), channel.provider()); 96 channel = SocketChannel.open(); 97 assertNotNull(channel); 98 assertSame(SelectorProvider.provider(), channel.provider()); 99 MockSocketChannel chan = new MockSocketChannel( 100 SelectorProvider.provider()); 101 assertTrue(chan.isConstructorCalled); 102 } 103 testValidOps()104 public void testValidOps() { 105 MockSocketChannel testMSChannel = new MockSocketChannel(null); 106 assertEquals(13, this.channel1.validOps()); 107 assertEquals(13, testMSChannel.validOps()); 108 } 109 testOpen()110 public void testOpen() throws IOException { 111 java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1]; 112 buf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL); 113 MockSocketChannel testMSChannel = new MockSocketChannel(null); 114 MockSocketChannel testMSChannelnotnull = new MockSocketChannel( 115 SelectorProvider.provider()); 116 SocketChannel testSChannel = MockSocketChannel.open(); 117 assertTrue(testSChannel.isOpen()); 118 assertNull(testMSChannel.provider()); 119 assertNotNull(testSChannel.provider()); 120 assertEquals(SelectorProvider.provider(), testSChannel.provider()); 121 assertNotNull(testMSChannelnotnull.provider()); 122 assertEquals(this.channel1.provider(), testMSChannelnotnull.provider()); 123 try { 124 this.channel1.write(buf); 125 fail("Should throw NotYetConnectedException"); 126 } catch (NotYetConnectedException e) { 127 // correct 128 } 129 } 130 testIsOpen()131 public void testIsOpen() throws Exception { 132 assertTrue(this.channel1.isOpen()); 133 this.channel1.close(); 134 assertFalse(this.channel1.isOpen()); 135 } 136 testIsConnected()137 public void testIsConnected() throws Exception { 138 assertFalse(this.channel1.isConnected());// not connected 139 this.channel1.configureBlocking(false); 140 assertFalse(this.channel1.connect(localAddr1)); 141 assertFalse(this.channel1.isConnected()); 142 assertTrue(this.channel1.isConnectionPending()); 143 assertTrue(tryFinish()); 144 assertTrue(this.channel1.isConnected()); 145 this.channel1.close(); 146 assertFalse(this.channel1.isConnected()); 147 } 148 testIsConnectionPending()149 public void testIsConnectionPending() throws Exception { 150 // ensure 151 ensureServerClosed(); 152 this.channel1.configureBlocking(false); 153 assertFalse(this.channel1.isConnectionPending()); 154 // finish 155 try { 156 this.channel1.finishConnect(); 157 fail("Should throw NoConnectionPendingException"); 158 } catch (NoConnectionPendingException e) { 159 // OK. 160 } 161 assertFalse(this.channel1.isConnectionPending()); 162 // connect 163 assertFalse(this.channel1.connect(localAddr1)); 164 assertTrue(this.channel1.isConnectionPending()); 165 this.channel1.close(); 166 167 assertFalse(this.channel1.isConnectionPending()); 168 } 169 testChannelBasicStatus()170 public void testChannelBasicStatus() { 171 Socket gotSocket = this.channel1.socket(); 172 assertFalse(gotSocket.isClosed()); 173 assertTrue(this.channel1.isBlocking()); 174 assertFalse(this.channel1.isRegistered()); 175 assertEquals((SelectionKey.OP_CONNECT | SelectionKey.OP_READ | 176 SelectionKey.OP_WRITE), this.channel1.validOps()); 177 assertEquals(SelectorProvider.provider(), this.channel1.provider()); 178 } 179 testOpenSocketAddress()180 public void testOpenSocketAddress() throws IOException { 181 this.channel1 = SocketChannel.open(localAddr1); 182 assertTrue(this.channel1.isConnected()); 183 184 SocketAddress newTypeAddress = new SubSocketAddress(); 185 try { 186 this.channel1 = SocketChannel.open(newTypeAddress); 187 fail("Should throw UnexpectedAddressTypeException"); 188 } catch (UnsupportedAddressTypeException e) { 189 // expected 190 } 191 192 SocketAddress unresolvedAddress = 193 InetSocketAddress.createUnresolved("127.0.0.1", 8080); 194 try { 195 this.channel1 = SocketChannel.open(unresolvedAddress); 196 fail("Should throw UnresolvedAddressException"); 197 } catch (UnresolvedAddressException e) { 198 // expected 199 } 200 201 try { 202 SocketChannel.open(null); 203 fail("Should throw an IllegalArgumentException"); 204 } catch (IllegalArgumentException e) { 205 // correct 206 } 207 } 208 ensureServerClosed()209 private void ensureServerClosed() throws IOException { 210 if (null != this.server1) { 211 this.server1.close(); 212 assertTrue(this.server1.isClosed()); 213 } 214 } 215 statusConnected_NotPending()216 private void statusConnected_NotPending() { 217 assertTrue(this.channel1.isConnected()); 218 assertFalse(this.channel1.isConnectionPending()); 219 assertTrue(this.channel1.isOpen()); 220 } 221 tryFinish()222 private boolean tryFinish() throws IOException { 223 /* 224 * the result of finish will be asserted in multi-thread tests. 225 */ 226 boolean connected = false; 227 assertTrue(this.channel1.isOpen()); 228 try { 229 connected = this.channel1.finishConnect(); 230 } catch (SocketException e) { 231 // Finish connection failed, probably due to reset by peer error. 232 } 233 if (connected) { 234 statusConnected_NotPending(); 235 } 236 return connected; 237 } 238 239 // Broken Test: Occasionally fail in CTS, but works in CoreTestRunner test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData()240 public void test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData() throws IOException { 241 // initialize write content 242 ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_HUGE); 243 for (int i = 0; i < CAPACITY_HUGE; i++) { 244 writeContent.put((byte) i); 245 } 246 writeContent.flip(); 247 248 // establish connection 249 channel1.connect(localAddr1); 250 Socket acceptedSocket = server1.accept(); 251 252 channel1.configureBlocking(false); 253 int writtenTotalCount = 0; 254 int writtenCount = 1; 255 long startTime = System.currentTimeMillis(); 256 // use SocketChannel.write(ByteBuffer) to try to write CAPACITY_HUGE bytes 257 while (writtenTotalCount < CAPACITY_HUGE && writtenCount > 0) { 258 writtenCount = channel1.write(writeContent); 259 if (writtenCount == 0 && writtenTotalCount < CAPACITY_HUGE) { 260 assertEquals(0, channel1.write(writeContent)); 261 break; 262 } 263 writtenTotalCount += writtenCount; 264 // if the channel could not finish writing in TIMEOUT ms, the 265 // test fails. It is used to guarantee the test never hangs even 266 // if there are bugs of SocketChannel implementation. 267 assertTimeout(startTime, TIMEOUT); 268 } 269 } 270 271 /* 272 * Fails if the difference between current time and start time is greater 273 * than timeout. 274 */ assertTimeout(long startTime, long timeout)275 private void assertTimeout(long startTime, long timeout) { 276 long currentTime = System.currentTimeMillis(); 277 if ((currentTime - startTime) > timeout) { 278 fail("Timeout"); 279 } 280 } 281 test_socketChannel_read_DirectByteBuffer()282 public void test_socketChannel_read_DirectByteBuffer() throws InterruptedException, IOException { 283 final ServerSocketChannel ssc = ServerSocketChannel.open(); 284 ssc.socket().bind(null, 0); 285 286 Thread server = new Thread() { 287 @Override public void run() { 288 try { 289 for (int i = 0; i < 2; ++i) { 290 ByteBuffer buf = ByteBuffer.allocate(10); 291 buf.put(data); 292 buf.rewind(); 293 ssc.accept().write(buf); 294 } 295 } catch (Exception ignored) { 296 } 297 } 298 }; 299 server.start(); 300 301 // First test with array based byte buffer 302 SocketChannel sc = SocketChannel.open(); 303 sc.connect(ssc.socket().getLocalSocketAddress()); 304 305 ByteBuffer buf = ByteBuffer.allocate(data.length); 306 buf.limit(data.length / 2); 307 sc.read(buf); 308 309 buf.limit(buf.capacity()); 310 sc.read(buf); 311 sc.close(); 312 313 // Make sure the buffer is filled correctly 314 buf.rewind(); 315 assertSameContent(data, buf); 316 317 // Now test with direct byte buffer 318 sc = SocketChannel.open(); 319 sc.connect(ssc.socket().getLocalSocketAddress()); 320 321 buf = ByteBuffer.allocateDirect(data.length); 322 buf.limit(data.length / 2); 323 sc.read(buf); 324 325 buf.limit(buf.capacity()); 326 sc.read(buf); 327 sc.close(); 328 329 // Make sure the buffer is filled correctly 330 buf.rewind(); 331 assertSameContent(data, buf); 332 } 333 assertSameContent(byte[] data, ByteBuffer buf)334 private void assertSameContent(byte[] data, ByteBuffer buf) { 335 for (byte b : data) { 336 if (b != buf.get()) { 337 int pos = buf.position() - 1; 338 fail("Content not equal. Buffer position: " + 339 (pos) + " expected: " + b + " was: " + buf.get(pos)); 340 } 341 } 342 } 343 344 public static boolean done = false; 345 public static byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 346 347 class MockSocketChannel extends SocketChannel { 348 349 private boolean isConstructorCalled = false; 350 MockSocketChannel(SelectorProvider provider)351 public MockSocketChannel(SelectorProvider provider) { 352 super(provider); 353 isConstructorCalled = true; 354 } 355 356 @Override socket()357 public Socket socket() { 358 return null; 359 } 360 361 @Override isConnected()362 public boolean isConnected() { 363 return false; 364 } 365 366 @Override isConnectionPending()367 public boolean isConnectionPending() { 368 return false; 369 } 370 371 @Override connect(SocketAddress address)372 public boolean connect(SocketAddress address) throws IOException { 373 return false; 374 } 375 376 @Override finishConnect()377 public boolean finishConnect() throws IOException { 378 return false; 379 } 380 381 @Override read(ByteBuffer target)382 public int read(ByteBuffer target) throws IOException { 383 return 0; 384 } 385 386 @Override read(ByteBuffer[] targets, int offset, int length)387 public long read(ByteBuffer[] targets, int offset, int length) 388 throws IOException { 389 return 0; 390 } 391 392 @Override write(ByteBuffer source)393 public int write(ByteBuffer source) throws IOException { 394 return 0; 395 } 396 397 @Override write(ByteBuffer[] sources, int offset, int length)398 public long write(ByteBuffer[] sources, int offset, int length) 399 throws IOException { 400 return 0; 401 } 402 403 @Override implCloseSelectableChannel()404 protected void implCloseSelectableChannel() throws IOException { 405 // empty 406 } 407 408 @Override implConfigureBlocking(boolean blockingMode)409 protected void implConfigureBlocking(boolean blockingMode) 410 throws IOException { 411 // empty 412 } 413 414 @Override getRemoteAddress()415 public SocketAddress getRemoteAddress() throws IOException { 416 return null; 417 } 418 419 @Override shutdownOutput()420 public SocketChannel shutdownOutput() throws IOException { 421 return null; 422 } 423 424 @Override shutdownInput()425 public SocketChannel shutdownInput() throws IOException { 426 return null; 427 } 428 429 @Override setOption(SocketOption<T> name, T value)430 public <T> SocketChannel setOption(SocketOption<T> name, T value) { 431 return null; 432 } 433 434 @Override bind(SocketAddress local)435 public SocketChannel bind(SocketAddress local) throws IOException { 436 return null; 437 } 438 439 @Override supportedOptions()440 public Set<SocketOption<?>> supportedOptions() { 441 return null; 442 } 443 444 @Override getOption(SocketOption<T> name)445 public <T> T getOption(SocketOption<T> name) throws IOException { 446 return null; 447 } 448 449 @Override getLocalAddress()450 public SocketAddress getLocalAddress() throws IOException { 451 return null; 452 } 453 } 454 455 class SubSocketAddress extends SocketAddress { 456 private static final long serialVersionUID = 1L; 457 458 // empty SubSocketAddress()459 public SubSocketAddress() { 460 super(); 461 } 462 } 463 } 464