001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.net.server;
015
016import static org.junit.Assert.assertNotNull;
017import static org.junit.Assert.assertTrue;
018
019import java.io.IOException;
020import java.net.InetAddress;
021import java.net.ServerSocket;
022import java.net.Socket;
023
024import org.junit.Before;
025import org.junit.Test;
026
027import ch.qos.logback.core.net.server.Client;
028import ch.qos.logback.core.net.server.ServerSocketListener;
029import ch.qos.logback.core.net.server.test.ServerSocketUtil;
030
031/**
032 * Unit tests for {@link ServerSocketListener}.
033 *
034 * @author Carl Harris
035 */
036public class ServerSocketListenerTest {
037
038    private ServerSocket serverSocket;
039    @SuppressWarnings("rawtypes")
040    private ServerSocketListener listener;
041
042    @Before
043    public void setUp() throws Exception {
044        serverSocket = ServerSocketUtil.createServerSocket();
045        assertNotNull(serverSocket);
046        listener = new InstrumentedServerSocketListener(serverSocket);
047    }
048
049    @Test
050    public void testAcceptClient() throws Exception {
051        RunnableClient localClient = new RunnableClient(InetAddress.getLocalHost(), serverSocket.getLocalPort());
052        Thread thread = new Thread(localClient);
053        thread.start();
054        synchronized (localClient) {
055            int retries = 200;
056            while (retries-- > 0 && !localClient.isConnected()) {
057                localClient.wait(10);
058            }
059        }
060        assertTrue(localClient.isConnected());
061        localClient.close();
062
063        serverSocket.setSoTimeout(5000);
064        Client client = listener.acceptClient();
065        assertNotNull(client);
066        client.close();
067    }
068
069    private static class InstrumentedServerSocketListener extends ServerSocketListener<RemoteClient> {
070
071        public InstrumentedServerSocketListener(ServerSocket serverSocket) {
072            super(serverSocket);
073        }
074
075        @Override
076        protected RemoteClient createClient(String id, Socket socket) throws IOException {
077            return new RemoteClient(socket);
078        }
079
080    }
081
082    private static class RemoteClient implements Client {
083
084        private final Socket socket;
085
086        public RemoteClient(Socket socket) {
087            this.socket = socket;
088        }
089
090        public void run() {
091        }
092
093        public void close() {
094            try {
095                socket.close();
096            } catch (IOException ex) {
097                ex.printStackTrace(System.err);
098            }
099        }
100
101    }
102
103    private static class RunnableClient implements Client {
104
105        private final InetAddress inetAddress;
106        private final int port;
107        private boolean connected;
108        private boolean closed;
109
110        public RunnableClient(InetAddress inetAddress, int port) {
111            super();
112            this.inetAddress = inetAddress;
113            this.port = port;
114        }
115
116        public synchronized boolean isConnected() {
117            return connected;
118        }
119
120        public synchronized void setConnected(boolean connected) {
121            this.connected = connected;
122        }
123
124        public void run() {
125            try {
126                Socket socket = new Socket(inetAddress, port);
127                synchronized (this) {
128                    setConnected(true);
129                    notifyAll();
130                    while (!closed && !Thread.currentThread().isInterrupted()) {
131                        try {
132                            wait();
133                        } catch (InterruptedException ex) {
134                            Thread.currentThread().interrupt();
135                        }
136                    }
137                    socket.close();
138                }
139            } catch (IOException ex) {
140                ex.printStackTrace(System.err);
141            }
142        }
143
144        public synchronized void close() {
145            closed = true;
146            notifyAll();
147        }
148
149    }
150}