Search in sources :

Example 1 with ExecutionCompletedEvent

use of dev.failsafe.event.ExecutionCompletedEvent in project failsafe by jhalterman.

the class OkHttpTesting method test.

private <T> void test(FailsafeExecutor<Response> failsafe, Call when, Then<Response> then, int expectedStatus, T expectedResult, Class<? extends Throwable>[] expectedExceptions) {
    AtomicReference<CompletableFuture<Response>> futureRef = new AtomicReference<>();
    AtomicReference<ExecutionCompletedEvent<Response>> completedEventRef = new AtomicReference<>();
    Waiter completionListenerWaiter = new Waiter();
    EventListener<ExecutionCompletedEvent<Response>> setCompletedEventFn = e -> {
        completedEventRef.set(e);
        completionListenerWaiter.resume();
    };
    List<Class<? extends Throwable>> expected = new LinkedList<>();
    Class<? extends Throwable>[] expectedExInner = expectedExceptions == null ? new Class[] {} : expectedExceptions;
    Collections.addAll(expected, expectedExInner);
    failsafe.onComplete(setCompletedEventFn);
    Runnable postTestFn = () -> {
        ignoreExceptions(() -> completionListenerWaiter.await(5000));
        ExecutionCompletedEvent<Response> completedEvent = completedEventRef.get();
        if (expectedExceptions == null) {
            assertEquals(completedEvent.getResult().code(), expectedStatus);
            assertNull(completedEvent.getException());
        } else {
            assertNull(completedEvent.getResult());
            assertMatches(completedEvent.getException(), expectedExceptions);
        }
        if (then != null)
            then.accept(futureRef.get(), completedEvent);
    };
    Consumer<Response> assertResult = response -> {
        String result = unwrapExceptions(() -> response.body().string());
        assertEquals(result, expectedResult);
        assertEquals(response.code(), expectedStatus);
    };
    // Run sync test and assert result
    System.out.println("\nRunning sync test");
    FailsafeCall failsafeCall = FailsafeCall.with(failsafe).compose(when);
    if (expectedExceptions == null) {
        assertResult.accept(unwrapExceptions(failsafeCall::execute));
    } else {
        assertThrows(failsafeCall::execute, expectedExceptions);
    }
    postTestFn.run();
    if (expectedExInner.length > 0)
        expected.add(0, ExecutionException.class);
    // Run async test and assert result
    System.out.println("\nRunning async test");
    failsafeCall = failsafeCall.clone();
    CompletableFuture<Response> future = failsafeCall.executeAsync();
    futureRef.set(future);
    if (expectedExInner.length == 0) {
        assertResult.accept(unwrapExceptions(future::get));
    } else {
        assertThrowsSup(future::get, expected);
    }
    postTestFn.run();
}
Also used : FailsafeCall(dev.failsafe.okhttp.FailsafeCall) ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Request(okhttp3.Request) FailsafeExecutor(dev.failsafe.FailsafeExecutor) Assert.assertNull(org.testng.Assert.assertNull) Assert.assertEquals(org.testng.Assert.assertEquals) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) EventListener(dev.failsafe.event.EventListener) ExecutionException(java.util.concurrent.ExecutionException) Consumer(java.util.function.Consumer) Waiter(net.jodah.concurrentunit.Waiter) List(java.util.List) OkHttpClient(okhttp3.OkHttpClient) Response(okhttp3.Response) Call(okhttp3.Call) LinkedList(java.util.LinkedList) Collections(java.util.Collections) Testing(dev.failsafe.testing.Testing) AtomicReference(java.util.concurrent.atomic.AtomicReference) LinkedList(java.util.LinkedList) ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Response(okhttp3.Response) CompletableFuture(java.util.concurrent.CompletableFuture) FailsafeCall(dev.failsafe.okhttp.FailsafeCall) Waiter(net.jodah.concurrentunit.Waiter) ExecutionException(java.util.concurrent.ExecutionException)

Example 2 with ExecutionCompletedEvent

use of dev.failsafe.event.ExecutionCompletedEvent in project failsafe by jhalterman.

the class Testing method testGetInternal.

