SocketTest.java revision 4557728efb66c455a52b7669a8eefef7a9e54854
1a9a57f2581773484d13e160fd3407692e825971aElliott Hughes/*
2a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * Copyright (C) 2009 The Android Open Source Project
3f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
4a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * you may not use this file except in compliance with the License.
6a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * You may obtain a copy of the License at
7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
8a9a57f2581773484d13e160fd3407692e825971aElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
10a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * Unless required by applicable law or agreed to in writing, software
11a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * See the License for the specific language governing permissions and
14a9a57f2581773484d13e160fd3407692e825971aElliott Hughes * limitations under the License.
15a9a57f2581773484d13e160fd3407692e825971aElliott Hughes */
16a9a57f2581773484d13e160fd3407692e825971aElliott Hughes
174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.java.net;
18a9a57f2581773484d13e160fd3407692e825971aElliott Hughes
190371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughesimport java.io.IOException;
200371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughesimport java.io.InputStream;
210371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughesimport java.io.OutputStream;
224557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.ConnectException;
234557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.InetAddress;
244557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.InetSocketAddress;
254557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.ServerSocket;
264557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.Socket;
274557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.SocketAddress;
284557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.SocketException;
294557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.net.SocketImpl;
308cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughesimport java.nio.channels.ServerSocketChannel;
318cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughesimport java.nio.channels.SocketChannel;
328cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
33a9a57f2581773484d13e160fd3407692e825971aElliott Hughespublic class SocketTest extends junit.framework.TestCase {
34a9a57f2581773484d13e160fd3407692e825971aElliott Hughes    /**
35a9a57f2581773484d13e160fd3407692e825971aElliott Hughes     * Our getLocalAddress and getLocalPort currently use getsockname(3).
36a9a57f2581773484d13e160fd3407692e825971aElliott Hughes     * This means they give incorrect results on closed sockets (as well
37a9a57f2581773484d13e160fd3407692e825971aElliott Hughes     * as requiring an unnecessary call into native code).
38a9a57f2581773484d13e160fd3407692e825971aElliott Hughes     */
39a9a57f2581773484d13e160fd3407692e825971aElliott Hughes    public void test_getLocalAddress_after_close() throws Exception {
40a9a57f2581773484d13e160fd3407692e825971aElliott Hughes        Socket s = new Socket();
41a9a57f2581773484d13e160fd3407692e825971aElliott Hughes        try {
42a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            // Bind to an ephemeral local port.
43a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            s.bind(new InetSocketAddress("localhost", 0));
44a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            assertTrue(s.getLocalAddress().isLoopbackAddress());
45a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            // What local port did we get?
46a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            int localPort = s.getLocalPort();
47a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            assertTrue(localPort > 0);
48a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            // Now close the socket...
49a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            s.close();
50a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            // The RI returns the ANY address but the original local port after close.
51a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            assertTrue(s.getLocalAddress().isAnyLocalAddress());
52a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            assertEquals(localPort, s.getLocalPort());
53a9a57f2581773484d13e160fd3407692e825971aElliott Hughes        } finally {
54a9a57f2581773484d13e160fd3407692e825971aElliott Hughes            s.close();
55a9a57f2581773484d13e160fd3407692e825971aElliott Hughes        }
56a9a57f2581773484d13e160fd3407692e825971aElliott Hughes    }
57ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes
58ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes    // http://code.google.com/p/android/issues/detail?id=7935
59ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes    public void test_newSocket_connection_refused() throws Exception {
60ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes        try {
61ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes            new Socket("localhost", 80);
62ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes            fail("connection should have been refused");
63ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes        } catch (ConnectException expected) {
64ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes        }
65ad4718b11db66d197b14cd0ec3ed17905bbedd34Elliott Hughes    }
668cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
678cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    // http://code.google.com/p/android/issues/detail?id=3123
688cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    // http://code.google.com/p/android/issues/detail?id=1933
698cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public void test_socketLocalAndRemoteAddresses() throws Exception {
708cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        checkSocketLocalAndRemoteAddresses(false);
718cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        checkSocketLocalAndRemoteAddresses(true);
728cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    }
738cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
748cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    public void checkSocketLocalAndRemoteAddresses(boolean setOptions) throws Exception {
758cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetAddress host = InetAddress.getLocalHost();
768cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
778cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        // Open a local server port.
788cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        ServerSocketChannel ssc = ServerSocketChannel.open();
798cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetSocketAddress listenAddr = new InetSocketAddress(host, 0);
808cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        ssc.socket().bind(listenAddr, 0);
818cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        ServerSocket ss = ssc.socket();
828cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
838cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        // Open a socket to the local port.
848cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        SocketChannel out = SocketChannel.open();
858cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        out.configureBlocking(false);
868cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        if (setOptions) {
878cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes            out.socket().setTcpNoDelay(false);
888cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        }
898cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetSocketAddress addr = new InetSocketAddress(host, ssc.socket().getLocalPort());
908cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        out.connect(addr);
918cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        while (!out.finishConnect()) {
928cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes            Thread.sleep(1);
938cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        }
948cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
958cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        SocketChannel in = ssc.accept();
968cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        if (setOptions) {
978cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes            in.socket().setTcpNoDelay(false);
988cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        }
998cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
1008cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetSocketAddress outRemoteAddress = (InetSocketAddress) out.socket().getRemoteSocketAddress();
1018cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetSocketAddress outLocalAddress = (InetSocketAddress) out.socket().getLocalSocketAddress();
1028cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetSocketAddress inLocalAddress = (InetSocketAddress) in.socket().getLocalSocketAddress();
1038cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        InetSocketAddress inRemoteAddress = (InetSocketAddress) in.socket().getRemoteSocketAddress();
1048cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        System.err.println("inLocalAddress: " + inLocalAddress);
1058cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        System.err.println("inRemoteAddress: " + inRemoteAddress);
1068cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        System.err.println("outLocalAddress: " + outLocalAddress);
1078cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        System.err.println("outRemoteAddress: " + outRemoteAddress);
1088cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
1098cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(outRemoteAddress.getPort(), ss.getLocalPort());
1108cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(inLocalAddress.getPort(), ss.getLocalPort());
1118cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(inRemoteAddress.getPort(), outLocalAddress.getPort());
1128cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
1138cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(inLocalAddress.getAddress(), ss.getInetAddress());
1148cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(inRemoteAddress.getAddress(), ss.getInetAddress());
1158cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(outLocalAddress.getAddress(), ss.getInetAddress());
1168cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(outRemoteAddress.getAddress(), ss.getInetAddress());
1178cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
1188cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        in.close();
1198cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        out.close();
1208cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        ssc.close();
1218cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
1228cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertNull(in.socket().getRemoteSocketAddress());
1238cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertNull(out.socket().getRemoteSocketAddress());
1248cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes
1258cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes        assertEquals(in.socket().getLocalSocketAddress(), ss.getLocalSocketAddress());
1268cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes    }
1270371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1280371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    // SocketOptions.setOption has weird behavior for setSoLinger/SO_LINGER.
1290371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    // This test ensures we do what the RI does.
1300371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    public void test_SocketOptions_setOption() throws Exception {
1310371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        class MySocketImpl extends SocketImpl {
1320371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public int option;
1330371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public Object value;
1340371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1350371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public boolean createCalled;
1360371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public boolean createStream;
1370371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1380371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public MySocketImpl() { super(); }
1390371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void accept(SocketImpl arg0) throws IOException { }
1400371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected int available() throws IOException { return 0; }
1410371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void bind(InetAddress arg0, int arg1) throws IOException { }
1420371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void close() throws IOException { }
1430371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void connect(String arg0, int arg1) throws IOException { }
1440371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void connect(InetAddress arg0, int arg1) throws IOException { }
1450371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void connect(SocketAddress arg0, int arg1) throws IOException { }
1460371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected InputStream getInputStream() throws IOException { return null; }
1470371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected OutputStream getOutputStream() throws IOException { return null; }
1480371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void listen(int arg0) throws IOException { }
1490371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void sendUrgentData(int arg0) throws IOException { }
1500371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public Object getOption(int arg0) throws SocketException { return null; }
1510371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1520371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            @Override protected void create(boolean isStream) throws IOException {
1530371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                this.createCalled = true;
1540371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                this.createStream = isStream;
1550371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            }
1560371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1570371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public void setOption(int option, Object value) throws SocketException {
1580371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                this.option = option;
1590371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                this.value = value;
1600371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            }
1610371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        }
1620371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1630371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        class MySocket extends Socket {
1640371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            public MySocket(SocketImpl impl) throws SocketException {
1650371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes                super(impl);
1660371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes            }
1670371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        }
1680371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1690371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        MySocketImpl impl = new MySocketImpl();
1700371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        Socket s = new MySocket(impl);
1710371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1720371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // Check that, as per the SocketOptions.setOption documentation, we pass false rather
1730371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // than -1 to the SocketImpl when setSoLinger is called with the first argument false.
1740371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        s.setSoLinger(false, -1);
1750371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(Boolean.FALSE, (Boolean) impl.value);
1760371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // We also check that SocketImpl.create was called. SocketChannelImpl.SocketAdapter
1770371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // subclasses Socket, and whether or not to call SocketImpl.create is the main behavioral
1780371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // difference.
1790371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(true, impl.createCalled);
1800371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        s.setSoLinger(false, 0);
1810371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(Boolean.FALSE, (Boolean) impl.value);
1820371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        s.setSoLinger(false, 1);
1830371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(Boolean.FALSE, (Boolean) impl.value);
1840371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1850371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        // Check that otherwise, we pass down an Integer.
1860371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        s.setSoLinger(true, 0);
1870371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(Integer.valueOf(0), (Integer) impl.value);
1880371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        s.setSoLinger(true, 1);
1890371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(Integer.valueOf(1), (Integer) impl.value);
1900371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    }
1910371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes
1920371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    public void test_setTrafficClass() throws Exception {
1930371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        Socket s = new Socket();
1940371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        s.setTrafficClass(123);
1950371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes        assertEquals(123, s.getTrafficClass());
1960371d85fa3ecb5f162d107cdbff0a99cd987fdccElliott Hughes    }
197a9a57f2581773484d13e160fd3407692e825971aElliott Hughes}
198