Search in sources :

Example 11 with TerminalSignalConsumer

use of io.servicetalk.concurrent.api.TerminalSignalConsumer in project servicetalk by apple.

the class AfterFinallyTest method testCallbackThrowsErrorOnComplete.

@Override
@Test
void testCallbackThrowsErrorOnComplete() {
    TerminalSignalConsumer mock = throwableMock(DELIBERATE_EXCEPTION);
    try {
        doFinally(publisher, mock).subscribe(subscriber);
        assertFalse(subscription.isCancelled());
        Exception e = assertThrows(DeliberateException.class, () -> publisher.onComplete());
        assertThat(e, is(sameInstance(DELIBERATE_EXCEPTION)));
    } finally {
        subscriber.awaitOnComplete();
        verify(mock).onComplete();
        verifyNoMoreInteractions(mock);
        assertFalse(subscription.isCancelled());
    }
}
Also used : TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) DeliberateException(io.servicetalk.concurrent.internal.DeliberateException) Test(org.junit.jupiter.api.Test)

Example 12 with TerminalSignalConsumer

use of io.servicetalk.concurrent.api.TerminalSignalConsumer in project servicetalk by apple.

the class AbstractCompletableOffloadingTest method testOffloading.

protected int testOffloading(BiFunction<Completable, Executor, Completable> offloadingFunction, TerminalOperation terminal) throws InterruptedException {
    Runnable appCode = () -> {
        try {
            // Insert a custom value into AsyncContext map
            AsyncContext.put(ASYNC_CONTEXT_CUSTOM_KEY, ASYNC_CONTEXT_VALUE);
            capture(CaptureSlot.APP);
            // Add thread/context recording test points
            final Completable original = testCompletable.liftSync(subscriber -> {
                capture(CaptureSlot.OFFLOADED_SUBSCRIBE);
                return subscriber;
            }).beforeOnSubscribe(cancellable -> capture(CaptureSlot.ORIGINAL_ON_SUBSCRIBE)).beforeFinally(new TerminalSignalConsumer() {

                @Override
                public void onComplete() {
                    capture(CaptureSlot.ORIGINAL_ON_COMPLETE);
                }

                @Override
                public void onError(final Throwable throwable) {
                    capture(CaptureSlot.ORIGINAL_ON_ERROR);
                }

                @Override
                public void cancel() {
                    capture(CaptureSlot.OFFLOADED_CANCEL);
                }
            });
            // Perform offloading and add more thread/context recording test points
            Completable offloaded = offloadingFunction.apply(original, testExecutor.executor()).liftSync(subscriber -> {
                capture(CaptureSlot.ORIGINAL_SUBSCRIBE);
                return subscriber;
            }).beforeOnSubscribe(cancellable -> capture(CaptureSlot.OFFLOADED_ON_SUBSCRIBE)).beforeFinally(new TerminalSignalConsumer() {

                @Override
                public void onComplete() {
                    capture(CaptureSlot.OFFLOADED_ON_COMPLETE);
                }

                @Override
                public void onError(final Throwable throwable) {
                    capture(CaptureSlot.OFFLOADED_ON_ERROR);
                }

                @Override
                public void cancel() {
                    capture(CaptureSlot.ORIGINAL_CANCEL);
                }
            });
            // subscribe and generate terminal
            toSource(offloaded).subscribe(testSubscriber);
            assertThat("Unexpected tasks " + testExecutor.executor().queuedTasksPending(), testExecutor.executor().queuedTasksPending(), lessThan(2));
            if (1 == testExecutor.executor().queuedTasksPending()) {
                // execute offloaded subscribe
                testExecutor.executor().executeNextTask();
            }
            Cancellable cancellable = testSubscriber.awaitSubscription();
            assertThat("No Cancellable", cancellable, notNullValue());
            testCompletable.awaitSubscribed();
            assertThat("Source is not subscribed", testCompletable.isSubscribed());
            assertThat("Thread was interrupted", !Thread.currentThread().isInterrupted());
            switch(terminal) {
                case CANCEL:
                    cancellable.cancel();
                    break;
                case COMPLETE:
                    testCompletable.onComplete();
                    break;
                case ERROR:
                    testCompletable.onError(DELIBERATE_EXCEPTION);
                    break;
                default:
                    throw new AssertionError("unexpected terminal mode");
            }
            assertThat("Unexpected tasks " + testExecutor.executor().queuedTasksPending(), testExecutor.executor().queuedTasksPending(), lessThan(2));
            if (1 == testExecutor.executor().queuedTasksPending()) {
                // execute offloaded terminal
                testExecutor.executor().executeNextTask();
            }
        } catch (Throwable all) {
            AbstractOffloadingTest.LOGGER.warn("Unexpected throwable", all);
            testSubscriber.onError(all);
        }
    };
    APP_EXECUTOR_EXT.executor().execute(appCode);
    // Ensure we reached the correct terminal condition
    switch(terminal) {
        case CANCEL:
            testCancellable.awaitCancelled();
            break;
        case ERROR:
            Throwable thrown = testSubscriber.awaitOnError();
            assertThat("unexpected exception " + thrown, thrown, sameInstance(DELIBERATE_EXCEPTION));
            break;
        case COMPLETE:
            testSubscriber.awaitOnComplete();
            break;
        default:
            throw new AssertionError("unexpected terminal mode");
    }
    // Ensure that Async Context Map was correctly set during signals
    ContextMap appMap = capturedContexts.captured(CaptureSlot.APP);
    assertThat(appMap, notNullValue());
    ContextMap subscribeMap = capturedContexts.captured(CaptureSlot.ORIGINAL_SUBSCRIBE);
    assertThat(subscribeMap, notNullValue());
    assertThat("Map was shared not copied", subscribeMap, not(sameInstance(appMap)));
    assertThat("Missing custom async context entry ", subscribeMap.get(ASYNC_CONTEXT_CUSTOM_KEY), sameInstance(ASYNC_CONTEXT_VALUE));
    EnumSet<CaptureSlot> checkSlots = EnumSet.complementOf(EnumSet.of(CaptureSlot.APP, CaptureSlot.ORIGINAL_SUBSCRIBE));
    checkSlots.stream().filter(slot -> null != capturedContexts.captured(slot)).forEach(slot -> {
        ContextMap map = capturedContexts.captured(slot);
        assertThat("Context map was not captured", map, is(notNullValue()));
        assertThat("Custom key missing from context map", map.containsKey(ASYNC_CONTEXT_CUSTOM_KEY));
        assertThat("Unexpected context map @ slot " + slot + " : " + map, map, sameInstance(subscribeMap));
    });
    // Ensure that all offloading completed.
    assertThat("Offloading pending", testExecutor.executor().queuedTasksPending(), is(0));
    return testExecutor.executor().queuedTasksExecuted();
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) BiFunction(java.util.function.BiFunction) Completable(io.servicetalk.concurrent.api.Completable) CoreMatchers.not(org.hamcrest.CoreMatchers.not) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) Cancellable(io.servicetalk.concurrent.Cancellable) TestCancellable(io.servicetalk.concurrent.api.TestCancellable) SourceAdapters.toSource(io.servicetalk.concurrent.api.SourceAdapters.toSource) TestCompletableSubscriber(io.servicetalk.concurrent.test.internal.TestCompletableSubscriber) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) AbstractOffloadingTest(io.servicetalk.concurrent.api.internal.AbstractOffloadingTest) ContextMap(io.servicetalk.context.api.ContextMap) AsyncContext(io.servicetalk.concurrent.api.AsyncContext) TestCompletable(io.servicetalk.concurrent.api.TestCompletable) Matchers.lessThan(org.hamcrest.Matchers.lessThan) Executor(io.servicetalk.concurrent.api.Executor) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) EnumSet(java.util.EnumSet) CoreMatchers.sameInstance(org.hamcrest.CoreMatchers.sameInstance) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) Completable(io.servicetalk.concurrent.api.Completable) TestCompletable(io.servicetalk.concurrent.api.TestCompletable) Cancellable(io.servicetalk.concurrent.Cancellable) TestCancellable(io.servicetalk.concurrent.api.TestCancellable) ContextMap(io.servicetalk.context.api.ContextMap)

