package io.dropwizard.metrics.graphite;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import javax.net.SocketFactory;
import java.io.ByteArrayOutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;
public class GraphiteTest {
private final String host = "example.com";
private final int port = 1234;
private final SocketFactory socketFactory = mock(SocketFactory.class);
private final InetSocketAddress address = new InetSocketAddress(host, port);
private final Socket socket = mock(Socket.class);
private final ByteArrayOutputStream output = spy(new ByteArrayOutputStream());
private Graphite graphite;
@Before
public void setUp() throws Exception {
final AtomicBoolean connected = new AtomicBoolean(true);
final AtomicBoolean closed = new AtomicBoolean(false);
when(socket.isConnected()).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return connected.get();
}
});
when(socket.isClosed()).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return closed.get();
}
});
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
connected.set(false);
closed.set(true);
return null;
}
}).when(socket).close();
when(socket.getOutputStream()).thenReturn(output);
// Mock behavior of socket.getOutputStream().close() calling socket.close();
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
invocation.callRealMethod();
socket.close();
return null;
}
}).when(output).close();
when(socketFactory.createSocket(any(InetAddress.class), anyInt())).thenReturn(socket);
}
@Test
public void connectsToGraphiteWithInetSocketAddress() throws Exception {
graphite = new Graphite(address, socketFactory);
graphite.connect();
verify(socketFactory).createSocket(address.getAddress(), address.getPort());
}
@Test
public void connectsToGraphiteWithHostAndPort() throws Exception {
graphite = new Graphite(host, port, socketFactory);
graphite.connect();
verify(socketFactory).createSocket(address.getAddress(), port);
}
@Test
public void measuresFailures() throws Exception {
graphite = new Graphite(address, socketFactory);
assertThat(graphite.getFailures())
.isZero();
}
@Test
public void disconnectsFromGraphite() throws Exception {
graphite = new Graphite(address, socketFactory);
graphite.connect();
graphite.close();
verify(socket).close();
}
@Test
public void doesNotAllowDoubleConnections() throws Exception {
graphite = new Graphite(address, socketFactory);
graphite.connect();
try {
graphite.connect();
failBecauseExceptionWasNotThrown(IllegalStateException.class);
} catch (IllegalStateException e) {
assertThat(e.getMessage())
.isEqualTo("Already connected");
}
}
@Test
public void writesValuesToGraphite() throws Exception {
graphite = new Graphite(address, socketFactory);
graphite.connect();
graphite.send("name", "value", 100);
graphite.close();
assertThat(output.toString())
.isEqualTo("name value 100\n");
}
@Test
public void sanitizesNames() throws Exception {
graphite = new Graphite(address, socketFactory);
graphite.connect();
graphite.send("name woo", "value", 100);
graphite.close();
assertThat(output.toString())
.isEqualTo("name-woo value 100\n");
}
@Test
public void sanitizesValues() throws Exception {
graphite = new Graphite(address, socketFactory);
graphite.connect();
graphite.send("name", "value woo", 100);
graphite.close();
assertThat(output.toString())
.isEqualTo("name value-woo 100\n");
}
@Test
public void notifiesIfGraphiteIsUnavailable() throws Exception {
final String unavailableHost = "unknown-host-10el6m7yg56ge7dm.com";
InetSocketAddress unavailableAddress = new InetSocketAddress(unavailableHost, 1234);
Graphite unavailableGraphite = new Graphite(unavailableAddress, socketFactory);
try {
unavailableGraphite.connect();
failBecauseExceptionWasNotThrown(UnknownHostException.class);
} catch (Exception e) {
assertThat(e.getMessage())
.isEqualTo(unavailableHost);
}
}
}