/** Timed offer reports drops if saturated */
 public void testDroppedTimedOffer() {
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 4);
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   long delay = timeoutMillis();
   for (int i = 1; i <= 4; ++i) assertTrue(p.offer(i, delay, MILLISECONDS, null) >= 0);
   long startTime = System.nanoTime();
   assertTrue(p.offer(5, delay, MILLISECONDS, null) < 0);
   s1.sn.request(64);
   assertTrue(p.offer(6, delay, MILLISECONDS, null) < 0);
   // 2 * delay should elapse but check only 1 * delay to allow timer slop
   assertTrue(millisElapsedSince(startTime) >= delay);
   s2.sn.request(64);
   p.close();
   s2.awaitComplete();
   assertTrue(s2.nexts >= 2);
   s1.awaitComplete();
   assertTrue(s1.nexts >= 2);
 }
 /** Timed offer invokes drop handler if saturated */
 public void testHandledDroppedTimedOffer() {
   AtomicInteger calls = new AtomicInteger();
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 4);
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   long delay = timeoutMillis();
   for (int i = 1; i <= 4; ++i)
     assertTrue(p.offer(i, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) >= 0);
   long startTime = System.nanoTime();
   assertTrue(p.offer(5, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) < 0);
   s1.sn.request(64);
   assertTrue(p.offer(6, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) < 0);
   assertTrue(millisElapsedSince(startTime) >= delay);
   s2.sn.request(64);
   p.close();
   s2.awaitComplete();
   s1.awaitComplete();
   assertTrue(calls.get() >= 2);
 }
 /** Timed offer succeeds if drop handler forces request */
 public void testRecoveredHandledDroppedTimedOffer() {
   AtomicInteger calls = new AtomicInteger();
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 4);
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   int n = 0;
   long delay = timeoutMillis();
   long startTime = System.nanoTime();
   for (int i = 1; i <= 6; ++i) {
     int d = p.offer(i, delay, MILLISECONDS, (s, x) -> reqHandle(calls, s));
     n = n + 2 + (d < 0 ? d : 0);
   }
   assertTrue(millisElapsedSince(startTime) >= delay);
   p.close();
   s2.awaitComplete();
   s1.awaitComplete();
   assertEquals(n, s1.nexts + s2.nexts);
   assertTrue(calls.get() >= 2);
 }
 /**
  * Upon subscription, the subscriber's onSubscribe is called, no other Subscriber methods are
  * invoked, the publisher hasSubscribers, isSubscribed is true, and existing subscriptions are
  * unaffected.
  */
 public void testSubscribe1() {
   TestSubscriber s = new TestSubscriber();
   SubmissionPublisher<Integer> p = basicPublisher();
   p.subscribe(s);
   assertTrue(p.hasSubscribers());
   assertEquals(1, p.getNumberOfSubscribers());
   assertTrue(p.getSubscribers().contains(s));
   assertTrue(p.isSubscribed(s));
   s.awaitSubscribe();
   assertNotNull(s.sn);
   assertEquals(0, s.nexts);
   assertEquals(0, s.errors);
   assertEquals(0, s.completes);
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s2);
   assertTrue(p.hasSubscribers());
   assertEquals(2, p.getNumberOfSubscribers());
   assertTrue(p.getSubscribers().contains(s));
   assertTrue(p.getSubscribers().contains(s2));
   assertTrue(p.isSubscribed(s));
   assertTrue(p.isSubscribed(s2));
   s2.awaitSubscribe();
   assertNotNull(s2.sn);
   assertEquals(0, s2.nexts);
   assertEquals(0, s2.errors);
   assertEquals(0, s2.completes);
   p.close();
 }
 /** submit returns number of lagged items, compatible with result of estimateMaximumLag. */
 public void testLaggedSubmit() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   assertEquals(1, p.submit(1));
   assertTrue(p.estimateMaximumLag() >= 1);
   assertTrue(p.submit(2) >= 2);
   assertTrue(p.estimateMaximumLag() >= 2);
   s1.sn.request(4);
   assertTrue(p.submit(3) >= 3);
   assertTrue(p.estimateMaximumLag() >= 3);
   s2.sn.request(4);
   p.submit(4);
   p.close();
   s2.awaitComplete();
   assertEquals(4, s2.nexts);
   s1.awaitComplete();
   assertEquals(4, s2.nexts);
 }
 /** If closed, upon subscription, the subscriber's onComplete method is invoked */
 public void testSubscribe2() {
   TestSubscriber s = new TestSubscriber();
   SubmissionPublisher<Integer> p = basicPublisher();
   p.close();
   p.subscribe(s);
   s.awaitComplete();
   assertEquals(0, s.nexts);
   assertEquals(0, s.errors);
   assertEquals(1, s.completes, 1);
 }
 /** consume returns a CompletableFuture that is done when publisher completes */
 public void testConsume() {
   AtomicInteger sum = new AtomicInteger();
   SubmissionPublisher<Integer> p = basicPublisher();
   CompletableFuture<Void> f =
       p.consume(
           (Integer x) -> {
             sum.getAndAdd(x.intValue());
           });
   int n = 20;
   for (int i = 1; i <= n; ++i) p.submit(i);
   p.close();
   f.join();
   assertEquals((n * (n + 1)) / 2, sum.get());
 }
 /** onNext items are issued in the same order to each subscriber */
 public void testOrder() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   for (int i = 1; i <= 20; ++i) p.submit(i);
   p.close();
   s2.awaitComplete();
   s1.awaitComplete();
   assertEquals(20, s2.nexts);
   assertEquals(1, s2.completes);
   assertEquals(20, s1.nexts);
   assertEquals(1, s1.completes);
 }
 /**
  * A publisher closedExceptionally reports isClosed with the closedException and throws ISE upon
  * attempted submission; a subsequent close or closeExceptionally has no additional effect.
  */
 public void testCloseExceptionally() {
   SubmissionPublisher<Integer> p = basicPublisher();
   checkInitialState(p);
   Throwable ex = new SPException();
   p.closeExceptionally(ex);
   assertTrue(p.isClosed());
   assertSame(p.getClosedException(), ex);
   try {
     p.submit(1);
     shouldThrow();
   } catch (IllegalStateException success) {
   }
   p.close();
   assertTrue(p.isClosed());
   assertSame(p.getClosedException(), ex);
 }
 /** Throwing an exception in onNext causes onError */
 public void testThrowOnNext() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   s1.awaitSubscribe();
   p.submit(1);
   s1.throwOnCall = true;
   p.submit(2);
   p.close();
   s2.awaitComplete();
   assertEquals(2, s2.nexts);
   s1.awaitComplete();
   assertEquals(1, s1.errors);
 }
 /** Closing a publisher causes onComplete to subscribers */
 public void testCloseCompletes() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   p.submit(1);
   p.close();
   assertTrue(p.isClosed());
   assertNull(p.getClosedException());
   s1.awaitComplete();
   assertEquals(1, s1.nexts);
   assertEquals(1, s1.completes);
   s2.awaitComplete();
   assertEquals(1, s2.nexts);
   assertEquals(1, s2.completes);
 }
 /** Cancelling a subscription eventually causes no more onNexts to be issued */
 public void testCancel() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   s1.awaitSubscribe();
   p.submit(1);
   s1.sn.cancel();
   for (int i = 2; i <= 20; ++i) p.submit(i);
   p.close();
   s2.awaitComplete();
   assertEquals(20, s2.nexts);
   assertEquals(1, s2.completes);
   assertTrue(s1.nexts < 20);
   assertFalse(p.isSubscribed(s1));
 }
 /** submit eventually issues requested items when buffer capacity is 1 */
 public void testCap1Submit() {
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 1);
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   for (int i = 1; i <= 20; ++i) {
     assertTrue(p.estimateMinimumDemand() <= 1);
     assertTrue(p.submit(i) >= 0);
   }
   p.close();
   s2.awaitComplete();
   s1.awaitComplete();
   assertEquals(20, s2.nexts);
   assertEquals(1, s2.completes);
   assertEquals(20, s1.nexts);
   assertEquals(1, s1.completes);
 }
 /** onNext is not issued when requests become zero */
 public void testRequest2() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   s1.request = false;
   p.submit(1);
   p.submit(2);
   p.close();
   s2.awaitComplete();
   assertEquals(2, s2.nexts);
   assertEquals(1, s2.completes);
   s1.awaitNext(1);
   assertEquals(1, s1.nexts);
 }
 /** Negative request causes error */
 public void testRequest3() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   s1.sn.request(-1L);
   p.submit(1);
   p.submit(2);
   p.close();
   s2.awaitComplete();
   assertEquals(2, s2.nexts);
   assertEquals(1, s2.completes);
   s1.awaitError();
   assertEquals(1, s1.errors);
   assertTrue(s1.lastError instanceof IllegalArgumentException);
 }
 /**
  * If a handler is supplied in constructor, it is invoked when subscriber throws an exception in
  * onNext
  */
 public void testThrowOnNextHandler() {
   AtomicInteger calls = new AtomicInteger();
   SubmissionPublisher<Integer> p =
       new SubmissionPublisher<Integer>(basicExecutor, 8, (s, e) -> calls.getAndIncrement());
   TestSubscriber s1 = new TestSubscriber();
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s1);
   p.subscribe(s2);
   s1.awaitSubscribe();
   p.submit(1);
   s1.throwOnCall = true;
   p.submit(2);
   p.close();
   s2.awaitComplete();
   assertEquals(2, s2.nexts);
   assertEquals(1, s2.completes);
   s1.awaitError();
   assertEquals(1, s1.errors);
   assertEquals(1, calls.get());
 }
 /** offer succeeds if drop handler forces request */
 public void testRecoveredHandledDroppedOffer() {
   AtomicInteger calls = new AtomicInteger();
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 4);
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   int n = 0;
   for (int i = 1; i <= 8; ++i) {
     int d = p.offer(i, (s, x) -> reqHandle(calls, s));
     n = n + 2 + (d < 0 ? d : 0);
   }
   p.close();
   s2.awaitComplete();
   s1.awaitComplete();
   assertEquals(n, s1.nexts + s2.nexts);
   assertTrue(calls.get() >= 2);
 }
 /** offer invokes drop handler if saturated */
 public void testHandledDroppedOffer() {
   AtomicInteger calls = new AtomicInteger();
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 4);
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   for (int i = 1; i <= 4; ++i) assertTrue(p.offer(i, (s, x) -> noopHandle(calls)) >= 0);
   p.offer(4, (s, x) -> noopHandle(calls));
   assertTrue(p.offer(6, (s, x) -> noopHandle(calls)) < 0);
   s1.sn.request(64);
   assertTrue(p.offer(7, (s, x) -> noopHandle(calls)) < 0);
   s2.sn.request(64);
   p.close();
   s2.awaitComplete();
   s1.awaitComplete();
   assertTrue(calls.get() >= 4);
 }
 /** offer reports drops if saturated */
 public void testDroppedOffer() {
   SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(basicExecutor, 4);
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   for (int i = 1; i <= 4; ++i) assertTrue(p.offer(i, null) >= 0);
   p.offer(5, null);
   assertTrue(p.offer(6, null) < 0);
   s1.sn.request(64);
   assertTrue(p.offer(7, null) < 0);
   s2.sn.request(64);
   p.close();
   s2.awaitComplete();
   assertTrue(s2.nexts >= 4);
   s1.awaitComplete();
   assertTrue(s1.nexts >= 4);
 }
 /** offer returns number of lagged items if not saturated */
 public void testLaggedOffer() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   assertTrue(p.offer(1, null) >= 1);
   assertTrue(p.offer(2, null) >= 2);
   s1.sn.request(4);
   assertTrue(p.offer(3, null) >= 3);
   s2.sn.request(4);
   p.offer(4, null);
   p.close();
   s2.awaitComplete();
   assertEquals(4, s2.nexts);
   s1.awaitComplete();
   assertEquals(4, s2.nexts);
 }
 /** onNext is issued only if requested */
 public void testRequest1() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   p.subscribe(s1);
   s1.awaitSubscribe();
   assertTrue(p.estimateMinimumDemand() == 0);
   TestSubscriber s2 = new TestSubscriber();
   p.subscribe(s2);
   p.submit(1);
   p.submit(2);
   s2.awaitNext(1);
   assertEquals(0, s1.nexts);
   s1.sn.request(3);
   p.submit(3);
   p.close();
   s2.awaitComplete();
   assertEquals(3, s2.nexts);
   assertEquals(1, s2.completes);
   s1.awaitComplete();
   assertTrue(s1.nexts > 0);
   assertEquals(1, s1.completes);
 }
 /** Timed offer returns number of lagged items if not saturated */
 public void testLaggedTimedOffer() {
   SubmissionPublisher<Integer> p = basicPublisher();
   TestSubscriber s1 = new TestSubscriber();
   s1.request = false;
   TestSubscriber s2 = new TestSubscriber();
   s2.request = false;
   p.subscribe(s1);
   p.subscribe(s2);
   s2.awaitSubscribe();
   s1.awaitSubscribe();
   long startTime = System.nanoTime();
   assertTrue(p.offer(1, LONG_DELAY_MS, MILLISECONDS, null) >= 1);
   assertTrue(p.offer(2, LONG_DELAY_MS, MILLISECONDS, null) >= 2);
   s1.sn.request(4);
   assertTrue(p.offer(3, LONG_DELAY_MS, MILLISECONDS, null) >= 3);
   s2.sn.request(4);
   p.offer(4, LONG_DELAY_MS, MILLISECONDS, null);
   p.close();
   s2.awaitComplete();
   assertEquals(4, s2.nexts);
   s1.awaitComplete();
   assertEquals(4, s2.nexts);
   assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
 }