Example #1
0
  @Test
  public void testMergeAsyncThenObserveOnLoop() {
    for (int i = 0; i < 500; i++) {
      if (i % 10 == 0) {
        System.out.println("testMergeAsyncThenObserveOnLoop >> " + i);
      }
      // Verify there is no MissingBackpressureException
      int NUM = (int) (RxRingBuffer.SIZE * 4.1);
      AtomicInteger c1 = new AtomicInteger();
      AtomicInteger c2 = new AtomicInteger();

      TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
      Observable<Integer> merged =
          Observable.merge(
              incrementingIntegers(c1).subscribeOn(Schedulers.computation()),
              incrementingIntegers(c2).subscribeOn(Schedulers.computation()));

      merged.observeOn(Schedulers.io()).take(NUM).subscribe(ts);
      ts.awaitTerminalEvent();
      ts.assertNoErrors();
      System.out.println(
          "testMergeAsyncThenObserveOn => Received: "
              + ts.getOnNextEvents().size()
              + "  Emitted: "
              + c1.get()
              + " / "
              + c2.get());
      assertEquals(NUM, ts.getOnNextEvents().size());
    }
  }
Example #2
0
  @Test
  public void testMergeAsync() {
    int NUM = (int) (RxRingBuffer.SIZE * 4.1);
    AtomicInteger c1 = new AtomicInteger();
    AtomicInteger c2 = new AtomicInteger();
    TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
    Observable<Integer> merged =
        Observable.merge(
            incrementingIntegers(c1).subscribeOn(Schedulers.computation()),
            incrementingIntegers(c2).subscribeOn(Schedulers.computation()));

    merged.take(NUM).subscribe(ts);
    ts.awaitTerminalEvent();
    ts.assertNoErrors();
    System.out.println(
        "testMergeAsync => Received: "
            + ts.getOnNextEvents().size()
            + "  Emitted: "
            + c1.get()
            + " / "
            + c2.get());
    assertEquals(NUM, ts.getOnNextEvents().size());
    // either one can starve the other, but neither should be capable of doing more than 5 batches
    // (taking 4.1)
    // TODO is it possible to make this deterministic rather than one possibly starving the other?
    // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair"
    // algoritms generally take a performance hit
    assertTrue(c1.get() < RxRingBuffer.SIZE * 5);
    assertTrue(c2.get() < RxRingBuffer.SIZE * 5);
  }
Example #3
0
  @Test
  public void testMergeAsyncThenObserveOn() {
    int NUM = (int) (RxRingBuffer.SIZE * 4.1);
    AtomicInteger c1 = new AtomicInteger();
    AtomicInteger c2 = new AtomicInteger();
    TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
    Observable<Integer> merged =
        Observable.merge(
            incrementingIntegers(c1).subscribeOn(Schedulers.computation()),
            incrementingIntegers(c2).subscribeOn(Schedulers.computation()));

    merged.observeOn(Schedulers.newThread()).take(NUM).subscribe(ts);
    ts.awaitTerminalEvent();
    ts.assertNoErrors();
    System.out.println(
        "testMergeAsyncThenObserveOn => Received: "
            + ts.getOnNextEvents().size()
            + "  Emitted: "
            + c1.get()
            + " / "
            + c2.get());
    assertEquals(NUM, ts.getOnNextEvents().size());
    // either one can starve the other, but neither should be capable of doing more than 5 batches
    // (taking 4.1)
    // TODO is it possible to make this deterministic rather than one possibly starving the other?
    // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair"
    // algoritms generally take a performance hit
    // akarnokd => run this in a loop over 10k times and never saw values get as high as 7*SIZE, but
    // since observeOn delays the unsubscription non-deterministically, the test will remain
    // unreliable
    assertTrue(c1.get() < RxRingBuffer.SIZE * 7);
    assertTrue(c2.get() < RxRingBuffer.SIZE * 7);
  }
