package biz.paluch.logging.gelf.intern.sender; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.IOException; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.util.Random; import org.apache.commons.lang.RandomStringUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import biz.paluch.logging.gelf.intern.ErrorReporter; import biz.paluch.logging.gelf.intern.GelfMessage; import external.MockitoExtension; /** * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) public class GelfTCPSenderUnitTests { @Mock private ErrorReporter errorReporter; @Captor private ArgumentCaptor<Exception> captor; @Test public void connectionRefusedShouldReportException() throws Exception { GelfTCPSender tcpSender = new GelfTCPSender("127.0.0.1", 65534, 100, 100, errorReporter); tcpSender.sendMessage(new GelfMessage()); verify(errorReporter).reportError(anyString(), captor.capture()); Exception exception = captor.getValue(); assertThat(exception.getClass()).isEqualTo(IOException.class); assertThat(exception.getCause().getClass()).isEqualTo(ConnectException.class); } @Test public void connectionTimeoutShouldReportException() throws Exception { GelfTCPSender tcpSender = new GelfTCPSender("8.8.8.8", 65534, 100, 100, errorReporter); tcpSender.sendMessage(new GelfMessage()); verify(errorReporter).reportError(anyString(), captor.capture()); Exception exception = captor.getValue(); assertThat(exception.getClass()).isEqualTo(IOException.class); assertThat(exception.getCause().getClass()).isEqualTo(ConnectException.class); } @Test public void connectionTimeoutShouldApply() throws Exception { long now = System.currentTimeMillis(); GelfTCPSender tcpSender = new GelfTCPSender("8.8.8.8", 65534, 1000, 1000, errorReporter); tcpSender.sendMessage(new GelfMessage()); long duration = System.currentTimeMillis() - now; assertThat(duration > 500).isTrue(); } @Test public void unknownHostShouldThrowException() throws Exception { try { new GelfTCPSender("unknown.host.unknown", 65534, 100, 100, errorReporter); fail("Missing UnknownHostException"); } catch (UnknownHostException e) { assertThat(e).isInstanceOf(UnknownHostException.class); } } @Test public void shouldOpenConnection() throws Exception { int port = randomPort(); ServerSocketChannel listener = ServerSocketChannel.open(); listener.socket().bind(new InetSocketAddress(port)); GelfTCPSender tcpSender = new GelfTCPSender("127.0.0.1", port, 1000, 1000, errorReporter); GelfMessage gelfMessage = new GelfMessage("short", "long", 1, "info"); gelfMessage.setHost("host"); GelfTCPSender spy = spy(tcpSender); spy.sendMessage(gelfMessage); verify(spy, times(3)).isConnected(); verify(spy).connect(); listener.close(); spy.close(); } @Test public void shouldSendDataToOpenPort() throws Exception { int port = randomPort(); ServerSocketChannel listener = ServerSocketChannel.open(); listener.socket().bind(new InetSocketAddress(port)); GelfTCPSender tcpSender = new GelfTCPSender("127.0.0.1", port, 1000, 1000, errorReporter); GelfMessage gelfMessage = new GelfMessage("short", "long", 1, "info"); gelfMessage.setHost("host"); tcpSender.sendMessage(gelfMessage); GelfTCPSender spy = spy(tcpSender); spy.sendMessage(gelfMessage); verify(spy, times(2)).isConnected(); verify(spy, never()).connect(); listener.close(); spy.close(); } @Test public void shouldSendDataToClosedPort() throws Exception { int port = randomPort(); ServerSocketChannel listener = ServerSocketChannel.open(); listener.socket().bind(new InetSocketAddress(port)); GelfTCPSender tcpSender = new GelfTCPSender("127.0.0.1", port, 1000, 1000, errorReporter); listener.socket().close(); listener.close(); GelfMessage gelfMessage = new GelfMessage("short", "long", 1, "info"); gelfMessage.setHost("host"); tcpSender.sendMessage(gelfMessage); GelfTCPSender spy = spy(tcpSender); spy.sendMessage(gelfMessage); verify(spy, times(2)).isConnected(); verify(spy).connect(); spy.close(); } @Test public void shouldSendHugeMessage() throws Exception { NoopGelfTCPSender tcpSender = new NoopGelfTCPSender("127.0.0.1", 1234, 1000, 1000, errorReporter); GelfMessage gelfMessage = new GelfMessage("short", "long", 1, "info"); gelfMessage.setHost("host"); for (int i = 0; i < 100; i++) { gelfMessage.addField(RandomStringUtils.random(1024), RandomStringUtils.random(1024)); } tcpSender.sendMessage(gelfMessage); ByteBuffer buffer = tcpSender.buffer; assertThat(buffer.get()).isEqualTo((byte) '{'); buffer.position(buffer.limit() - 2); assertThat(buffer.get()).isEqualTo((byte) '}'); assertThat(buffer.get()).isEqualTo((byte) 0); } protected int randomPort() { Random random = new Random(); return random.nextInt(50000) + 1024; } static class NoopGelfTCPSender extends GelfTCPSender { ByteBuffer buffer; public NoopGelfTCPSender(String host, int port, int connectTimeoutMs, int readTimeoutMs, ErrorReporter errorReporter) throws IOException { super(host, port, connectTimeoutMs, readTimeoutMs, errorReporter); } @Override protected boolean isConnected() throws IOException { return true; } @Override protected void write(ByteBuffer buffer) throws IOException { this.buffer = buffer; } } }