--- jsr166/src/test/tck/JSR166TestCase.java 2014/12/31 19:05:42 1.123 +++ jsr166/src/test/tck/JSR166TestCase.java 2015/07/03 05:48:30 1.135 @@ -15,7 +15,9 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; @@ -27,6 +29,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Enumeration; +import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.PropertyPermission; @@ -49,6 +52,7 @@ import java.util.regex.Pattern; import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestCase; +import junit.framework.TestResult; import junit.framework.TestSuite; /** @@ -159,6 +163,15 @@ public class JSR166TestCase extends Test Integer.getInteger("jsr166.runsPerTest", 1); /** + * The number of repetitions of the test suite (for finding leaks?). + */ + private static final int suiteRuns = + Integer.getInteger("jsr166.suiteRuns", 1); + + public JSR166TestCase() { super(); } + public JSR166TestCase(String name) { super(name); } + + /** * A filter for tests to run, matching strings of the form * methodName(className), e.g. "testInvokeAll5(ForkJoinPoolTest)" * Usefully combined with jsr166.runsPerTest. @@ -197,24 +210,28 @@ public class JSR166TestCase extends Test /** * Runs all JSR166 unit tests using junit.textui.TestRunner. - * Optional command line arg provides the number of iterations to - * repeat running the tests. */ public static void main(String[] args) { + main(suite(), args); + } + + /** + * Runs all unit tests in the given test suite. + * Actual behavior influenced by jsr166.* system properties. + */ + static void main(Test suite, String[] args) { if (useSecurityManager) { System.err.println("Setting a permissive security manager"); Policy.setPolicy(permissivePolicy()); System.setSecurityManager(new SecurityManager()); } - int iters = (args.length == 0) ? 1 : Integer.parseInt(args[0]); - - Test s = suite(); - for (int i = 0; i < iters; ++i) { - junit.textui.TestRunner.run(s); + for (int i = 0; i < suiteRuns; i++) { + TestResult result = junit.textui.TestRunner.run(suite); + if (!result.wasSuccessful()) + System.exit(1); System.gc(); System.runFinalization(); } - System.exit(0); } public static TestSuite newTestSuite(Object... suiteOrClasses) { @@ -264,10 +281,7 @@ public class JSR166TestCase extends Test 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; } - public static boolean atLeastJava9() { - // As of 2014-05, java9 still uses 52.0 class file version - return JAVA_SPECIFICATION_VERSION.startsWith("1.9"); - } + public static boolean atLeastJava9() { return JAVA_CLASS_VERSION >= 53.0; } /** * Collects all JSR166 unit tests as one suite. @@ -371,6 +385,68 @@ public class JSR166TestCase extends Test return suite; } + /** Returns list of junit-style test method names in given class. */ + public static ArrayList testMethodNames(Class testClass) { + Method[] methods = testClass.getDeclaredMethods(); + ArrayList names = new ArrayList(methods.length); + for (Method method : methods) { + if (method.getName().startsWith("test") + && Modifier.isPublic(method.getModifiers()) + // method.getParameterCount() requires jdk8+ + && method.getParameterTypes().length == 0) { + names.add(method.getName()); + } + } + return names; + } + + /** + * Returns junit-style testSuite for the given test class, but + * parameterized by passing extra data to each test. + */ + public static Test parameterizedTestSuite + (Class testClass, + Class dataClass, + ExtraData data) { + try { + TestSuite suite = new TestSuite(); + Constructor c = + testClass.getDeclaredConstructor(dataClass, String.class); + for (String methodName : testMethodNames(testClass)) + suite.addTest((Test) c.newInstance(data, methodName)); + return suite; + } catch (Exception e) { + throw new Error(e); + } + } + + /** + * Returns junit-style testSuite for the jdk8 extension of the + * given test class, but parameterized by passing extra data to + * each test. Uses reflection to allow compilation in jdk7. + */ + public static Test jdk8ParameterizedTestSuite + (Class testClass, + Class dataClass, + ExtraData data) { + if (atLeastJava8()) { + String name = testClass.getName(); + String name8 = name.replaceAll("Test$", "8Test"); + if (name.equals(name8)) throw new Error(name); + try { + return (Test) + Class.forName(name8) + .getMethod("testSuite", new Class[] { dataClass }) + .invoke(null, data); + } catch (Exception e) { + throw new Error(e); + } + } else { + return new TestSuite(); + } + + } + // Delays for timing-dependent tests, in milliseconds. public static long SHORT_DELAY_MS; @@ -405,11 +481,12 @@ public class JSR166TestCase extends Test } /** - * Returns a new Date instance representing a time delayMillis - * milliseconds in the future. + * Returns a new Date instance representing a time at least + * delayMillis milliseconds in the future. */ Date delayedDate(long delayMillis) { - return new Date(System.currentTimeMillis() + delayMillis); + // Add 1 because currentTimeMillis is known to round into the past. + return new Date(System.currentTimeMillis() + delayMillis + 1); } /** @@ -465,7 +542,7 @@ public class JSR166TestCase extends Test } /** - * Find missing try { ... } finally { joinPool(e); } + * Finds missing try { ... } finally { joinPool(e); } */ void checkForkJoinPoolThreadLeaks() throws InterruptedException { Thread[] survivors = new Thread[5]; @@ -477,7 +554,6 @@ public class JSR166TestCase extends Test // 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)); @@ -563,11 +639,11 @@ public class JSR166TestCase extends Test public void threadAssertEquals(Object x, Object y) { try { assertEquals(x, y); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (AssertionFailedError fail) { + threadRecordFailure(fail); + throw fail; + } catch (Throwable fail) { + threadUnexpectedException(fail); } } @@ -579,9 +655,9 @@ public class JSR166TestCase extends Test public void threadAssertSame(Object x, Object y) { try { assertSame(x, y); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; + } catch (AssertionFailedError fail) { + threadRecordFailure(fail); + throw fail; } } @@ -651,7 +727,7 @@ public class JSR166TestCase extends Test " did not terminate in a timely manner"); } catch (SecurityException ok) { // Allowed in case test doesn't have privs - } catch (InterruptedException ie) { + } catch (InterruptedException fail) { fail("Unexpected InterruptedException"); } } @@ -682,7 +758,7 @@ public class JSR166TestCase extends Test // No need to optimize the failing case via Thread.join. delay(millis); assertTrue(thread.isAlive()); - } catch (InterruptedException ie) { + } catch (InterruptedException fail) { fail("Unexpected InterruptedException"); } } @@ -704,7 +780,7 @@ public class JSR166TestCase extends Test delay(millis); for (Thread thread : threads) assertTrue(thread.isAlive()); - } catch (InterruptedException ie) { + } catch (InterruptedException fail) { fail("Unexpected InterruptedException"); } } @@ -726,8 +802,8 @@ public class JSR166TestCase extends Test future.get(timeoutMillis, MILLISECONDS); shouldThrow(); } catch (TimeoutException success) { - } catch (Exception e) { - threadUnexpectedException(e); + } catch (Exception fail) { + threadUnexpectedException(fail); } finally { future.cancel(true); } assertTrue(millisElapsedSince(startTime) >= timeoutMillis); } @@ -883,10 +959,10 @@ public class JSR166TestCase extends Test void sleep(long millis) { try { delay(millis); - } catch (InterruptedException ie) { + } catch (InterruptedException fail) { AssertionFailedError afe = new AssertionFailedError("Unexpected InterruptedException"); - afe.initCause(ie); + afe.initCause(fail); throw afe; } } @@ -924,7 +1000,7 @@ public class JSR166TestCase extends Test /** * Returns the number of milliseconds since time given by * startNanoTime, which must have been previously returned from a - * call to {@link System.nanoTime()}. + * call to {@link System#nanoTime()}. */ static long millisElapsedSince(long startNanoTime) { return NANOSECONDS.toMillis(System.nanoTime() - startNanoTime); @@ -978,8 +1054,8 @@ public class JSR166TestCase extends Test void awaitTermination(Thread t, long timeoutMillis) { try { t.join(timeoutMillis); - } catch (InterruptedException ie) { - threadUnexpectedException(ie); + } catch (InterruptedException fail) { + threadUnexpectedException(fail); } finally { if (t.getState() != Thread.State.TERMINATED) { t.interrupt(); @@ -1005,8 +1081,8 @@ public class JSR166TestCase extends Test public final void run() { try { realRun(); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); } } } @@ -1060,8 +1136,8 @@ public class JSR166TestCase extends Test threadShouldThrow("InterruptedException"); } catch (InterruptedException success) { threadAssertFalse(Thread.interrupted()); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); } } } @@ -1072,8 +1148,8 @@ public class JSR166TestCase extends Test public final T call() { try { return realCall(); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); return null; } } @@ -1090,8 +1166,8 @@ public class JSR166TestCase extends Test return result; } catch (InterruptedException success) { threadAssertFalse(Thread.interrupted()); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); } return null; } @@ -1131,16 +1207,16 @@ public class JSR166TestCase extends Test public void await(CountDownLatch latch) { try { assertTrue(latch.await(LONG_DELAY_MS, MILLISECONDS)); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); } } public void await(Semaphore semaphore) { try { assertTrue(semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS)); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); } } @@ -1334,8 +1410,8 @@ public class JSR166TestCase extends Test @Override protected final void compute() { try { realCompute(); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); } } } @@ -1349,8 +1425,8 @@ public class JSR166TestCase extends Test @Override protected final T compute() { try { return realCompute(); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); return null; } } @@ -1374,12 +1450,12 @@ public class JSR166TestCase extends Test public int await() { try { return super.await(2 * LONG_DELAY_MS, MILLISECONDS); - } catch (TimeoutException e) { + } catch (TimeoutException timedOut) { throw new AssertionFailedError("timed out"); - } catch (Exception e) { + } catch (Exception fail) { AssertionFailedError afe = - new AssertionFailedError("Unexpected exception: " + e); - afe.initCause(e); + new AssertionFailedError("Unexpected exception: " + fail); + afe.initCause(fail); throw afe; } } @@ -1407,9 +1483,7 @@ public class JSR166TestCase extends Test q.remove(); shouldThrow(); } catch (NoSuchElementException success) {} - } catch (InterruptedException ie) { - threadUnexpectedException(ie); - } + } catch (InterruptedException fail) { threadUnexpectedException(fail); } } void assertSerialEquals(Object x, Object y) { @@ -1428,8 +1502,8 @@ public class JSR166TestCase extends Test oos.flush(); oos.close(); return bos.toByteArray(); - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); return new byte[0]; } } @@ -1442,8 +1516,8 @@ public class JSR166TestCase extends Test T clone = (T) ois.readObject(); assertSame(o.getClass(), clone.getClass()); return clone; - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (Throwable fail) { + threadUnexpectedException(fail); return null; } } @@ -1468,4 +1542,12 @@ public class JSR166TestCase extends Test shouldThrow(expectedExceptionClass.getName()); } } + + public void assertIteratorExhausted(Iterator it) { + try { + it.next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertFalse(it.hasNext()); + } }