/** 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); }
/** * A new SubmissionPublisher has no subscribers, is not closed, has the given buffer size, and * uses the given executor */ public void testConstructor2() { Executor e = Executors.newFixedThreadPool(1); SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(e, 8); checkInitialState(p); assertSame(p.getExecutor(), e); assertEquals(8, p.getMaxBufferCapacity()); }
/** 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); }
/** offer(null) throws NPE */ public void testNullOffer() { SubmissionPublisher<Integer> p = basicPublisher(); try { p.offer(null, null); shouldThrow(); } catch (NullPointerException success) { } }
/** consume(null) throws NPE */ public void testConsumeNPE() { SubmissionPublisher<Integer> p = basicPublisher(); try { CompletableFuture<Void> f = p.consume(null); shouldThrow(); } catch (NullPointerException success) { } }
/** * A default-constructed SubmissionPublisher has no subscribers, is not closed, has default buffer * size, and uses the defaultExecutor */ public void testConstructor1() { SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(); checkInitialState(p); assertEquals(p.getMaxBufferCapacity(), Flow.defaultBufferSize()); Executor e = p.getExecutor(), c = ForkJoinPool.commonPool(); if (ForkJoinPool.getCommonPoolParallelism() > 1) assertSame(e, c); else assertNotSame(e, c); }
/** subscribe(null) throws NPE */ public void testSubscribe6() { SubmissionPublisher<Integer> p = basicPublisher(); try { p.subscribe(null); shouldThrow(); } catch (NullPointerException success) { } checkInitialState(p); }
/** consume eventually stops processing published items if cancelled */ public void testCancelledConsume() { AtomicInteger count = new AtomicInteger(); SubmissionPublisher<Integer> p = basicPublisher(); CompletableFuture<Void> f = p.consume(x -> count.getAndIncrement()); f.cancel(true); int n = 1000000; // arbitrary limit for (int i = 1; i <= n; ++i) p.submit(i); assertTrue(count.get() < n); }
/** 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); }
@Override public Publisher<Long> createFailedPublisher() { if (!DependencyUtils.hasJdk9Flow()) { throw new SkipException("no jdk 9 classes found"); } SubmissionPublisher<Long> pub = new SubmissionPublisher<>(); pub.closeExceptionally(new Exception("jdk9-test")); return Publishers.convert(pub); }
/** If closedExceptionally, upon subscription, the subscriber's onError method is invoked */ public void testSubscribe3() { TestSubscriber s = new TestSubscriber(); SubmissionPublisher<Integer> p = basicPublisher(); Throwable ex = new SPException(); p.closeExceptionally(ex); assertTrue(p.isClosed()); assertSame(p.getClosedException(), ex); p.subscribe(s); s.awaitError(); assertEquals(0, s.nexts); assertEquals(1, s.errors); }
/** An exception thrown in onSubscribe causes onError */ public void testSubscribe5() { TestSubscriber s = new TestSubscriber(); SubmissionPublisher<Integer> p = basicPublisher(); s.throwOnCall = true; try { p.subscribe(s); } catch (Exception ok) { } s.awaitError(); assertEquals(0, s.nexts); assertEquals(1, s.errors); assertEquals(0, s.completes); }
/** 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); }
/** Timed offer with null item or TimeUnit throws NPE */ public void testNullTimedOffer() { SubmissionPublisher<Integer> p = basicPublisher(); long startTime = System.nanoTime(); try { p.offer(null, LONG_DELAY_MS, MILLISECONDS, null); shouldThrow(); } catch (NullPointerException success) { } try { p.offer(1, LONG_DELAY_MS, null, null); shouldThrow(); } catch (NullPointerException success) { } assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); }
/** * A new SubmissionPublisher has no subscribers, a non-null executor, a power-of-two capacity, is * not closed, and reports zero demand and lag */ void checkInitialState(SubmissionPublisher<?> p) { assertFalse(p.hasSubscribers()); assertEquals(0, p.getNumberOfSubscribers()); assertTrue(p.getSubscribers().isEmpty()); assertFalse(p.isClosed()); assertNull(p.getClosedException()); int n = p.getMaxBufferCapacity(); assertTrue((n & (n - 1)) == 0); // power of two assertNotNull(p.getExecutor()); assertEquals(0, p.estimateMinimumDemand()); assertEquals(0, p.estimateMaximumLag()); }
/** Closing a publisher exceptionally causes onError to subscribers */ public void testCloseExceptionallyError() { SubmissionPublisher<Integer> p = basicPublisher(); TestSubscriber s1 = new TestSubscriber(); TestSubscriber s2 = new TestSubscriber(); p.subscribe(s1); p.subscribe(s2); p.submit(1); p.closeExceptionally(new SPException()); assertTrue(p.isClosed()); s1.awaitError(); assertTrue(s1.nexts <= 1); assertEquals(1, s1.errors); s2.awaitError(); assertTrue(s2.nexts <= 1); assertEquals(1, s2.errors); }
/** 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); }
/** 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); }
/** 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); }
/** 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()); }
/** 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 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); }
/** 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); }
/** * 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); }
/** * Upon attempted resubscription, the subscriber's onError is called and the subscription is * cancelled. */ public void testSubscribe4() { 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); p.subscribe(s); s.awaitError(); assertEquals(0, s.nexts); assertEquals(1, s.errors); assertFalse(p.isSubscribed(s)); }
/** * estimateMinimumDemand reports 0 until request, nonzero after request, and zero again after * delivery */ public void testEstimateMinimumDemand() { TestSubscriber s = new TestSubscriber(); SubmissionPublisher<Integer> p = basicPublisher(); s.request = false; p.subscribe(s); s.awaitSubscribe(); assertEquals(0, p.estimateMinimumDemand()); s.sn.request(1); assertEquals(1, p.estimateMinimumDemand()); p.submit(1); s.awaitNext(1); assertEquals(0, p.estimateMinimumDemand()); }
/** 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)); }