// Copyright 2018, Oath Inc. // Licensed under the terms of the Apache License 2.0 license. See LICENSE file in Ultrabrew Metrics // for terms. package io.ultrabrew.metrics.reporters.opentsdb; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import io.ultrabrew.metrics.Counter; import io.ultrabrew.metrics.MetricRegistry; import java.io.IOException; import java.net.URI; import mockit.Capturing; import mockit.Deencapsulation; import mockit.Expectations; import mockit.Mocked; import mockit.Verifications; import org.apache.http.StatusLine; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.impl.client.CloseableHttpClient; import org.junit.jupiter.api.Test; import org.slf4j.Logger; public class OpenTSDBReporterTest { private static final URI TEST_URI = URI.create("http://localhost:4242/"); private OpenTSDBReporter makeReporter() { return OpenTSDBReporter.builder() .withBaseUri(TEST_URI) .build(); } @Test public void testReporting(@Mocked CloseableHttpClient httpClient, @Mocked CloseableHttpResponse closeableHttpResponse, @Mocked StatusLine statusLine) throws InterruptedException, IOException { new Expectations() {{ httpClient.execute((HttpUriRequest) any); result = closeableHttpResponse; closeableHttpResponse.getStatusLine(); result = statusLine; statusLine.getStatusCode(); result = 200; }}; MetricRegistry registry = new MetricRegistry(); OpenTSDBReporter reporter = makeReporter(); registry.addReporter(reporter); Counter counter = registry.counter("counter"); counter.inc("tag", "value"); Thread.sleep(3000); new Verifications() {{ HttpUriRequest request; httpClient.execute(request = withCapture()); assertEquals("/api/v1/put", request.getURI().getPath()); times = 1; }}; } @Test public void testReportingBaseUriWithPath(@Mocked CloseableHttpClient httpClient, @Mocked CloseableHttpResponse closeableHttpResponse, @Mocked StatusLine statusLine) throws InterruptedException, IOException { new Expectations() {{ httpClient.execute((HttpUriRequest) any); result = closeableHttpResponse; closeableHttpResponse.getStatusLine(); result = statusLine; statusLine.getStatusCode(); result = 200; }}; MetricRegistry registry = new MetricRegistry(); OpenTSDBReporter reporter = OpenTSDBReporter.builder() .withBaseUri(URI.create("http://localhost:4242/some/path/")) .build(); registry.addReporter(reporter); Counter counter = registry.counter("counter"); counter.inc("tag", "value"); Thread.sleep(3000); new Verifications() {{ HttpUriRequest request; httpClient.execute(request = withCapture()); assertEquals("/some/path/api/v1/put", request.getURI().getPath()); times = 1; }}; } @Test public void testSetApiEndpoint(@Mocked CloseableHttpClient httpClient, @Mocked CloseableHttpResponse closeableHttpResponse, @Mocked StatusLine statusLine) throws InterruptedException, IOException { new Expectations() {{ httpClient.execute((HttpUriRequest) any); result = closeableHttpResponse; closeableHttpResponse.getStatusLine(); result = statusLine; statusLine.getStatusCode(); result = 200; }}; MetricRegistry registry = new MetricRegistry(); OpenTSDBReporter reporter = OpenTSDBReporter.builder() .withBaseUri(URI.create("http://localhost:4242/")) .withApiEndpoint("very/special/put") .build(); registry.addReporter(reporter); Counter counter = registry.counter("counter"); counter.inc("tag", "value"); Thread.sleep(3000); new Verifications() {{ HttpUriRequest request; httpClient.execute(request = withCapture()); assertEquals("/very/special/put", request.getURI().getPath()); times = 1; }}; } @Test public void testUploadFailedServerError(@Mocked CloseableHttpClient httpClient, @Mocked CloseableHttpResponse closeableHttpResponse, @Mocked StatusLine statusLine, @Capturing Logger logger) throws IOException, InterruptedException { new Expectations() {{ httpClient.execute((HttpUriRequest) any); result = closeableHttpResponse; closeableHttpResponse.getStatusLine(); result = statusLine; statusLine.getStatusCode(); result = 500; }}; MetricRegistry registry = new MetricRegistry(); OpenTSDBReporter reporter = makeReporter(); registry.addReporter(reporter); Counter counter = registry.counter("counter"); counter.inc("tag", "value"); Thread.sleep(3000); new Verifications() {{ logger.error(anyString, withInstanceOf(IllegalStateException.class)); }}; } @Test public void testUploadFailedException(@Mocked CloseableHttpClient httpClient, @Capturing Logger logger) throws IOException, InterruptedException { new Expectations() {{ httpClient.execute((HttpUriRequest) any); result = new IOException(); }}; MetricRegistry registry = new MetricRegistry(); OpenTSDBReporter reporter = makeReporter(); registry.addReporter(reporter); Counter counter = registry.counter("counter"); counter.inc("tag", "value"); Thread.sleep(3000); new Verifications() {{ logger.error(anyString, withInstanceOf(Throwable.class)); }}; } @Test public void testSetWindow() { OpenTSDBReporter r = OpenTSDBReporter.builder() .withBaseUri(TEST_URI) .withWindowSize(12765) .build(); long actualWindowSizeMillis = Deencapsulation.getField(r, "windowStepSizeMillis"); assertEquals(12765 * 1000, actualWindowSizeMillis); } @Test public void testSetBatchSize() { OpenTSDBReporter r = OpenTSDBReporter.builder() .withBaseUri(TEST_URI) .withBatchSize(123) .build(); OpenTSDBHttpClient client = Deencapsulation.getField(r, "client"); int actualBatchSize = Deencapsulation.getField(client, "batchSize"); assertEquals(123, actualBatchSize); } @Test public void testMissingBaseUri() { assertThrows(IllegalArgumentException.class, () -> OpenTSDBReporter.builder().build()); } @Test public void testInvalidBaseUri() { assertThrows(IllegalArgumentException.class, () -> OpenTSDBReporter.builder().withBaseUri(URI.create("http://localhost:4242"))); } @Test public void testInvalidBatchSize() { assertThrows(IllegalArgumentException.class, () -> OpenTSDBReporter.builder().withBatchSize(0)); } }