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