Beispiel #1
0
 /**
  * https://github.com/ReactiveX/RxJava/issues/198
  *
  * <p>Rx Design Guidelines 5.2
  *
  * <p>"when calling the Subscribe method that only has an onNext argument, the OnError behavior
  * will be to rethrow the exception on the thread that the message comes out from the Observable.
  * The OnCompleted behavior in this case is to do nothing."
  *
  * @throws InterruptedException
  */
 @Test
 @Ignore("Subscribers can't throw")
 public void testErrorThrownWithoutErrorHandlerAsynchronous() throws InterruptedException {
   final CountDownLatch latch = new CountDownLatch(1);
   final AtomicReference<Throwable> exception = new AtomicReference<>();
   Observable.create(
           observer -> {
             new Thread(
                     () -> {
                       try {
                         observer.onError(new Error("failure"));
                       } catch (Throwable e) {
                         // without an onError handler it has to just throw on whatever thread
                         // invokes it
                         exception.set(e);
                       }
                       latch.countDown();
                     })
                 .start();
           })
       .subscribe();
   // wait for exception
   latch.await(3000, TimeUnit.MILLISECONDS);
   assertNotNull(exception.get());
   assertEquals("failure", exception.get().getMessage());
 }
 /**
  * Incrementing int without backpressure.
  *
  * @param counter
  * @return
  */
 private static Observable<Integer> firehose(final AtomicInteger counter) {
   return Observable.create(
       s -> {
         Subscription s2 = new FirehoseNoBackpressure(counter, s);
         s.onSubscribe(s2);
       });
 }
Beispiel #3
0
  @Test
  public void testPublishLast() throws InterruptedException {
    final AtomicInteger count = new AtomicInteger();
    ConnectableObservable<String> connectable =
        Observable.<String>create(
                observer -> {
                  observer.onSubscribe(EmptySubscription.INSTANCE);
                  count.incrementAndGet();
                  new Thread(
                          () -> {
                            observer.onNext("first");
                            observer.onNext("last");
                            observer.onComplete();
                          })
                      .start();
                })
            .takeLast(1)
            .publish();

    // subscribe once
    final CountDownLatch latch = new CountDownLatch(1);
    connectable.subscribe(
        value -> {
          assertEquals("last", value);
          latch.countDown();
        });

    // subscribe twice
    connectable.subscribe();

    Disposable subscription = connectable.connect();
    assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
    assertEquals(1, count.get());
    subscription.dispose();
  }
Beispiel #4
0
  @Test
  public void testReplay() throws InterruptedException {
    final AtomicInteger counter = new AtomicInteger();
    ConnectableObservable<String> o =
        Observable.<String>create(
                observer -> {
                  observer.onSubscribe(EmptySubscription.INSTANCE);
                  new Thread(
                          new Runnable() {

                            @Override
                            public void run() {
                              counter.incrementAndGet();
                              observer.onNext("one");
                              observer.onComplete();
                            }
                          })
                      .start();
                })
            .replay();

    // we connect immediately and it will emit the value
    Disposable s = o.connect();
    try {

      // we then expect the following 2 subscriptions to get that same value
      final CountDownLatch latch = new CountDownLatch(2);

      // subscribe once
      o.subscribe(
          v -> {
            assertEquals("one", v);
            latch.countDown();
          });

      // subscribe again
      o.subscribe(
          v -> {
            assertEquals("one", v);
            latch.countDown();
          });

      if (!latch.await(1000, TimeUnit.MILLISECONDS)) {
        fail("subscriptions did not receive values");
      }
      assertEquals(1, counter.get());
    } finally {
      s.dispose();
    }
  }
  /**
   * Incrementing int without backpressure.
   *
   * @param counter
   * @return
   */
  private static Observable<Integer> firehose(final AtomicInteger counter) {
    return Observable.create(
        new OnSubscribe<Integer>() {

          int i = 0;

          @Override
          public void call(final Subscriber<? super Integer> s) {
            while (!s.isUnsubscribed()) {
              s.onNext(i++);
              counter.incrementAndGet();
            }
            System.out.println("unsubscribed after: " + i);
          }
        });
  }
