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

Comparing jsr166/src/test/tck/JSR166TestCase.java (file contents):
Revision 1.129 by jsr166, Fri Feb 27 22:10:29 2015 UTC vs.
Revision 1.184 by jsr166, Wed Feb 10 00:05:20 2016 UTC

# Line 6 | Line 6
6   * Pat Fisher, Mike Judd.
7   */
8  
9 + /*
10 + * @test
11 + * @summary JSR-166 tck tests
12 + * @modules java.management
13 + * @build *
14 + * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase
15 + */
16 +
17   import static java.util.concurrent.TimeUnit.MILLISECONDS;
18 + import static java.util.concurrent.TimeUnit.MINUTES;
19   import static java.util.concurrent.TimeUnit.NANOSECONDS;
20  
21   import java.io.ByteArrayInputStream;
# Line 15 | Line 24 | import java.io.ObjectInputStream;
24   import java.io.ObjectOutputStream;
25   import java.lang.management.ManagementFactory;
26   import java.lang.management.ThreadInfo;
27 + import java.lang.management.ThreadMXBean;
28 + import java.lang.reflect.Constructor;
29   import java.lang.reflect.Method;
30 + import java.lang.reflect.Modifier;
31 + import java.nio.file.Files;
32 + import java.nio.file.Paths;
33   import java.security.CodeSource;
34   import java.security.Permission;
35   import java.security.PermissionCollection;
# Line 35 | Line 49 | import java.util.concurrent.BlockingQueu
49   import java.util.concurrent.Callable;
50   import java.util.concurrent.CountDownLatch;
51   import java.util.concurrent.CyclicBarrier;
52 + import java.util.concurrent.ExecutionException;
53 + import java.util.concurrent.Executors;
54   import java.util.concurrent.ExecutorService;
55 + import java.util.concurrent.ForkJoinPool;
56   import java.util.concurrent.Future;
57   import java.util.concurrent.RecursiveAction;
58   import java.util.concurrent.RecursiveTask;
# Line 45 | Line 62 | import java.util.concurrent.ThreadFactor
62   import java.util.concurrent.ThreadPoolExecutor;
63   import java.util.concurrent.TimeoutException;
64   import java.util.concurrent.atomic.AtomicReference;
65 + import java.util.regex.Matcher;
66   import java.util.regex.Pattern;
67  
68   import junit.framework.AssertionFailedError;
69   import junit.framework.Test;
70   import junit.framework.TestCase;
71 + import junit.framework.TestResult;
72   import junit.framework.TestSuite;
73  
74   /**
# Line 62 | Line 81 | import junit.framework.TestSuite;
81   *
82   * <ol>
83   *
84 < * <li> All assertions in code running in generated threads must use
84 > * <li>All assertions in code running in generated threads must use
85   * the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link
86   * #threadAssertEquals}, or {@link #threadAssertNull}, (not
87   * {@code fail}, {@code assertTrue}, etc.) It is OK (but not
88   * particularly recommended) for other code to use these forms too.
89   * Only the most typically used JUnit assertion methods are defined
90 < * this way, but enough to live with.</li>
90 > * this way, but enough to live with.
91   *
92 < * <li> If you override {@link #setUp} or {@link #tearDown}, make sure
92 > * <li>If you override {@link #setUp} or {@link #tearDown}, make sure
93   * to invoke {@code super.setUp} and {@code super.tearDown} within
94   * them. These methods are used to clear and check for thread
95 < * assertion failures.</li>
95 > * assertion failures.
96   *
97   * <li>All delays and timeouts must use one of the constants {@code
98   * SHORT_DELAY_MS}, {@code SMALL_DELAY_MS}, {@code MEDIUM_DELAY_MS},
# Line 84 | Line 103 | import junit.framework.TestSuite;
103   * is always discriminable as larger than SHORT and smaller than
104   * MEDIUM.  And so on. These constants are set to conservative values,
105   * but even so, if there is ever any doubt, they can all be increased
106 < * in one spot to rerun tests on slower platforms.</li>
106 > * in one spot to rerun tests on slower platforms.
107   *
108 < * <li> All threads generated must be joined inside each test case
108 > * <li>All threads generated must be joined inside each test case
109   * method (or {@code fail} to do so) before returning from the
110   * method. The {@code joinPool} method can be used to do this when
111 < * using Executors.</li>
111 > * using Executors.
112   *
113   * </ol>
114   *
115   * <p><b>Other notes</b>
116   * <ul>
117   *
118 < * <li> Usually, there is one testcase method per JSR166 method
118 > * <li>Usually, there is one testcase method per JSR166 method
119   * covering "normal" operation, and then as many exception-testing
120   * methods as there are exceptions the method can throw. Sometimes
121   * there are multiple tests per JSR166 method when the different
122   * "normal" behaviors differ significantly. And sometimes testcases
123 < * cover multiple methods when they cannot be tested in
105 < * isolation.</li>
123 > * cover multiple methods when they cannot be tested in isolation.
124   *
125 < * <li> The documentation style for testcases is to provide as javadoc
125 > * <li>The documentation style for testcases is to provide as javadoc
126   * a simple sentence or two describing the property that the testcase
127   * method purports to test. The javadocs do not say anything about how
128 < * the property is tested. To find out, read the code.</li>
128 > * the property is tested. To find out, read the code.
129   *
130 < * <li> These tests are "conformance tests", and do not attempt to
130 > * <li>These tests are "conformance tests", and do not attempt to
131   * test throughput, latency, scalability or other performance factors
132   * (see the separate "jtreg" tests for a set intended to check these
133   * for the most central aspects of functionality.) So, most tests use
134   * the smallest sensible numbers of threads, collection sizes, etc
135 < * needed to check basic conformance.</li>
135 > * needed to check basic conformance.
136   *
137   * <li>The test classes currently do not declare inclusion in
138   * any particular package to simplify things for people integrating
139 < * them in TCK test suites.</li>
139 > * them in TCK test suites.
140   *
141 < * <li> As a convenience, the {@code main} of this class (JSR166TestCase)
142 < * runs all JSR166 unit tests.</li>
141 > * <li>As a convenience, the {@code main} of this class (JSR166TestCase)
142 > * runs all JSR166 unit tests.
143   *
144   * </ul>
145   */
# Line 160 | Line 178 | public class JSR166TestCase extends Test
178          Integer.getInteger("jsr166.runsPerTest", 1);
179  
180      /**
181 +     * The number of repetitions of the test suite (for finding leaks?).
182 +     */
183 +    private static final int suiteRuns =
184 +        Integer.getInteger("jsr166.suiteRuns", 1);
185 +
186 +    /**
187 +     * The scaling factor to apply to standard delays used in tests.
188 +     */
189 +    private static final int delayFactor =
190 +        Integer.getInteger("jsr166.delay.factor", 1);
191 +
192 +    public JSR166TestCase() { super(); }
193 +    public JSR166TestCase(String name) { super(name); }
194 +
195 +    /**
196       * A filter for tests to run, matching strings of the form
197       * methodName(className), e.g. "testInvokeAll5(ForkJoinPoolTest)"
198       * Usefully combined with jsr166.runsPerTest.
# Line 171 | Line 204 | public class JSR166TestCase extends Test
204          return (regex == null) ? null : Pattern.compile(regex);
205      }
206  
207 <    protected void runTest() throws Throwable {
207 >    // Instrumentation to debug very rare, but very annoying hung test runs.
208 >    static volatile TestCase currentTestCase;
209 >    // static volatile int currentRun = 0;
210 >    static {
211 >        Runnable checkForWedgedTest = new Runnable() { public void run() {
212 >            // Avoid spurious reports with enormous runsPerTest.
213 >            // A single test case run should never take more than 1 second.
214 >            // But let's cap it at the high end too ...
215 >            final int timeoutMinutes =
216 >                Math.min(15, Math.max(runsPerTest / 60, 1));
217 >            for (TestCase lastTestCase = currentTestCase;;) {
218 >                try { MINUTES.sleep(timeoutMinutes); }
219 >                catch (InterruptedException unexpected) { break; }
220 >                if (lastTestCase == currentTestCase) {
221 >                    System.err.printf(
222 >                        "Looks like we're stuck running test: %s%n",
223 >                        lastTestCase);
224 > //                     System.err.printf(
225 > //                         "Looks like we're stuck running test: %s (%d/%d)%n",
226 > //                         lastTestCase, currentRun, runsPerTest);
227 > //                     System.err.println("availableProcessors=" +
228 > //                         Runtime.getRuntime().availableProcessors());
229 > //                     System.err.printf("cpu model = %s%n", cpuModel());
230 >                    dumpTestThreads();
231 >                    // one stack dump is probably enough; more would be spam
232 >                    break;
233 >                }
234 >                lastTestCase = currentTestCase;
235 >            }}};
236 >        Thread thread = new Thread(checkForWedgedTest, "checkForWedgedTest");
237 >        thread.setDaemon(true);
238 >        thread.start();
239 >    }
240 >
241 > //     public static String cpuModel() {
242 > //         try {
243 > //             Matcher matcher = Pattern.compile("model name\\s*: (.*)")
244 > //                 .matcher(new String(
245 > //                      Files.readAllBytes(Paths.get("/proc/cpuinfo")), "UTF-8"));
246 > //             matcher.find();
247 > //             return matcher.group(1);
248 > //         } catch (Exception ex) { return null; }
249 > //     }
250 >
251 >    public void runBare() throws Throwable {
252 >        currentTestCase = this;
253          if (methodFilter == null
254 <            || methodFilter.matcher(toString()).find()) {
255 <            for (int i = 0; i < runsPerTest; i++) {
256 <                if (profileTests)
257 <                    runTestProfiled();
258 <                else
259 <                    super.runTest();
260 <            }
254 >            || methodFilter.matcher(toString()).find())
255 >            super.runBare();
256 >    }
257 >
258 >    protected void runTest() throws Throwable {
259 >        for (int i = 0; i < runsPerTest; i++) {
260 >            // currentRun = i;
261 >            if (profileTests)
262 >                runTestProfiled();
263 >            else
264 >                super.runTest();
265          }
266      }
267  
268      protected void runTestProfiled() throws Throwable {
269 <        // Warmup run, notably to trigger all needed classloading.
270 <        super.runTest();
189 <        long t0 = System.nanoTime();
190 <        try {
269 >        for (int i = 0; i < 2; i++) {
270 >            long startTime = System.nanoTime();
271              super.runTest();
272 <        } finally {
273 <            long elapsedMillis = millisElapsedSince(t0);
274 <            if (elapsedMillis >= profileThreshold)
272 >            long elapsedMillis = millisElapsedSince(startTime);
273 >            if (elapsedMillis < profileThreshold)
274 >                break;
275 >            // Never report first run of any test; treat it as a
276 >            // warmup run, notably to trigger all needed classloading,
277 >            if (i > 0)
278                  System.out.printf("%n%s: %d%n", toString(), elapsedMillis);
279          }
280      }
281  
282      /**
283       * Runs all JSR166 unit tests using junit.textui.TestRunner.
201     * Optional command line arg provides the number of iterations to
202     * repeat running the tests.
284       */
285      public static void main(String[] args) {
286 +        main(suite(), args);
287 +    }
288 +
289 +    static class PithyResultPrinter extends junit.textui.ResultPrinter {
290 +        PithyResultPrinter(java.io.PrintStream writer) { super(writer); }
291 +        long runTime;
292 +        public void startTest(Test test) {}
293 +        protected void printHeader(long runTime) {
294 +            this.runTime = runTime; // defer printing for later
295 +        }
296 +        protected void printFooter(TestResult result) {
297 +            if (result.wasSuccessful()) {
298 +                getWriter().println("OK (" + result.runCount() + " tests)"
299 +                    + "  Time: " + elapsedTimeAsString(runTime));
300 +            } else {
301 +                getWriter().println("Time: " + elapsedTimeAsString(runTime));
302 +                super.printFooter(result);
303 +            }
304 +        }
305 +    }
306 +
307 +    /**
308 +     * Returns a TestRunner that doesn't bother with unnecessary
309 +     * fluff, like printing a "." for each test case.
310 +     */
311 +    static junit.textui.TestRunner newPithyTestRunner() {
312 +        junit.textui.TestRunner runner = new junit.textui.TestRunner();
313 +        runner.setPrinter(new PithyResultPrinter(System.out));
314 +        return runner;
315 +    }
316 +
317 +    /**
318 +     * Runs all unit tests in the given test suite.
319 +     * Actual behavior influenced by jsr166.* system properties.
320 +     */
321 +    static void main(Test suite, String[] args) {
322          if (useSecurityManager) {
323              System.err.println("Setting a permissive security manager");
324              Policy.setPolicy(permissivePolicy());
325              System.setSecurityManager(new SecurityManager());
326          }
327 <        int iters = (args.length == 0) ? 1 : Integer.parseInt(args[0]);
328 <
329 <        Test s = suite();
330 <        for (int i = 0; i < iters; ++i) {
214 <            junit.textui.TestRunner.run(s);
327 >        for (int i = 0; i < suiteRuns; i++) {
328 >            TestResult result = newPithyTestRunner().doRun(suite);
329 >            if (!result.wasSuccessful())
330 >                System.exit(1);
331              System.gc();
332              System.runFinalization();
333          }
218        System.exit(0);
334      }
335  
336      public static TestSuite newTestSuite(Object... suiteOrClasses) {
# Line 266 | Line 381 | public class JSR166TestCase extends Test
381      public static boolean atLeastJava7() { return JAVA_CLASS_VERSION >= 51.0; }
382      public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; }
383      public static boolean atLeastJava9() {
384 <        // As of 2014-05, java9 still uses 52.0 class file version
385 <        return JAVA_SPECIFICATION_VERSION.startsWith("1.9");
384 >        return JAVA_CLASS_VERSION >= 53.0
385 >            // As of 2015-09, java9 still uses 52.0 class file version
386 >            || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?(9|[0-9][0-9])$");
387 >    }
388 >    public static boolean atLeastJava10() {
389 >        return JAVA_CLASS_VERSION >= 54.0
390 >            || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?[0-9][0-9]$");
391      }
392  
393      /**
# Line 356 | Line 476 | public class JSR166TestCase extends Test
476                  "LongAdderTest",
477                  "SplittableRandomTest",
478                  "StampedLockTest",
479 +                "SubmissionPublisherTest",
480                  "ThreadLocalRandom8Test",
481              };
482              addNamedTestClasses(suite, java8TestClassNames);
# Line 364 | Line 485 | public class JSR166TestCase extends Test
485          // Java9+ test classes
486          if (atLeastJava9()) {
487              String[] java9TestClassNames = {
488 <                "ThreadPoolExecutor9Test",
488 >                // Currently empty, but expecting varhandle tests
489              };
490              addNamedTestClasses(suite, java9TestClassNames);
491          }
# Line 372 | Line 493 | public class JSR166TestCase extends Test
493          return suite;
494      }
495  
496 +    /** Returns list of junit-style test method names in given class. */
497 +    public static ArrayList<String> testMethodNames(Class<?> testClass) {
498 +        Method[] methods = testClass.getDeclaredMethods();
499 +        ArrayList<String> names = new ArrayList<String>(methods.length);
500 +        for (Method method : methods) {
501 +            if (method.getName().startsWith("test")
502 +                && Modifier.isPublic(method.getModifiers())
503 +                // method.getParameterCount() requires jdk8+
504 +                && method.getParameterTypes().length == 0) {
505 +                names.add(method.getName());
506 +            }
507 +        }
508 +        return names;
509 +    }
510 +
511 +    /**
512 +     * Returns junit-style testSuite for the given test class, but
513 +     * parameterized by passing extra data to each test.
514 +     */
515 +    public static <ExtraData> Test parameterizedTestSuite
516 +        (Class<? extends JSR166TestCase> testClass,
517 +         Class<ExtraData> dataClass,
518 +         ExtraData data) {
519 +        try {
520 +            TestSuite suite = new TestSuite();
521 +            Constructor c =
522 +                testClass.getDeclaredConstructor(dataClass, String.class);
523 +            for (String methodName : testMethodNames(testClass))
524 +                suite.addTest((Test) c.newInstance(data, methodName));
525 +            return suite;
526 +        } catch (Exception e) {
527 +            throw new Error(e);
528 +        }
529 +    }
530 +
531 +    /**
532 +     * Returns junit-style testSuite for the jdk8 extension of the
533 +     * given test class, but parameterized by passing extra data to
534 +     * each test.  Uses reflection to allow compilation in jdk7.
535 +     */
536 +    public static <ExtraData> Test jdk8ParameterizedTestSuite
537 +        (Class<? extends JSR166TestCase> testClass,
538 +         Class<ExtraData> dataClass,
539 +         ExtraData data) {
540 +        if (atLeastJava8()) {
541 +            String name = testClass.getName();
542 +            String name8 = name.replaceAll("Test$", "8Test");
543 +            if (name.equals(name8)) throw new Error(name);
544 +            try {
545 +                return (Test)
546 +                    Class.forName(name8)
547 +                    .getMethod("testSuite", new Class[] { dataClass })
548 +                    .invoke(null, data);
549 +            } catch (Exception e) {
550 +                throw new Error(e);
551 +            }
552 +        } else {
553 +            return new TestSuite();
554 +        }
555 +    }
556 +
557      // Delays for timing-dependent tests, in milliseconds.
558  
559      public static long SHORT_DELAY_MS;
# Line 380 | Line 562 | public class JSR166TestCase extends Test
562      public static long LONG_DELAY_MS;
563  
564      /**
565 <     * Returns the shortest timed delay. This could
566 <     * be reimplemented to use for example a Property.
565 >     * Returns the shortest timed delay. This can be scaled up for
566 >     * slow machines using the jsr166.delay.factor system property.
567       */
568      protected long getShortDelay() {
569 <        return 50;
569 >        return 50 * delayFactor;
570      }
571  
572      /**
# Line 406 | Line 588 | public class JSR166TestCase extends Test
588      }
589  
590      /**
591 <     * Returns a new Date instance representing a time delayMillis
592 <     * milliseconds in the future.
591 >     * Returns a new Date instance representing a time at least
592 >     * delayMillis milliseconds in the future.
593       */
594      Date delayedDate(long delayMillis) {
595 <        return new Date(System.currentTimeMillis() + delayMillis);
595 >        // Add 1 because currentTimeMillis is known to round into the past.
596 >        return new Date(System.currentTimeMillis() + delayMillis + 1);
597      }
598  
599      /**
# Line 426 | Line 609 | public class JSR166TestCase extends Test
609       * the same test have no effect.
610       */
611      public void threadRecordFailure(Throwable t) {
612 +        System.err.println(t);
613 +        dumpTestThreads();
614          threadFailure.compareAndSet(null, t);
615      }
616  
# Line 433 | Line 618 | public class JSR166TestCase extends Test
618          setDelays();
619      }
620  
621 +    void tearDownFail(String format, Object... args) {
622 +        String msg = toString() + ": " + String.format(format, args);
623 +        System.err.println(msg);
624 +        dumpTestThreads();
625 +        throw new AssertionFailedError(msg);
626 +    }
627 +
628      /**
629       * Extra checks that get done for all test cases.
630       *
# Line 460 | Line 652 | public class JSR166TestCase extends Test
652          }
653  
654          if (Thread.interrupted())
655 <            throw new AssertionFailedError("interrupt status set in main thread");
655 >            tearDownFail("interrupt status set in main thread");
656  
657          checkForkJoinPoolThreadLeaks();
658      }
659  
660      /**
661 <     * Finds missing try { ... } finally { joinPool(e); }
661 >     * Finds missing PoolCleaners
662       */
663      void checkForkJoinPoolThreadLeaks() throws InterruptedException {
664 <        Thread[] survivors = new Thread[5];
664 >        Thread[] survivors = new Thread[7];
665          int count = Thread.enumerate(survivors);
666          for (int i = 0; i < count; i++) {
667              Thread thread = survivors[i];
# Line 477 | Line 669 | public class JSR166TestCase extends Test
669              if (name.startsWith("ForkJoinPool-")) {
670                  // give thread some time to terminate
671                  thread.join(LONG_DELAY_MS);
672 <                if (!thread.isAlive()) continue;
673 <                thread.stop();
674 <                throw new AssertionFailedError
483 <                    (String.format("Found leaked ForkJoinPool thread test=%s thread=%s%n",
484 <                                   toString(), name));
672 >                if (thread.isAlive())
673 >                    tearDownFail("Found leaked ForkJoinPool thread thread=%s",
674 >                                 thread);
675              }
676          }
677 +
678 +        if (!ForkJoinPool.commonPool()
679 +            .awaitQuiescence(LONG_DELAY_MS, MILLISECONDS))
680 +            tearDownFail("ForkJoin common pool thread stuck");
681      }
682  
683      /**
# Line 496 | Line 690 | public class JSR166TestCase extends Test
690              fail(reason);
691          } catch (AssertionFailedError t) {
692              threadRecordFailure(t);
693 <            fail(reason);
693 >            throw t;
694          }
695      }
696  
# Line 623 | Line 817 | public class JSR166TestCase extends Test
817      /**
818       * Delays, via Thread.sleep, for the given millisecond delay, but
819       * if the sleep is shorter than specified, may re-sleep or yield
820 <     * until time elapses.
820 >     * until time elapses.  Ensures that the given time, as measured
821 >     * by System.nanoTime(), has elapsed.
822       */
823      static void delay(long millis) throws InterruptedException {
824 <        long startTime = System.nanoTime();
825 <        long ns = millis * 1000 * 1000;
826 <        for (;;) {
824 >        long nanos = millis * (1000 * 1000);
825 >        final long wakeupTime = System.nanoTime() + nanos;
826 >        do {
827              if (millis > 0L)
828                  Thread.sleep(millis);
829              else // too short to sleep
830                  Thread.yield();
831 <            long d = ns - (System.nanoTime() - startTime);
832 <            if (d > 0L)
833 <                millis = d / (1000 * 1000);
834 <            else
835 <                break;
831 >            nanos = wakeupTime - System.nanoTime();
832 >            millis = nanos / (1000 * 1000);
833 >        } while (nanos >= 0L);
834 >    }
835 >
836 >    /**
837 >     * Allows use of try-with-resources with per-test thread pools.
838 >     */
839 >    class PoolCleaner implements AutoCloseable {
840 >        private final ExecutorService pool;
841 >        public PoolCleaner(ExecutorService pool) { this.pool = pool; }
842 >        public void close() { joinPool(pool); }
843 >    }
844 >
845 >    /**
846 >     * An extension of PoolCleaner that has an action to release the pool.
847 >     */
848 >    class PoolCleanerWithReleaser extends PoolCleaner {
849 >        private final Runnable releaser;
850 >        public PoolCleanerWithReleaser(ExecutorService pool, Runnable releaser) {
851 >            super(pool);
852 >            this.releaser = releaser;
853          }
854 +        public void close() {
855 +            try {
856 +                releaser.run();
857 +            } finally {
858 +                super.close();
859 +            }
860 +        }
861 +    }
862 +
863 +    PoolCleaner cleaner(ExecutorService pool) {
864 +        return new PoolCleaner(pool);
865 +    }
866 +
867 +    PoolCleaner cleaner(ExecutorService pool, Runnable releaser) {
868 +        return new PoolCleanerWithReleaser(pool, releaser);
869 +    }
870 +
871 +    PoolCleaner cleaner(ExecutorService pool, CountDownLatch latch) {
872 +        return new PoolCleanerWithReleaser(pool, releaser(latch));
873 +    }
874 +
875 +    Runnable releaser(final CountDownLatch latch) {
876 +        return new Runnable() { public void run() {
877 +            do { latch.countDown(); }
878 +            while (latch.getCount() > 0);
879 +        }};
880      }
881  
882      /**
883       * Waits out termination of a thread pool or fails doing so.
884       */
885 <    void joinPool(ExecutorService exec) {
885 >    void joinPool(ExecutorService pool) {
886          try {
887 <            exec.shutdown();
888 <            if (!exec.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS))
889 <                fail("ExecutorService " + exec +
890 <                     " did not terminate in a timely manner");
887 >            pool.shutdown();
888 >            if (!pool.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS)) {
889 >                try {
890 >                    threadFail("ExecutorService " + pool +
891 >                               " did not terminate in a timely manner");
892 >                } finally {
893 >                    // last resort, for the benefit of subsequent tests
894 >                    pool.shutdownNow();
895 >                    pool.awaitTermination(MEDIUM_DELAY_MS, MILLISECONDS);
896 >                }
897 >            }
898          } catch (SecurityException ok) {
899              // Allowed in case test doesn't have privs
900          } catch (InterruptedException fail) {
901 <            fail("Unexpected InterruptedException");
901 >            threadFail("Unexpected InterruptedException");
902          }
903      }
904  
905 +    /** Like Runnable, but with the freedom to throw anything */
906 +    interface Action { public void run() throws Throwable; }
907 +
908      /**
909 <     * A debugging tool to print all stack traces, as jstack does.
909 >     * Runs all the given actions in parallel, failing if any fail.
910 >     * Useful for running multiple variants of tests that are
911 >     * necessarily individually slow because they must block.
912       */
913 <    static void printAllStackTraces() {
914 <        for (ThreadInfo info :
915 <                 ManagementFactory.getThreadMXBean()
916 <                 .dumpAllThreads(true, true))
913 >    void testInParallel(Action ... actions) {
914 >        ExecutorService pool = Executors.newCachedThreadPool();
915 >        try (PoolCleaner cleaner = cleaner(pool)) {
916 >            ArrayList<Future<?>> futures = new ArrayList<>(actions.length);
917 >            for (final Action action : actions)
918 >                futures.add(pool.submit(new CheckedRunnable() {
919 >                    public void realRun() throws Throwable { action.run();}}));
920 >            for (Future<?> future : futures)
921 >                try {
922 >                    assertNull(future.get(LONG_DELAY_MS, MILLISECONDS));
923 >                } catch (ExecutionException ex) {
924 >                    threadUnexpectedException(ex.getCause());
925 >                } catch (Exception ex) {
926 >                    threadUnexpectedException(ex);
927 >                }
928 >        }
929 >    }
930 >
931 >    /**
932 >     * A debugging tool to print stack traces of most threads, as jstack does.
933 >     * Uninteresting threads are filtered out.
934 >     */
935 >    static void dumpTestThreads() {
936 >        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
937 >        System.err.println("------ stacktrace dump start ------");
938 >        for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
939 >            String name = info.getThreadName();
940 >            if ("Signal Dispatcher".equals(name))
941 >                continue;
942 >            if ("Reference Handler".equals(name)
943 >                && info.getLockName().startsWith("java.lang.ref.Reference$Lock"))
944 >                continue;
945 >            if ("Finalizer".equals(name)
946 >                && info.getLockName().startsWith("java.lang.ref.ReferenceQueue$Lock"))
947 >                continue;
948 >            if ("checkForWedgedTest".equals(name))
949 >                continue;
950              System.err.print(info);
951 +        }
952 +        System.err.println("------ stacktrace dump end ------");
953      }
954  
955      /**
# Line 684 | Line 969 | public class JSR166TestCase extends Test
969              delay(millis);
970              assertTrue(thread.isAlive());
971          } catch (InterruptedException fail) {
972 <            fail("Unexpected InterruptedException");
972 >            threadFail("Unexpected InterruptedException");
973          }
974      }
975  
# Line 706 | Line 991 | public class JSR166TestCase extends Test
991              for (Thread thread : threads)
992                  assertTrue(thread.isAlive());
993          } catch (InterruptedException fail) {
994 <            fail("Unexpected InterruptedException");
994 >            threadFail("Unexpected InterruptedException");
995          }
996      }
997  
# Line 984 | Line 1269 | public class JSR166TestCase extends Test
1269          } finally {
1270              if (t.getState() != Thread.State.TERMINATED) {
1271                  t.interrupt();
1272 <                fail("Test timed out");
1272 >                threadFail("timed out waiting for thread to terminate");
1273              }
1274          }
1275      }
# Line 1109 | Line 1394 | public class JSR166TestCase extends Test
1394      public static final String TEST_STRING = "a test string";
1395  
1396      public static class StringTask implements Callable<String> {
1397 <        public String call() { return TEST_STRING; }
1397 >        final String value;
1398 >        public StringTask() { this(TEST_STRING); }
1399 >        public StringTask(String value) { this.value = value; }
1400 >        public String call() { return value; }
1401      }
1402  
1403      public Callable<String> latchAwaitingStringTask(final CountDownLatch latch) {
# Line 1122 | Line 1410 | public class JSR166TestCase extends Test
1410              }};
1411      }
1412  
1413 <    public Runnable awaiter(final CountDownLatch latch) {
1413 >    public Runnable countDowner(final CountDownLatch latch) {
1414          return new CheckedRunnable() {
1415              public void realRun() throws InterruptedException {
1416 <                await(latch);
1416 >                latch.countDown();
1417              }};
1418      }
1419  
1420 +    class LatchAwaiter extends CheckedRunnable {
1421 +        static final int NEW = 0;
1422 +        static final int RUNNING = 1;
1423 +        static final int DONE = 2;
1424 +        final CountDownLatch latch;
1425 +        int state = NEW;
1426 +        LatchAwaiter(CountDownLatch latch) { this.latch = latch; }
1427 +        public void realRun() throws InterruptedException {
1428 +            state = 1;
1429 +            await(latch);
1430 +            state = 2;
1431 +        }
1432 +    }
1433 +
1434 +    public LatchAwaiter awaiter(CountDownLatch latch) {
1435 +        return new LatchAwaiter(latch);
1436 +    }
1437 +
1438      public void await(CountDownLatch latch) {
1439          try {
1440 <            assertTrue(latch.await(LONG_DELAY_MS, MILLISECONDS));
1440 >            if (!latch.await(LONG_DELAY_MS, MILLISECONDS))
1441 >                fail("timed out waiting for CountDownLatch for "
1442 >                     + (LONG_DELAY_MS/1000) + " sec");
1443          } catch (Throwable fail) {
1444              threadUnexpectedException(fail);
1445          }
# Line 1139 | Line 1447 | public class JSR166TestCase extends Test
1447  
1448      public void await(Semaphore semaphore) {
1449          try {
1450 <            assertTrue(semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS));
1450 >            if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS))
1451 >                fail("timed out waiting for Semaphore for "
1452 >                     + (LONG_DELAY_MS/1000) + " sec");
1453          } catch (Throwable fail) {
1454              threadUnexpectedException(fail);
1455          }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines