org.eclipse.microprofile.fault.tolerance.tck.RetryTest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of microprofile-fault-tolerance-tck Show documentation
Show all versions of microprofile-fault-tolerance-tck Show documentation
Fault Tolerance for MicroProfile :: TCK
/*
*******************************************************************************
* Copyright (c) 2016-2019 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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.eclipse.microprofile.fault.tolerance.tck;
import org.eclipse.microprofile.fault.tolerance.tck.config.ConfigAnnotationAsset;
import org.eclipse.microprofile.fault.tolerance.tck.retry.clientserver.RetryClassLevelClientForMaxRetries;
import org.eclipse.microprofile.fault.tolerance.tck.retry.clientserver.RetryClientForMaxRetries;
import org.eclipse.microprofile.fault.tolerance.tck.retry.clientserver.RetryClientWithDelay;
import org.eclipse.microprofile.fault.tolerance.tck.retry.clientserver.RetryClientWithNoDelayAndJitter;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.testng.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.testng.Assert;
import org.testng.annotations.Test;
import jakarta.inject.Inject;
/**
* Test when maxDuration is reached, no more retries will be perfomed. Test the delay and jitter were taken into
* consideration.
*
* @author Emily Jiang
*
*/
public class RetryTest extends Arquillian {
private @Inject RetryClientForMaxRetries clientForMaxRetry;
private @Inject RetryClientWithDelay clientForDelay;
private @Inject RetryClassLevelClientForMaxRetries clientForClassLevelMaxRetry;
private @Inject RetryClientWithNoDelayAndJitter retryClientWithNoDelayAndJitter;
@Deployment
public static WebArchive deploy() {
ConfigAnnotationAsset config = new ConfigAnnotationAsset()
.autoscaleMethod(RetryClientWithDelay.class, "serviceA");
JavaArchive testJar = ShrinkWrap
.create(JavaArchive.class, "ftRetry.jar")
.addClasses(RetryClientForMaxRetries.class,
RetryClientWithDelay.class,
RetryClassLevelClientForMaxRetries.class,
RetryClientWithNoDelayAndJitter.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
.addAsManifestResource(config, "microprofile-config.properties");
WebArchive war = ShrinkWrap
.create(WebArchive.class, "ftRetry.war")
.addAsLibrary(testJar);
return war;
}
/**
* Test maxRetries.
*
* As serviceA is annotated with maxRetries = 5, serviceA should be executed 6 times.
*/
@Test
public void testRetryMaxRetries() {
try {
clientForMaxRetry.serviceA();
Assert.fail("serviceA should throw a RuntimeException in testRetryMaxRetries");
} catch (RuntimeException ex) {
// Expected
}
Assert.assertEquals(clientForMaxRetry.getRetryCountForConnectionService(), 6,
"The max number of execution should be 6");
}
@Test
public void testRetryMaxDuration() {
try {
clientForMaxRetry.serviceB();
Assert.fail("serviceB should throw a RuntimeException in testRetryMaxDuration");
} catch (RuntimeException ex) {
// Expected
}
// The writing service invocation takes 100ms plus a jitter of 0-200ms with the max duration of 1000ms,
// the max invocation should be less than 10
int retries = clientForMaxRetry.getRetryCountForWritingService();
Assert.assertTrue(retries < 11, "The max retry counter should be less than 11 but it was " + retries);
}
@Test
public void testRetryMaxDurationSeconds() {
try {
clientForMaxRetry.serviceC();
Assert.fail("serviceC should throw a RuntimeException in testRetryMaxDuration");
} catch (RuntimeException ex) {
// Expected
}
// The writing service invocation takes 100ms plus a jitter of 0-200ms with the max duration of 1000ms,
// the max invocation should be less than 10
int retries = clientForMaxRetry.getRetryCountForWritingService();
Assert.assertTrue(retries < 11, "The max retry counter should be less than 11 but it was " + retries);
}
@Test
public void testRetryWithDelay() {
try {
clientForDelay.serviceA();
Assert.fail("serviceA should throw a RuntimeException in testRetryWithDelay");
} catch (RuntimeException ex) {
// Expected
}
int retryCountForConnectionService = clientForDelay.getRetryCountForConnectionService();
Assert.assertTrue(retryCountForConnectionService > 4,
"The max number of execution should be greater than 4 but it was " + retryCountForConnectionService);
clientForDelay.assertDelayInRange();
}
/**
* Testing whether the {@code @Retry} annotation on method serviceB overrides the Class level {@code @Retry}
* annotation.
*
* Delay is 0 and jitter 400ms. Invocation takes 3200ms and effective delay must be between 0 and 400ms.
*/
@Test
public void testRetryWithNoDelayAndJitter() {
try {
retryClientWithNoDelayAndJitter.serviceA();
Assert.fail("serviceA should throw a RuntimeException in testRetryWithDelay");
} catch (RuntimeException ex) {
// Expected
}
final int retryCountForConnectionService = retryClientWithNoDelayAndJitter.getRetryCountForConnectionService();
// we have positive delays
Assert.assertTrue(retryClientWithNoDelayAndJitter.positiveDelays() > 0,
"Using jitter must cause some effective delay even when delay is set to 0");
Assert.assertTrue(retryCountForConnectionService > 8 && retryCountForConnectionService < 100,
"The max number of execution should be between 8 and 100 but it was " + retryCountForConnectionService +
". Too many retries mean jitter is not being applied.");
}
/**
* Analogous to testRetryMaxRetries but using a Class level rather than method level annotation.
*
* With maxRetries = 2, serviceA should be executed 3 times.
*/
@Test
public void testClassLevelRetryMaxRetries() {
try {
clientForClassLevelMaxRetry.serviceA();
Assert.fail("serviceA should throw a RuntimeException in testClassLevelRetryMaxRetries");
} catch (RuntimeException ex) {
// Expected
}
int retries = clientForClassLevelMaxRetry.getRetryCountForConnectionService();
Assert.assertEquals(retries, 3, "The max number of execution should be 3 but it was " + retries);
}
/**
* Analogous to testRetryMaxDuration, testing whether the {@code @Retry} annotation on method serviceB overrides the
* Class level {@code @Retry} annotation.
*
* Ensure that serviceB is executed more than the maxRetries of 2 specified at the Class level.
*/
@Test
public void testClassLevelRetryMaxDuration() {
try {
clientForClassLevelMaxRetry.serviceB();
Assert.fail("serviceB should throw a RuntimeException in testClassLevelRetryMaxDuration");
} catch (RuntimeException ex) {
// Expected
}
// The writing service invocation takes 100ms plus a jitter of 0-200ms with the max duration of 1000ms,
// the max invocation should be less than 10
int retryCountforWritingService = clientForClassLevelMaxRetry.getRetryCountForWritingService();
Assert.assertTrue(retryCountforWritingService < 11,
"The max retry counter should be less than 11 but it was " + retryCountforWritingService);
// Further test that we have retried more than the maximum number of retries specified in the Class level {@code
// @Retry} annotation
Assert.assertTrue(retryCountforWritingService > 3,
"The max retry counter should be greater than 3 but it was " + retryCountforWritingService);
}
/**
* Analogous to testRetryMaxDurationSeconds, testing whether the {@code @Retry} annotation on method serviceB
* overrides the Class level {@code @Retry} annotation.
*
* Ensure that serviceB is executed more than the maxRetries of 2 specified at the Class level.
*/
@Test
public void testClassLevelRetryMaxDurationSeconds() {
try {
clientForClassLevelMaxRetry.serviceC();
Assert.fail("serviceC should throw a RuntimeException in testClassLevelRetryMaxDurationSeconds");
} catch (RuntimeException ex) {
// Expected
}
// The writing service invocation takes 100ms plus a jitter of 0-200ms with the max duration of 1000ms,
// the max invocation should be less than 10
int retries = clientForClassLevelMaxRetry.getRetryCountForWritingService();
Assert.assertTrue(retries < 11, "The max retry counter should be less than 11 but it was" + retries);
}
}