ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/SubmissionPublisherTest.java
(Generate patch)

Comparing jsr166/src/test/tck/SubmissionPublisherTest.java (file contents):
Revision 1.10 by dl, Sat Sep 12 11:25:15 2015 UTC vs.
Revision 1.30 by jsr166, Mon Dec 16 22:55:54 2019 UTC

# Line 6 | Line 6
6   */
7  
8   import java.util.concurrent.CompletableFuture;
9 + import java.util.concurrent.CountDownLatch;
10   import java.util.concurrent.Executor;
11   import java.util.concurrent.Executors;
12   import java.util.concurrent.Flow;
13   import java.util.concurrent.ForkJoinPool;
13 import java.util.concurrent.LinkedBlockingQueue;
14   import java.util.concurrent.SubmissionPublisher;
15 import java.util.concurrent.ThreadFactory;
16 import java.util.concurrent.ThreadPoolExecutor;
17 import java.util.concurrent.TimeUnit;
15   import java.util.concurrent.atomic.AtomicInteger;
19 import java.util.function.BiConsumer;
20 import java.util.function.BiFunction;
21 import java.util.function.BiPredicate;
22 import java.util.stream.Stream;
16   import junit.framework.Test;
17   import junit.framework.TestSuite;
18  
26 import static java.util.concurrent.Flow.Publisher;
19   import static java.util.concurrent.Flow.Subscriber;
20   import static java.util.concurrent.Flow.Subscription;
21   import static java.util.concurrent.TimeUnit.MILLISECONDS;
30 import static java.util.concurrent.TimeUnit.SECONDS;
22  
23   public class SubmissionPublisherTest extends JSR166TestCase {
24  
# Line 38 | Line 29 | public class SubmissionPublisherTest ext
29          return new TestSuite(SubmissionPublisherTest.class);
30      }
31  
32 <    // Factory for single thread pool in case commonPool parallelism is zero
42 <    static final class DaemonThreadFactory implements ThreadFactory {
43 <        public Thread newThread(Runnable r) {
44 <            Thread t = new Thread(r);
45 <            t.setDaemon(true);
46 <            return t;
47 <        }
48 <    }
49 <
50 <    static final Executor basicExecutor =
51 <        (ForkJoinPool.getCommonPoolParallelism() > 1) ?
52 <        ForkJoinPool.commonPool() :
53 <        new ThreadPoolExecutor(1, 1, 60, SECONDS,
54 <                               new LinkedBlockingQueue<Runnable>(),
55 <                               new DaemonThreadFactory());
32 >    final Executor basicExecutor = basicPublisher().getExecutor();
33  
34      static SubmissionPublisher<Integer> basicPublisher() {
35 <        return new SubmissionPublisher<Integer>(basicExecutor,
59 <                                                Flow.defaultBufferSize());
35 >        return new SubmissionPublisher<Integer>();
36      }
37  
38      static class SPException extends RuntimeException {}
# Line 168 | Line 144 | public class SubmissionPublisherTest ext
144      /**
145       * A default-constructed SubmissionPublisher has no subscribers,
146       * is not closed, has default buffer size, and uses the
147 <     * ForkJoinPool.commonPool executor
147 >     * defaultExecutor
148       */
149      public void testConstructor1() {
150 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>();
150 >        SubmissionPublisher<Integer> p = new SubmissionPublisher<>();
151          checkInitialState(p);
176        assertSame(p.getExecutor(), ForkJoinPool.commonPool());
152          assertEquals(p.getMaxBufferCapacity(), Flow.defaultBufferSize());
153 +        Executor e = p.getExecutor(), c = ForkJoinPool.commonPool();
154 +        if (ForkJoinPool.getCommonPoolParallelism() > 1)
155 +            assertSame(e, c);
156 +        else
157 +            assertNotSame(e, c);
158      }
159  
160      /**
# Line 183 | Line 163 | public class SubmissionPublisherTest ext
163       */
164      public void testConstructor2() {
165          Executor e = Executors.newFixedThreadPool(1);
166 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(e, 8);
166 >        SubmissionPublisher<Integer> p = new SubmissionPublisher<>(e, 8);
167          checkInitialState(p);
168          assertSame(p.getExecutor(), e);
169          assertEquals(8, p.getMaxBufferCapacity());
170      }
171  
172      /**
173 <     * A null Executor argument to SubmissionPublisher constructor throws NPE
173 >     * A null Executor argument to SubmissionPublisher constructor
174 >     * throws NullPointerException
175       */
176      public void testConstructor3() {
177          try {
# Line 201 | Line 182 | public class SubmissionPublisherTest ext
182  
183      /**
184       * A negative capacity argument to SubmissionPublisher constructor
185 <     * throws IAE
185 >     * throws IllegalArgumentException
186       */
187      public void testConstructor4() {
188          Executor e = Executors.newFixedThreadPool(1);
# Line 213 | Line 194 | public class SubmissionPublisherTest ext
194  
195      /**
196       * A closed publisher reports isClosed with no closedException and
197 <     * throws ISE upon attempted submission; a subsequent close or
198 <     * closeExceptionally has no additional effect.
197 >     * throws IllegalStateException upon attempted submission; a
198 >     * subsequent close or closeExceptionally has no additional
199 >     * effect.
200       */
201      public void testClose() {
202          SubmissionPublisher<Integer> p = basicPublisher();
# Line 234 | Line 216 | public class SubmissionPublisherTest ext
216  
217      /**
218       * A publisher closedExceptionally reports isClosed with the
219 <     * closedException and throws ISE upon attempted submission; a
220 <     * subsequent close or closeExceptionally has no additional
221 <     * effect.
219 >     * closedException and throws IllegalStateException upon attempted
220 >     * submission; a subsequent close or closeExceptionally has no
221 >     * additional effect.
222       */
223      public void testCloseExceptionally() {
224          SubmissionPublisher<Integer> p = basicPublisher();
# Line 352 | Line 334 | public class SubmissionPublisherTest ext
334          TestSubscriber s = new TestSubscriber();
335          SubmissionPublisher<Integer> p = basicPublisher();
336          s.throwOnCall = true;
337 <        try {
356 <            p.subscribe(s);
357 <        } catch (Exception ok) {}
337 >        p.subscribe(s);
338          s.awaitError();
339          assertEquals(0, s.nexts);
340          assertEquals(1, s.errors);
# Line 396 | Line 376 | public class SubmissionPublisherTest ext
376  
377      /**
378       * Closing a publisher exceptionally causes onError to subscribers
379 +     * after they are subscribed
380       */
381      public void testCloseExceptionallyError() {
382          SubmissionPublisher<Integer> p = basicPublisher();
# Line 406 | Line 387 | public class SubmissionPublisherTest ext
387          p.submit(1);
388          p.closeExceptionally(new SPException());
389          assertTrue(p.isClosed());
390 +        s1.awaitSubscribe();
391          s1.awaitError();
392          assertTrue(s1.nexts <= 1);
393          assertEquals(1, s1.errors);
394 +        s2.awaitSubscribe();
395          s2.awaitError();
396          assertTrue(s2.nexts <= 1);
397          assertEquals(1, s2.errors);
# Line 418 | Line 401 | public class SubmissionPublisherTest ext
401       * Cancelling a subscription eventually causes no more onNexts to be issued
402       */
403      public void testCancel() {
404 <        SubmissionPublisher<Integer> p = basicPublisher();
404 >        SubmissionPublisher<Integer> p =
405 >            new SubmissionPublisher<>(basicExecutor, 4); // must be < 20
406          TestSubscriber s1 = new TestSubscriber();
407          TestSubscriber s2 = new TestSubscriber();
408          p.subscribe(s1);
# Line 462 | Line 446 | public class SubmissionPublisherTest ext
446       */
447      public void testThrowOnNextHandler() {
448          AtomicInteger calls = new AtomicInteger();
449 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>
450 <            (basicExecutor, 8,
467 <             (s, e) -> calls.getAndIncrement());
449 >        SubmissionPublisher<Integer> p = new SubmissionPublisher<>(
450 >            basicExecutor, 8, (s, e) -> calls.getAndIncrement());
451          TestSubscriber s1 = new TestSubscriber();
452          TestSubscriber s2 = new TestSubscriber();
453          p.subscribe(s1);
# Line 511 | Line 494 | public class SubmissionPublisherTest ext
494          s1.request = false;
495          p.subscribe(s1);
496          s1.awaitSubscribe();
497 <        assertTrue(p.estimateMinimumDemand() == 0);
497 >        assertEquals(0, p.estimateMinimumDemand());
498          TestSubscriber s2 = new TestSubscriber();
499          p.subscribe(s2);
500          p.submit(1);
# Line 552 | Line 535 | public class SubmissionPublisherTest ext
535      }
536  
537      /**
538 <     * Negative request causes error
538 >     * Non-positive request causes error
539       */
540      public void testRequest3() {
541          SubmissionPublisher<Integer> p = basicPublisher();
542          TestSubscriber s1 = new TestSubscriber();
543          TestSubscriber s2 = new TestSubscriber();
544 +        TestSubscriber s3 = new TestSubscriber();
545          p.subscribe(s1);
546          p.subscribe(s2);
547 +        p.subscribe(s3);
548 +        s3.awaitSubscribe();
549          s2.awaitSubscribe();
550          s1.awaitSubscribe();
551          s1.sn.request(-1L);
552 +        s3.sn.request(0L);
553          p.submit(1);
554          p.submit(2);
555          p.close();
# Line 572 | Line 559 | public class SubmissionPublisherTest ext
559          s1.awaitError();
560          assertEquals(1, s1.errors);
561          assertTrue(s1.lastError instanceof IllegalArgumentException);
562 +        s3.awaitError();
563 +        assertEquals(1, s3.errors);
564 +        assertTrue(s3.lastError instanceof IllegalArgumentException);
565      }
566  
567      /**
568       * estimateMinimumDemand reports 0 until request, nonzero after
569 <     * request, and zero again after delivery
569 >     * request
570       */
571      public void testEstimateMinimumDemand() {
572          TestSubscriber s = new TestSubscriber();
# Line 587 | Line 577 | public class SubmissionPublisherTest ext
577          assertEquals(0, p.estimateMinimumDemand());
578          s.sn.request(1);
579          assertEquals(1, p.estimateMinimumDemand());
590        p.submit(1);
591        s.awaitNext(1);
592        assertEquals(0, p.estimateMinimumDemand());
580      }
581  
582      /**
# Line 645 | Line 632 | public class SubmissionPublisherTest ext
632       * submit eventually issues requested items when buffer capacity is 1
633       */
634      public void testCap1Submit() {
635 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
636 <            basicExecutor, 1);
635 >        SubmissionPublisher<Integer> p
636 >            = new SubmissionPublisher<>(basicExecutor, 1);
637          TestSubscriber s1 = new TestSubscriber();
638          TestSubscriber s2 = new TestSubscriber();
639          p.subscribe(s1);
640          p.subscribe(s2);
641          for (int i = 1; i <= 20; ++i) {
655            assertTrue(p.estimateMinimumDemand() <= 1);
642              assertTrue(p.submit(i) >= 0);
643          }
644          p.close();
# Line 724 | Line 710 | public class SubmissionPublisherTest ext
710       * offer reports drops if saturated
711       */
712      public void testDroppedOffer() {
713 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
714 <            basicExecutor, 4);
713 >        SubmissionPublisher<Integer> p
714 >            = new SubmissionPublisher<>(basicExecutor, 4);
715          TestSubscriber s1 = new TestSubscriber();
716          s1.request = false;
717          TestSubscriber s2 = new TestSubscriber();
# Line 753 | Line 739 | public class SubmissionPublisherTest ext
739       */
740      public void testHandledDroppedOffer() {
741          AtomicInteger calls = new AtomicInteger();
742 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
743 <            basicExecutor, 4);
742 >        SubmissionPublisher<Integer> p
743 >            = new SubmissionPublisher<>(basicExecutor, 4);
744          TestSubscriber s1 = new TestSubscriber();
745          s1.request = false;
746          TestSubscriber s2 = new TestSubscriber();
# Line 781 | Line 767 | public class SubmissionPublisherTest ext
767       */
768      public void testRecoveredHandledDroppedOffer() {
769          AtomicInteger calls = new AtomicInteger();
770 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
771 <            basicExecutor, 4);
770 >        SubmissionPublisher<Integer> p
771 >            = new SubmissionPublisher<>(basicExecutor, 4);
772          TestSubscriber s1 = new TestSubscriber();
773          s1.request = false;
774          TestSubscriber s2 = new TestSubscriber();
# Line 862 | Line 848 | public class SubmissionPublisherTest ext
848       * Timed offer reports drops if saturated
849       */
850      public void testDroppedTimedOffer() {
851 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
852 <            basicExecutor, 4);
851 >        SubmissionPublisher<Integer> p
852 >            = new SubmissionPublisher<>(basicExecutor, 4);
853          TestSubscriber s1 = new TestSubscriber();
854          s1.request = false;
855          TestSubscriber s2 = new TestSubscriber();
# Line 894 | Line 880 | public class SubmissionPublisherTest ext
880       */
881      public void testHandledDroppedTimedOffer() {
882          AtomicInteger calls = new AtomicInteger();
883 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
884 <            basicExecutor, 4);
883 >        SubmissionPublisher<Integer> p
884 >            = new SubmissionPublisher<>(basicExecutor, 4);
885          TestSubscriber s1 = new TestSubscriber();
886          s1.request = false;
887          TestSubscriber s2 = new TestSubscriber();
# Line 924 | Line 910 | public class SubmissionPublisherTest ext
910       */
911      public void testRecoveredHandledDroppedTimedOffer() {
912          AtomicInteger calls = new AtomicInteger();
913 <        SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
914 <            basicExecutor, 4);
913 >        SubmissionPublisher<Integer> p
914 >            = new SubmissionPublisher<>(basicExecutor, 4);
915          TestSubscriber s1 = new TestSubscriber();
916          s1.request = false;
917          TestSubscriber s2 = new TestSubscriber();
# Line 956 | Line 942 | public class SubmissionPublisherTest ext
942      public void testConsume() {
943          AtomicInteger sum = new AtomicInteger();
944          SubmissionPublisher<Integer> p = basicPublisher();
945 <        CompletableFuture<Void> f =
946 <            p.consume((Integer x) -> { sum.getAndAdd(x.intValue()); });
945 >        CompletableFuture<Void> f =
946 >            p.consume((Integer x) -> sum.getAndAdd(x.intValue()));
947          int n = 20;
948          for (int i = 1; i <= n; ++i)
949              p.submit(i);
# Line 972 | Line 958 | public class SubmissionPublisherTest ext
958      public void testConsumeNPE() {
959          SubmissionPublisher<Integer> p = basicPublisher();
960          try {
961 <            CompletableFuture<Void> f = p.consume(null);
961 >            CompletableFuture<Void> unused = p.consume(null);
962              shouldThrow();
963 <        } catch(NullPointerException success) {
978 <        }
963 >        } catch (NullPointerException success) {}
964      }
965  
966      /**
# Line 991 | Line 976 | public class SubmissionPublisherTest ext
976              p.submit(i);
977          assertTrue(count.get() < n);
978      }
979 <    
979 >
980 >    /**
981 >     * Tests scenario for
982 >     * JDK-8187947: A race condition in SubmissionPublisher
983 >     * cvs update -D '2017-11-25' src/main/java/util/concurrent/SubmissionPublisher.java && ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=SubmissionPublisherTest -Djsr166.methodFilter=testMissedSignal tck; cvs update -A src/main/java/util/concurrent/SubmissionPublisher.java
984 >     */
985 >    public void testMissedSignal_8187947() throws Exception {
986 >        if (!atLeastJava9()) return; // backport to jdk8 too hard
987 >        final int N =
988 >            ((ForkJoinPool.getCommonPoolParallelism() < 2) // JDK-8212899
989 >             ? (1 << 5)
990 >             : (1 << 10))
991 >            * (expensiveTests ? (1 << 10) : 1);
992 >        final CountDownLatch finished = new CountDownLatch(1);
993 >        final SubmissionPublisher<Boolean> pub = new SubmissionPublisher<>();
994 >        class Sub implements Subscriber<Boolean> {
995 >            int received;
996 >            public void onSubscribe(Subscription s) {
997 >                s.request(N);
998 >            }
999 >            public void onNext(Boolean item) {
1000 >                if (++received == N)
1001 >                    finished.countDown();
1002 >                else
1003 >                    CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE));
1004 >            }
1005 >            public void onError(Throwable t) { throw new AssertionError(t); }
1006 >            public void onComplete() {}
1007 >        }
1008 >        pub.subscribe(new Sub());
1009 >        checkTimedGet(
1010 >            CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE)),
1011 >            null);
1012 >        await(finished);
1013 >    }
1014   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines