Search in sources :

Example 1 with LegacyTestSingle

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

the class BeforeFinallyHttpOperatorTest method cancelWhileDeliveringPayload.

@Test
void cancelWhileDeliveringPayload() {
    TestPublisher<Buffer> payload = new TestPublisher.Builder<Buffer>().disableAutoOnSubscribe().build();
    Subscription payloadSubscription = mock(Subscription.class);
    LegacyTestSingle<StreamingHttpResponse> responseSingle = new LegacyTestSingle<>(true);
    final ResponseSubscriber subscriber = new ResponseSubscriber();
    toSource(responseSingle.liftSync(new BeforeFinallyHttpOperator(beforeFinally, true))).subscribe(subscriber);
    assertThat("onSubscribe not called.", subscriber.cancellable, is(notNullValue()));
    responseSingle.onSuccess(reqRespFactory.ok().payloadBody(payload));
    verifyNoInteractions(beforeFinally);
    responseSingle.verifyNotCancelled();
    subscriber.verifyResponseReceived();
    assert subscriber.response != null;
    BlockingQueue<Buffer> receivedPayload = new LinkedBlockingDeque<>();
    AtomicReference<TerminalNotification> subscriberTerminal = new AtomicReference<>();
    toSource(subscriber.response.payloadBody()).subscribe(new PublisherSource.Subscriber<Buffer>() {

        @Nullable
        private Subscription subscription;

        @Override
        public void onSubscribe(final Subscription subscription) {
            this.subscription = subscription;
            subscription.request(MAX_VALUE);
        }

        @Override
        public void onNext(@Nullable final Buffer buffer) {
            assert buffer != null;
            receivedPayload.add(buffer);
            if (receivedPayload.size() == 1) {
                assert subscription != null;
                subscription.cancel();
                // intentionally cancel two times to make sure it's idempotent
                subscription.cancel();
                verify(payloadSubscription, Mockito.never()).cancel();
                verifyNoMoreInteractions(beforeFinally);
                payload.onNext(EMPTY_BUFFER);
            }
            verify(payloadSubscription, Mockito.never()).cancel();
            verifyNoMoreInteractions(beforeFinally);
        // Cancel will be propagated after this method returns
        }

        @Override
        public void onError(final Throwable t) {
            subscriberTerminal.set(TerminalNotification.error(t));
        }

        @Override
        public void onComplete() {
            subscriberTerminal.set(TerminalNotification.complete());
        }
    });
    payload.onSubscribe(payloadSubscription);
    verify(payloadSubscription, Mockito.never()).cancel();
    payload.onNext(EMPTY_BUFFER);
    verify(payloadSubscription).cancel();
    verify(beforeFinally).cancel();
    assertThat("Unexpected payload body items", receivedPayload, contains(EMPTY_BUFFER, EMPTY_BUFFER));
    assertThat("Unexpected payload body termination", subscriberTerminal.get(), is(nullValue()));
    verifyNoMoreInteractions(beforeFinally);
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) PublisherSource(io.servicetalk.concurrent.PublisherSource) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Nullable(javax.annotation.Nullable) LegacyTestSingle(io.servicetalk.concurrent.api.LegacyTestSingle) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 2 with LegacyTestSingle

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

the class BeforeFinallyHttpOperatorTest method cancelBeforeOnSuccess.