Beispiel #6
0
  @Ignore // FIXME throwing is not allowed from the create?!
  @Test
  public void testOnSubscribeFails() {
    Subscriber<String> observer = TestHelper.mockSubscriber();

    final RuntimeException re = new RuntimeException("bad impl");
    Observable<String> o =
        Observable.create(
            s -> {
              throw re;
            });

    o.subscribe(observer);
    verify(observer, times(0)).onNext(anyString());
    verify(observer, times(0)).onComplete();
    verify(observer, times(1)).onError(re);
  }
  private static Observable<Integer> incrementingIntegers(
      final AtomicInteger counter, final ConcurrentLinkedQueue<Thread> threadsSeen) {
    return Observable.create(
        new Publisher<Integer>() {

          @Override
          public void subscribe(final Subscriber<? super Integer> s) {
            s.onSubscribe(
                new Subscription() {
                  int i = 0;

                  volatile boolean cancelled;

                  final AtomicLong requested = new AtomicLong();

                  @Override
                  public void request(long n) {
                    if (SubscriptionHelper.validateRequest(n)) {
                      return;
                    }
                    if (threadsSeen != null) {
                      threadsSeen.offer(Thread.currentThread());
                    }
                    long _c = BackpressureHelper.add(requested, n);
                    if (_c == 0) {
                      while (!cancelled) {
                        counter.incrementAndGet();
                        s.onNext(i++);
                        if (requested.decrementAndGet() == 0) {
                          // we're done emitting the number requested so return
                          return;
                        }
                      }
                    }
                  }

                  @Override
                  public void cancel() {
                    cancelled = true;
                  }
                });
          }
        });
  }
  @Test
  public void testRequestToObservable() {
    TestSubscriber<Integer> ts = new TestSubscriber<>();
    ts.request(3);
    final AtomicLong requested = new AtomicLong();
    Observable.<Integer>create(
            s ->
                s.onSubscribe(
                    new Subscription() {

                      @Override
                      public void request(long n) {
                        requested.set(n);
                      }

                      @Override
                      public void cancel() {}
                    }))
        .subscribe(ts);
    assertEquals(3, requested.get());
  }
Beispiel #9
0
  @Test
  public void testCacheWithCapacity() throws InterruptedException {
    final AtomicInteger counter = new AtomicInteger();
    Observable<String> o =
        Observable.<String>create(
                observer -> {
                  observer.onSubscribe(EmptySubscription.INSTANCE);
                  new Thread(
                          () -> {
                            counter.incrementAndGet();
                            observer.onNext("one");
                            observer.onComplete();
                          })
                      .start();
                })
            .cache(1);

    // we then expect the following 2 subscriptions to get that same value
    final CountDownLatch latch = new CountDownLatch(2);

    // subscribe once
    o.subscribe(
        v -> {
          assertEquals("one", v);
          latch.countDown();
        });

    // subscribe again
    o.subscribe(
        v -> {
          assertEquals("one", v);
          latch.countDown();
        });

    if (!latch.await(1000, TimeUnit.MILLISECONDS)) {
      fail("subscriptions did not receive values");
    }
    assertEquals(1, counter.get());
  }
  @Test
  public void testRequestThroughTakeWhereRequestIsSmallerThanTake() {
    TestSubscriber<Integer> ts = new TestSubscriber<>((Long) null);
    ts.request(3);
    final AtomicLong requested = new AtomicLong();
    Observable.<Integer>create(
            s ->
                s.onSubscribe(
                    new Subscription() {

                      @Override
                      public void request(long n) {
                        requested.set(n);
                      }

                      @Override
                      public void cancel() {}
                    }))
        .take(10)
        .subscribe(ts);
    assertEquals(3, requested.get());
  }
  private static Observable<Integer> incrementingIntegers(
      final AtomicInteger counter, final ConcurrentLinkedQueue<Thread> threadsSeen) {
    return Observable.create(
        new OnSubscribe<Integer>() {

          final AtomicLong requested = new AtomicLong();

          @Override
          public void call(final Subscriber<? super Integer> s) {
            s.setProducer(
                new Producer() {
                  int i = 0;

                  @Override
                  public void request(long n) {
                    if (n == 0) {
                      // nothing to do
                      return;
                    }
                    if (threadsSeen != null) {
                      threadsSeen.offer(Thread.currentThread());
                    }
                    long _c = requested.getAndAdd(n);
                    if (_c == 0) {
                      while (!s.isUnsubscribed()) {
                        counter.incrementAndGet();
                        s.onNext(i++);
                        if (requested.decrementAndGet() == 0) {
                          // we're done emitting the number requested so return
                          return;
                        }
                      }
                    }
                  }
                });
          }
        });
  }
  @Test
  public void testRequestThroughTakeThatReducesRequest() {
    TestSubscriber<Integer> ts = new TestSubscriber<>((Long) null);
    ts.request(3);
    final AtomicLong requested = new AtomicLong();
    Observable.<Integer>create(
            s ->
                s.onSubscribe(
                    new Subscription() {

                      @Override
                      public void request(long n) {
                        requested.set(n);
                      }

                      @Override
                      public void cancel() {}
                    }))
        .take(2)
        .subscribe(ts);

    // FIXME the take now requests Long.MAX_PATH if downstream requests at least the limit
    assertEquals(Long.MAX_VALUE, requested.get());
  }