/**
 * This method helps ensure behavior is identical between sync and async executions.
 * <p>
 * Does a .get, .getAsync, .getAsyncExecution, and .getStageAsync against the failsafe, performing pre-test setup and
 * post-test assertion checks. {@code expectedResult} and {@code expectedExceptions} are verified against the returned
 * result or thrown exceptions _and_ the ExecutionCompletedEvent's result and failure.
 *
 * @param given The pre-execution setup to perform. Useful for resetting stats and mocks.
 * @param failsafe The FailsafeExecutor to execute with
 * @param when the Supplier to provide to the FailsafeExecutor
 * @param then post-test Assertions that are provided with Future (if any) and ExecutionCompletedEvent
 * @param expectedResult The expected result to assert against the actual result
 * @param expectedExceptions The expected exceptions to assert against the actual exceptions
 * @param runAsyncExecutions Indicates whether to run the AsyncExecution tests, including .getAsyncExecution. These
 * may be skipped for tests that involve timeouts, which don't work reliably against AsyncExecutions, since those may
 * return immediately.
 */
private static <T> void testGetInternal(boolean runAsyncExecutions, CheckedRunnable given, FailsafeExecutor<T> failsafe, ContextualSupplier<T, T> when, Then<T> then, T expectedResult, Class<? extends Throwable>[] expectedExceptions) {
    AtomicReference<CompletableFuture<T>> futureRef = new AtomicReference<>();
    AtomicReference<ExecutionCompletedEvent<T>> completedEventRef = new AtomicReference<>();
    Waiter completionListenerWaiter = new Waiter();
    EventListener<ExecutionCompletedEvent<T>> setCompletedEventFn = e -> {
        completedEventRef.set(e);
        completionListenerWaiter.resume();
    };
    List<Class<? extends Throwable>> expected = new LinkedList<>();
    Class<? extends Throwable>[] expectedExInner = expectedExceptions == null ? new Class[] {} : expectedExceptions;
    Collections.addAll(expected, expectedExInner);
    // Assert results by treating COMPLETE_SIGNAL as a null expected result
    Consumer<T> resultAssertion = result -> {
        if (result == COMPLETE_SIGNAL)
            assertNull(expectedResult);
        else
            assertEquals(result, expectedResult);
    };
    Runnable postTestFn = () -> {
        ignoreExceptions(() -> completionListenerWaiter.await(5000));
        ExecutionCompletedEvent<T> completedEvent = completedEventRef.get();
        if (expectedExInner.length > 0) {
            assertNull(completedEvent.getResult());
            assertMatches(completedEvent.getException(), Arrays.asList(expectedExInner));
        } else {
            resultAssertion.accept(completedEvent.getResult());
            assertNull(completedEvent.getException());
        }
        if (then != null)
            then.accept(futureRef.get(), completedEvent);
    };
    // Run sync test
    System.out.println("\nRunning sync test");
    if (given != null)
        uncheck(given).run();
    if (expectedExInner.length == 0) {
        resultAssertion.accept(unwrapExceptions(() -> failsafe.onComplete(setCompletedEventFn).get(when)));
    } else {
        assertThrows(() -> failsafe.onComplete(setCompletedEventFn).get(when), t -> {
            // Insert FailsafeException into expected exceptions if needed
            if (t instanceof FailsafeException && !FailsafeException.class.equals(expected.get(0)) && !RuntimeException.class.isAssignableFrom(expected.get(0)))
                return Lists.of(FailsafeException.class, expectedExInner);
            return expected;
        });
    }
    postTestFn.run();
    if (expectedExInner.length > 0)
        expected.add(0, ExecutionException.class);
    // Create async tester
    Consumer<Function<FailsafeExecutor<T>, CompletableFuture<T>>> asyncTester = test -> {
        if (given != null)
            uncheck(given).run();
        CompletableFuture<T> future = test.apply(failsafe.onComplete(setCompletedEventFn));
        futureRef.set(future);
        if (expectedExInner.length == 0)
            resultAssertion.accept(unwrapExceptions(future::get));
        else
            assertThrowsSup(future::get, expected);
        postTestFn.run();
    };
    // Run async test
    System.out.println("\nRunning async test");
    asyncTester.accept(executor -> executor.getAsync(when));
    // Run async execution test
    if (runAsyncExecutions) {
        System.out.println("\nRunning async execution test");
        AsyncRunnable<T> asyncExecutionWhen = exec -> {
            // Run supplier in a different thread
            runInThread(() -> {
                try {
                    T result = when.get(exec);
                    if (result == COMPLETE_SIGNAL)
                        exec.complete();
                    else
                        exec.recordResult(result);
                } catch (Throwable t) {
                    exec.recordException(t);
                }
            });
        };
        asyncTester.accept(executor -> executor.getAsyncExecution(asyncExecutionWhen));
    }
    // Run stage async test
    System.out.println("\nRunning get stage async test");
    ContextualSupplier<T, ? extends CompletionStage<T>> stageAsyncWhen = ctx -> {
        CompletableFuture<T> promise = new CompletableFuture<>();
        // Run supplier in a different thread
        runInThread(() -> {
            try {
                promise.complete(when.get(ctx));
            } catch (Throwable t) {
                promise.completeExceptionally(t);
            }
        });
        return promise;
    };
    asyncTester.accept(executor -> executor.getStageAsync(stageAsyncWhen));
}
Also used : Lists(dev.failsafe.internal.util.Lists) ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Arrays(java.util.Arrays) FailsafeExecutor(dev.failsafe.FailsafeExecutor) Assert.assertNull(org.testng.Assert.assertNull) java.util.concurrent(java.util.concurrent) InternalTesting(dev.failsafe.internal.InternalTesting) Assert.assertEquals(org.testng.Assert.assertEquals) FailsafeException(dev.failsafe.FailsafeException) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) EventListener(dev.failsafe.event.EventListener) Consumer(java.util.function.Consumer) Waiter(net.jodah.concurrentunit.Waiter) List(java.util.List) RetryPolicy(dev.failsafe.RetryPolicy) LinkedList(java.util.LinkedList) Collections(java.util.Collections) dev.failsafe.function(dev.failsafe.function) FailsafeException(dev.failsafe.FailsafeException) AtomicReference(java.util.concurrent.atomic.AtomicReference) LinkedList(java.util.LinkedList) ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Function(java.util.function.Function) Waiter(net.jodah.concurrentunit.Waiter)