Example #4
0
  @Test
  public void testZipAsync() {
    int NUM = (int) (RxRingBuffer.SIZE * 2.1);
    AtomicInteger c1 = new AtomicInteger();
    AtomicInteger c2 = new AtomicInteger();
    TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
    Observable<Integer> zipped =
        Observable.zip(
            incrementingIntegers(c1).subscribeOn(Schedulers.computation()),
            incrementingIntegers(c2).subscribeOn(Schedulers.computation()),
            new Func2<Integer, Integer, Integer>() {

              @Override
              public Integer call(Integer t1, Integer t2) {
                return t1 + t2;
              }
            });

    zipped.take(NUM).subscribe(ts);
    ts.awaitTerminalEvent();
    ts.assertNoErrors();
    System.out.println(
        "testZipAsync => Received: "
            + ts.getOnNextEvents().size()
            + "  Emitted: "
            + c1.get()
            + " / "
            + c2.get());
    assertEquals(NUM, ts.getOnNextEvents().size());
    assertTrue(c1.get() < RxRingBuffer.SIZE * 3);
    assertTrue(c2.get() < RxRingBuffer.SIZE * 3);
  }
Example #5
0
  @Setup
  public void setup() {
    source = Single.just(1);

    flatmapped =
        source.flatMap(
            new Func1<Integer, Single<Integer>>() {
              @Override
              public Single<Integer> call(Integer t) {
                return Single.just(t);
              }
            });

    flatmapped =
        source.flatMap(
            new Func1<Integer, Single<Integer>>() {
              @Override
              public Single<Integer> call(Integer t) {
                return source;
              }
            });

    sourceObserveOn = source.observeOn(Schedulers.computation());

    sourceSubscribeOn = source.subscribeOn(Schedulers.computation());

    // ----------

    scheduledExecutor = Executors.newScheduledThreadPool(1);

    Scheduler s = Schedulers.from(scheduledExecutor);

    sourceObserveOnScheduledExecutor = source.observeOn(s);

    sourceSubscribeOnScheduledExecutor = source.subscribeOn(s);

    // ----------

    executor = Executors.newSingleThreadExecutor();

    Scheduler se = Schedulers.from(executor);

    sourceObserveOnExecutor = source.observeOn(se);

    sourceSubscribeOnExecutor = source.subscribeOn(se);

    // --------

    //        Scheduler fj = Schedulers.from(ForkJoinPool.commonPool());

    //        sourceObserveOnFJ = source.observeOn(fj);

    //        sourceSubscribeOnFJ = source.subscribeOn(fj);
  }
  @Test
  public void testInterruptTerminalEventAwaitTimed() {
    TestSubscriber<Integer> ts = TestSubscriber.create();

    final Thread t0 = Thread.currentThread();
    Worker w = Schedulers.computation().createWorker();
    try {
      w.schedule(
          new Action0() {
            @Override
            public void call() {
              t0.interrupt();
            }
          },
          200,
          TimeUnit.MILLISECONDS);

      try {
        ts.awaitTerminalEvent(5, TimeUnit.SECONDS);
        fail("Did not interrupt wait!");
      } catch (RuntimeException ex) {
        if (!(ex.getCause() instanceof InterruptedException)) {
          fail("The cause is not InterruptedException! " + ex.getCause());
        }
      }
    } finally {
      w.unsubscribe();
    }
  }
  private HttpImageGetter continueBind(final TextView view, final String html, final Object id) {
    CharSequence encoded = HtmlUtils.encode(html, loading);
    if (containsImages(html)) rawHtmlCache.put(id, encoded);
    else {
      rawHtmlCache.remove(id);
      fullHtmlCache.put(id, encoded);
      return show(view, encoded);
    }

    if (TextUtils.isEmpty(encoded)) return hide(view);

    show(view, encoded);
    view.setTag(id);
    Observable.just(html)
        .subscribeOn(Schedulers.computation())
        .map(
            new Func1<String, CharSequence>() {
              @Override
              public CharSequence call(String htmlString) {
                return HtmlUtils.encode(htmlString, HttpImageGetter.this);
              }
            })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            new ObserverAdapter<CharSequence>() {
              @Override
              public void onNext(CharSequence htmlCharSequence) {
                fullHtmlCache.put(id, htmlCharSequence);
                if (id.equals(view.getTag())) {
                  show(view, htmlCharSequence);
                }
              }
            });
    return this;
  }
  @Test
  public void testInterruptTerminalEventAwaitAndUnsubscribe() {
    TestSubscriber<Integer> ts = TestSubscriber.create();

    final Thread t0 = Thread.currentThread();
    Worker w = Schedulers.computation().createWorker();
    try {
      w.schedule(
          new Action0() {
            @Override
            public void call() {
              t0.interrupt();
            }
          },
          200,
          TimeUnit.MILLISECONDS);

      ts.awaitTerminalEventAndUnsubscribeOnTimeout(5, TimeUnit.SECONDS);
      if (!ts.isUnsubscribed()) {
        fail("Did not unsubscribe!");
      }
    } finally {
      w.unsubscribe();
    }
  }
  private void fetchGitHubSearch(@NonNull final String searchString) {
    Preconditions.checkNotNull(searchString, "Search String cannot be null.");

    Log.d(TAG, "fetchGitHubSearch(" + searchString + ")");
    if (requestMap.containsKey(searchString.hashCode())
        && !requestMap.get(searchString.hashCode()).isUnsubscribed()) {
      Log.d(TAG, "Found an ongoing request for repository " + searchString);
      return;
    }
    final String uri = gitHubRepositorySearchStore.getUriForKey(searchString).toString();
    Subscription subscription =
        createNetworkObservable(searchString)
            .subscribeOn(Schedulers.computation())
            .map(
                (repositories) -> {
                  final List<Integer> repositoryIds = new ArrayList<>();
                  for (GitHubRepository repository : repositories) {
                    gitHubRepositoryStore.put(repository);
                    repositoryIds.add(repository.getId());
                  }
                  return new GitHubRepositorySearch(searchString, repositoryIds);
                })
            .doOnCompleted(() -> completeRequest(uri))
            .doOnError(doOnError(uri))
            .subscribe(
                gitHubRepositorySearchStore::put,
                e ->
                    Log.e(
                        TAG,
                        "Error fetching GitHub repository search for '" + searchString + "'",
                        e));
    requestMap.put(searchString.hashCode(), subscription);
    startRequest(uri);
  }
  /**
   * Make sure we get a MissingBackpressureException propagated through when we have a fast temporal
   * (hot) producer.
   */
  @Test
  public void testHotOperatorBackpressure() {
    TestSubscriber<String> ts = new TestSubscriber<String>();
    Observable.timer(0, 1, TimeUnit.MICROSECONDS)
        .observeOn(Schedulers.computation())
        .map(
            new Func1<Long, String>() {

              @Override
              public String call(Long t1) {
                System.out.println(t1);
                try {
                  Thread.sleep(100);
                } catch (InterruptedException e) {
                }
                return t1 + " slow value";
              }
            })
        .subscribe(ts);

    ts.awaitTerminalEvent();
    System.out.println("Errors: " + ts.getOnErrorEvents());
    assertEquals(1, ts.getOnErrorEvents().size());
    assertEquals(MissingBackpressureException.class, ts.getOnErrorEvents().get(0).getClass());
  }
  private Observable<Void> handleHystrixRequest(final HttpServerResponse<O> response) {
    writeHeaders(response);

    final Subject<Void, Void> subject = PublishSubject.create();
    final MultipleAssignmentSubscription subscription = new MultipleAssignmentSubscription();
    Subscription actionSubscription =
        Observable.timer(0, interval, TimeUnit.MILLISECONDS, Schedulers.computation())
            .subscribe(
                new Action1<Long>() {
                  @Override
                  public void call(Long tick) {
                    if (!response.getChannel().isOpen()) {
                      subscription.unsubscribe();
                      return;
                    }
                    try {
                      writeMetric(JsonMapper.toJson(metrics), response);
                    } catch (Exception e) {
                      subject.onError(e);
                    }
                  }
                });
    subscription.set(actionSubscription);
    return subject;
  }