Example 13 with TerminalSignalConsumer

use of io.servicetalk.concurrent.api.TerminalSignalConsumer in project servicetalk by apple.

the class BeforeFinallyTest method testCallbackThrowsErrorOnComplete.

@Override
@Test
void testCallbackThrowsErrorOnComplete() {
    TerminalSignalConsumer mock = throwableMock(DELIBERATE_EXCEPTION);
    doFinally(publisher, mock).subscribe(subscriber);
    assertFalse(subscription.isCancelled());
    publisher.onComplete();
    Throwable receivedError = subscriber.awaitOnError();
    assertThat(receivedError, is(notNullValue()));
    assertThat(receivedError, sameInstance(DELIBERATE_EXCEPTION));
    verify(mock).onComplete();
    verifyNoMoreInteractions(mock);
    assertFalse(subscription.isCancelled());
}
Also used : TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) Test(org.junit.jupiter.api.Test)

Example 14 with TerminalSignalConsumer

use of io.servicetalk.concurrent.api.TerminalSignalConsumer in project servicetalk by apple.

the class BeforeFinallyTest method testCallbackThrowsErrorOnComplete.

@Test
@Override
void testCallbackThrowsErrorOnComplete() {
    TerminalSignalConsumer mock = throwableMock(DELIBERATE_EXCEPTION);
    toSource(doFinally(Completable.completed(), mock)).subscribe(listener);
    assertThat(listener.awaitOnError(), is(DELIBERATE_EXCEPTION));
    verify(mock).onComplete();
    verifyNoMoreInteractions(mock);
}
Also used : TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) Test(org.junit.jupiter.api.Test)