Example 3 with ExecutionCompletedEvent

use of dev.failsafe.event.ExecutionCompletedEvent in project failsafe by jhalterman.

the class FutureCancellationTest method testCancelWithNestedRetries.

/**
 * Asserts that cancelling a FailsafeFuture causes both retry policies to stop.
 */
public void testCancelWithNestedRetries() throws Throwable {
    // Given
    Stats outerRetryStats = new Stats();
    Stats innerRetryStats = new Stats();
    RetryPolicy<Object> outerRetryPolicy = withStatsAndLogs(RetryPolicy.builder(), outerRetryStats).build();
    RetryPolicy<Object> innerRetryPolicy = withStatsAndLogs(RetryPolicy.builder().withMaxRetries(3).withDelay(Duration.ofMillis(100)), innerRetryStats).build();
    AtomicReference<Future<Void>> futureRef = new AtomicReference<>();
    AtomicReference<ExecutionCompletedEvent<Object>> completedRef = new AtomicReference<>();
    Waiter waiter = new Waiter();
    // When
    futureRef.set(Failsafe.with(outerRetryPolicy, innerRetryPolicy).onComplete(e -> {
        completedRef.set(e);
        waiter.resume();
    }).runAsync(ctx -> {
        if (ctx.isFirstAttempt())
            throw new IllegalStateException();
        else
            futureRef.get().cancel(false);
    }));
    // Then
    assertThrows(() -> futureRef.get().get(1, TimeUnit.SECONDS), CancellationException.class);
    waiter.await(1000);
    assertNull(completedRef.get().getResult());
    assertTrue(completedRef.get().getException() instanceof CancellationException);
    assertEquals(outerRetryStats.failedAttemptCount, 0);
    assertEquals(innerRetryStats.failedAttemptCount, 1);
}
Also used : ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Waiter(net.jodah.concurrentunit.Waiter) ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Assert(org.testng.Assert) java.util.concurrent(java.util.concurrent) Duration(java.time.Duration) BeforeMethod(org.testng.annotations.BeforeMethod) dev.failsafe(dev.failsafe) Test(org.testng.annotations.Test) ContextualRunnable(dev.failsafe.function.ContextualRunnable) AtomicReference(java.util.concurrent.atomic.AtomicReference) Testing(dev.failsafe.testing.Testing) AtomicReference(java.util.concurrent.atomic.AtomicReference) Waiter(net.jodah.concurrentunit.Waiter)

Example 4 with ExecutionCompletedEvent

use of dev.failsafe.event.ExecutionCompletedEvent in project failsafe by jhalterman.

the class RetrofitTesting method test.

