/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.integration.support.management;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import java.util.Deque;
import org.hamcrest.Matchers;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.test.util.TestUtils;
/**
* @author Dave Syer
* @author Gary Russell
* @author Artem Bilan
* @author Steven Swor
*/
@Ignore("Very sensitive to the time. Don't forget to test after some changes.")
public class ExponentialMovingAverageRatioTests {
private final ExponentialMovingAverageRatio history = new ExponentialMovingAverageRatio(
0.5, 10, true);
@Test
public void testGetCount() {
assertEquals(0, history.getCount());
history.success();
assertEquals(1, history.getCount());
}
@Test
@SuppressWarnings("unchecked")
public void testGetTimeSinceLastMeasurement() throws Exception {
long sleepTime = 20L;
// fill history with the same value.
long now = System.nanoTime() - 2 * sleepTime * 1000000;
for (int i = 0; i < TestUtils.getPropertyValue(history, "retention", Integer.class); i++) {
history.success(now);
}
final Deque<Long> times = TestUtils.getPropertyValue(history, "times", Deque.class);
assertEquals(Long.valueOf(now), times.peekFirst());
assertEquals(Long.valueOf(now), times.peekLast());
//increment just so we'll have a different value between first and last
history.success(System.nanoTime() - sleepTime * 1000000);
assertNotEquals(times.peekFirst(), times.peekLast());
/*
* We've called Thread.sleep twice with the same value in quick
* succession. If timeSinceLastSend is pulling off the correct end of
* the queue, then we should be closer to the sleep time than we are to
* 2 x sleepTime, but we should definitely be greater than the sleep
* time.
*/
double timeSinceLastMeasurement = history.getTimeSinceLastMeasurement();
assertThat(timeSinceLastMeasurement, Matchers.greaterThan((double) (sleepTime / 100)));
assertThat(timeSinceLastMeasurement, Matchers.lessThanOrEqualTo(1.5 * sleepTime / 100));
}
@Test
public void testGetEarlyMean() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
}
@Test
public void testGetEarlyFailure() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.failure();
assertEquals(0, history.getMean(), 0.01);
}
@Test
public void testDecayedMean() throws Exception {
history.failure(System.nanoTime() - 200000000);
assertEquals(average(0, Math.exp(-0.4)), history.getMean(), 0.01);
history.success();
history.failure();
double mean = history.getMean();
Statistics statistics = history.getStatistics();
Thread.sleep(50);
assertThat(history.getMean(), greaterThan(mean));
assertThat(history.getStatistics().getMean(), greaterThan(statistics.getMean()));
}
@Test
public void testGetMean() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
}
@Test
public void testGetMeanFailuresHighRate() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.success(); // need an extra now that we can't determine the time between the first and previous
history.success();
assertEquals(average(1), history.getMean(), 0.01);
history.failure();
assertEquals(average(1, 0.5), history.getMean(), 0.1);
history.success();
assertEquals(average(1, 0.5, 0.67), history.getMean(), 0.1);
}
@Test
public void testGetMeanFailuresLowRate() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.failure(); // need an extra now that we can't determine the time between the first and previous
history.failure();
assertEquals(average(0), history.getMean(), 0.01);
history.failure();
assertEquals(average(0, 0), history.getMean(), 0.01);
history.success();
assertEquals(average(0, 0, 0.33), history.getMean(), 0.1);
}
@Test
public void testGetStandardDeviation() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.success();
assertEquals(0, history.getStandardDeviation(), 1);
}
@Test
public void testReset() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.success();
history.failure();
assertThat(history.getStandardDeviation(), not(equalTo(0)));
history.reset();
assertEquals(0, history.getStandardDeviation(), 0.01);
assertEquals(0, history.getCount());
assertEquals(0, history.getTimeSinceLastMeasurement(), 0.01);
assertEquals(1, history.getMean(), 0.01);
assertEquals(0, history.getMin(), 0.01);
assertEquals(0, history.getMax(), 0.01);
history.success();
assertEquals(1, history.getMin(), 0.01);
}
private double average(double... values) {
int count = 0;
double sum = 0;
for (double d : values) {
sum += d;
count++;
}
return sum / count;
}
@Test
public void testRatio() {
ExponentialMovingAverageRatio ratio = new ExponentialMovingAverageRatio(60, 10, true);
for (int i = 0; i < 100; i++) {
if (i % 10 == 1) {
ratio.failure();
}
else {
ratio.success();
}
}
assertEquals(0.9, ratio.getMax(), 0.02);
assertEquals(0.9, ratio.getMean(), 0.03);
}
@Test
@Ignore
public void testPerf() {
ExponentialMovingAverageRatio ratio = new ExponentialMovingAverageRatio(60, 10);
for (int i = 0; i < 100000; i++) {
if (i % 10 == 0) {
ratio.failure();
}
else {
ratio.success();
}
}
}
}