Example #12
0
  @Test(timeout = 2000)
  public void testOnBackpressureBuffer() {
    int NUM = (int) (RxRingBuffer.SIZE * 1.1); // > 1 so that take doesn't prevent buffer overflow
    AtomicInteger c = new AtomicInteger();
    TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
    firehose(c)
        .takeWhile(
            new Func1<Integer, Boolean>() {

              @Override
              public Boolean call(Integer t1) {
                return t1 < 100000;
              }
            })
        .onBackpressureBuffer()
        .observeOn(Schedulers.computation())
        .map(SLOW_PASS_THRU)
        .take(NUM)
        .subscribe(ts);
    ts.awaitTerminalEvent();
    ts.assertNoErrors();
    System.out.println(
        "testOnBackpressureBuffer => Received: "
            + ts.getOnNextEvents().size()
            + "  Emitted: "
            + c.get());
    assertEquals(NUM, ts.getOnNextEvents().size());
    // it buffers, so we should get the right value sequentially
    assertEquals(NUM - 1, ts.getOnNextEvents().get(NUM - 1).intValue());
  }
  /**
   * Attempts to confirm that when pauses exist between events, the ScheduledObserver does not lose
   * or reorder any events since the scheduler will not block, but will be re-scheduled when it
   * receives new events after each pause.
   *
   * <p>This is non-deterministic in proving success, but if it ever fails (non-deterministically)
   * it is a sign of potential issues as thread-races and scheduling should not affect output.
   */
  @Test
  public void testObserveOnOrderingConcurrency() {
    final AtomicInteger count = new AtomicInteger();
    final int _multiple = 99;

    Observable.range(1, 10000)
        .map(
            new Func1<Integer, Integer>() {

              @Override
              public Integer call(Integer t1) {
                if (randomIntFrom0to100() > 98) {
                  try {
                    Thread.sleep(2);
                  } catch (InterruptedException e) {
                    e.printStackTrace();
                  }
                }
                return t1 * _multiple;
              }
            })
        .observeOn(Schedulers.computation())
        .toBlocking()
        .forEach(
            new Action1<Integer>() {

              @Override
              public void call(Integer t1) {
                assertEquals(count.incrementAndGet() * _multiple, t1.intValue());
                assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
              }
            });
  }
  /** Confirm that running on a ThreadPoolScheduler allows multiple threads but is still ordered. */
  @Test
  public void testObserveOnWithThreadPoolScheduler() {
    final AtomicInteger count = new AtomicInteger();
    final int _multiple = 99;

    Observable.range(1, 100000)
        .map(
            new Func1<Integer, Integer>() {

              @Override
              public Integer call(Integer t1) {
                return t1 * _multiple;
              }
            })
        .observeOn(Schedulers.computation())
        .toBlocking()
        .forEach(
            new Action1<Integer>() {

              @Override
              public void call(Integer t1) {
                assertEquals(count.incrementAndGet() * _multiple, t1.intValue());
                assertTrue(Thread.currentThread().getName().startsWith("RxComputationThreadPool"));
              }
            });
  }
Example #15
0
  @Test
  public void testObserveOnWithSlowConsumer() {
    int NUM = (int) (RxRingBuffer.SIZE * 0.2);
    AtomicInteger c = new AtomicInteger();
    TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
    incrementingIntegers(c)
        .observeOn(Schedulers.computation())
        .map(
            new Func1<Integer, Integer>() {

              @Override
              public Integer call(Integer i) {
                try {
                  Thread.sleep(1);
                } catch (InterruptedException e) {
                  e.printStackTrace();
                }
                return i;
              }
            })
        .take(NUM)
        .subscribe(ts);
    ts.awaitTerminalEvent();
    ts.assertNoErrors();
    System.out.println(
        "testObserveOnWithSlowConsumer => Received: "
            + ts.getOnNextEvents().size()
            + "  Emitted: "
            + c.get());
    assertEquals(NUM, ts.getOnNextEvents().size());
    assertTrue(c.get() < RxRingBuffer.SIZE * 2);
  }
  @Test
  @SuppressWarnings("unchecked")
  public void testOrdering() throws InterruptedException {
    Observable<String> obs = Observable.just("one", null, "two", "three", "four");

    Observer<String> observer = mock(Observer.class);

    InOrder inOrder = inOrder(observer);
    TestSubscriber<String> ts = new TestSubscriber<String>(observer);

    obs.observeOn(Schedulers.computation()).subscribe(ts);

    ts.awaitTerminalEvent(1000, TimeUnit.MILLISECONDS);
    if (ts.getOnErrorEvents().size() > 0) {
      for (Throwable t : ts.getOnErrorEvents()) {
        t.printStackTrace();
      }
      fail("failed with exception");
    }

    inOrder.verify(observer, times(1)).onNext("one");
    inOrder.verify(observer, times(1)).onNext(null);
    inOrder.verify(observer, times(1)).onNext("two");
    inOrder.verify(observer, times(1)).onNext("three");
    inOrder.verify(observer, times(1)).onNext("four");
    inOrder.verify(observer, times(1)).onCompleted();
    inOrder.verifyNoMoreInteractions();
  }
 /** https://github.com/ReactiveX/RxJava/issues/1147 */
 @Test
 public void testRaceForTerminalState() {
   final List<Integer> expected = Arrays.asList(1);
   for (int i = 0; i < 100000; i++) {
     TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
     Observable.just(1).subscribeOn(Schedulers.computation()).cache().subscribe(ts);
     ts.awaitTerminalEvent();
     ts.assertReceivedOnNext(expected);
     ts.assertTerminalEvent();
   }
 }
