diff options
author | Jesse Wilson <jessewilson@google.com> | 2010-09-28 19:36:39 -0700 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2010-09-28 19:36:39 -0700 |
commit | 4d743816cad738bfeccf6dc210fc7c9bd84a8777 (patch) | |
tree | ac006911433f05d1d8ffee194fa9942c524839fc | |
parent | 1f8243e3d2b5a3f8e0398c304d1dea0395cbc368 (diff) | |
download | libcore-4d743816cad738bfeccf6dc210fc7c9bd84a8777.zip libcore-4d743816cad738bfeccf6dc210fc7c9bd84a8777.tar.gz libcore-4d743816cad738bfeccf6dc210fc7c9bd84a8777.tar.bz2 |
Tests for ServerSocketFactory.getDefault().
Motivated by http://b/2587385
Change-Id: If30898859f869c88342d1069a2425575752ebf6e
3 files changed, 156 insertions, 35 deletions
diff --git a/luni/src/main/java/java/net/ServerSocket.java b/luni/src/main/java/java/net/ServerSocket.java index 6ddf59e..e7e7f9f 100644 --- a/luni/src/main/java/java/net/ServerSocket.java +++ b/luni/src/main/java/java/net/ServerSocket.java @@ -336,10 +336,10 @@ public class ServerSocket { } /** - * Binds this server socket to the given local socket address. The default - * number of pending connections may be backlogged. If the {@code localAddr} - * is set to {@code null} the socket will be bound to an available local - * address on any free port of the system. + * Binds this server socket to the given local socket address with a maximum + * backlog of 50 unaccepted connections. If the {@code localAddr} is set to + * {@code null} the socket will be bound to an available local address on + * any free port of the system. * * @param localAddr * the local address and port to bind on. @@ -356,20 +356,15 @@ public class ServerSocket { /** * Binds this server socket to the given local socket address. If the * {@code localAddr} is set to {@code null} the socket will be bound to an - * available local address on any free port of the system. The value for - * {@code backlog} must e greater than {@code 0} otherwise the default value - * will be used. + * available local address on any free port of the system. * - * @param localAddr - * the local machine address and port to bind on. - * @param backlog - * the number of pending connection requests, before requests - * will be rejected. - * @throws IllegalArgumentException - * if the {@code SocketAddress} is not supported. - * @throws IOException - * if the socket is already bound or a problem occurs during - * binding. + * @param localAddr the local machine address and port to bind on. + * @param backlog the maximum number of unaccepted connections. Passing 0 or + * a negative value yields the default backlog of 50. + * @throws IllegalArgumentException if the {@code SocketAddress} is not + * supported. + * @throws IOException if the socket is already bound or a problem occurs + * during binding. */ public void bind(SocketAddress localAddr, int backlog) throws IOException { checkClosedAndCreate(true); diff --git a/luni/src/main/java/javax/net/ServerSocketFactory.java b/luni/src/main/java/javax/net/ServerSocketFactory.java index f2d2c0d..15ab773 100644 --- a/luni/src/main/java/javax/net/ServerSocketFactory.java +++ b/luni/src/main/java/javax/net/ServerSocketFactory.java @@ -64,10 +64,10 @@ public abstract class ServerSocketFactory { } /** - * Creates a new server socket which is bound to the given port. + * Creates a new server socket which is bound to the given port with a + * maximum backlog of 50 unaccepted connections. * - * @param port - * the port on which the created socket has to listen. + * @param port the port on which the created socket has to listen. * @return the created bound server socket. * @throws IOException * if an error occurs while creating a new server socket. @@ -78,13 +78,11 @@ public abstract class ServerSocketFactory { * Creates a new server socket which is bound to the given port and * configures its maximum of queued connections. * - * @param port - * the port on which the created socket has to listen. - * @param backlog - * the maximum of queued connections. + * @param port the port on which the created socket has to listen. + * @param backlog the maximum number of unaccepted connections. Passing 0 or + * a negative value yields the default backlog of 50. * @return the created bound server socket. - * @throws IOException - * if an error occurs while creating a new server socket. + * @throws IOException if an error occurs while creating a new server socket. */ public abstract ServerSocket createServerSocket(int port, int backlog) throws IOException; @@ -92,16 +90,13 @@ public abstract class ServerSocketFactory { * Creates a new server socket which is bound to the given address on the * specified port and configures its maximum of queued connections. * - * @param port - * the port on which the created socket has to listen. - * @param backlog - * the maximum of queued connections. - * @param iAddress - * the address of the network interface which is used by the - * created socket. + * @param port the port on which the created socket has to listen. + * @param backlog the maximum number of unaccepted connections. Passing 0 or + * a negative value yields the default backlog of 50. + * @param iAddress the address of the network interface which is used by the + * created socket. * @return the created bound server socket. - * @throws IOException - * if an error occurs while creating a new server socket. + * @throws IOException if an error occurs while creating a new server socket. */ public abstract ServerSocket createServerSocket(int port, int backlog, InetAddress iAddress) throws IOException; diff --git a/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java b/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java new file mode 100644 index 0000000..77996dd --- /dev/null +++ b/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.javax.net; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.net.ServerSocketFactory; +import junit.framework.TestCase; + +public class ServerSocketFactoryTest extends TestCase { + + public void testCreateServerSocket() throws IOException { + ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(); + serverSocket.bind(new InetSocketAddress(0)); + testSocket(serverSocket, 50); + } + + public void testCreateServerSocketWithPort() throws IOException { + ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0); + testSocket(serverSocket, 50); + } + + public void testCreateServerSocketWithPortNoBacklog() throws IOException { + ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 1); + testSocket(serverSocket, 1); + } + + public void testCreateServerSocketWithPortZeroBacklog() throws IOException { + ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 0); + testSocket(serverSocket, 50); + } + + public void testCreateServerSocketWithPortAndBacklog() throws IOException { + ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 50); + testSocket(serverSocket, 50); + } + + private void testSocket(final ServerSocket serverSocket, int specifiedBacklog) + throws IOException { + final byte[] data = "abc".getBytes(); + + new Thread(new Runnable() { + public void run() { + try { + Socket s = serverSocket.accept(); + s.getOutputStream().write(data); + s.close(); + } catch (IOException e) { + } + } + }).start(); + + Socket socket = new Socket(InetAddress.getLocalHost(), serverSocket.getLocalPort()); + assertBacklog(specifiedBacklog, new InetSocketAddress( + InetAddress.getLocalHost(), serverSocket.getLocalPort())); + + InputStream in = socket.getInputStream(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + transfer(in, out); + assertEquals(Arrays.toString(data), Arrays.toString(out.toByteArray())); + socket.close(); + + serverSocket.close(); + } + + /** + * Validates that the backlog of the listening address is as specified. + */ + private void assertBacklog(int specifiedBacklog, InetSocketAddress serverAddress) + throws IOException { + List<Socket> backlog = new ArrayList<Socket>(); + int peak = 0; + try { + int max = 100; + for (int i = 0; i < max; i++) { + Socket socket = new Socket(); + backlog.add(socket); + socket.connect(serverAddress, 500); + peak++; + } + fail("Failed to exhaust backlog after " + max + " connections!"); + } catch (IOException expected) { + } + + System.out.println("backlog peaked at " + peak); + + for (Socket socket : backlog) { + socket.close(); + } + + /* + * In 4.5 of UNIX Network Programming, Stevens says: + * "Berkeley-derived implementations add a fudge factor to the + * backlog: it is multiplied by 1.5." + * + * We've observed that Linux always adds 3 to the user-specified + * backlog. + */ + assertTrue(peak >= specifiedBacklog && peak <= (specifiedBacklog + 3) * 1.5); + } + + private void transfer(InputStream in, ByteArrayOutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + int count; + while ((count = in.read(buffer)) != -1) { + out.write(buffer, 0, count); + } + } +} |