/*
* Copyright (c) 2011 Google Inc.
*
* 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 com.google.api.client.util;
import junit.framework.TestCase;
/**
* Tests {@link ExponentialBackOff}.
*
* @author Ravi Mistry
*/
public class ExponentialBackOffTest extends TestCase {
public ExponentialBackOffTest(String name) {
super(name);
}
public void testConstructor() {
ExponentialBackOff backOffPolicy = new ExponentialBackOff();
assertEquals(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS,
backOffPolicy.getInitialIntervalMillis());
assertEquals(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS,
backOffPolicy.getCurrentIntervalMillis());
assertEquals(ExponentialBackOff.DEFAULT_RANDOMIZATION_FACTOR,
backOffPolicy.getRandomizationFactor());
assertEquals(ExponentialBackOff.DEFAULT_MULTIPLIER, backOffPolicy.getMultiplier());
assertEquals(
ExponentialBackOff.DEFAULT_MAX_INTERVAL_MILLIS, backOffPolicy.getMaxIntervalMillis());
assertEquals(ExponentialBackOff.DEFAULT_MAX_ELAPSED_TIME_MILLIS,
backOffPolicy.getMaxElapsedTimeMillis());
}
public void testBuilder() {
ExponentialBackOff backOffPolicy = new ExponentialBackOff.Builder().build();
assertEquals(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS,
backOffPolicy.getInitialIntervalMillis());
assertEquals(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS,
backOffPolicy.getCurrentIntervalMillis());
assertEquals(ExponentialBackOff.DEFAULT_RANDOMIZATION_FACTOR,
backOffPolicy.getRandomizationFactor());
assertEquals(ExponentialBackOff.DEFAULT_MULTIPLIER, backOffPolicy.getMultiplier());
assertEquals(
ExponentialBackOff.DEFAULT_MAX_INTERVAL_MILLIS, backOffPolicy.getMaxIntervalMillis());
assertEquals(ExponentialBackOff.DEFAULT_MAX_ELAPSED_TIME_MILLIS,
backOffPolicy.getMaxElapsedTimeMillis());
int testInitialInterval = 1;
double testRandomizationFactor = 0.1;
double testMultiplier = 5.0;
int testMaxInterval = 10;
int testMaxElapsedTime = 900000;
backOffPolicy = new ExponentialBackOff.Builder()
.setInitialIntervalMillis(testInitialInterval)
.setRandomizationFactor(testRandomizationFactor)
.setMultiplier(testMultiplier)
.setMaxIntervalMillis(testMaxInterval)
.setMaxElapsedTimeMillis(testMaxElapsedTime)
.build();
assertEquals(testInitialInterval, backOffPolicy.getInitialIntervalMillis());
assertEquals(testInitialInterval, backOffPolicy.getCurrentIntervalMillis());
assertEquals(testRandomizationFactor, backOffPolicy.getRandomizationFactor());
assertEquals(testMultiplier, backOffPolicy.getMultiplier());
assertEquals(testMaxInterval, backOffPolicy.getMaxIntervalMillis());
assertEquals(testMaxElapsedTime, backOffPolicy.getMaxElapsedTimeMillis());
}
public void testBackOff() throws Exception {
int testInitialInterval = 500;
double testRandomizationFactor = 0.1;
double testMultiplier = 2.0;
int testMaxInterval = 5000;
int testMaxElapsedTime = 900000;
ExponentialBackOff backOffPolicy = new ExponentialBackOff.Builder()
.setInitialIntervalMillis(testInitialInterval)
.setRandomizationFactor(testRandomizationFactor)
.setMultiplier(testMultiplier)
.setMaxIntervalMillis(testMaxInterval)
.setMaxElapsedTimeMillis(testMaxElapsedTime)
.build();
int[] expectedResults = {500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000};
for (int expected : expectedResults) {
assertEquals(expected, backOffPolicy.getCurrentIntervalMillis());
// Assert that the next back off falls in the expected range.
int minInterval = (int) (expected - (testRandomizationFactor * expected));
int maxInterval = (int) (expected + (testRandomizationFactor * expected));
long actualInterval = backOffPolicy.nextBackOffMillis();
assertTrue(minInterval <= actualInterval && actualInterval <= maxInterval);
}
}
public void testGetRandomizedInterval() {
// 33% chance of being 1.
assertEquals(1, ExponentialBackOff.getRandomValueFromInterval(0.5, 0, 2));
assertEquals(1, ExponentialBackOff.getRandomValueFromInterval(0.5, 0.33, 2));
// 33% chance of being 2.
assertEquals(2, ExponentialBackOff.getRandomValueFromInterval(0.5, 0.34, 2));
assertEquals(2, ExponentialBackOff.getRandomValueFromInterval(0.5, 0.66, 2));
// 33% chance of being 3.
assertEquals(3, ExponentialBackOff.getRandomValueFromInterval(0.5, 0.67, 2));
assertEquals(3, ExponentialBackOff.getRandomValueFromInterval(0.5, 0.99, 2));
}
static class MyNanoClock implements NanoClock {
private int i = 0;
private long startSeconds;
MyNanoClock() {
}
MyNanoClock(long startSeconds) {
this.startSeconds = startSeconds;
}
public long nanoTime() {
return (startSeconds + i++) * 1000000000;
}
}
public void testGetElapsedTimeMillis() {
ExponentialBackOff backOffPolicy =
new ExponentialBackOff.Builder().setNanoClock(new MyNanoClock()).build();
long elapsedTimeMillis = backOffPolicy.getElapsedTimeMillis();
assertEquals("elapsedTimeMillis=" + elapsedTimeMillis, 1000, elapsedTimeMillis);
}
public void testMaxElapsedTime() throws Exception {
ExponentialBackOff backOffPolicy =
new ExponentialBackOff.Builder().setNanoClock(new MyNanoClock(10000)).build();
assertTrue(backOffPolicy.nextBackOffMillis() != BackOff.STOP);
// Change the currentElapsedTimeMillis to be 0 ensuring that the elapsed time will be greater
// than the max elapsed time.
backOffPolicy.startTimeNanos = 0;
assertEquals(BackOff.STOP, backOffPolicy.nextBackOffMillis());
}
public void testBackOffOverflow() throws Exception {
int testInitialInterval = Integer.MAX_VALUE / 2;
double testMultiplier = 2.1;
int testMaxInterval = Integer.MAX_VALUE;
ExponentialBackOff backOffPolicy = new ExponentialBackOff.Builder()
.setInitialIntervalMillis(testInitialInterval)
.setMultiplier(testMultiplier)
.setMaxIntervalMillis(testMaxInterval)
.build();
backOffPolicy.nextBackOffMillis();
// Assert that when an overflow is possible the current interval is set to the max interval.
assertEquals(testMaxInterval, backOffPolicy.getCurrentIntervalMillis());
}
}