private <T> void test(FailsafeExecutor<Response<T>> failsafe, Call<T> when, Then<Response<T>> then, int expectedStatus, T expectedResult, Class<? extends Throwable>[] expectedExceptions) {
    AtomicReference<CompletableFuture<Response<T>>> futureRef = new AtomicReference<>();
    AtomicReference<ExecutionCompletedEvent<Response<T>>> completedEventRef = new AtomicReference<>();
    Waiter completionListenerWaiter = new Waiter();
    EventListener<ExecutionCompletedEvent<Response<T>>> setCompletedEventFn = e -> {
        completedEventRef.set(e);
        completionListenerWaiter.resume();
    };
    List<Class<? extends Throwable>> expected = new LinkedList<>();
    Class<? extends Throwable>[] expectedExInner = expectedExceptions == null ? new Class[] {} : expectedExceptions;
    Collections.addAll(expected, expectedExInner);
    failsafe.onComplete(setCompletedEventFn);
    Runnable postTestFn = () -> {
        ignoreExceptions(() -> completionListenerWaiter.await(5000));
        ExecutionCompletedEvent<Response<T>> completedEvent = completedEventRef.get();
        if (expectedExceptions == null) {
            assertEquals(completedEvent.getResult().code(), expectedStatus);
            assertNull(completedEvent.getException());
        } else {
            assertNull(completedEvent.getResult());
            assertMatches(completedEvent.getException(), expectedExceptions);
        }
        if (then != null)
            then.accept(futureRef.get(), completedEvent);
    };
    Consumer<Response<T>> assertResult = response -> {
        T result = unwrapExceptions(response::body);
        assertEquals(result, expectedResult);
        assertEquals(response.code(), expectedStatus);
    };
    // Run sync test and assert result
    System.out.println("\nRunning sync test");
    FailsafeCall<T> failsafeCall = FailsafeCall.with(failsafe).compose(when);
    if (expectedExceptions == null) {
        assertResult.accept(unwrapExceptions(failsafeCall::execute));
    } else {
        assertThrows(failsafeCall::execute, expectedExceptions);
    }
    postTestFn.run();
    if (expectedExInner.length > 0)
        expected.add(0, ExecutionException.class);
    // Run async test and assert result
    System.out.println("\nRunning async test");
    failsafeCall = failsafeCall.clone();
    CompletableFuture<Response<T>> future = failsafeCall.executeAsync();
    futureRef.set(future);
    if (expectedExInner.length == 0) {
        assertResult.accept(unwrapExceptions(future::get));
    } else {
        assertThrowsSup(future::get, expected);
    }
    postTestFn.run();
}
Also used : ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) FailsafeExecutor(dev.failsafe.FailsafeExecutor) Assert.assertNull(org.testng.Assert.assertNull) Assert.assertEquals(org.testng.Assert.assertEquals) CompletableFuture(java.util.concurrent.CompletableFuture) Response(retrofit2.Response) AtomicReference(java.util.concurrent.atomic.AtomicReference) EventListener(dev.failsafe.event.EventListener) ExecutionException(java.util.concurrent.ExecutionException) Consumer(java.util.function.Consumer) FailsafeCall(dev.failsafe.retrofit.FailsafeCall) Waiter(net.jodah.concurrentunit.Waiter) List(java.util.List) LinkedList(java.util.LinkedList) Call(retrofit2.Call) Collections(java.util.Collections) Testing(dev.failsafe.testing.Testing) AtomicReference(java.util.concurrent.atomic.AtomicReference) LinkedList(java.util.LinkedList) ExecutionCompletedEvent(dev.failsafe.event.ExecutionCompletedEvent) Response(retrofit2.Response) CompletableFuture(java.util.concurrent.CompletableFuture) Waiter(net.jodah.concurrentunit.Waiter) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

ExecutionCompletedEvent (dev.failsafe.event.ExecutionCompletedEvent)4 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 Waiter (net.jodah.concurrentunit.Waiter)4 FailsafeExecutor (dev.failsafe.FailsafeExecutor)3 EventListener (dev.failsafe.event.EventListener)3 Testing (dev.failsafe.testing.Testing)3 Collections (java.util.Collections)3 LinkedList (java.util.LinkedList)3 List (java.util.List)3 Consumer (java.util.function.Consumer)3 Assert.assertEquals (org.testng.Assert.assertEquals)3 Assert.assertNull (org.testng.Assert.assertNull)3 java.util.concurrent (java.util.concurrent)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 ExecutionException (java.util.concurrent.ExecutionException)2 Function (java.util.function.Function)2 dev.failsafe (dev.failsafe)1 FailsafeException (dev.failsafe.FailsafeException)1 RetryPolicy (dev.failsafe.RetryPolicy)1 dev.failsafe.function (dev.failsafe.function)1