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 dalvik.annotation.BrokenTest; 21 import java.io.IOException; 22 import java.net.InetAddress; 23 import java.net.InetSocketAddress; 24 import java.net.ServerSocket; 25 import java.net.Socket; 26 import java.net.SocketAddress; 27 import java.net.SocketException; 28 import java.nio.ByteBuffer; 29 import java.nio.channels.NoConnectionPendingException; 30 import java.nio.channels.NotYetConnectedException; 31 import java.nio.channels.SelectionKey; 32 import java.nio.channels.ServerSocketChannel; 33 import java.nio.channels.SocketChannel; 34 import java.nio.channels.UnresolvedAddressException; 35 import java.nio.channels.UnsupportedAddressTypeException; 36 import java.nio.channels.spi.SelectorProvider; 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 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 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 // ------------------------------------------------------------------- 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 104 public void testValidOps() { 105 MockSocketChannel testMSChannel = new MockSocketChannel(null); 106 assertEquals(13, this.channel1.validOps()); 107 assertEquals(13, testMSChannel.validOps()); 108 } 109 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 131 public void testIsOpen() throws Exception { 132 assertTrue(this.channel1.isOpen()); 133 this.channel1.close(); 134 assertFalse(this.channel1.isOpen()); 135 } 136 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 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 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 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 SocketChannel channel1IP = null; 202 try { 203 channel1IP = SocketChannel.open(null); 204 fail("Should throw an IllegalArgumentException"); 205 } catch (IllegalArgumentException e) { 206 // correct 207 } 208 assertNull(channel1IP); 209 } 210 211 private void ensureServerClosed() throws IOException { 212 if (null != this.server1) { 213 this.server1.close(); 214 assertTrue(this.server1.isClosed()); 215 } 216 } 217 218 private void statusConnected_NotPending() { 219 assertTrue(this.channel1.isConnected()); 220 assertFalse(this.channel1.isConnectionPending()); 221 assertTrue(this.channel1.isOpen()); 222 } 223 224 private boolean tryFinish() throws IOException { 225 /* 226 * the result of finish will be asserted in multi-thread tests. 227 */ 228 boolean connected = false; 229 assertTrue(this.channel1.isOpen()); 230 try { 231 connected = this.channel1.finishConnect(); 232 } catch (SocketException e) { 233 // Finish connection failed, probably due to reset by peer error. 234 } 235 if (connected) { 236 statusConnected_NotPending(); 237 } 238 return connected; 239 } 240 241 @BrokenTest("Occasionally fail in CTS, but works in CoreTestRunner") 242 public void test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData() throws IOException { 243 // initialize write content 244 ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_HUGE); 245 for (int i = 0; i < CAPACITY_HUGE; i++) { 246 writeContent.put((byte) i); 247 } 248 writeContent.flip(); 249 250 // establish connection 251 channel1.connect(localAddr1); 252 Socket acceptedSocket = server1.accept(); 253 254 channel1.configureBlocking(false); 255 int writtenTotalCount = 0; 256 int writtenCount = 1; 257 long startTime = System.currentTimeMillis(); 258 // use SocketChannel.write(ByteBuffer) to try to write CAPACITY_HUGE bytes 259 while (writtenTotalCount < CAPACITY_HUGE && writtenCount > 0) { 260 writtenCount = channel1.write(writeContent); 261 if (writtenCount == 0 && writtenTotalCount < CAPACITY_HUGE) { 262 assertEquals(0, channel1.write(writeContent)); 263 break; 264 } 265 writtenTotalCount += writtenCount; 266 // if the channel could not finish writing in TIMEOUT ms, the 267 // test fails. It is used to guarantee the test never hangs even 268 // if there are bugs of SocketChannel implementation. 269 assertTimeout(startTime, TIMEOUT); 270 } 271 } 272 273 /* 274 * Fails if the difference between current time and start time is greater 275 * than timeout. 276 */ 277 private void assertTimeout(long startTime, long timeout) { 278 long currentTime = System.currentTimeMillis(); 279 if ((currentTime - startTime) > timeout) { 280 fail("Timeout"); 281 } 282 } 283 284 public void test_socketChannel_read_DirectByteBuffer() throws InterruptedException, IOException { 285 final ServerSocketChannel ssc = ServerSocketChannel.open(); 286 ssc.socket().bind(null, 0); 287 288 Thread server = new Thread() { 289 @Override public void run() { 290 try { 291 for (int i = 0; i < 2; ++i) { 292 ByteBuffer buf = ByteBuffer.allocate(10); 293 buf.put(data); 294 buf.rewind(); 295 ssc.accept().write(buf); 296 } 297 } catch (Exception ignored) { 298 } 299 } 300 }; 301 server.start(); 302 303 // First test with array based byte buffer 304 SocketChannel sc = SocketChannel.open(); 305 sc.connect(ssc.socket().getLocalSocketAddress()); 306 307 ByteBuffer buf = ByteBuffer.allocate(data.length); 308 buf.limit(data.length / 2); 309 sc.read(buf); 310 311 buf.limit(buf.capacity()); 312 sc.read(buf); 313 sc.close(); 314 315 // Make sure the buffer is filled correctly 316 buf.rewind(); 317 assertSameContent(data, buf); 318 319 // Now test with direct byte buffer 320 sc = SocketChannel.open(); 321 sc.connect(ssc.socket().getLocalSocketAddress()); 322 323 buf = ByteBuffer.allocateDirect(data.length); 324 buf.limit(data.length / 2); 325 sc.read(buf); 326 327 buf.limit(buf.capacity()); 328 sc.read(buf); 329 sc.close(); 330 331 // Make sure the buffer is filled correctly 332 buf.rewind(); 333 assertSameContent(data, buf); 334 } 335 336 private void assertSameContent(byte[] data, ByteBuffer buf) { 337 for (byte b : data) { 338 if (b != buf.get()) { 339 int pos = buf.position() - 1; 340 fail("Content not equal. Buffer position: " + 341 (pos) + " expected: " + b + " was: " + buf.get(pos)); 342 } 343 } 344 } 345 346 public static boolean done = false; 347 public static byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 348 349 class MockSocketChannel extends SocketChannel { 350 351 private boolean isConstructorCalled = false; 352 353 public MockSocketChannel(SelectorProvider provider) { 354 super(provider); 355 isConstructorCalled = true; 356 } 357 358 public Socket socket() { 359 return null; 360 } 361 362 public boolean isConnected() { 363 return false; 364 } 365 366 public boolean isConnectionPending() { 367 return false; 368 } 369 370 public boolean connect(SocketAddress address) throws IOException { 371 return false; 372 } 373 374 public boolean finishConnect() throws IOException { 375 return false; 376 } 377 378 public int read(ByteBuffer target) throws IOException { 379 return 0; 380 } 381 382 public long read(ByteBuffer[] targets, int offset, int length) 383 throws IOException { 384 return 0; 385 } 386 387 public int write(ByteBuffer source) throws IOException { 388 return 0; 389 } 390 391 public long write(ByteBuffer[] sources, int offset, int length) 392 throws IOException { 393 return 0; 394 } 395 396 protected void implCloseSelectableChannel() throws IOException { 397 // empty 398 } 399 400 protected void implConfigureBlocking(boolean blockingMode) 401 throws IOException { 402 // empty 403 } 404 } 405 406 class SubSocketAddress extends SocketAddress { 407 private static final long serialVersionUID = 1L; 408 409 // empty 410 public SubSocketAddress() { 411 super(); 412 } 413 } 414 } 415