// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.metrics.simple; import static org.junit.Assert.*; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.Set; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.google.common.collect.ImmutableMap; import com.yahoo.metrics.simple.UntypedMetric.AssumedType; /** * Functional tests for the value buckets, as implemented in the class Bucket, * and by extension the value store itself, UntypedValue. * * @author Steinar Knutsen */ public class BucketTest { private Bucket bucket; @Before public void setUp() throws Exception { bucket = new Bucket(); } @After public void tearDown() throws Exception { bucket = null; } @Test public final void testEntrySet() { assertEquals(0, bucket.entrySet().size()); for (int i = 0; i < 4; ++i) { bucket.put(new Sample(new Measurement(i), new Identifier("nalle_" + i, null), AssumedType.GAUGE)); } assertEquals(4, bucket.entrySet().size()); for (int i = 0; i < 4; ++i) { bucket.put(new Sample(new Measurement(i), new Identifier("nalle", new Point(new ImmutableMap.Builder().put("dim", Integer.valueOf(i)).build())), AssumedType.GAUGE)); } assertEquals(8, bucket.entrySet().size()); int nalle = 0, nalle0 = 0, nalle1 = 0, nalle2 = 0, nalle3 = 0; for (Entry x : bucket.entrySet()) { String metricName = x.getKey().getName(); switch (metricName) { case "nalle": ++nalle; break; case "nalle_0": ++nalle0; break; case "nalle_1": ++nalle1; break; case "nalle_2": ++nalle2; break; case "nalle_3": ++nalle3; break; default: throw new IllegalStateException(); } } assertEquals(4, nalle); assertEquals(1, nalle0); assertEquals(1, nalle1); assertEquals(1, nalle2); assertEquals(1, nalle3); } @Test public final void testPutSampleWithUnsupportedType() { boolean caughtIt = false; try { bucket.put(new Sample(new Measurement(1), new Identifier("nalle", null), AssumedType.NONE)); } catch (Exception e) { caughtIt = true; } assertTrue(caughtIt); } @Test public final void testPutIdentifierUntypedValue() { UntypedMetric v = new UntypedMetric(null); v.add(2); bucket.put(new Sample(new Measurement(3), new Identifier("nalle", null), AssumedType.GAUGE)); bucket.put(new Identifier("nalle", null), v); assertEquals(1, bucket.entrySet().size()); // check raw overwriting Entry stored = bucket.entrySet().iterator().next(); assertEquals(new Identifier("nalle", null), stored.getKey()); assertTrue(stored.getValue().isCounter()); } @Test public final void testHasIdentifier() { for (int i = 0; i < 4; ++i) { bucket.put(new Sample(new Measurement(i), new Identifier("nalle_" + i, new Point( new ImmutableMap.Builder().put(String.valueOf(i), Integer.valueOf(i)).build())), AssumedType.GAUGE)); } for (int i = 0; i < 4; ++i) { assertTrue(bucket.hasIdentifier(new Identifier("nalle_" + i, new Point(new ImmutableMap.Builder().put( String.valueOf(i), Integer.valueOf(i)).build())))); } } @Test public final void testOkMerge() { bucket.put(new Sample(new Measurement(2), new Identifier("nalle", null), AssumedType.GAUGE)); Bucket otherNew = new Bucket(); otherNew.put(new Sample(new Measurement(3), new Identifier("nalle", null), AssumedType.GAUGE)); Bucket otherOld = new Bucket(); otherOld.put(new Sample(new Measurement(5), new Identifier("nalle", null), AssumedType.GAUGE)); bucket.merge(otherNew, true); bucket.merge(otherOld, false); Set> entries = bucket.entrySet(); assertEquals(1, entries.size()); Entry entry = entries.iterator().next(); assertEquals(10, entry.getValue().getSum(), 0.0); assertEquals(3, entry.getValue().getLast(), 0.0); assertEquals(2, entry.getValue().getMin(), 0.0); assertEquals(5, entry.getValue().getMax(), 0.0); assertEquals(3, entry.getValue().getCount()); } @Test public final void testMergeDifferentMetrics() { bucket.put(new Sample(new Measurement(2), new Identifier("nalle", null), AssumedType.GAUGE)); Bucket otherNew = new Bucket(); otherNew.put(new Sample(new Measurement(3), new Identifier("other", null), AssumedType.GAUGE)); bucket.merge(otherNew, true); Set> entries = bucket.entrySet(); assertEquals(2, entries.size()); Collection> nalle_values = bucket.getValuesForMetric("nalle"); assertEquals(1, nalle_values.size()); Collection> other_values = bucket.getValuesForMetric("other"); assertEquals(1, other_values.size()); UntypedMetric nalle_v = nalle_values.iterator().next().getValue(); assertEquals(1, nalle_v.getCount()); assertEquals(2, nalle_v.getSum(), 0.0); assertEquals(2, nalle_v.getLast(), 0.0); assertEquals(2, nalle_v.getMin(), 0.0); assertEquals(2, nalle_v.getMax(), 0.0); UntypedMetric other_v = other_values.iterator().next().getValue(); assertEquals(1, other_v.getCount()); assertEquals(3, other_v.getSum(), 0.0); assertEquals(3, other_v.getLast(), 0.0); assertEquals(3, other_v.getMax(), 0.0); assertEquals(3, other_v.getMin(), 0.0); } private static class CheckThatItWasLogged extends Handler { final boolean[] loggingMarker; public CheckThatItWasLogged(boolean[] loggingMarker) { this.loggingMarker = loggingMarker; } @Override public void publish(LogRecord record) { loggingMarker[0] = true; } @Override public void flush() { } @Override public void close() throws SecurityException { } } @Test public final void testMismatchedMerge() { Logger log = Logger.getLogger(Bucket.class.getName()); boolean[] loggingMarker = new boolean[1]; loggingMarker[0] = false; log.setUseParentHandlers(false); Handler logHandler = new CheckThatItWasLogged(loggingMarker); log.addHandler(logHandler); Bucket other = new Bucket(); bucket.put(new Sample(new Measurement(2), new Identifier("nalle", null), AssumedType.GAUGE)); other.put(new Sample(new Measurement(3), new Identifier("nalle", null), AssumedType.COUNTER)); bucket.merge(other, true); assertTrue(loggingMarker[0]); log.removeHandler(logHandler); log.setUseParentHandlers(true); } @Test public final void testGetAllMetricNames() { twoMetricsUniqueDimensions(); Collection names = bucket.getAllMetricNames(); assertEquals(2, names.size()); assertTrue(names.contains("nalle")); assertTrue(names.contains("nalle2")); } @Test public final void testGetValuesForMetric() { twoMetricsUniqueDimensions(); Collection> values = bucket.getValuesForMetric("nalle"); assertEquals(4, values.size()); } private void twoMetricsUniqueDimensions() { for (int i = 0; i < 4; ++i) { bucket.put(new Sample(new Measurement(i), new Identifier("nalle", new Point(new ImmutableMap.Builder() .put(String.valueOf(i), Integer.valueOf(i)).build())), AssumedType.GAUGE)); bucket.put(new Sample(new Measurement(i), new Identifier("nalle2", new Point( new ImmutableMap.Builder().put(String.valueOf(i), Integer.valueOf(i)).build())), AssumedType.GAUGE)); } } @Test public final void testGetValuesByMetricName() { twoMetricsUniqueDimensions(); Map>> values = bucket.getValuesByMetricName(); assertEquals(2, values.size()); assertEquals(4, values.get("nalle").size()); assertEquals(4, values.get("nalle2").size()); } }