/*
* Copyright 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 net.jodah.failsafe;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.io.IOException;
import java.net.ConnectException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.testng.annotations.Test;
import net.jodah.failsafe.RetryPolicy;
@Test
public class RetryPolicyTest {
void shouldFail(Runnable runnable, Class<? extends Exception> expected) {
try {
runnable.run();
fail("A failure was expected");
} catch (Exception e) {
assertTrue(e.getClass().isAssignableFrom(expected), "The expected exception was not of the expected type " + e);
}
}
public void testCanRetryForNull() {
RetryPolicy policy = new RetryPolicy();
assertFalse(policy.canRetryFor(null, null));
}
public void testCanRetryForCompletionPredicate() {
RetryPolicy policy = new RetryPolicy()
.retryIf((result, failure) -> result == "test" || failure instanceof IllegalArgumentException);
assertTrue(policy.canRetryFor("test", null));
// No retries needed for successful result
assertFalse(policy.canRetryFor(0, null));
assertTrue(policy.canRetryFor(null, new IllegalArgumentException()));
assertFalse(policy.canRetryFor(null, new IllegalStateException()));
}
public void testCanRetryForFailurePredicate() {
RetryPolicy policy = new RetryPolicy().retryOn(failure -> failure instanceof ConnectException);
assertTrue(policy.canRetryFor(null, new ConnectException()));
assertFalse(policy.canRetryFor(null, new IllegalStateException()));
}
public void testCanRetryForResultPredicate() {
RetryPolicy policy = new RetryPolicy().retryIf((Integer result) -> result > 100);
assertTrue(policy.canRetryFor(110, null));
assertFalse(policy.canRetryFor(50, null));
}
@SuppressWarnings("unchecked")
public void testCanRetryForFailure() {
RetryPolicy policy = new RetryPolicy();
assertTrue(policy.canRetryFor(null, new Exception()));
assertTrue(policy.canRetryFor(null, new IllegalArgumentException()));
policy = new RetryPolicy().retryOn(Exception.class);
assertTrue(policy.canRetryFor(null, new Exception()));
assertTrue(policy.canRetryFor(null, new IllegalArgumentException()));
policy = new RetryPolicy().retryOn(RuntimeException.class);
assertTrue(policy.canRetryFor(null, new IllegalArgumentException()));
assertFalse(policy.canRetryFor(null, new Exception()));
policy = new RetryPolicy().retryOn(IllegalArgumentException.class, IOException.class);
assertTrue(policy.canRetryFor(null, new IllegalArgumentException()));
assertTrue(policy.canRetryFor(null, new IOException()));
assertFalse(policy.canRetryFor(null, new RuntimeException()));
assertFalse(policy.canRetryFor(null, new IllegalStateException()));
policy = new RetryPolicy().retryOn(Arrays.asList(IllegalArgumentException.class));
assertTrue(policy.canRetryFor(null, new IllegalArgumentException()));
assertFalse(policy.canRetryFor(null, new RuntimeException()));
assertFalse(policy.canRetryFor(null, new IllegalStateException()));
}
public void testCanRetryForResult() {
RetryPolicy policy = new RetryPolicy().retryWhen(10);
assertTrue(policy.canRetryFor(10, null));
assertFalse(policy.canRetryFor(5, null));
assertTrue(policy.canRetryFor(5, new Exception()));
}
public void testCanAbortForNull() {
RetryPolicy policy = new RetryPolicy();
assertFalse(policy.canAbortFor(null, null));
}
public void testCanAbortForCompletionPredicate() {
RetryPolicy policy = new RetryPolicy()
.abortIf((result, failure) -> result == "test" || failure instanceof IllegalArgumentException);
assertTrue(policy.canAbortFor("test", null));
assertFalse(policy.canAbortFor(0, null));
assertTrue(policy.canAbortFor(null, new IllegalArgumentException()));
assertFalse(policy.canAbortFor(null, new IllegalStateException()));
}
public void testCanAbortForFailurePredicate() {
RetryPolicy policy = new RetryPolicy().abortOn(failure -> failure instanceof ConnectException);
assertTrue(policy.canAbortFor(null, new ConnectException()));
assertFalse(policy.canAbortFor(null, new IllegalArgumentException()));
}
public void testCanAbortForResultPredicate() {
RetryPolicy policy = new RetryPolicy().abortIf((Integer result) -> result > 100);
assertTrue(policy.canAbortFor(110, null));
assertFalse(policy.canAbortFor(50, null));
assertFalse(policy.canAbortFor(50, new IllegalArgumentException()));
}
@SuppressWarnings("unchecked")
public void testCanAbortForFailure() {
RetryPolicy policy = new RetryPolicy().abortOn(Exception.class);
assertTrue(policy.canAbortFor(null, new Exception()));
assertTrue(policy.canAbortFor(null, new IllegalArgumentException()));
policy = new RetryPolicy().abortOn(IllegalArgumentException.class, IOException.class);
assertTrue(policy.canAbortFor(null, new IllegalArgumentException()));
assertTrue(policy.canAbortFor(null, new IOException()));
assertFalse(policy.canAbortFor(null, new RuntimeException()));
assertFalse(policy.canAbortFor(null, new IllegalStateException()));
policy = new RetryPolicy().abortOn(Arrays.asList(IllegalArgumentException.class));
assertTrue(policy.canAbortFor(null, new IllegalArgumentException()));
assertFalse(policy.canAbortFor(null, new RuntimeException()));
assertFalse(policy.canAbortFor(null, new IllegalStateException()));
}
public void testCanAbortForResult() {
RetryPolicy policy = new RetryPolicy().abortWhen(10);
assertTrue(policy.canAbortFor(10, null));
assertFalse(policy.canAbortFor(5, null));
assertFalse(policy.canAbortFor(5, new IllegalArgumentException()));
}
public void shouldRequireValidBackoff() {
shouldFail(() -> new RetryPolicy().withBackoff(0, 0, null), NullPointerException.class);
shouldFail(
() -> new RetryPolicy().withMaxDuration(1, TimeUnit.MILLISECONDS).withBackoff(100, 120, TimeUnit.MILLISECONDS),
IllegalStateException.class);
shouldFail(() -> new RetryPolicy().withBackoff(-3, 10, TimeUnit.MILLISECONDS), IllegalArgumentException.class);
shouldFail(() -> new RetryPolicy().withBackoff(100, 10, TimeUnit.MILLISECONDS), IllegalArgumentException.class);
shouldFail(() -> new RetryPolicy().withBackoff(5, 10, TimeUnit.MILLISECONDS, .5), IllegalArgumentException.class);
}
public void shouldRequireValidDelay() {
shouldFail(() -> new RetryPolicy().withDelay(5, null), NullPointerException.class);
shouldFail(() -> new RetryPolicy().withMaxDuration(1, TimeUnit.MILLISECONDS).withDelay(100, TimeUnit.MILLISECONDS),
IllegalStateException.class);
shouldFail(() -> new RetryPolicy().withBackoff(1, 2, TimeUnit.MILLISECONDS).withDelay(100, TimeUnit.MILLISECONDS),
IllegalStateException.class);
shouldFail(() -> new RetryPolicy().withDelay(-1, TimeUnit.MILLISECONDS), IllegalArgumentException.class);
}
public void shouldRequireValidMaxRetries() {
shouldFail(() -> new RetryPolicy().withMaxRetries(-4), IllegalArgumentException.class);
}
public void shouldRequireValidMaxDuration() {
shouldFail(
() -> new RetryPolicy().withDelay(100, TimeUnit.MILLISECONDS).withMaxDuration(100, TimeUnit.MILLISECONDS),
IllegalStateException.class);
}
public void testCopy() {
RetryPolicy rp = new RetryPolicy();
rp.withBackoff(2, 20, TimeUnit.SECONDS, 2.5);
rp.withMaxDuration(60, TimeUnit.SECONDS);
rp.withMaxRetries(3);
RetryPolicy rp2 = rp.copy();
assertEquals(rp.getDelay().toNanos(), rp2.getDelay().toNanos());
assertEquals(rp.getDelayFactor(), rp2.getDelayFactor());
assertEquals(rp.getMaxDelay().toNanos(), rp2.getMaxDelay().toNanos());
assertEquals(rp.getMaxDuration().toNanos(), rp2.getMaxDuration().toNanos());
assertEquals(rp.getMaxRetries(), rp2.getMaxRetries());
}
}