Example #18
0
  @Test(timeout = 10000)
  public void testOnBackpressureDropWithAction() {
    for (int i = 0; i < 100; i++) {
      final AtomicInteger emitCount = new AtomicInteger();
      final AtomicInteger dropCount = new AtomicInteger();
      final AtomicInteger passCount = new AtomicInteger();
      final int NUM = RxRingBuffer.SIZE * 3; // > 1 so that take doesn't prevent buffer overflow
      TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
      firehose(emitCount)
          .onBackpressureDrop(
              new Action1<Integer>() {
                @Override
                public void call(Integer i) {
                  dropCount.incrementAndGet();
                }
              })
          .doOnNext(
              new Action1<Integer>() {
                @Override
                public void call(Integer integer) {
                  passCount.incrementAndGet();
                }
              })
          .observeOn(Schedulers.computation())
          .map(SLOW_PASS_THRU)
          .take(NUM)
          .subscribe(ts);
      ts.awaitTerminalEvent();
      ts.assertNoErrors();

      List<Integer> onNextEvents = ts.getOnNextEvents();
      Integer lastEvent = onNextEvents.get(NUM - 1);
      System.out.println(
          testName.getMethodName()
              + " => Received: "
              + onNextEvents.size()
              + " Passed: "
              + passCount.get()
              + " Dropped: "
              + dropCount.get()
              + "  Emitted: "
              + emitCount.get()
              + " Last value: "
              + lastEvent);
      assertEquals(NUM, onNextEvents.size());
      // in reality, NUM < passCount
      assertTrue(NUM <= passCount.get());
      // it drop, so we should get some number far higher than what would have sequentially
      // incremented
      assertTrue(NUM - 1 <= lastEvent.intValue());
      assertTrue(0 < dropCount.get());
      assertEquals(emitCount.get(), passCount.get() + dropCount.get());
    }
  }
  public static void main(String[] args) {

    Object signal = new Object();

    synchronized (signal) {
      PublishSubject<String> subject = PublishSubject.create();

      subject.subscribe(
          (letter) -> {
            System.out.println("Subscribe 1: " + letter);

            ThreadUtils.sleep(500);

            if (letter.equals("eta")) {
              synchronized (signal) {
                signal.notify();
              }
            }
          });

      Observable.from(DataGenerator.generateGreekAlphabet())
          .subscribeOn(Schedulers.computation())
          .subscribe(
              (letter) -> {
                subject.onNext(letter);
              },
              (t) -> {
                subject.onError(t);
              },
              () -> {
                System.out.println("Subscriber 1: Completed");
                subject.onCompleted();
                synchronized (signal) {
                  signal.notify();
                }
              });
      ThreadUtils.wait(signal);

      subject.subscribe(
          (letter) -> {
            System.out.println("Subscribe 2: " + letter);
          },
          (t) -> {
            subject.onError(t);
          },
          () -> {
            System.out.println("Subscriber 2: Completed");
          });

      ThreadUtils.wait(signal);
    }

    System.exit(0);
  }
