/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.metrics2.lib; import static org.apache.hadoop.metrics2.lib.Interns.info; import static org.apache.hadoop.test.MetricsAsserts.mockMetricsRecordBuilder; import static org.mockito.Mockito.times; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Matchers.anyDouble; import static org.mockito.Matchers.eq; import org.apache.hadoop.metrics2.MetricsRecordBuilder; import org.apache.hadoop.util.Time; import org.junit.Test; /** * This class tests various cases of the algorithms implemented in * {@link RollingAverages}. */ public class TestRollingAverages { /** * Tests if the results are correct if no samples are inserted, dry run of * empty roll over. */ @Test(timeout = 30000) public void testRollingAveragesEmptyRollover() throws Exception { final MetricsRecordBuilder rb = mockMetricsRecordBuilder(); /* 5s interval and 2 windows */ try (final RollingAverages rollingAverages = new RollingAverages(5000, 2)) { /* Check it initially */ rollingAverages.snapshot(rb, true); verify(rb, never()).addGauge( info("FooRollingAvgTime", "Rolling average time for foo"), (long) 0); verify(rb, never()).addGauge( info("BarAvgTime", "Rolling average time for bar"), (long) 0); /* sleep 6s longer than 5s interval to wait for rollover done */ Thread.sleep(6000); rollingAverages.snapshot(rb, false); verify(rb, never()).addGauge( info("FooRollingAvgTime", "Rolling average time for foo"), (long) 0); verify(rb, never()).addGauge( info("BarAvgTime", "Rolling average time for bar"), (long) 0); } } /** * Tests the case: * <p> * 5s interval and 2 sliding windows * </p> * <p> * sample stream: 1000 times 1, 2, and 3, respectively, e.g. [1, 1...1], [2, * 2...2] and [3, 3...3] * </p> */ @Test(timeout = 30000) public void testRollingAveragesRollover() throws Exception { final MetricsRecordBuilder rb = mockMetricsRecordBuilder(); final String name = "foo2"; final int windowSizeMs = 5000; // 5s roll over interval final int numWindows = 2; final int numOpsPerIteration = 1000; try (RollingAverages rollingAverages = new RollingAverages(windowSizeMs, numWindows)) { /* Push values for three intervals */ final long start = Time.monotonicNow(); for (int i = 1; i <= 3; i++) { /* insert value */ for (long j = 1; j <= numOpsPerIteration; j++) { rollingAverages.add(name, i); } /** * Sleep until 1s after the next windowSize seconds interval, to let the * metrics roll over */ final long sleep = (start + (windowSizeMs * i) + 1000) - Time.monotonicNow(); Thread.sleep(sleep); /* Verify that the window reset, check it has the values we pushed in */ rollingAverages.snapshot(rb, false); /* * #1 window with a series of 1 1000 * times, e.g. [1, 1...1], similarly, #2 window, e.g. [2, 2...2], * #3 window, e.g. [3, 3...3] */ final double rollingSum = numOpsPerIteration * (i > 1 ? (i - 1) : 0) + numOpsPerIteration * i; /* one empty window or all 2 windows full */ final long rollingTotal = i > 1 ? 2 * numOpsPerIteration : numOpsPerIteration; verify(rb).addGauge( info("[Foo2]RollingAvgTime", "Rolling average time for foo2"), rollingSum / rollingTotal); /* Verify the metrics were added the right number of times */ verify(rb, times(i)).addGauge( eq(info("[Foo2]RollingAvgTime", "Rolling average time for foo2")), anyDouble()); } } } }