--- jsr166/src/test/tck/JSR166TestCase.java 2013/01/21 19:43:52 1.95 +++ jsr166/src/test/tck/JSR166TestCase.java 2013/03/20 20:29:02 1.103 @@ -11,6 +11,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -179,11 +182,42 @@ public class JSR166TestCase extends Test return suite; } + public static void addNamedTestClasses(TestSuite suite, + String... testClassNames) { + for (String testClassName : testClassNames) { + try { + Class testClass = Class.forName(testClassName); + Method m = testClass.getDeclaredMethod("suite", + new Class[0]); + suite.addTest(newTestSuite((Test)m.invoke(null))); + } catch (Exception e) { + throw new Error("Missing test class", e); + } + } + } + + public static final double JAVA_CLASS_VERSION; + static { + try { + JAVA_CLASS_VERSION = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Double run() { + return Double.valueOf(System.getProperty("java.class.version"));}}); + } catch (Throwable t) { + throw new Error(t); + } + } + + public static boolean atLeastJava6() { return JAVA_CLASS_VERSION >= 50.0; } + public static boolean atLeastJava7() { return JAVA_CLASS_VERSION >= 51.0; } + public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; } + /** * Collects all JSR166 unit tests as one suite. */ public static Test suite() { - return newTestSuite( + // Java7+ test classes + TestSuite suite = newTestSuite( ForkJoinPoolTest.suite(), ForkJoinTaskTest.suite(), RecursiveActionTest.suite(), @@ -248,6 +282,22 @@ public class JSR166TestCase extends Test TreeSetTest.suite(), TreeSubMapTest.suite(), TreeSubSetTest.suite()); + + // Java8+ test classes + if (atLeastJava8()) { + String[] java8TestClassNames = { + "LongAdderTest", + "LongAccumulatorTest", + "DoubleAdderTest", + "DoubleAccumulatorTest", + "CompletableFutureTest", + "ForkJoinPool8Test", + "StampedLockTest", + }; + addNamedTestClasses(suite, java8TestClassNames); + } + + return suite; } @@ -339,6 +389,29 @@ public class JSR166TestCase extends Test if (Thread.interrupted()) throw new AssertionFailedError("interrupt status set in main thread"); + + checkForkJoinPoolThreadLeaks(); + } + + /** + * Find missing try { ... } finally { joinPool(e); } + */ + void checkForkJoinPoolThreadLeaks() throws InterruptedException { + Thread[] survivors = new Thread[5]; + int count = Thread.enumerate(survivors); + for (int i = 0; i < count; i++) { + Thread thread = survivors[i]; + String name = thread.getName(); + if (name.startsWith("ForkJoinPool-")) { + // give thread some time to terminate + thread.join(LONG_DELAY_MS); + if (!thread.isAlive()) continue; + thread.stop(); + throw new AssertionFailedError + (String.format("Found leaked ForkJoinPool thread test=%s thread=%s%n", + toString(), name)); + } + } } /** @@ -514,11 +587,11 @@ public class JSR166TestCase extends Test /** * A debugging tool to print all stack traces, as jstack does. */ - void printAllStackTraces() { - System.err.println( - Arrays.toString( - java.lang.management.ManagementFactory.getThreadMXBean() - .dumpAllThreads(true, true))); + static void printAllStackTraces() { + for (ThreadInfo info : + ManagementFactory.getThreadMXBean() + .dumpAllThreads(true, true)) + System.err.print(info); } /**