/* * Copyright (C) 2015 SoftIndex LLC. * * Licensed 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 io.datakernel.jmx; import org.junit.Test; import java.util.Random; import static org.junit.Assert.assertEquals; public class EventStatsTest { private static final Random RANDOM = new Random(); @Test public void ifRateIsConstantEventStatsShouldApproximateThatRateAfterEnoughTimePassed() { double smoothingWindow = 1.0; EventStats eventStats = EventStats.create(smoothingWindow); long currentTimestamp = 0; int events = 1000; double rate = 20.0; double period = 1.0 / rate; int periodInMillis = (int) (period * 1000); for (int i = 0; i < events; i++) { eventStats.recordEvent(); eventStats.refresh(currentTimestamp); currentTimestamp += periodInMillis; } double acceptableError = 1E-5; assertEquals(rate, eventStats.getSmoothedRate(), acceptableError); } @Test public void counterShouldResetRateAfterResetMethodCall() { double smoothingWindow = 1.0; EventStats eventStats = EventStats.create(smoothingWindow); long currentTimestamp = 0; int events = 1000; double rate = 20.0; double period = 1.0 / rate; int periodInMillis = (int) (period * 1000); for (int i = 0; i < events; i++) { eventStats.recordEvent(); currentTimestamp += periodInMillis; eventStats.refresh(currentTimestamp); } double rateBeforeReset = eventStats.getSmoothedRate(); eventStats.resetStats(); double rateAfterReset = eventStats.getSmoothedRate(); double initRateOfReset = 0.0; double acceptableError = 1E-5; assertEquals(rate, rateBeforeReset, acceptableError); assertEquals(initRateOfReset, rateAfterReset, acceptableError); } @Test public void counterShouldProperlyAggregateEvents() { int iterations = 1000; final int period = 100; long currentTimestamp = 0; double smoothingWindow = 10.0; EventStats stats_1 = EventStats.create(smoothingWindow); EventStats stats_2 = EventStats.create(smoothingWindow); EventStats stats_3 = EventStats.create(smoothingWindow); for (int i = 0; i < iterations; i++) { stats_1.recordEvents(1); stats_2.recordEvents(2); // we do not record event to stats_3 currentTimestamp += period; stats_1.refresh(currentTimestamp); stats_2.refresh(currentTimestamp); stats_3.refresh(currentTimestamp); } EventStats accumulator = EventStats.createAccumulator(); accumulator.add(stats_1); accumulator.add(stats_2); accumulator.add(stats_3); double acceptableError = 0.1; assertEquals(30.0, accumulator.getSmoothedRate(), acceptableError); } @Test public void itShouldConvergeProperlyWhenNoEventsOccurredBetweenRefreshes() { double smoothingWindow = 10.0; EventStats stats = EventStats.create(smoothingWindow); int iterations = 1000; long currentTimestamp = 0; final int period = 200; for (int i = 0; i < iterations; i++) { // event occurs only once per two refreshes int eventsPerRefresh = i % 2; stats.recordEvents(eventsPerRefresh); currentTimestamp += period; stats.refresh(currentTimestamp); } assertEquals(500, stats.getTotalCount()); double acceptableError = 0.25; assertEquals(2.5, stats.getSmoothedRate(), acceptableError); } @Test public void itShouldConvergeProperlyWhenPeriodIsNotStableButPeriodExpectationIsStable() { double smoothingWindow = 10.0; EventStats stats = EventStats.create(smoothingWindow); int iterations = 1000; long currentTimestamp = 0; final int period = 200; for (int i = 0; i < iterations; i++) { stats.recordEvents(1); int currentPeriod = period + uniformRandom(-50, 50); currentTimestamp += currentPeriod; stats.refresh(currentTimestamp); } assertEquals(1000, stats.getTotalCount()); double acceptableError = 0.25; assertEquals(5.0, stats.getSmoothedRate(), acceptableError); } @Test public void itShouldConvergeProperlyWhenAmountOfEventsPerPeriodIsNotStableButExpectationOfAmountOfEventIsStable() { double smoothingWindow = 50.0; EventStats stats = EventStats.create(smoothingWindow); int iterations = 10000; long currentTimestamp = 0; final int period = 200; for (int i = 0; i < iterations; i++) { stats.recordEvents(uniformRandom(0, 10)); currentTimestamp += period; stats.refresh(currentTimestamp); } double acceptableError = 2.0; assertEquals(25.0, stats.getSmoothedRate(), acceptableError); } public static int uniformRandom(int min, int max) { return min + Math.abs(RANDOM.nextInt()) % (max - min + 1); } }