package rescuecore2.connection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import java.io.IOException;
import java.net.Socket;
import rescuecore2.registry.Registry;
public class ConnectionManagerTest {
private static final int PORT = 34332;
private static final int PORT2 = 34333;
private static final int DELAY = 1000;
private static final int TIMEOUT = 1000;
private static final String MESSAGE_1 = "Message 1";
private ConnectionManager manager;
private TestConnectionManagerListener listener;
private Registry registry;
@Before
public void setup() {
manager = new ConnectionManager();
listener = new TestConnectionManagerListener();
registry = new Registry();
registry.registerMessageFactory(new TestMessageFactory("", MESSAGE_1));
}
@After
public void cleanup() {
manager.shutdown();
}
@Test
public void testListen() throws IOException, InterruptedException {
manager.listen(PORT, registry, listener);
// Check that connecting to the socket results in a new Connection.
new Socket("localhost", PORT);
assertTrue(listener.waitForCount(1, TIMEOUT));
// Sleep for a bit and make a new connection
Thread.sleep(DELAY);
new Socket("localhost", PORT);
assertTrue(listener.waitForCount(2, TIMEOUT));
// Make a bunch of new connections and check that they all arrive
new Socket("localhost", PORT);
new Socket("localhost", PORT);
new Socket("localhost", PORT);
new Socket("localhost", PORT);
assertTrue(listener.waitForCount(6, TIMEOUT));
}
@Test
public void testListenMultiplePorts() throws IOException, InterruptedException {
manager.listen(PORT, registry, listener);
manager.listen(PORT2, registry, listener);
// Check that connecting to each socket results in a new Connection.
new Socket("localhost", PORT);
new Socket("localhost", PORT2);
assertTrue(listener.waitForCount(2, TIMEOUT));
}
@Test
public void testShutdown() throws IOException, InterruptedException {
manager.listen(PORT, registry, listener);
manager.listen(PORT2, registry, listener);
// Check that connecting to each socket results in a new Connection.
new Socket("localhost", PORT);
new Socket("localhost", PORT2);
assertTrue(listener.waitForCount(2, TIMEOUT));
assertTrue(manager.isAlive());
manager.shutdown();
assertFalse(manager.isAlive());
// Check that further connections are rejected
try {
new Socket("localhost", PORT);
fail("Expected an IOException");
}
catch (IOException e) {
// Expected
}
try {
new Socket("localhost", PORT2);
fail("Expected an IOException");
}
catch (IOException e) {
// Expected
}
Thread.sleep(DELAY);
assertEquals(2, listener.getCount());
}
@Test
public void testShutdownPreventsListen() throws IOException, InterruptedException {
manager.listen(PORT, registry, listener);
// Check that connecting to the socket results in a new Connection.
new Socket("localhost", PORT);
assertTrue(listener.waitForCount(1, TIMEOUT));
manager.shutdown();
// Check that attempting to listen again fails
try {
manager.listen(PORT2, registry, listener);
fail("Expected an IOException when trying to listen after shutdown");
}
catch (IOException e) {
// Expected
}
try {
new Socket("localhost", PORT2);
fail("Expected an IOException");
}
catch (IOException e) {
// Expected
}
Thread.sleep(DELAY);
assertEquals(1, listener.getCount());
}
@Test
public void testInterruptedShutdown() throws IOException, InterruptedException {
manager.listen(PORT, registry, listener);
// Check that connecting to the socket results in a new Connection.
new Socket("localhost", PORT);
assertTrue(listener.waitForCount(1, TIMEOUT));
Thread.currentThread().interrupt();
manager.shutdown();
// Check that connecting to the port fails
// This may or may not throw an exception, but the new connection should not be registered even if it arrives before the server socket closes.
try {
new Socket("localhost", PORT);
}
catch (IOException e) {
// Expected
}
Thread.sleep(DELAY);
assertEquals(1, listener.getCount());
// Check that attempting to listen again fails
try {
manager.listen(PORT2, registry, listener);
fail("Expected an IOException when trying to listen after shutdown");
}
catch (IOException e) {
// Expected
}
try {
new Socket("localhost", PORT2);
fail("Expected an IOException");
}
catch (IOException e) {
// Expected
}
Thread.sleep(DELAY);
assertEquals(1, listener.getCount());
}
private class TestConnectionManagerListener implements ConnectionManagerListener {
private int count;
public TestConnectionManagerListener() {
count = 0;
}
@Override
public synchronized void newConnection(Connection c) {
++count;
this.notifyAll();
}
public synchronized int getCount() {
return count;
}
public synchronized boolean waitForCount(int goal, long timeout) {
long end = System.currentTimeMillis() + timeout;
while (count < goal) {
long now = System.currentTimeMillis();
if (now > end) {
return false;
}
try {
wait(end - now);
}
catch (InterruptedException e) {
return count >= goal;
}
}
return true;
}
}
}