/*
 * 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);
        }
    }
}