Example #20
0
 @Test
 public void testSubscribeOnScheduling() {
   // in a loop for repeating the concurrency in this to increase chance of failure
   for (int i = 0; i < 100; i++) {
     int NUM = (int) (RxRingBuffer.SIZE * 2.1);
     AtomicInteger c = new AtomicInteger();
     ConcurrentLinkedQueue<Thread> threads = new ConcurrentLinkedQueue<Thread>();
     TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
     // observeOn is there to make it async and need backpressure
     incrementingIntegers(c, threads)
         .subscribeOn(Schedulers.computation())
         .observeOn(Schedulers.computation())
         .take(NUM)
         .subscribe(ts);
     ts.awaitTerminalEvent();
     ts.assertNoErrors();
     System.out.println(
         "testSubscribeOnScheduling => Received: "
             + ts.getOnNextEvents().size()
             + "  Emitted: "
             + c.get());
     assertEquals(NUM, ts.getOnNextEvents().size());
     assertTrue(c.get() < RxRingBuffer.SIZE * 4);
     Thread first = null;
     for (Thread t : threads) {
       System.out.println("testSubscribeOnScheduling => thread: " + t);
       if (first == null) {
         first = t;
       } else {
         if (!first.equals(t)) {
           fail("Expected to see the same thread");
         }
       }
     }
     System.out.println(
         "testSubscribeOnScheduling => Number of batch requests seen: " + threads.size());
     assertTrue(threads.size() > 1);
     System.out.println(
         "-------------------------------------------------------------------------------------------");
   }
 }
Example #21
0
 @Test
 public void testObserveOn() {
   int NUM = (int) (RxRingBuffer.SIZE * 2.1);
   AtomicInteger c = new AtomicInteger();
   TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
   incrementingIntegers(c).observeOn(Schedulers.computation()).take(NUM).subscribe(ts);
   ts.awaitTerminalEvent();
   ts.assertNoErrors();
   System.out.println(
       "testObserveOn => Received: " + ts.getOnNextEvents().size() + "  Emitted: " + c.get());
   assertEquals(NUM, ts.getOnNextEvents().size());
   assertTrue(c.get() < RxRingBuffer.SIZE * 4);
 }
Example #22
0
 @Test(timeout = 2000)
 public void testFirehoseFailsAsExpected() {
   AtomicInteger c = new AtomicInteger();
   TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
   firehose(c).observeOn(Schedulers.computation()).map(SLOW_PASS_THRU).subscribe(ts);
   ts.awaitTerminalEvent();
   System.out.println(
       "testFirehoseFailsAsExpected => Received: "
           + ts.getOnNextEvents().size()
           + "  Emitted: "
           + c.get());
   assertEquals(1, ts.getOnErrorEvents().size());
   assertTrue(ts.getOnErrorEvents().get(0) instanceof MissingBackpressureException);
 }
 private Observable<String> loadData() {
   // wait 3 seconds in background thread
   // then strings are observed on main thread
   return Observable.create(
           new Observable.OnSubscribe<String>() {
             @Override
             public void call(Subscriber<? super String> subscriber) {
               SystemClock.sleep(3000);
               subscriber.onNext(new Date().toString());
               subscriber.onCompleted();
             }
           })
       .subscribeOn(Schedulers.computation())
       .observeOn(AndroidSchedulers.mainThread());
 }
