use of io.servicetalk.concurrent.test.internal.TestPublisherSubscriber in project servicetalk by apple.
the class ScanWithPublisherTest method cancelStillAllowsMaps.
@ParameterizedTest(name = "{displayName} [{index}] {arguments}")
@MethodSource("cancelStillAllowsMapsParams")
void cancelStillAllowsMaps(boolean onError, boolean cancelBefore, boolean withLifetime) {
final AtomicInteger finalizations = new AtomicInteger(0);
TestPublisher<Integer> publisher = new TestPublisher<>();
TestPublisherSubscriber<Integer> subscriber = new TestPublisherSubscriber<>();
toSource(scanWithOperator(publisher, withLifetime, new ScanWithLifetimeMapper<Integer, Integer>() {
private int sum;
@Nullable
@Override
public Integer mapOnNext(@Nullable final Integer next) {
if (next != null) {
sum += next;
}
return next;
}
@Override
public Integer mapOnError(final Throwable cause) {
return sum;
}
@Override
public Integer mapOnComplete() {
return sum;
}
@Override
public boolean mapTerminal() {
return true;
}
@Override
public void afterFinally() {
finalizations.incrementAndGet();
}
})).subscribe(subscriber);
Subscription s = subscriber.awaitSubscription();
if (cancelBefore) {
s.request(4);
s.cancel();
} else {
s.request(3);
}
publisher.onNext(1, 2, 3);
if (!cancelBefore) {
s.cancel();
s.request(1);
}
if (onError) {
publisher.onError(DELIBERATE_EXCEPTION);
} else {
publisher.onComplete();
}
if (!withLifetime) {
assertThat(subscriber.takeOnNext(4), contains(1, 2, 3, 6));
subscriber.awaitOnComplete();
}
if (withLifetime) {
assertThat(finalizations.get(), is(1));
}
}
use of io.servicetalk.concurrent.test.internal.TestPublisherSubscriber in project servicetalk by apple.
the class PublisherProcessorConcurrencyTest method concurrentEmissionAndConsumption.
@Test
void concurrentEmissionAndConsumption() throws Exception {
final int items = 10_000;
final Collection<Integer> expected = Publisher.range(0, items).toFuture().get();
final CountDownLatch done = new CountDownLatch(1);
PublisherSource.Processor<Integer, Integer> processor = newPublisherProcessor(fixedSize(items));
TestPublisherSubscriber<Integer> subscriber = new TestPublisherSubscriber<>();
toSource(fromSource(processor).afterFinally(done::countDown)).subscribe(subscriber);
CyclicBarrier barrier = new CyclicBarrier(2);
Future<Object> producerFuture = executorService.submit(() -> {
barrier.await();
for (int i = 0; i < items; i++) {
processor.onNext(i);
}
processor.onComplete();
return null;
});
Future<Object> requesterFuture = executorService.submit(() -> {
barrier.await();
for (int i = 0; i < items; i++) {
subscriber.awaitSubscription().request(1);
}
return null;
});
producerFuture.get();
requesterFuture.get();
done.await();
assertThat(subscriber.takeOnNext(expected.size()), contains(expected.toArray()));
subscriber.awaitOnComplete();
}
use of io.servicetalk.concurrent.test.internal.TestPublisherSubscriber 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.test.internal.TestPublisherSubscriber in project servicetalk by apple.
the class MulticastExactlyPublisherTest method concurrentRequestN.
@Test
void concurrentRequestN() throws InterruptedException {
final int expectedSubscribers = 50;
Publisher<Integer> multicast = source.multicastToExactly(expectedSubscribers, expectedSubscribers);
@SuppressWarnings("unchecked") TestPublisherSubscriber<Integer>[] subscribers = (TestPublisherSubscriber<Integer>[]) new TestPublisherSubscriber[expectedSubscribers];
final int expectedSubscribersMinus1 = expectedSubscribers - 1;
for (int i = 0; i < expectedSubscribersMinus1; ++i) {
subscribers[i] = new TestPublisherSubscriber<>();
toSource(multicast).subscribe(subscribers[i]);
}
subscribers[expectedSubscribersMinus1] = new TestPublisherSubscriber<>();
toSource(multicast).subscribe(subscribers[expectedSubscribersMinus1]);
for (int i = 0; i < expectedSubscribersMinus1; ++i) {
subscribers[i].awaitSubscription();
}
source.onSubscribe(subscription);
ExecutorService executorService = new ThreadPoolExecutor(0, expectedSubscribers, 1, SECONDS, new SynchronousQueue<>());
try {
CyclicBarrier barrier = new CyclicBarrier(expectedSubscribers);
CountDownLatch doneLatch = new CountDownLatch(expectedSubscribers);
AtomicReference<Throwable> throwableRef = new AtomicReference<>();
for (int i = 1; i <= expectedSubscribers; ++i) {
executorService.execute(requestIRunnable(subscribers, i, barrier, throwableRef, doneLatch));
}
doneLatch.await();
assertThat(throwableRef.get(), is(nullValue()));
assertThat(subscription.requested(), is(1L));
assertThat(subscription.isCancelled(), is(false));
} finally {
executorService.shutdown();
}
}
use of io.servicetalk.concurrent.test.internal.TestPublisherSubscriber in project servicetalk by apple.
the class DefaultAsyncContextProviderTest method testSubscriptionIsWrapped.
@Test
void testSubscriptionIsWrapped() throws Exception {
TestSubscription testSubscription = new TestSubscription();
TestPublisherSubscriber<Integer> testSubscriber = new TestPublisherSubscriber<>();
TestPublisher<Integer> testPublisher = new TestPublisher.Builder<Integer>().disableAutoOnSubscribe().build(sub -> {
sub.onSubscribe(testSubscription);
return sub;
});
toSource(testPublisher.map(x -> {
AsyncContext.put(K1, "v1");
return x;
}).liftSync((PublisherOperator<Integer, Integer>) subscriber -> new Subscriber<Integer>() {
@Nullable
private Subscription upstreamSubscription;
private boolean isSubscribed;
private boolean queuedItemDelivered;
@Nullable
private Integer queuedItem;
@Override
public void onSubscribe(final Subscription subscription) {
assert upstreamSubscription == null;
upstreamSubscription = subscription;
subscription.request(1);
}
@Override
public void onNext(@Nullable final Integer integer) {
if (isSubscribed) {
subscriber.onNext(integer);
} else {
queuedItem = integer;
trySubscribeToQueue();
}
}
@Override
public void onError(final Throwable t) {
trySubscribeToQueue();
subscriber.onError(t);
}
@Override
public void onComplete() {
trySubscribeToQueue();
subscriber.onComplete();
}
private void trySubscribeToQueue() {
assert upstreamSubscription != null;
if (isSubscribed) {
return;
}
isSubscribed = true;
subscriber.onSubscribe(new Subscription() {
@Override
public void request(final long n) {
if (!SubscriberUtils.isRequestNValid(n)) {
upstreamSubscription.request(n);
return;
}
if (!queuedItemDelivered) {
queuedItemDelivered = true;
subscriber.onNext(queuedItem);
if (n > 1) {
upstreamSubscription.request(n - 1);
}
} else {
upstreamSubscription.request(n);
}
}
@Override
public void cancel() {
upstreamSubscription.cancel();
}
});
}
}).map(x -> {
assertEquals("v1", AsyncContext.get(K1));
return x;
})).subscribe(testSubscriber);
// Operator delivers demand before giving the Subscription downstream, wait for implicit demand first.
testSubscription.awaitRequestN(1);
testPublisher.onNext(1);
Subscription subscription = testSubscriber.awaitSubscription();
executor.submit(() -> {
try {
subscription.request(1);
} catch (Throwable cause) {
testPublisher.onError(cause);
}
}).get();
testPublisher.onComplete();
assertThat(testSubscriber.takeOnNext(), is(1));
testSubscriber.awaitOnComplete();
}
Aggregations