Example 15 with TerminalSignalConsumer

use of io.servicetalk.concurrent.api.TerminalSignalConsumer in project servicetalk by apple.

the class AbstractWhenFinallyTest method testCallbackThrowsErrorWhenCancel.

@Test
void testCallbackThrowsErrorWhenCancel() {
    TerminalSignalConsumer mock = throwableMock(DELIBERATE_EXCEPTION);
    LegacyTestCompletable completable = new LegacyTestCompletable();
    try {
        toSource(doFinally(completable, mock)).subscribe(listener);
        Exception e = assertThrows(DeliberateException.class, () -> listener.awaitSubscription().cancel());
        assertThat(e, is(sameInstance(DELIBERATE_EXCEPTION)));
    } finally {
        completable.verifyCancelled();
        verify(mock).cancel();
        verifyNoMoreInteractions(mock);
    }
}
Also used : TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) LegacyTestCompletable(io.servicetalk.concurrent.api.LegacyTestCompletable) DeliberateException(io.servicetalk.concurrent.internal.DeliberateException) Test(org.junit.jupiter.api.Test)

Aggregations

TerminalSignalConsumer (io.servicetalk.concurrent.api.TerminalSignalConsumer)16 Test (org.junit.jupiter.api.Test)11 DeliberateException (io.servicetalk.concurrent.internal.DeliberateException)8 AsyncContext (io.servicetalk.concurrent.api.AsyncContext)4 ContextMap (io.servicetalk.context.api.ContextMap)4 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)4 PublisherSource (io.servicetalk.concurrent.PublisherSource)3 Executor (io.servicetalk.concurrent.api.Executor)3 Single (io.servicetalk.concurrent.api.Single)3 SourceAdapters.toSource (io.servicetalk.concurrent.api.SourceAdapters.toSource)3 AbstractOffloadingTest (io.servicetalk.concurrent.api.internal.AbstractOffloadingTest)3 EnumSet (java.util.EnumSet)3 BiFunction (java.util.function.BiFunction)3 CoreMatchers.is (org.hamcrest.CoreMatchers.is)3 CoreMatchers.not (org.hamcrest.CoreMatchers.not)3 CoreMatchers.notNullValue (org.hamcrest.CoreMatchers.notNullValue)3 CoreMatchers.sameInstance (org.hamcrest.CoreMatchers.sameInstance)3 Matchers.lessThan (org.hamcrest.Matchers.lessThan)3 Buffer (io.servicetalk.buffer.api.Buffer)2 Publisher (io.servicetalk.concurrent.api.Publisher)2