SocketTest.java revision 4557728efb66c455a52b7669a8eefef7a9e54854
1/*
2 * Copyright (C) 2009 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
17package libcore.java.net;
18
19import java.io.IOException;
20import java.io.InputStream;
21import java.io.OutputStream;
22import java.net.ConnectException;
23import java.net.InetAddress;
24import java.net.InetSocketAddress;
25import java.net.ServerSocket;
26import java.net.Socket;
27import java.net.SocketAddress;
28import java.net.SocketException;
29import java.net.SocketImpl;
30import java.nio.channels.ServerSocketChannel;
31import java.nio.channels.SocketChannel;
32
33public class SocketTest extends junit.framework.TestCase {
34    /**
35     * Our getLocalAddress and getLocalPort currently use getsockname(3).
36     * This means they give incorrect results on closed sockets (as well
37     * as requiring an unnecessary call into native code).
38     */
39    public void test_getLocalAddress_after_close() throws Exception {
40        Socket s = new Socket();
41        try {
42            // Bind to an ephemeral local port.
43            s.bind(new InetSocketAddress("localhost", 0));
44            assertTrue(s.getLocalAddress().isLoopbackAddress());
45            // What local port did we get?
46            int localPort = s.getLocalPort();
47            assertTrue(localPort > 0);
48            // Now close the socket...
49            s.close();
50            // The RI returns the ANY address but the original local port after close.
51            assertTrue(s.getLocalAddress().isAnyLocalAddress());
52            assertEquals(localPort, s.getLocalPort());
53        } finally {
54            s.close();
55        }
56    }
57
58    // http://code.google.com/p/android/issues/detail?id=7935
59    public void test_newSocket_connection_refused() throws Exception {
60        try {
61            new Socket("localhost", 80);
62            fail("connection should have been refused");
63        } catch (ConnectException expected) {
64        }
65    }
66
67    // http://code.google.com/p/android/issues/detail?id=3123
68    // http://code.google.com/p/android/issues/detail?id=1933
69    public void test_socketLocalAndRemoteAddresses() throws Exception {
70        checkSocketLocalAndRemoteAddresses(false);
71        checkSocketLocalAndRemoteAddresses(true);
72    }
73
74    public void checkSocketLocalAndRemoteAddresses(boolean setOptions) throws Exception {
75        InetAddress host = InetAddress.getLocalHost();
76
77        // Open a local server port.
78        ServerSocketChannel ssc = ServerSocketChannel.open();
79        InetSocketAddress listenAddr = new InetSocketAddress(host, 0);
80        ssc.socket().bind(listenAddr, 0);
81        ServerSocket ss = ssc.socket();
82
83        // Open a socket to the local port.
84        SocketChannel out = SocketChannel.open();
85        out.configureBlocking(false);
86        if (setOptions) {
87            out.socket().setTcpNoDelay(false);
88        }
89        InetSocketAddress addr = new InetSocketAddress(host, ssc.socket().getLocalPort());
90        out.connect(addr);
91        while (!out.finishConnect()) {
92            Thread.sleep(1);
93        }
94
95        SocketChannel in = ssc.accept();
96        if (setOptions) {
97            in.socket().setTcpNoDelay(false);
98        }
99
100        InetSocketAddress outRemoteAddress = (InetSocketAddress) out.socket().getRemoteSocketAddress();
101        InetSocketAddress outLocalAddress = (InetSocketAddress) out.socket().getLocalSocketAddress();
102        InetSocketAddress inLocalAddress = (InetSocketAddress) in.socket().getLocalSocketAddress();
103        InetSocketAddress inRemoteAddress = (InetSocketAddress) in.socket().getRemoteSocketAddress();
104        System.err.println("inLocalAddress: " + inLocalAddress);
105        System.err.println("inRemoteAddress: " + inRemoteAddress);
106        System.err.println("outLocalAddress: " + outLocalAddress);
107        System.err.println("outRemoteAddress: " + outRemoteAddress);
108
109        assertEquals(outRemoteAddress.getPort(), ss.getLocalPort());
110        assertEquals(inLocalAddress.getPort(), ss.getLocalPort());
111        assertEquals(inRemoteAddress.getPort(), outLocalAddress.getPort());
112
113        assertEquals(inLocalAddress.getAddress(), ss.getInetAddress());
114        assertEquals(inRemoteAddress.getAddress(), ss.getInetAddress());
115        assertEquals(outLocalAddress.getAddress(), ss.getInetAddress());
116        assertEquals(outRemoteAddress.getAddress(), ss.getInetAddress());
117
118        in.close();
119        out.close();
120        ssc.close();
121
122        assertNull(in.socket().getRemoteSocketAddress());
123        assertNull(out.socket().getRemoteSocketAddress());
124
125        assertEquals(in.socket().getLocalSocketAddress(), ss.getLocalSocketAddress());
126    }
127
128    // SocketOptions.setOption has weird behavior for setSoLinger/SO_LINGER.
129    // This test ensures we do what the RI does.
130    public void test_SocketOptions_setOption() throws Exception {
131        class MySocketImpl extends SocketImpl {
132            public int option;
133            public Object value;
134
135            public boolean createCalled;
136            public boolean createStream;
137
138            public MySocketImpl() { super(); }
139            @Override protected void accept(SocketImpl arg0) throws IOException { }
140            @Override protected int available() throws IOException { return 0; }
141            @Override protected void bind(InetAddress arg0, int arg1) throws IOException { }
142            @Override protected void close() throws IOException { }
143            @Override protected void connect(String arg0, int arg1) throws IOException { }
144            @Override protected void connect(InetAddress arg0, int arg1) throws IOException { }
145            @Override protected void connect(SocketAddress arg0, int arg1) throws IOException { }
146            @Override protected InputStream getInputStream() throws IOException { return null; }
147            @Override protected OutputStream getOutputStream() throws IOException { return null; }
148            @Override protected void listen(int arg0) throws IOException { }
149            @Override protected void sendUrgentData(int arg0) throws IOException { }
150            public Object getOption(int arg0) throws SocketException { return null; }
151
152            @Override protected void create(boolean isStream) throws IOException {
153                this.createCalled = true;
154                this.createStream = isStream;
155            }
156
157            public void setOption(int option, Object value) throws SocketException {
158                this.option = option;
159                this.value = value;
160            }
161        }
162
163        class MySocket extends Socket {
164            public MySocket(SocketImpl impl) throws SocketException {
165                super(impl);
166            }
167        }
168
169        MySocketImpl impl = new MySocketImpl();
170        Socket s = new MySocket(impl);
171
172        // Check that, as per the SocketOptions.setOption documentation, we pass false rather
173        // than -1 to the SocketImpl when setSoLinger is called with the first argument false.
174        s.setSoLinger(false, -1);
175        assertEquals(Boolean.FALSE, (Boolean) impl.value);
176        // We also check that SocketImpl.create was called. SocketChannelImpl.SocketAdapter
177        // subclasses Socket, and whether or not to call SocketImpl.create is the main behavioral
178        // difference.
179        assertEquals(true, impl.createCalled);
180        s.setSoLinger(false, 0);
181        assertEquals(Boolean.FALSE, (Boolean) impl.value);
182        s.setSoLinger(false, 1);
183        assertEquals(Boolean.FALSE, (Boolean) impl.value);
184
185        // Check that otherwise, we pass down an Integer.
186        s.setSoLinger(true, 0);
187        assertEquals(Integer.valueOf(0), (Integer) impl.value);
188        s.setSoLinger(true, 1);
189        assertEquals(Integer.valueOf(1), (Integer) impl.value);
190    }
191
192    public void test_setTrafficClass() throws Exception {
193        Socket s = new Socket();
194        s.setTrafficClass(123);
195        assertEquals(123, s.getTrafficClass());
196    }
197}
198