Example #24
0
  @Test
  public void testFlatMapTransformsMaxConcurrentNormal() {
    final int m = 2;
    final AtomicInteger subscriptionCount = new AtomicInteger();
    Observable<Integer> onNext =
        compose(
                Observable.from(Arrays.asList(1, 2, 3)).observeOn(Schedulers.computation()),
                subscriptionCount,
                m)
            .subscribeOn(Schedulers.computation());
    Observable<Integer> onCompleted =
        compose(Observable.from(Arrays.asList(4)), subscriptionCount, m)
            .subscribeOn(Schedulers.computation());
    Observable<Integer> onError = Observable.from(Arrays.asList(5));

    Observable<Integer> source = Observable.from(Arrays.asList(10, 20, 30));

    @SuppressWarnings("unchecked")
    Observer<Object> o = mock(Observer.class);
    TestSubscriber<Object> ts = new TestSubscriber<Object>(o);

    source.flatMap(just(onNext), just(onError), just0(onCompleted), m).subscribe(ts);

    ts.awaitTerminalEvent(1, TimeUnit.SECONDS);
    ts.assertNoErrors();
    ts.assertTerminalEvent();

    verify(o, times(3)).onNext(1);
    verify(o, times(3)).onNext(2);
    verify(o, times(3)).onNext(3);
    verify(o).onNext(4);
    verify(o).onCompleted();

    verify(o, never()).onNext(5);
    verify(o, never()).onError(any(Throwable.class));
  }
  @Test
  public void testOnErrorCutsAheadOfOnNext() {
    final PublishSubject<Long> subject = PublishSubject.create();

    final AtomicLong counter = new AtomicLong();
    TestSubscriber<Long> ts =
        new TestSubscriber<Long>(
            new Observer<Long>() {

              @Override
              public void onCompleted() {}

              @Override
              public void onError(Throwable e) {}

              @Override
              public void onNext(Long t) {
                // simulate slow consumer to force backpressure failure
                try {
                  Thread.sleep(1);
                } catch (InterruptedException e) {
                }
              }
            });
    subject.observeOn(Schedulers.computation()).subscribe(ts);

    // this will blow up with backpressure
    while (counter.get() < 102400) {
      subject.onNext(counter.get());
      counter.incrementAndGet();
    }

    ts.awaitTerminalEvent();
    assertEquals(1, ts.getOnErrorEvents().size());
    assertTrue(ts.getOnErrorEvents().get(0) instanceof MissingBackpressureException);
    // assert that the values are sequential, that cutting in didn't allow skipping some but
    // emitting others.
    // example [0, 1, 2] not [0, 1, 4]
    assertTrue(
        ts.getOnNextEvents().size()
            == ts.getOnNextEvents().get(ts.getOnNextEvents().size() - 1) + 1);
    // we should emit the error without emitting the full buffer size
    assertTrue(ts.getOnNextEvents().size() < RxRingBuffer.SIZE);
  }
Example #26
0
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    a = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);

    Observable.range(0, limit)
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(integer -> a.add(integer.toString()));

    setListAdapter(a);

    getListView()
        .setOnScrollListener(
            new AbsListView.OnScrollListener() {
              @Override
              public void onScrollStateChanged(AbsListView view, int scrollState) {}

              @Override
              public void onScroll(
                  AbsListView view,
                  int firstVisibleItem,
                  int visibleItemCount,
                  int totalItemCount) {
                t.setText(
                    "f:" + firstVisibleItem + " vc:" + visibleItemCount + " tc:" + totalItemCount);
                if (totalItemCount >= limit
                    && (firstVisibleItem > totalItemCount - 2 * visibleItemCount)) {
                  int count = 2 * visibleItemCount;
                  limit = totalItemCount + count;
                  Observable.range(totalItemCount, count)
                      .subscribeOn(Schedulers.computation())
                      .observeOn(AndroidSchedulers.mainThread())
                      .subscribe(
                          integer -> {
                            a.add(integer.toString());
                            t.append("+" + integer.toString());
                          });
                }
              }
            });
  }
