/*
*
* Copyright 2017: Robert Winkler
*
* 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 io.github.resilience4j.metrics;
import com.codahale.metrics.MetricRegistry;
import io.github.resilience4j.test.HelloWorldService;
import io.vavr.CheckedFunction0;
import io.vavr.CheckedFunction1;
import io.vavr.CheckedRunnable;
import io.vavr.collection.Stream;
import io.vavr.control.Try;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import javax.xml.ws.WebServiceException;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
public class TimerTest {
private HelloWorldService helloWorldService;
private Timer timer;
private MetricRegistry metricRegistry;
@Before
public void setUp(){
metricRegistry = new MetricRegistry();
timer = Timer.ofMetricRegistry(TimerTest.class.getName(), metricRegistry);
helloWorldService = mock(HelloWorldService.class);
}
@Test
public void shouldDecorateCheckedSupplier() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorldWithException()).willReturn("Hello world");
// And measure the time with Metrics
CheckedFunction0<String> timedSupplier = Timer.decorateCheckedSupplier(timer, helloWorldService::returnHelloWorldWithException);
String value = timedSupplier.apply();
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
assertThat(metricRegistry.getCounters().size()).isEqualTo(2);
assertThat(metricRegistry.getTimers().size()).isEqualTo(1);
assertThat(value).isEqualTo("Hello world");
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorldWithException();
}
@Test
public void shouldDecorateCallable() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorldWithException()).willReturn("Hello world");
// And measure the time with Metrics
Callable<String> timedSupplier = Timer.decorateCallable(timer, helloWorldService::returnHelloWorldWithException);
String value = timedSupplier.call();
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
assertThat(value).isEqualTo("Hello world");
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorldWithException();
}
@Test
public void shouldExecuteCallable() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorldWithException()).willReturn("Hello world");
// And measure the time with Metrics
String value = timer.executeCallable(helloWorldService::returnHelloWorldWithException);
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
assertThat(value).isEqualTo("Hello world");
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorldWithException();
}
@Test
public void shouldDecorateRunnable() throws Throwable {
// And measure the time with Metrics
Runnable timedRunnable = Timer.decorateRunnable(timer, helloWorldService::sayHelloWorld);
timedRunnable.run();
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).sayHelloWorld();
}
@Test
public void shouldExecuteRunnable() throws Throwable {
// And measure the time with Metrics
timer.executeRunnable(helloWorldService::sayHelloWorld);
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).sayHelloWorld();
}
@Test
public void shouldExecuteCompletionStageSupplier() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
// And measure the time with Metrics
Supplier<CompletionStage<String>> completionStageSupplier =
() -> CompletableFuture.supplyAsync(helloWorldService::returnHelloWorld);
CompletionStage<String> stringCompletionStage = timer.executeCompletionStageSupplier(completionStageSupplier);
String value = stringCompletionStage.toCompletableFuture().get();
assertThat(value).isEqualTo("Hello world");
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorld();
}
@Test
public void shouldExecuteCompletionStageAndReturnWithExceptionAtSyncStage() throws Throwable {
Supplier<CompletionStage<String>> completionStageSupplier = () -> {
throw new WebServiceException("BAM! At sync stage");
};
Assertions.assertThatThrownBy(() -> timer.executeCompletionStageSupplier(completionStageSupplier))
.isInstanceOf(WebServiceException.class);
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(0);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(1);
}
@Test
public void shouldExecuteCompletionStageAndReturnWithExceptionAtASyncStage() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorld()).willThrow(new WebServiceException("BAM!"));
// And measure the time with Metrics
Supplier<CompletionStage<String>> completionStageSupplier =
() -> CompletableFuture.supplyAsync(helloWorldService::returnHelloWorld);
CompletionStage<String> stringCompletionStage = timer.executeCompletionStageSupplier(completionStageSupplier);
Assertions.assertThatThrownBy(() -> stringCompletionStage.toCompletableFuture().get())
.isInstanceOf(ExecutionException.class).hasCause(new WebServiceException("BAM!"));
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(0);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(1);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorld();
}
@Test
public void shouldDecorateCheckedRunnableAndReturnWithSuccess() throws Throwable {
// And measure the time with Metrics
CheckedRunnable timedRunnable = Timer.decorateCheckedRunnable(timer, helloWorldService::sayHelloWorldWithException);
timedRunnable.run();
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(Mockito.times(1)).sayHelloWorldWithException();
}
@Test
public void shouldDecorateSupplierAndReturnWithException() throws Throwable {
// And measure the time with Metrics
BDDMockito.given(helloWorldService.returnHelloWorld()).willThrow(new RuntimeException("BAM!"));
// And measure the time with Metrics
Supplier<String> supplier = Timer.decorateSupplier(timer, helloWorldService::returnHelloWorld);
Try<String> result = Try.of(supplier::get);
assertThat(result.isFailure()).isTrue();
assertThat(result.failed().get()).isInstanceOf(RuntimeException.class);
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(0);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(1);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorld();
}
@Test
public void shouldDecorateSupplier() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
// And measure the time with Metrics
Supplier<String> timedSupplier = Timer.decorateSupplier(timer, helloWorldService::returnHelloWorld);
Stream.range(0,2).forEach((i) -> timedSupplier.get());
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(2);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(2);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(2)).returnHelloWorld();
}
@Test
public void shouldExecuteSupplier() throws Throwable {
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorld()).willReturn("Hello world").willThrow(new IllegalArgumentException("BAM!"));
// And measure the time with Metrics
Stream.range(0,2).forEach((i) -> {
try{
timer.executeSupplier(helloWorldService::returnHelloWorld);
}catch (Exception e){
Assertions.assertThat(e).isInstanceOf(IllegalArgumentException.class);
}
});
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(2);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(1);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(times(2)).returnHelloWorld();
}
@Test
public void shouldDecorateFunctionAndReturnWithSuccess() throws Throwable {
// Given
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorldWithName("Tom")).willReturn("Hello world Tom");
//When
Function<String, String> function = Timer.decorateFunction(timer, helloWorldService::returnHelloWorldWithName);
//Then
assertThat(function.apply("Tom")).isEqualTo("Hello world Tom");
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorldWithName("Tom");
}
@Test
public void shouldDecorateCheckedFunctionAndReturnWithSuccess() throws Throwable {
// Given
// Given the HelloWorldService returns Hello world
BDDMockito.given(helloWorldService.returnHelloWorldWithNameWithException("Tom")).willReturn("Hello world Tom");
//When
CheckedFunction1<String, String> function = Timer.decorateCheckedFunction(timer, helloWorldService::returnHelloWorldWithNameWithException);
//Then
assertThat(function.apply("Tom")).isEqualTo("Hello world Tom");
assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1);
assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0);
// Then the helloWorldService should be invoked 1 time
BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorldWithNameWithException("Tom");
}
}