@ParameterizedTest(name = "{displayName} [{index}] discardEventsAfterCancel={0}")
@ValueSource(booleans = { false, true })
void cancelBeforeOnSuccess(boolean discardEventsAfterCancel) {
    LegacyTestSingle<StreamingHttpResponse> responseSingle = new LegacyTestSingle<>(true);
    final ResponseSubscriber subscriber = new ResponseSubscriber();
    toSource(responseSingle.liftSync(new BeforeFinallyHttpOperator(beforeFinally, discardEventsAfterCancel))).subscribe(subscriber);
    assertThat("onSubscribe not called.", subscriber.cancellable, is(notNullValue()));
    subscriber.cancellable.cancel();
    verify(beforeFinally).cancel();
    responseSingle.verifyCancelled();
    responseSingle.onSuccess(reqRespFactory.newResponse(OK));
    if (discardEventsAfterCancel) {
        subscriber.verifyNoResponseReceived();
    } else {
        subscriber.verifyResponseReceived();
        assert subscriber.response != null;
        Exception ex = assertThrows(Exception.class, () -> subscriber.response.payloadBody().toFuture().get());
        assertThat(ex.getCause(), instanceOf(CancellationException.class));
    }
    verifyNoMoreInteractions(beforeFinally);
}
Also used : CancellationException(java.util.concurrent.CancellationException) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) CancellationException(java.util.concurrent.CancellationException) LegacyTestSingle(io.servicetalk.concurrent.api.LegacyTestSingle) ValueSource(org.junit.jupiter.params.provider.ValueSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 3 with LegacyTestSingle

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

the class BeforeFinallyHttpOperatorTest method cancelBeforeOnNextThenTerminate.

@ParameterizedTest(name = "{displayName} [{index}] discardEventsAfterCancel={0} payloadTerminal={1}")
@MethodSource("booleanTerminalNotification")
void cancelBeforeOnNextThenTerminate(boolean discardEventsAfterCancel, TerminalNotification payloadTerminal) {
    TestPublisher<Buffer> payload = new TestPublisher.Builder<Buffer>().disableAutoOnSubscribe().build();
    TestSubscription payloadSubscription = new TestSubscription();
    TestPublisherSubscriber<Buffer> payloadSubscriber = new TestPublisherSubscriber<>();
    LegacyTestSingle<StreamingHttpResponse> responseSingle = new LegacyTestSingle<>(true);
    final ResponseSubscriber subscriber = new ResponseSubscriber();
    toSource(responseSingle.liftSync(new BeforeFinallyHttpOperator(beforeFinally, discardEventsAfterCancel))).subscribe(subscriber);
    assertThat("onSubscribe not called.", subscriber.cancellable, is(notNullValue()));
    responseSingle.onSuccess(reqRespFactory.ok().payloadBody(payload));
    verifyNoInteractions(beforeFinally);
    responseSingle.verifyNotCancelled();
    subscriber.verifyResponseReceived();
    subscriber.cancellable.cancel();
    verifyNoInteractions(beforeFinally);
    // We unconditionally cancel and let the original single handle the cancel post terminate
    responseSingle.verifyCancelled();
    assert subscriber.response != null;
    toSource(subscriber.response.payloadBody()).subscribe(payloadSubscriber);
    payload.onSubscribe(payloadSubscription);
    payloadSubscriber.awaitSubscription().request(MAX_VALUE);
    assertThat("Payload was prematurely cancelled", payloadSubscription.isCancelled(), is(false));
    payloadSubscriber.awaitSubscription().cancel();
    assertThat("Payload was not cancelled", payloadSubscription.isCancelled(), is(true));
    payload.onNext(EMPTY_BUFFER);
    if (payloadTerminal.cause() == null) {
        payload.onComplete();
    } else {
        payload.onError(payloadTerminal.cause());
    }
    if (discardEventsAfterCancel) {
        assertThat("Unexpected payload body items", payloadSubscriber.pollAllOnNext(), empty());
        assertThat("Payload body terminated unexpectedly", payloadSubscriber.pollTerminal(100, MILLISECONDS), is(nullValue()));
    } else {
        assertThat("Unexpected payload body items", payloadSubscriber.pollAllOnNext(), contains(EMPTY_BUFFER));
        if (payloadTerminal.cause() == null) {
            payloadSubscriber.awaitOnComplete();
        } else {
            assertThat(payloadSubscriber.awaitOnError(), is(DELIBERATE_EXCEPTION));
        }
    }
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) TestPublisherSubscriber(io.servicetalk.concurrent.test.internal.TestPublisherSubscriber) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) LegacyTestSingle(io.servicetalk.concurrent.api.LegacyTestSingle) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 4 with LegacyTestSingle

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

the class BeforeFinallyHttpOperatorTest method cancelWhileDeliveringPayloadThenTerminate.

