blob: 8add40b293d9b3b8f8d05b12a02963c6f19804ba [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc.
*
* 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 com.google.caliper.runner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.google.caliper.bridge.OpenedSocket;
import com.google.caliper.bridge.StartupAnnounceMessage;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
/**
* Tests for {@link ServerSocketService}.
*/
@RunWith(JUnit4.class)
public class ServerSocketServiceTest {
private final ServerSocketService service = new ServerSocketService();
private int port;
@Before public void startService() {
service.startAsync().awaitRunning();
port = service.getPort();
}
@After public void stopService() {
service.stopAsync().awaitTerminated();
}
@Test public void getConnectionId_requestComesInFirst() throws Exception {
UUID id = UUID.randomUUID();
ListenableFuture<OpenedSocket> pendingServerConnection = service.getConnection(id);
assertFalse(pendingServerConnection.isDone());
OpenedSocket clientSocket = openConnectionAndIdentify(id);
// Assert that the ends are hooked up to each other
assertEndsConnected(clientSocket, pendingServerConnection.get());
}
@Test public void getConnectionIdTwice_acceptComesFirst() throws Exception {
UUID id = UUID.randomUUID();
OpenedSocket clientSocket = openConnectionAndIdentify(id);
ListenableFuture<OpenedSocket> pendingServerConnection = service.getConnection(id);
// wait for the service to fully initialize the connection
OpenedSocket serverSocket = pendingServerConnection.get();
assertEndsConnected(clientSocket, serverSocket);
try {
// the second request is an error
service.getConnection(id).get();
fail();
} catch (IllegalStateException expected) {}
}
@Test public void getConnectionStoppedService() throws Exception {
UUID id = UUID.randomUUID();
ListenableFuture<OpenedSocket> pendingServerConnection = service.getConnection(id);
assertFalse(pendingServerConnection.isDone());
service.stopAsync().awaitTerminated();
assertTrue(pendingServerConnection.isDone());
try {
pendingServerConnection.get();
fail();
} catch (ExecutionException e) {
assertEquals("The socket has been closed", e.getCause().getMessage());
}
try {
service.getConnection(UUID.randomUUID());
fail();
} catch (IllegalStateException expected) {}
}
private OpenedSocket openClientConnection() throws IOException {
return OpenedSocket.fromSocket(new Socket(InetAddress.getLoopbackAddress(), port));
}
/**
* Opens a connection to the service and identifies itself using the id.
*/
private OpenedSocket openConnectionAndIdentify(UUID id) throws IOException {
OpenedSocket clientSocket = openClientConnection();
OpenedSocket.Writer writer = clientSocket.writer();
writer.write(new StartupAnnounceMessage(id));
writer.flush();
return clientSocket;
}
private void assertEndsConnected(OpenedSocket clientSocket, OpenedSocket serverSocket)
throws IOException {
serverSocket.writer().write("hello client!");
serverSocket.writer().flush(); // necessary to prevent deadlock
assertEquals("hello client!", clientSocket.reader().read());
clientSocket.writer().write("hello server!");
clientSocket.writer().flush(); // ditto
assertEquals("hello server!", serverSocket.reader().read());
}
}