Example #27
0
  @Test(timeout = 30000)
  public void flatMapRangeMixedAsyncLoop() {
    for (int i = 0; i < 2000; i++) {
      if (i % 10 == 0) {
        System.out.println("flatMapRangeAsyncLoop > " + i);
      }
      TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
      Observable.range(0, 1000)
          .flatMap(
              new Func1<Integer, Observable<Integer>>() {
                final Random rnd = new Random();

                @Override
                public Observable<Integer> call(Integer t) {
                  Observable<Integer> r = Observable.just(t);
                  if (rnd.nextBoolean()) {
                    r = r.asObservable();
                  }
                  return r;
                }
              })
          .observeOn(Schedulers.computation())
          .subscribe(ts);

      ts.awaitTerminalEvent(2500, TimeUnit.MILLISECONDS);
      if (ts.getOnCompletedEvents().isEmpty()) {
        System.out.println(ts.getOnNextEvents().size());
      }
      ts.assertTerminalEvent();
      ts.assertNoErrors();
      List<Integer> list = ts.getOnNextEvents();
      if (list.size() < 1000) {
        Set<Integer> set = new HashSet<Integer>(list);
        for (int j = 0; j < 1000; j++) {
          if (!set.contains(j)) {
            System.out.println(j + " missing");
          }
        }
      }
      assertEquals(1000, list.size());
    }
  }
Example #28
0
  /** 进入APP倒计时 使用RxJava进行异步处理 每秒调用一次enterMain */
  public void startTiming() {

    // 订阅事件,每秒判断一次是否进入APP,并刷新UI展示
    Subscription subscription =
        Observable.interval(TIME_SECOND, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                new Action1<Long>() {
                  @Override
                  public void call(Long aLong) {
                    // aLong代表interval调用次数
                    enterApp(aLong);
                    Log.d("test leak", aLong + "");
                  }
                });

    // 将 订阅事件 加入 subscription集合(Set),用于与Activity生命周期绑定,onDestroy时解除事件注册
    compositeSubscription.add(subscription);
  }
Example #29
0
  @Ignore // don't care for any reordering
  @Test(timeout = 10000)
  public void flatMapRangeAsyncLoop() {
    for (int i = 0; i < 2000; i++) {
      if (i % 10 == 0) {
        System.out.println("flatMapRangeAsyncLoop > " + i);
      }
      TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
      Observable.range(0, 1000)
          .flatMap(
              new Func1<Integer, Observable<Integer>>() {
                @Override
                public Observable<Integer> call(Integer t) {
                  return Observable.just(t);
                }
              })
          .observeOn(Schedulers.computation())
          .subscribe(ts);

      ts.awaitTerminalEvent(2500, TimeUnit.MILLISECONDS);
      if (ts.getOnCompletedEvents().isEmpty()) {
        System.out.println(ts.getOnNextEvents().size());
      }
      ts.assertTerminalEvent();
      ts.assertNoErrors();
      List<Integer> list = ts.getOnNextEvents();
      assertEquals(1000, list.size());
      boolean f = false;
      for (int j = 0; j < list.size(); j++) {
        if (list.get(j) != j) {
          System.out.println(j + " " + list.get(j));
          f = true;
        }
      }
      if (f) {
        Assert.fail("Results are out of order!");
      }
    }
  }
Example #30
0
  @Test(timeout = 10000)
  public void testOnBackpressureDrop() {
    long t = System.currentTimeMillis();
    for (int i = 0; i < 100; i++) {
      // stop the test if we are getting close to the timeout because slow machines
      // may not get through 100 iterations
      if (System.currentTimeMillis() - t > TimeUnit.SECONDS.toMillis(9)) {
        break;
      }
      int NUM = (int) (RxRingBuffer.SIZE * 1.1); // > 1 so that take doesn't prevent buffer overflow
      AtomicInteger c = new AtomicInteger();
      TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
      firehose(c)
          .onBackpressureDrop()
          .observeOn(Schedulers.computation())
          .map(SLOW_PASS_THRU)
          .take(NUM)
          .subscribe(ts);
      ts.awaitTerminalEvent();
      ts.assertNoErrors();

      List<Integer> onNextEvents = ts.getOnNextEvents();
      assertEquals(NUM, onNextEvents.size());

      Integer lastEvent = onNextEvents.get(NUM - 1);

      System.out.println(
          "testOnBackpressureDrop => Received: "
              + onNextEvents.size()
              + "  Emitted: "
              + c.get()
              + " Last value: "
              + lastEvent);
      // it drop, so we should get some number far higher than what would have sequentially
      // incremented
      assertTrue(NUM - 1 <= lastEvent.intValue());
    }
  }