/*
* Copyright 2013 Cloudera 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 org.apache.solr.client.solrj.retry;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.junit.Test;
public class FlexibleBoundedExponentialBackoffRetryTest extends Assert {
@Test
public void testBasic() throws Exception {
long baseSleepTimeNanos = 100;
long maxSleepNanos = 500;
int maxRetries = 100;
long maxElapsedTimeNanos = 5000;
RetryPolicy policy = new FlexibleBoundedExponentialBackoffRetry(
baseSleepTimeNanos, maxSleepNanos, maxRetries, maxElapsedTimeNanos);
long elapsedTimeNanos = 10;
CountingSleeper sleeper = new CountingSleeper();
for (int retryCount = 0; retryCount < maxRetries + 5; retryCount++) {
boolean retry = policy.allowRetry(retryCount, elapsedTimeNanos, sleeper);
if (retryCount < maxRetries) {
assertTrue(retry);
assertEquals(retryCount + 1, sleeper.count);
} else {
assertFalse(retry);
assertEquals(maxRetries, sleeper.count);
}
assertTrue(sleeper.time >= baseSleepTimeNanos);
}
policy = new FlexibleBoundedExponentialBackoffRetry(
TimeUnit.SECONDS.toNanos(2), TimeUnit.SECONDS.toNanos(3), 100, TimeUnit.SECONDS.toNanos(4));
assertEquals(
"baseSleepTime[secs]:2.0, maxSleepTime[secs]:3.0, maxRetries:100, maxElapsedTime[secs]:4.0",
policy.toString());
policy = new FlexibleBoundedExponentialBackoffRetry(0, 0, maxRetries, maxElapsedTimeNanos);
sleeper = new CountingSleeper();
assertTrue(policy.allowRetry(0, elapsedTimeNanos, sleeper));
assertEquals(1, sleeper.count);
assertEquals(0, sleeper.time);
assertFalse(policy.allowRetry(-1, elapsedTimeNanos, sleeper)); // negative retryCount
assertFalse(policy.allowRetry(0, maxElapsedTimeNanos, sleeper)); // reached maxElapsedTimeMs
assertTrue(policy.allowRetry(0, 0, sleeper));
policy = new FlexibleBoundedExponentialBackoffRetry(
Long.MAX_VALUE, Long.MAX_VALUE, maxRetries, maxElapsedTimeNanos);
sleeper = new CountingSleeper();
assertTrue(policy.allowRetry(0, elapsedTimeNanos, sleeper));
assertEquals(1, sleeper.count);
assertEquals(Long.MAX_VALUE, sleeper.time);
try {
new FlexibleBoundedExponentialBackoffRetry(
-1, maxSleepNanos-1, maxRetries, maxElapsedTimeNanos);
fail();
} catch (IllegalArgumentException e) {
; // expected
}
try {
new FlexibleBoundedExponentialBackoffRetry(
baseSleepTimeNanos, maxSleepNanos, -1, maxElapsedTimeNanos);
fail();
} catch (IllegalArgumentException e) {
; // expected
}
try {
new FlexibleBoundedExponentialBackoffRetry(
baseSleepTimeNanos, baseSleepTimeNanos-1, maxRetries, maxElapsedTimeNanos);
fail();
} catch (IllegalArgumentException e) {
; // expected
}
try {
new FlexibleBoundedExponentialBackoffRetry(
baseSleepTimeNanos, maxSleepNanos, maxRetries, -1);
fail();
} catch (IllegalArgumentException e) {
; // expected
}
}
///////////////////////////////////////////////////////////////////////////////
// Nested classes:
///////////////////////////////////////////////////////////////////////////////
private static final class CountingSleeper implements RetrySleeper {
int count = 0;
long time = 0;
@Override
public void sleepFor(long time, TimeUnit unit) throws InterruptedException {
this.count++;
this.time += time;
}
}
}