• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
testSocketSimple()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
testWildcardAddress()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
testServerSocketClose()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
testSetReuseAddress()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
testTimeoutException()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
testNativeSocketChannelOpen()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
disable_testConnectWithIP4IPAddr()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
disable_testSocketConnectClose()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