ServerSocketChannelTest.java revision ff81b740a338ba964e0ba1c40d925fb2ceb37bf2
1/*
2 * Copyright (C) 2011 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.nio.channels;
18
19import java.io.IOException;
20import java.net.InetAddress;
21import java.net.InetSocketAddress;
22import java.net.NetworkInterface;
23import java.net.ServerSocket;
24import java.net.SocketOption;
25import java.net.StandardSocketOptions;
26import java.nio.channels.ClosedChannelException;
27import java.nio.channels.ServerSocketChannel;
28import java.nio.channels.SocketChannel;
29import java.util.Enumeration;
30import java.util.Set;
31
32public class ServerSocketChannelTest extends junit.framework.TestCase {
33    // http://code.google.com/p/android/issues/detail?id=16579
34    public void testNonBlockingAccept() throws Exception {
35        ServerSocketChannel ssc = ServerSocketChannel.open();
36        try {
37            ssc.configureBlocking(false);
38            ssc.bind(null);
39            // Should return immediately, since we're non-blocking.
40            assertNull(ssc.accept());
41        } finally {
42            ssc.close();
43        }
44    }
45
46    /** Checks the state of the ServerSocketChannel and associated ServerSocket after open() */
47    public void test_open_initialState() throws Exception {
48        ServerSocketChannel ssc = ServerSocketChannel.open();
49        try {
50            assertNull(ssc.getLocalAddress());
51
52            ServerSocket socket = ssc.socket();
53            assertFalse(socket.isBound());
54            assertFalse(socket.isClosed());
55            assertEquals(-1, socket.getLocalPort());
56            assertNull(socket.getLocalSocketAddress());
57            assertNull(socket.getInetAddress());
58            assertTrue(socket.getReuseAddress());
59
60            assertSame(ssc, socket.getChannel());
61        } finally {
62            ssc.close();
63        }
64    }
65
66    public void test_bind_nullBindsToAll() throws Exception {
67        ServerSocketChannel ssc = ServerSocketChannel.open();
68        ssc.bind(null);
69        InetSocketAddress boundAddress = (InetSocketAddress) ssc.getLocalAddress();
70        assertTrue(boundAddress.getAddress().isAnyLocalAddress());
71        assertFalse(boundAddress.getAddress().isLinkLocalAddress());
72        assertFalse(boundAddress.getAddress().isLoopbackAddress());
73
74        // Attempt to connect to the "any" address.
75        assertTrue(canConnect(boundAddress));
76
77        // Go through all local IPs and try to connect to each in turn - all should succeed.
78        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
79        while (interfaces.hasMoreElements()) {
80            NetworkInterface nic = interfaces.nextElement();
81            Enumeration<InetAddress> inetAddresses = nic.getInetAddresses();
82            while (inetAddresses.hasMoreElements()) {
83                InetSocketAddress address =
84                        new InetSocketAddress(inetAddresses.nextElement(), boundAddress.getPort());
85                assertTrue(canConnect(address));
86            }
87        }
88
89        ssc.close();
90    }
91
92    public void test_bind_loopback() throws Exception {
93        ServerSocketChannel ssc = ServerSocketChannel.open();
94        ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
95        InetSocketAddress boundAddress = (InetSocketAddress) ssc.getLocalAddress();
96        assertFalse(boundAddress.getAddress().isAnyLocalAddress());
97        assertFalse(boundAddress.getAddress().isLinkLocalAddress());
98        assertTrue(boundAddress.getAddress().isLoopbackAddress());
99
100        // Attempt to connect to the "loopback" address. Note: There can be several loopback
101        // addresses, such as 127.0.0.1 (IPv4) and 0:0:0:0:0:0:0:1 (IPv6) and only one will be
102        // bound.
103        InetSocketAddress loopbackAddress =
104                new InetSocketAddress(InetAddress.getLoopbackAddress(), boundAddress.getPort());
105        assertTrue(canConnect(loopbackAddress));
106
107        // Go through all local IPs and try to connect to each in turn - all should fail except
108        // for the loopback.
109        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
110        while (interfaces.hasMoreElements()) {
111            NetworkInterface nic = interfaces.nextElement();
112            Enumeration<InetAddress> inetAddresses = nic.getInetAddresses();
113            while (inetAddresses.hasMoreElements()) {
114                InetSocketAddress address =
115                        new InetSocketAddress(inetAddresses.nextElement(), boundAddress.getPort());
116                if (!address.equals(loopbackAddress)) {
117                    assertFalse(canConnect(address));
118                }
119            }
120        }
121
122        ssc.close();
123    }
124
125    private static boolean canConnect(InetSocketAddress address) {
126        try {
127            SocketChannel socketChannel = SocketChannel.open(address);
128            socketChannel.close();
129            return true;
130        } catch (IOException e) {
131            return false;
132        }
133    }
134
135    public void test_supportedOptions() throws Exception {
136        ServerSocketChannel ssc = ServerSocketChannel.open();
137        Set<SocketOption<?>> options = ssc.supportedOptions();
138
139        // Probe some values. This is not intended to be complete.
140        assertTrue(options.contains(StandardSocketOptions.SO_REUSEADDR));
141        assertFalse(options.contains(StandardSocketOptions.IP_MULTICAST_TTL));
142    }
143
144    public void test_getOption_unsupportedOption() throws Exception {
145        ServerSocketChannel ssc = ServerSocketChannel.open();
146        try {
147            ssc.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
148            fail();
149        } catch (UnsupportedOperationException expected) {}
150
151        ssc.close();
152    }
153
154    public void test_getOption_afterClose() throws Exception {
155        ServerSocketChannel ssc = ServerSocketChannel.open();
156        ssc.close();
157
158        try {
159            ssc.getOption(StandardSocketOptions.SO_RCVBUF);
160            fail();
161        } catch (ClosedChannelException expected) {}
162    }
163
164    public void test_setOption_afterClose() throws Exception {
165        ServerSocketChannel ssc = ServerSocketChannel.open();
166        ssc.close();
167
168        try {
169            ssc.setOption(StandardSocketOptions.SO_RCVBUF, 1234);
170            fail();
171        } catch (ClosedChannelException expected) {}
172    }
173
174    public void test_getOption_SO_RCVBUF_defaults() throws Exception {
175        ServerSocketChannel ssc = ServerSocketChannel.open();
176
177        int value = ssc.getOption(StandardSocketOptions.SO_RCVBUF);
178        assertTrue(value > 0);
179        assertEquals(value, ssc.socket().getReceiveBufferSize());
180
181        ssc.close();
182    }
183
184    public void test_setOption_SO_RCVBUF_afterOpen() throws Exception {
185        ServerSocketChannel ssc = ServerSocketChannel.open();
186
187        trySetReceiveBufferSizeOption(ssc);
188
189        ssc.close();
190    }
191
192    private static void trySetReceiveBufferSizeOption(ServerSocketChannel ssc) throws IOException {
193        int initialValue = ssc.getOption(StandardSocketOptions.SO_RCVBUF);
194        try {
195            ssc.setOption(StandardSocketOptions.SO_RCVBUF, -1);
196            fail();
197        } catch (IllegalArgumentException expected) {}
198        int actualValue = ssc.getOption(StandardSocketOptions.SO_RCVBUF);
199        assertEquals(initialValue, actualValue);
200        assertEquals(initialValue, ssc.socket().getReceiveBufferSize());
201
202        int newBufferSize = initialValue - 1;
203        ssc.setOption(StandardSocketOptions.SO_RCVBUF, newBufferSize);
204        actualValue = ssc.getOption(StandardSocketOptions.SO_RCVBUF);
205        // The Linux Kernel actually doubles the value it is given and may choose to ignore it.
206        // This assertion may be brittle.
207        assertTrue(actualValue != initialValue);
208        assertEquals(actualValue, ssc.socket().getReceiveBufferSize());
209    }
210
211    public void test_getOption_SO_REUSEADDR_defaults() throws Exception {
212        ServerSocketChannel ssc = ServerSocketChannel.open();
213
214        boolean value = ssc.getOption(StandardSocketOptions.SO_REUSEADDR);
215        assertTrue(value);
216        assertTrue(ssc.socket().getReuseAddress());
217
218        ssc.close();
219    }
220
221    public void test_setOption_SO_REUSEADDR_afterOpen() throws Exception {
222        ServerSocketChannel ssc = ServerSocketChannel.open();
223
224        boolean initialValue = ssc.getOption(StandardSocketOptions.SO_REUSEADDR);
225        ssc.setOption(StandardSocketOptions.SO_REUSEADDR, !initialValue);
226        assertEquals(!initialValue, (boolean) ssc.getOption(StandardSocketOptions.SO_REUSEADDR));
227        assertEquals(!initialValue, ssc.socket().getReuseAddress());
228
229        ssc.close();
230    }
231
232}
233