Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2008 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 android.core;
     18 
     19 import junit.framework.Assert;
     20 import junit.framework.TestCase;
     21 
     22 import java.io.IOException;
     23 import java.net.InetAddress;
     24 import java.net.InetSocketAddress;
     25 import java.net.ServerSocket;
     26 import java.net.Socket;
     27 import java.net.SocketException;
     28 import java.net.SocketTimeoutException;
     29 import java.nio.channels.SocketChannel;
     30 import java.util.concurrent.Semaphore;
     31 
     32 import android.test.suitebuilder.annotation.LargeTest;
     33 import android.test.suitebuilder.annotation.SmallTest;
     34 import android.test.suitebuilder.annotation.Suppress;
     35 
     36 /**
     37  * Regression tests for various socket related problems. And a few general
     38  * socket tests.
     39  */
     40 public class SocketTest extends TestCase {
     41 
     42     private static final String NON_EXISTING_ADDRESS = "123.123.123.123";
     43 
     44     private static final String KNOW_GOOD_ADDRESS = "209.85.129.147";
     45 
     46     private static final String PACKAGE_DROPPING_ADDRESS = "191.167.0.1";
     47 
     48     // Test for basic bind/connect/accept behavior.
     49     @SmallTest
     50     public void testSocketSimple() throws Exception {
     51         ServerSocket ss;
     52         Socket s, s1;
     53         int port;
     54 
     55         IOException lastEx = null;
     56 
     57         ss = new ServerSocket();
     58 
     59         for (port = 9900; port < 9999; port++) {
     60             try {
     61                 ss.bind(new InetSocketAddress("127.0.0.1", port));
     62                 lastEx = null;
     63                 break;
     64             } catch (IOException ex) {
     65                 lastEx = ex;
     66             }
     67         }
     68 
     69         if (lastEx != null) {
     70             throw lastEx;
     71         }
     72 
     73         s = new Socket("127.0.0.1", port);
     74 
     75         s1 = ss.accept();
     76 
     77         s.getOutputStream().write(0xa5);
     78 
     79         assertEquals(0xa5, s1.getInputStream().read());
     80 
     81         s1.getOutputStream().write(0x5a);
     82         assertEquals(0x5a, s.getInputStream().read());
     83     }
     84 
     85     // Regression test for #820068: Wildcard address
     86     @SmallTest
     87     public void testWildcardAddress() throws Exception {
     88         Socket s2 = new Socket();
     89         s2.bind(new InetSocketAddress((InetAddress) null, 12345));
     90         byte[] addr = s2.getLocalAddress().getAddress();
     91         for (int i = 0; i < 4; i++) {
     92             assertEquals("Not the wildcard address", 0, addr[i]);
     93         }
     94     }
     95 
     96     // Regression test for #865753: server sockets not closing properly
     97     @SmallTest
     98     public void testServerSocketClose() throws Exception {
     99         ServerSocket s3 = new ServerSocket(23456);
    100         s3.close();
    101         ServerSocket s4 = new ServerSocket(23456);
    102         s4.close();
    103     }
    104 
    105     // Regression test for #876985: SO_REUSEADDR not working properly
    106 
    107     private Exception serverError = null;
    108 
    109     @LargeTest
    110     public void testSetReuseAddress() throws IOException {
    111         InetSocketAddress addr = new InetSocketAddress(8383);
    112 
    113         final ServerSocket serverSock = new ServerSocket();
    114         serverSock.setReuseAddress(true);
    115         serverSock.bind(addr);
    116 
    117         final Semaphore semThreadEnd = new Semaphore(0);
    118         new Thread() {
    119             @Override
    120             public void run() {
    121                 try {
    122                     Socket sock = serverSock.accept();
    123                     sock.getInputStream().read();
    124                     sock.close();
    125                 } catch (IOException e) {
    126                     serverError = e;
    127                 }
    128                 semThreadEnd.release();
    129             }
    130         }.start();
    131 
    132         // Give the server a bit of time for startup
    133         try {
    134             Thread.sleep(2000);
    135         } catch (InterruptedException ex) {
    136             // Ignored.
    137         }
    138 
    139         Socket client = new Socket("localhost", 8383);
    140         client.getOutputStream().write(1);
    141         // Just leave this connection open from the client side. It will be
    142         // closed from the server side so the server stays in the TIME_WAIT
    143         // state for a while. setReuseAddress() should be able to handle this.
    144 
    145         try {
    146             semThreadEnd.acquire();
    147         } catch (InterruptedException e) {
    148             // ignore
    149         }
    150         serverSock.close();
    151 
    152         ServerSocket serverSock2 = new ServerSocket();
    153         serverSock2.setReuseAddress(true);
    154         serverSock2.bind(addr);
    155         serverSock2.close();
    156 
    157         if (serverError != null) {
    158             throw new RuntimeException("Server must complete without error", serverError);
    159         }
    160     }
    161 
    162     // Regression for 916701, a wrong exception was thrown after timeout of
    163     // a ServerSocket.
    164     @LargeTest
    165     public void testTimeoutException() throws IOException {
    166         ServerSocket s = new ServerSocket(9800);
    167         s.setSoTimeout(2000);
    168         try {
    169             s.accept();
    170         } catch (SocketTimeoutException e) {
    171             // this is ok.
    172         }
    173     }
    174 
    175     // Regression for issue 1001980, openening a SocketChannel threw an Exception
    176     @SmallTest
    177     public void testNativeSocketChannelOpen() throws IOException {
    178         SocketChannel.open();
    179     }
    180 
    181 // Regression test for issue 1018016, connecting ignored a set timeout.
    182 //
    183 // Disabled because test behaves differently depending on networking
    184 // environment. It works fine in the emulator and one the device with
    185 // WLAN, but when 3G comes into play, the possible existence of a
    186 // proxy makes it fail.
    187 //
    188 //    @LargeTest
    189 //    public void testSocketSetSOTimeout() throws IOException {
    190 //        Socket sock = new Socket();
    191 //        int timeout = 5000;
    192 //        long start = System.currentTimeMillis();
    193 //        try {
    194 //            sock.connect(new InetSocketAddress(NON_EXISTING_ADDRESS, 80), timeout);
    195 //        } catch (SocketTimeoutException e) {
    196 //            // expected
    197 //            long delay = System.currentTimeMillis() - start;
    198 //            if (Math.abs(delay - timeout) > 1000) {
    199 //                fail("timeout was not accurate. expected: " + timeout
    200 //                        + " actual: " + delay + " miliseconds.");
    201 //            }
    202 //        } finally {
    203 //            try {
    204 //                sock.close();
    205 //            } catch (IOException ioe) {
    206 //                // ignore
    207 //            }
    208 //        }
    209 //    }
    210 
    211     /**
    212      * Regression test for 1062928: Dotted IP addresses (e.g., 192.168.100.1)
    213      * appear to be broken in the M5 SDK.
    214      *
    215      * Tests that a connection given a ip-addressv4 such as 192.168.100.100 does
    216      * not fail - sdk m5 seems only to accept dns names instead of ip numbers.
    217      * ip 209.85.129.147 (one address of www.google.com) on port 80 (http) is
    218      * used to test the connection.
    219      */
    220 
    221 // Commenting out this test since it is flaky, even at the best of times.  See
    222 // #1191317 for Info.
    223     @Suppress
    224     public void disable_testConnectWithIP4IPAddr() {
    225         // call a Google Web server
    226         InetSocketAddress scktAddrss = new InetSocketAddress(KNOW_GOOD_ADDRESS,
    227                 80);
    228         Socket clntSckt = new Socket();
    229         try {
    230             clntSckt.connect(scktAddrss, 5000);
    231         } catch (Throwable e) {
    232             fail("connection problem:" + e.getClass().getName() + ": "
    233                     + e.getMessage());
    234         } finally {
    235             try {
    236                 clntSckt.close();
    237             } catch (Exception e) {
    238                 // ignore
    239             }
    240         }
    241     }
    242 
    243 
    244     // Regression test for #1058962: Socket.close() does not cause
    245     // socket.connect() to return immediately.
    246     private Socket client;
    247 
    248     private Exception error;
    249 
    250     private boolean connected;
    251 
    252 // This test isn't working now, but really should work.
    253 // TODO Enable this test again.
    254 
    255     @Suppress
    256     public void disable_testSocketConnectClose() {
    257         try {
    258             client = new Socket();
    259 
    260             new Thread() {
    261                 @Override
    262                 public void run() {
    263                     try {
    264                         client.connect(new InetSocketAddress(PACKAGE_DROPPING_ADDRESS, 1357));
    265                     } catch (Exception ex) {
    266                         error = ex;
    267                     }
    268 
    269                     connected = true;
    270                 }
    271             }.start();
    272 
    273             Thread.sleep(1000);
    274 
    275             Assert.assertNull("Connect must not fail immediately. Maybe try different address.", error);
    276             Assert.assertFalse("Connect must not succeed. Maybe try different address.", connected);
    277 
    278             client.close();
    279 
    280             Thread.sleep(1000);
    281 
    282             if (error == null) {
    283                 fail("Socket connect still ongoing");
    284             } else if (!(error instanceof SocketException)) {
    285                 fail("Socket connect interrupted with wrong error: " + error.toString());
    286             }
    287 
    288         } catch (Exception ex) {
    289             throw new RuntimeException(ex);
    290         }
    291 
    292     }
    293 
    294 }
    295