Home | History | Annotate | Download | only in channels
      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