package io.pcp.parfait.dropwizard; import static tec.uom.se.AbstractUnit.ONE; import static tec.uom.se.unit.Units.GRAY; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import javax.measure.Unit; import io.pcp.parfait.dropwizard.metricadapters.CountingAdapter; import io.pcp.parfait.dropwizard.metricadapters.GaugeAdapter; import io.pcp.parfait.dropwizard.metricadapters.HistogramAdapter; import io.pcp.parfait.dropwizard.metricadapters.MeteredAdapter; import io.pcp.parfait.dropwizard.metricadapters.TimerAdapter; import com.codahale.metrics.Counter; import com.codahale.metrics.Gauge; import com.codahale.metrics.Histogram; import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import com.codahale.metrics.MetricSet; import com.codahale.metrics.Snapshot; import com.codahale.metrics.Timer; import io.pcp.parfait.Monitorable; import io.pcp.parfait.ValueSemantics; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class MetricAdapterFactoryImplTest { private static final int INITIAL_VALUE = 12345; private static final String NAME = "NAME"; private static final String TRANSLATED_NAME ="TRANSLATED_NAME"; private static final String DESCRIPTION = "some description"; private MetricAdapterFactoryImpl metricAdapterFactory; @Mock private Counter counter; @Mock private Gauge gauge; @Mock private Meter meter; @Mock private Histogram histogram; @Mock private Timer timer; @Mock private Snapshot snapshot; @Mock private MetricDescriptorLookup metricDescriptorLookup; @Mock private MetricDescriptor mockDescriptor; @Mock private MetricNameTranslator metricNameTranslator; @Before public void setUp() { when(gauge.getValue()).thenReturn(INITIAL_VALUE); when(histogram.getSnapshot()).thenReturn(snapshot); when(timer.getSnapshot()).thenReturn(snapshot); metricAdapterFactory = new MetricAdapterFactoryImpl(metricDescriptorLookup, metricNameTranslator); when(mockDescriptor.getUnit()).thenReturn(GRAY); when(mockDescriptor.getDescription()).thenReturn(DESCRIPTION); when(mockDescriptor.getSemantics()).thenReturn(ValueSemantics.FREE_RUNNING); when(metricDescriptorLookup.getDescriptorFor(anyString())).thenReturn(mockDescriptor); when(metricNameTranslator.translate(NAME)).thenReturn(TRANSLATED_NAME); } @Test(expected = IllegalArgumentException.class) public void shouldThrowIllegalArgumentExceptionWhenMetricIsAMetricSet() { metricAdapterFactory.createMetricAdapterFor(NAME, mock(MetricSet.class)); } @Test(expected = UnsupportedOperationException.class) public void shouldThrowUnsupportedOperationExceptionWhenMetricIsUnrecognized() { metricAdapterFactory.createMetricAdapterFor(NAME, mock(Metric.class)); } @Test public void shouldNotConvertMetricNamesWhenNoConverterIsProvided() { metricAdapterFactory = new MetricAdapterFactoryImpl(metricDescriptorLookup); assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, counter)).getName(), is(NAME)); } @Test public void shouldUseTranslatedMetricNameToLookUpDescriptor() { metricAdapterFactory = new MetricAdapterFactoryImpl(metricDescriptorLookup, metricNameTranslator); metricAdapterFactory.createMetricAdapterFor(NAME, counter); verify(metricDescriptorLookup).getDescriptorFor(TRANSLATED_NAME); } // // Counter // @Test public void shouldProduceACountingAdapterWhenTheMetricIsACounter() { assertThat(metricAdapterFactory.createMetricAdapterFor(NAME, counter), is(instanceOf(CountingAdapter.class))); } @Test public void shouldUseTranslatedNameForNameOfReturnedCounterAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, counter)).getName(), is(TRANSLATED_NAME)); } @Test public void shouldUseRetrievedDescriptionForCounterAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, counter)).getDescription(), startsWith(DESCRIPTION)); } @Test public void shouldSpecifyOneAsUnitOfMeasurementInReturnedCounterAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, counter)).getUnit(), Matchers.<Unit>is(ONE)); } @Test public void shouldSpecifyFreeRunningAsValueSemanticsInReturnedCounterAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, counter)).getSemantics(), is(ValueSemantics.FREE_RUNNING)); } // // Gauge // @Test public void shouldProduceAGaugeAdapterWhenTheMetricIsAGauge() { assertThat(metricAdapterFactory.createMetricAdapterFor(NAME, gauge), is(instanceOf(GaugeAdapter.class))); } @Test public void shouldUseTranslatedNameForNameOfReturnedGaugeAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, gauge)).getName(), is(TRANSLATED_NAME)); } @Test public void shouldUseRetrievedDescriptionForGaugeAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, gauge)).getDescription(), startsWith(DESCRIPTION)); } @Test public void shouldSpecifyFreeRunningAsValueSemanticsInReturnedGaugeAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, gauge)).getSemantics(), is(ValueSemantics.FREE_RUNNING)); } @Test public void shouldUseUnitFromMetricDescriptorInGaugeAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, gauge)).getUnit(), Matchers.<Unit>is(GRAY)); } // // Histogram // @Test public void shouldProduceAHistogramAdapterWhenTheMetricIsAHistogram() { assertThat(metricAdapterFactory.createMetricAdapterFor(NAME, histogram), is(instanceOf(HistogramAdapter.class))); } @Test public void shouldUseTranslatedNameForNameOfReturnedHistogramAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getName(), startsWith(TRANSLATED_NAME)); } @Test public void shouldUseRetrievedDescriptionForHistogramAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getDescription(), startsWith(DESCRIPTION)); } @Test public void shouldUseUnitFromMetricDescriptorInHistogramAdapter() { assertThat(getMonitorableByName(TRANSLATED_NAME + ".mean", metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getUnit(), Matchers.<Unit>is(GRAY)); assertThat(getMonitorableByName(TRANSLATED_NAME + ".median", metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getUnit(), Matchers.<Unit>is(GRAY)); assertThat(getMonitorableByName(TRANSLATED_NAME + ".max", metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getUnit(), Matchers.<Unit>is(GRAY)); assertThat(getMonitorableByName(TRANSLATED_NAME + ".min", metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getUnit(), Matchers.<Unit>is(GRAY)); assertThat(getMonitorableByName(TRANSLATED_NAME + ".stddev", metricAdapterFactory.createMetricAdapterFor(NAME, histogram)).getUnit(), Matchers.<Unit>is(GRAY)); } // // Timer // @Test public void shouldProduceATimerAdapterWhenTheMetricIsATimer() { assertThat(metricAdapterFactory.createMetricAdapterFor(NAME, timer), is(instanceOf(TimerAdapter.class))); } @Test public void shouldUseTranslatedNameForNameOfReturnedTimerAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, timer)).getName(), startsWith(TRANSLATED_NAME)); } @Test public void shouldUseRetrievedDescriptionForTimerAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, timer)).getDescription(), startsWith(DESCRIPTION)); } // // Meter // @Test public void shouldProduceAMeteredAdapter_WhenTheMetricIsAMeter() { assertThat(metricAdapterFactory.createMetricAdapterFor(NAME, meter), is(instanceOf(MeteredAdapter.class))); } @Test public void shouldUseTranslatedNameForNameOfReturnedMeteredAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, meter)).getName(), startsWith(TRANSLATED_NAME)); } @Test public void shouldUseRetrievedDescriptionForMeteredAdapter() { assertThat(getFirstMonitorable(metricAdapterFactory.createMetricAdapterFor(NAME, meter)).getDescription(), startsWith(DESCRIPTION)); } private Monitorable getMonitorableByName(String name, MetricAdapter metricAdapter) { for (Monitorable monitorable : metricAdapter.getMonitorables()) { if (monitorable.getName().equals(name)) { return monitorable; } } throw new IllegalStateException("Couldn't locate metric :" + name); } private Monitorable getFirstMonitorable(MetricAdapter metricAdapter) { return metricAdapter.getMonitorables().iterator().next(); } }