@ParameterizedTest(name = "{displayName} [{index}] fromOnNext={0} payloadTerminal={1}")
@MethodSource("booleanTerminalNotification")
void cancelWhileDeliveringPayloadThenTerminate(boolean fromOnNext, TerminalNotification payloadTerminal) {
    TestPublisher<Buffer> payload = new TestPublisher.Builder<Buffer>().disableAutoOnSubscribe().build();
    TestSubscription payloadSubscription = new TestSubscription();
    LegacyTestSingle<StreamingHttpResponse> responseSingle = new LegacyTestSingle<>(true);
    final ResponseSubscriber subscriber = new ResponseSubscriber();
    toSource(responseSingle.liftSync(new BeforeFinallyHttpOperator(beforeFinally, true))).subscribe(subscriber);
    assertThat("onSubscribe not called.", subscriber.cancellable, is(notNullValue()));
    responseSingle.onSuccess(reqRespFactory.ok().payloadBody(payload));
    verifyNoInteractions(beforeFinally);
    responseSingle.verifyNotCancelled();
    subscriber.verifyResponseReceived();
    assert subscriber.response != null;
    BlockingQueue<Buffer> receivedPayload = new LinkedBlockingDeque<>();
    AtomicReference<TerminalNotification> subscriberTerminal = new AtomicReference<>();
    toSource(subscriber.response.payloadBody()).subscribe(new PublisherSource.Subscriber<Buffer>() {

        @Nullable
        private Subscription subscription;

        @Override
        public void onSubscribe(final Subscription subscription) {
            this.subscription = subscription;
            subscription.request(1L);
        }

        @Override
        public void onNext(@Nullable final Buffer buffer) {
            assert buffer != null;
            receivedPayload.add(buffer);
            if (fromOnNext) {
                assert subscription != null;
                subscription.cancel();
            }
            if (payloadTerminal.cause() == null) {
                payload.onComplete();
            } else {
                payload.onError(payloadTerminal.cause());
            }
        }

        @Override
        public void onError(final Throwable t) {
            subscriberTerminal.set(TerminalNotification.error(t));
            cancelFromTerminal();
        }

        @Override
        public void onComplete() {
            subscriberTerminal.set(TerminalNotification.complete());
            cancelFromTerminal();
        }

        private void cancelFromTerminal() {
            if (!fromOnNext) {
                assert subscription != null;
                subscription.cancel();
            }
        }
    });
    payload.onSubscribe(payloadSubscription);
    assertThat("Payload was prematurely cancelled", payloadSubscription.isCancelled(), is(false));
    payload.onNext(EMPTY_BUFFER);
    assertThat("Payload was not cancelled", payloadSubscription.isCancelled(), is(true));
    assertThat("Unexpected payload body items", receivedPayload, contains(EMPTY_BUFFER));
    assertThat("Unexpected payload body termination", subscriberTerminal.get(), equalTo(payloadTerminal));
    if (payloadTerminal.cause() == null) {
        verify(beforeFinally).onComplete();
    } else {
        verify(beforeFinally).onError(payloadTerminal.cause());
    }
    verifyNoMoreInteractions(beforeFinally);
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) PublisherSource(io.servicetalk.concurrent.PublisherSource) TerminalNotification(io.servicetalk.concurrent.internal.TerminalNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Nullable(javax.annotation.Nullable) LegacyTestSingle(io.servicetalk.concurrent.api.LegacyTestSingle) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 5 with LegacyTestSingle

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

the class BeforeFinallyHttpOperatorTest method cancelAfterOnNextThenTerminate.

@ParameterizedTest(name = "{displayName} [{index}] discardEventsAfterCancel={0} payloadTerminal={1}")
@MethodSource("booleanTerminalNotification")
void cancelAfterOnNextThenTerminate(boolean discardEventsAfterCancel, TerminalNotification payloadTerminal) {
    TestPublisher<Buffer> payload = new TestPublisher.Builder<Buffer>().disableAutoOnSubscribe().build();
    TestSubscription payloadSubscription = new TestSubscription();
    TestPublisherSubscriber<Buffer> payloadSubscriber = new TestPublisherSubscriber<>();
    LegacyTestSingle<StreamingHttpResponse> responseSingle = new LegacyTestSingle<>(true);
    final ResponseSubscriber subscriber = new ResponseSubscriber();
    toSource(responseSingle.liftSync(new BeforeFinallyHttpOperator(beforeFinally, discardEventsAfterCancel))).subscribe(subscriber);
    assertThat("onSubscribe not called.", subscriber.cancellable, is(notNullValue()));
    responseSingle.onSuccess(reqRespFactory.ok().payloadBody(payload));
    verifyNoInteractions(beforeFinally);
    responseSingle.verifyNotCancelled();
    subscriber.verifyResponseReceived();
    assert subscriber.response != null;
    toSource(subscriber.response.payloadBody()).subscribe(payloadSubscriber);
    payload.onSubscribe(payloadSubscription);
    payloadSubscriber.awaitSubscription().request(MAX_VALUE);
    payload.onNext(EMPTY_BUFFER);
    if (payloadTerminal.cause() == null) {
        payload.onComplete();
    } else {
        payload.onError(payloadTerminal.cause());
    }
    assertThat("Unexpected payload body items", payloadSubscriber.pollAllOnNext(), contains(EMPTY_BUFFER));
    if (payloadTerminal.cause() == null) {
        payloadSubscriber.awaitOnComplete();
    } else {
        assertThat(payloadSubscriber.awaitOnError(), is(DELIBERATE_EXCEPTION));
    }
    assertThat("Payload was prematurely cancelled", payloadSubscription.isCancelled(), is(false));
    payloadSubscriber.awaitSubscription().cancel();
    assertThat("Payload was not cancelled", payloadSubscription.isCancelled(), is(true));
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) TestSubscription(io.servicetalk.concurrent.api.TestSubscription) TestPublisherSubscriber(io.servicetalk.concurrent.test.internal.TestPublisherSubscriber) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) LegacyTestSingle(io.servicetalk.concurrent.api.LegacyTestSingle) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Aggregations

LegacyTestSingle (io.servicetalk.concurrent.api.LegacyTestSingle)8 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)6 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)6 Buffer (io.servicetalk.buffer.api.Buffer)5 TestSubscription (io.servicetalk.concurrent.api.TestSubscription)4 Test (org.junit.jupiter.api.Test)3 MethodSource (org.junit.jupiter.params.provider.MethodSource)3 PublisherSource (io.servicetalk.concurrent.PublisherSource)2 Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)2 DeliberateException (io.servicetalk.concurrent.internal.DeliberateException)2 TerminalNotification (io.servicetalk.concurrent.internal.TerminalNotification)2 TestPublisherSubscriber (io.servicetalk.concurrent.test.internal.TestPublisherSubscriber)2 LinkedBlockingDeque (java.util.concurrent.LinkedBlockingDeque)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Nullable (javax.annotation.Nullable)2 ValueSource (org.junit.jupiter.params.provider.ValueSource)2 TestPublisher (io.servicetalk.concurrent.api.TestPublisher)1 CancellationException (java.util.concurrent.CancellationException)1