Search in sources :

Example 96 with Subscriber

use of org.reactivestreams.Subscriber in project reactive-streams-jvm by reactive-streams.

the class PublisherVerificationTest method demandIgnoringAsynchronousPublisherVerification.

/**
 * Verification using a Publisher that publishes elements even with no demand available, from multiple threads (!).
 */
final PublisherVerification<Integer> demandIgnoringAsynchronousPublisherVerification(final ExecutorService signallersPool, final boolean swallowOnNextExceptions) {
    final AtomicInteger startedSignallingThreads = new AtomicInteger(0);
    final int maxSignallingThreads = 2;
    final AtomicBoolean concurrentAccessCaused = new AtomicBoolean(false);
    return new PublisherVerification<Integer>(newTestEnvironment()) {

        @Override
        public Publisher<Integer> createPublisher(long elements) {
            return new Publisher<Integer>() {

                @Override
                public void subscribe(final Subscriber<? super Integer> s) {
                    s.onSubscribe(new NoopSubscription() {

                        @Override
                        public void request(final long n) {
                            Runnable signalling = new Runnable() {

                                @Override
                                public void run() {
                                    for (long i = 0; i <= n; i++) {
                                        try {
                                            final long signal = i;
                                            signallersPool.execute(new Runnable() {

                                                @Override
                                                public void run() {
                                                    try {
                                                        s.onNext((int) signal);
                                                    } catch (Exception ex) {
                                                        if (!swallowOnNextExceptions) {
                                                            throw new RuntimeException("onNext threw an exception!", ex);
                                                        } else {
                                                        // yes, swallow the exception, we're not asserting and they'd just end up being logged (stdout),
                                                        // which we do not need in this specific PublisherVerificationTest
                                                        }
                                                    }
                                                }
                                            });
                                        } catch (Exception ex) {
                                            if (ex instanceof TestEnvironment.Latch.ExpectedOpenLatchException) {
                                                if (concurrentAccessCaused.compareAndSet(false, true)) {
                                                    throw new RuntimeException("Concurrent access detected", ex);
                                                } else {
                                                    // error signalled once already, stop more errors from propagating
                                                    return;
                                                }
                                            } else if (ex instanceof RejectedExecutionException) {
                                            // ignore - this may happen since one thread may have already gotten into a concurrent access
                                            // problem and initiated the pool's shutdown. It will then throw RejectedExecutionException.
                                            } else {
                                                if (concurrentAccessCaused.get()) {
                                                    return;
                                                } else {
                                                    throw new RuntimeException(ex);
                                                }
                                            }
                                        }
                                    }
                                }
                            };
                            // must be guarded like this in case a Subscriber triggers request() synchronously from it's onNext()
                            while (startedSignallingThreads.getAndAdd(1) < maxSignallingThreads) {
                                signallersPool.execute(signalling);
                            }
                        }
                    });
                }
            };
        }

        @Override
        public Publisher<Integer> createFailedPublisher() {
            return SKIP;
        }
    };
}
Also used : Publisher(org.reactivestreams.Publisher) TestException(org.reactivestreams.tck.flow.support.TestException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Subscriber(org.reactivestreams.Subscriber)

Example 97 with Subscriber

use of org.reactivestreams.Subscriber in project reactive-streams-jvm by reactive-streams.

the class PublisherVerificationTest method required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue_forSynchronousPublisher.

@Test
public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue_forSynchronousPublisher() throws Throwable {
    final AtomicInteger sent = new AtomicInteger();
    customPublisherVerification(new Publisher<Integer>() {

        @Override
        public void subscribe(final Subscriber<? super Integer> downstream) {
            downstream.onSubscribe(new Subscription() {

                boolean started;

                boolean cancelled;

                @Override
                public void request(long n) {
                    if (!started) {
                        started = true;
                        while (!cancelled) {
                            downstream.onNext(sent.getAndIncrement());
                        }
                    }
                }

                @Override
                public void cancel() {
                    cancelled = true;
                }
            });
        }
    }).required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue();
    // 11 due to the implementation of this particular TCK test (see impl)
    Assert.assertEquals(sent.get(), 11);
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Subscriber(org.reactivestreams.Subscriber) Publisher(org.reactivestreams.Publisher) Subscription(org.reactivestreams.Subscription) Test(org.testng.annotations.Test)

Example 98 with Subscriber

use of org.reactivestreams.Subscriber in project reactive-streams-jvm by reactive-streams.

the class PublisherVerificationTest method stochastic_spec103_mustSignalOnMethodsSequentially_shouldFailBy_concurrentlyAccessingOnNext.

@Test
public void stochastic_spec103_mustSignalOnMethodsSequentially_shouldFailBy_concurrentlyAccessingOnNext() throws Throwable {
    final AtomicInteger startedSignallingThreads = new AtomicInteger(0);
    // this is an arbitrary number, we just need "many threads" to try to force an concurrent access scenario
    final int maxSignallingThreads = 10;
    final ExecutorService signallersPool = Executors.newFixedThreadPool(maxSignallingThreads);
    final AtomicBoolean concurrentAccessCaused = new AtomicBoolean(false);
    // highly specialised threadpool driven publisher which aims to FORCE concurrent access,
    // so that we can confirm the test is able to catch this.
    final Publisher<Integer> concurrentAccessPublisher = new Publisher<Integer>() {

        @Override
        public void subscribe(final Subscriber<? super Integer> s) {
            s.onSubscribe(new NoopSubscription() {

                @Override
                public void request(final long n) {
                    Runnable signalling = new Runnable() {

                        @Override
                        public void run() {
                            for (long i = 0; i < n; i++) {
                                try {
                                    // shutdown cleanly in when the threadpool is shutting down
                                    if (Thread.interrupted()) {
                                        return;
                                    }
                                    s.onNext((int) i);
                                } catch (Exception ex) {
                                    // signal others to shut down
                                    signallersPool.shutdownNow();
                                    if (ex instanceof TestEnvironment.Latch.ExpectedOpenLatchException) {
                                        if (!concurrentAccessCaused.getAndSet(true)) {
                                            throw new RuntimeException("Concurrent access detected", ex);
                                        } else {
                                            // error signalled once already, stop more errors from propagating
                                            return;
                                        }
                                    } else {
                                        throw new RuntimeException(ex);
                                    }
                                }
                            }
                        }
                    };
                    // must be guarded like this in case a Subscriber triggers request() synchronously from it's onNext()
                    while (startedSignallingThreads.getAndAdd(1) < maxSignallingThreads && !signallersPool.isShutdown()) {
                        try {
                            signallersPool.execute(signalling);
                        } catch (RejectedExecutionException ex) {
                            // ignore, should be safe as it means the pool is shutting down -> which means we triggered the problem we wanted to
                            return;
                        }
                    }
                }
            });
        }
    };
    try {
        requireTestFailure(new ThrowingRunnable() {

            @Override
            public void run() throws Throwable {
                customPublisherVerification(concurrentAccessPublisher).stochastic_spec103_mustSignalOnMethodsSequentially();
            }
        }, "Illegal concurrent access detected");
    } finally {
        signallersPool.shutdownNow();
        signallersPool.awaitTermination(1, TimeUnit.SECONDS);
    }
}
Also used : Publisher(org.reactivestreams.Publisher) TestException(org.reactivestreams.tck.flow.support.TestException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Subscriber(org.reactivestreams.Subscriber) ExecutorService(java.util.concurrent.ExecutorService) Test(org.testng.annotations.Test)

Example 99 with Subscriber

use of org.reactivestreams.Subscriber in project reactive-streams-jvm by reactive-streams.

the class PublisherVerificationTest method multiSubscribersPublisherVerification.

/**
 * Verification using a Publisher that supports multiple subscribers
 * @param shouldBlowUp if true {@link RuntimeException} will be thrown during second subscription.
 */
final PublisherVerification<Integer> multiSubscribersPublisherVerification(final boolean shouldBlowUp) {
    return new PublisherVerification<Integer>(newTestEnvironment()) {

        @Override
        public Publisher<Integer> createPublisher(final long elements) {
            return new Publisher<Integer>() {

                private final Collection<CancelableSubscription> subscriptions = new CopyOnWriteArrayList<CancelableSubscription>();

                private final AtomicLong source = new AtomicLong(elements);

                @Override
                public void subscribe(Subscriber<? super Integer> s) {
                    // onSubscribe first
                    CancelableSubscription subscription = new CancelableSubscription(s);
                    s.onSubscribe(subscription);
                    if (shouldBlowUp && !subscriptions.isEmpty()) {
                        s.onError(new RuntimeException("Unexpected additional subscriber"));
                    } else {
                        subscriptions.add(subscription);
                    }
                }

                class CancelableSubscription implements Subscription {

                    final AtomicBoolean canceled = new AtomicBoolean();

                    Subscriber<? super Integer> subscriber;

                    CancelableSubscription(Subscriber<? super Integer> subscriber) {
                        this.subscriber = subscriber;
                    }

                    @Override
                    public void request(long n) {
                        if (!canceled.get()) {
                            for (long i = 0; i < n; i++) {
                                if (source.getAndDecrement() < 0) {
                                    canceled.set(true);
                                    subscriber.onComplete();
                                } else {
                                    subscriber.onNext((int) i);
                                }
                            }
                        }
                    }

                    @Override
                    public void cancel() {
                        canceled.set(true);
                        subscriber = null;
                        subscriptions.remove(this);
                    }
                }
            };
        }

        @Override
        public Publisher<Integer> createFailedPublisher() {
            return SKIP;
        }
    };
}
Also used : Publisher(org.reactivestreams.Publisher) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicLong(java.util.concurrent.atomic.AtomicLong) Subscriber(org.reactivestreams.Subscriber) Collection(java.util.Collection)

Example 100 with Subscriber

use of org.reactivestreams.Subscriber in project cyclops by aol.

the class IterableFlatMapTest method flatMapAsyncRS.

@Test
public void flatMapAsyncRS() {
    for (int k = 0; k < 1000; k++) {
        complete = new AtomicBoolean(false);
        count = new AtomicInteger(0);
        ReactiveSubscriber<Integer> sub = Spouts.reactiveSubscriber();
        Spouts.of(1, 2, 3).peek(System.out::println).concatMap(i -> nextAsyncRS()).subscribe(new Subscriber<Integer>() {

            @Override
            public void onSubscribe(Subscription s) {
                subs = s;
            }

            @Override
            public void onNext(Integer integer) {
                System.out.println("RECIEVED " + integer);
                assertThat(integer, Matchers.isOneOf(1, 2));
                System.out.println("count " + count.incrementAndGet());
            }

            @Override
            public void onError(Throwable t) {
            }

            @Override
            public void onComplete() {
                complete.set(true);
            }
        });
        subs.request(Long.MAX_VALUE);
        while (!complete.get()) {
        }
        assertThat(count.get(), equalTo(6));
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Maybe(cyclops.control.Maybe) Arrays(java.util.Arrays) Spouts.of(cyclops.reactive.Spouts.of) Spouts(cyclops.reactive.Spouts) ReactiveSubscriber(com.oath.cyclops.types.reactive.ReactiveSubscriber) CoreMatchers.equalTo(org.hamcrest.CoreMatchers.equalTo) Matchers(org.hamcrest.Matchers) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Test(org.junit.Test) Collectors(java.util.stream.Collectors) Matchers.hasItems(org.hamcrest.Matchers.hasItems) ReactiveSeq(cyclops.reactive.ReactiveSeq) Flux(reactor.core.publisher.Flux) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ForkJoinPool(java.util.concurrent.ForkJoinPool) Subscription(org.reactivestreams.Subscription) Schedulers(reactor.core.scheduler.Schedulers) AsyncSubscriber(com.oath.cyclops.types.reactive.AsyncSubscriber) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assert(org.junit.Assert) Subscriber(org.reactivestreams.Subscriber) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Subscription(org.reactivestreams.Subscription) Test(org.junit.Test)

Aggregations

Subscriber (org.reactivestreams.Subscriber)104 Subscription (org.reactivestreams.Subscription)67 Test (org.junit.Test)56 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)34 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)29 List (java.util.List)26 Publisher (org.reactivestreams.Publisher)23 ProtonClient (io.vertx.proton.ProtonClient)22 ProtonConnection (io.vertx.proton.ProtonConnection)22 Message (org.apache.qpid.proton.message.Message)20 Arrays (java.util.Arrays)18 AtomicReference (java.util.concurrent.atomic.AtomicReference)18 AmqpValue (org.apache.qpid.proton.amqp.messaging.AmqpValue)18 ArrayList (java.util.ArrayList)17 Handler (io.vertx.core.Handler)16 Logger (io.vertx.core.impl.logging.Logger)16 LoggerFactory (io.vertx.core.impl.logging.LoggerFactory)16 ProtonStreams (io.vertx.proton.streams.ProtonStreams)16 ExecutionException (java.util.concurrent.ExecutionException)16 Symbol (org.apache.qpid.proton.amqp.Symbol)16