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);
}
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);
}
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));
}
}
}
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);
}
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));
}
Aggregations