--- jsr166/src/test/tck/JSR166TestCase.java 2010/08/25 21:40:03 1.50 +++ jsr166/src/test/tck/JSR166TestCase.java 2010/10/06 02:58:04 1.59 @@ -7,11 +7,17 @@ */ import junit.framework.*; -import java.util.*; +import java.util.PropertyPermission; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import java.io.*; -import java.security.*; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.security.SecurityPermission; /** * Base class for JSR166 Junit TCK tests. Defines some constants, @@ -36,7 +42,7 @@ import java.security.*; * them. These methods are used to clear and check for thread * assertion failures. * - *
  • All delays and timeouts must use one of the constants {@code + *
  • All delays and timeouts must use one of the constants {@code * SHORT_DELAY_MS}, {@code SMALL_DELAY_MS}, {@code MEDIUM_DELAY_MS}, * {@code LONG_DELAY_MS}. The idea here is that a SHORT is always * discriminable from zero time, and always allows enough time for the @@ -99,9 +105,8 @@ public class JSR166TestCase extends Test Policy.setPolicy(permissivePolicy()); System.setSecurityManager(new SecurityManager()); } - int iters = 1; - if (args.length > 0) - iters = Integer.parseInt(args[0]); + 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); @@ -117,70 +122,70 @@ public class JSR166TestCase extends Test public static Test suite() { TestSuite suite = new TestSuite("JSR166 Unit Tests"); - suite.addTest(new TestSuite(ForkJoinPoolTest.class)); - suite.addTest(new TestSuite(ForkJoinTaskTest.class)); - suite.addTest(new TestSuite(RecursiveActionTest.class)); - suite.addTest(new TestSuite(RecursiveTaskTest.class)); - suite.addTest(new TestSuite(LinkedTransferQueueTest.class)); - suite.addTest(new TestSuite(PhaserTest.class)); - suite.addTest(new TestSuite(ThreadLocalRandomTest.class)); - suite.addTest(new TestSuite(AbstractExecutorServiceTest.class)); - suite.addTest(new TestSuite(AbstractQueueTest.class)); - suite.addTest(new TestSuite(AbstractQueuedSynchronizerTest.class)); - suite.addTest(new TestSuite(AbstractQueuedLongSynchronizerTest.class)); - suite.addTest(new TestSuite(ArrayBlockingQueueTest.class)); - suite.addTest(new TestSuite(ArrayDequeTest.class)); - suite.addTest(new TestSuite(AtomicBooleanTest.class)); - suite.addTest(new TestSuite(AtomicIntegerArrayTest.class)); - suite.addTest(new TestSuite(AtomicIntegerFieldUpdaterTest.class)); - suite.addTest(new TestSuite(AtomicIntegerTest.class)); - suite.addTest(new TestSuite(AtomicLongArrayTest.class)); - suite.addTest(new TestSuite(AtomicLongFieldUpdaterTest.class)); - suite.addTest(new TestSuite(AtomicLongTest.class)); - suite.addTest(new TestSuite(AtomicMarkableReferenceTest.class)); - suite.addTest(new TestSuite(AtomicReferenceArrayTest.class)); - suite.addTest(new TestSuite(AtomicReferenceFieldUpdaterTest.class)); - suite.addTest(new TestSuite(AtomicReferenceTest.class)); - suite.addTest(new TestSuite(AtomicStampedReferenceTest.class)); - suite.addTest(new TestSuite(ConcurrentHashMapTest.class)); - suite.addTest(new TestSuite(ConcurrentLinkedDequeTest.class)); - suite.addTest(new TestSuite(ConcurrentLinkedQueueTest.class)); - suite.addTest(new TestSuite(ConcurrentSkipListMapTest.class)); - suite.addTest(new TestSuite(ConcurrentSkipListSubMapTest.class)); - suite.addTest(new TestSuite(ConcurrentSkipListSetTest.class)); - suite.addTest(new TestSuite(ConcurrentSkipListSubSetTest.class)); - suite.addTest(new TestSuite(CopyOnWriteArrayListTest.class)); - suite.addTest(new TestSuite(CopyOnWriteArraySetTest.class)); - suite.addTest(new TestSuite(CountDownLatchTest.class)); - suite.addTest(new TestSuite(CyclicBarrierTest.class)); - suite.addTest(new TestSuite(DelayQueueTest.class)); - suite.addTest(new TestSuite(EntryTest.class)); - suite.addTest(new TestSuite(ExchangerTest.class)); - suite.addTest(new TestSuite(ExecutorsTest.class)); - suite.addTest(new TestSuite(ExecutorCompletionServiceTest.class)); - suite.addTest(new TestSuite(FutureTaskTest.class)); - suite.addTest(new TestSuite(LinkedBlockingDequeTest.class)); - suite.addTest(new TestSuite(LinkedBlockingQueueTest.class)); - suite.addTest(new TestSuite(LinkedListTest.class)); - suite.addTest(new TestSuite(LockSupportTest.class)); - suite.addTest(new TestSuite(PriorityBlockingQueueTest.class)); - suite.addTest(new TestSuite(PriorityQueueTest.class)); - suite.addTest(new TestSuite(ReentrantLockTest.class)); - suite.addTest(new TestSuite(ReentrantReadWriteLockTest.class)); - suite.addTest(new TestSuite(ScheduledExecutorTest.class)); - suite.addTest(new TestSuite(ScheduledExecutorSubclassTest.class)); - suite.addTest(new TestSuite(SemaphoreTest.class)); - suite.addTest(new TestSuite(SynchronousQueueTest.class)); - suite.addTest(new TestSuite(SystemTest.class)); - suite.addTest(new TestSuite(ThreadLocalTest.class)); - suite.addTest(new TestSuite(ThreadPoolExecutorTest.class)); - suite.addTest(new TestSuite(ThreadPoolExecutorSubclassTest.class)); - suite.addTest(new TestSuite(ThreadTest.class)); - suite.addTest(new TestSuite(TimeUnitTest.class)); - suite.addTest(new TestSuite(TreeMapTest.class)); - suite.addTest(new TestSuite(TreeSetTest.class)); - suite.addTest(new TestSuite(TreeSubMapTest.class)); - suite.addTest(new TestSuite(TreeSubSetTest.class)); + suite.addTest(ForkJoinPoolTest.suite()); + suite.addTest(ForkJoinTaskTest.suite()); + suite.addTest(RecursiveActionTest.suite()); + suite.addTest(RecursiveTaskTest.suite()); + suite.addTest(LinkedTransferQueueTest.suite()); + suite.addTest(PhaserTest.suite()); + suite.addTest(ThreadLocalRandomTest.suite()); + suite.addTest(AbstractExecutorServiceTest.suite()); + suite.addTest(AbstractQueueTest.suite()); + suite.addTest(AbstractQueuedSynchronizerTest.suite()); + suite.addTest(AbstractQueuedLongSynchronizerTest.suite()); + suite.addTest(ArrayBlockingQueueTest.suite()); + suite.addTest(ArrayDequeTest.suite()); + suite.addTest(AtomicBooleanTest.suite()); + suite.addTest(AtomicIntegerArrayTest.suite()); + suite.addTest(AtomicIntegerFieldUpdaterTest.suite()); + suite.addTest(AtomicIntegerTest.suite()); + suite.addTest(AtomicLongArrayTest.suite()); + suite.addTest(AtomicLongFieldUpdaterTest.suite()); + suite.addTest(AtomicLongTest.suite()); + suite.addTest(AtomicMarkableReferenceTest.suite()); + suite.addTest(AtomicReferenceArrayTest.suite()); + suite.addTest(AtomicReferenceFieldUpdaterTest.suite()); + suite.addTest(AtomicReferenceTest.suite()); + suite.addTest(AtomicStampedReferenceTest.suite()); + suite.addTest(ConcurrentHashMapTest.suite()); + suite.addTest(ConcurrentLinkedDequeTest.suite()); + suite.addTest(ConcurrentLinkedQueueTest.suite()); + suite.addTest(ConcurrentSkipListMapTest.suite()); + suite.addTest(ConcurrentSkipListSubMapTest.suite()); + suite.addTest(ConcurrentSkipListSetTest.suite()); + suite.addTest(ConcurrentSkipListSubSetTest.suite()); + suite.addTest(CopyOnWriteArrayListTest.suite()); + suite.addTest(CopyOnWriteArraySetTest.suite()); + suite.addTest(CountDownLatchTest.suite()); + suite.addTest(CyclicBarrierTest.suite()); + suite.addTest(DelayQueueTest.suite()); + suite.addTest(EntryTest.suite()); + suite.addTest(ExchangerTest.suite()); + suite.addTest(ExecutorsTest.suite()); + suite.addTest(ExecutorCompletionServiceTest.suite()); + suite.addTest(FutureTaskTest.suite()); + suite.addTest(LinkedBlockingDequeTest.suite()); + suite.addTest(LinkedBlockingQueueTest.suite()); + suite.addTest(LinkedListTest.suite()); + suite.addTest(LockSupportTest.suite()); + suite.addTest(PriorityBlockingQueueTest.suite()); + suite.addTest(PriorityQueueTest.suite()); + suite.addTest(ReentrantLockTest.suite()); + suite.addTest(ReentrantReadWriteLockTest.suite()); + suite.addTest(ScheduledExecutorTest.suite()); + suite.addTest(ScheduledExecutorSubclassTest.suite()); + suite.addTest(SemaphoreTest.suite()); + suite.addTest(SynchronousQueueTest.suite()); + suite.addTest(SystemTest.suite()); + suite.addTest(ThreadLocalTest.suite()); + suite.addTest(ThreadPoolExecutorTest.suite()); + suite.addTest(ThreadPoolExecutorSubclassTest.suite()); + suite.addTest(ThreadTest.suite()); + suite.addTest(TimeUnitTest.suite()); + suite.addTest(TreeMapTest.suite()); + suite.addTest(TreeSetTest.suite()); + suite.addTest(TreeSubMapTest.suite()); + suite.addTest(TreeSubSetTest.suite()); return suite; } @@ -206,134 +211,196 @@ public class JSR166TestCase extends Test */ protected void setDelays() { SHORT_DELAY_MS = getShortDelay(); - SMALL_DELAY_MS = SHORT_DELAY_MS * 5; + SMALL_DELAY_MS = SHORT_DELAY_MS * 5; MEDIUM_DELAY_MS = SHORT_DELAY_MS * 10; - LONG_DELAY_MS = SHORT_DELAY_MS * 50; + LONG_DELAY_MS = SHORT_DELAY_MS * 50; } /** - * Flag set true if any threadAssert methods fail + * The first exception encountered if any threadAssertXXX method fails. */ - volatile boolean threadFailed; + private final AtomicReference threadFailure + = new AtomicReference(null); /** - * Initializes test to indicate that no thread assertions have failed + * Records an exception so that it can be rethrown later in the test + * harness thread, triggering a test case failure. Only the first + * failure is recorded; subsequent calls to this method from within + * the same test have no effect. */ + public void threadRecordFailure(Throwable t) { + threadFailure.compareAndSet(null, t); + } + public void setUp() { setDelays(); - threadFailed = false; } /** - * Triggers test case failure if any thread assertions have failed - */ - public void tearDown() { - assertFalse(threadFailed); + * Triggers test case failure if any thread assertions have failed, + * by rethrowing, in the test harness thread, any exception recorded + * earlier by threadRecordFailure. + */ + public void tearDown() throws Exception { + Throwable t = threadFailure.get(); + if (t != null) { + if (t instanceof Error) + throw (Error) t; + else if (t instanceof RuntimeException) + throw (RuntimeException) t; + else if (t instanceof Exception) + throw (Exception) t; + else { + AssertionFailedError afe = + new AssertionFailedError(t.toString()); + afe.initCause(t); + throw afe; + } + } } /** - * Fail, also setting status to indicate current testcase should fail + * Just like fail(reason), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ public void threadFail(String reason) { - threadFailed = true; - fail(reason); + try { + fail(reason); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + fail(reason); + } } /** - * If expression not true, set status to indicate current testcase - * should fail + * Just like assertTrue(b), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ public void threadAssertTrue(boolean b) { - if (!b) { - threadFailed = true; + try { assertTrue(b); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; } } /** - * If expression not false, set status to indicate current testcase - * should fail + * Just like assertFalse(b), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ public void threadAssertFalse(boolean b) { - if (b) { - threadFailed = true; + try { assertFalse(b); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; } } /** - * If argument not null, set status to indicate current testcase - * should fail + * Just like assertNull(x), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ public void threadAssertNull(Object x) { - if (x != null) { - threadFailed = true; + try { assertNull(x); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; } } /** - * If arguments not equal, set status to indicate current testcase - * should fail + * Just like assertEquals(x, y), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ public void threadAssertEquals(long x, long y) { - if (x != y) { - threadFailed = true; + try { assertEquals(x, y); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; } } /** - * If arguments not equal, set status to indicate current testcase - * should fail + * Just like assertEquals(x, y), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ public void threadAssertEquals(Object x, Object y) { - if (x != y && (x == null || !x.equals(y))) { - threadFailed = true; + try { assertEquals(x, y); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } catch (Throwable t) { + threadUnexpectedException(t); } } /** - * threadFail with message "should throw exception" + * Just like assertSame(x, y), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. */ - public void threadShouldThrow() { - threadFailed = true; - fail("should throw exception"); + public void threadAssertSame(Object x, Object y) { + try { + assertSame(x, y); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } } /** - * threadFail with message "should throw" + exceptionName + * Calls threadFail with message "should throw exception". */ - public void threadShouldThrow(String exceptionName) { - threadFailed = true; - fail("should throw " + exceptionName); + public void threadShouldThrow() { + threadFail("should throw exception"); } /** - * threadFail with message "Unexpected exception" + * Calls threadFail with message "should throw" + exceptionName. */ - public void threadUnexpectedException() { - threadFailed = true; - fail("Unexpected exception"); + public void threadShouldThrow(String exceptionName) { + threadFail("should throw " + exceptionName); } /** - * threadFail with message "Unexpected exception", with argument + * Records the given exception using {@link #threadRecordFailure}, + * then rethrows the exception, wrapping it in an + * AssertionFailedError if necessary. */ - public void threadUnexpectedException(Throwable ex) { - threadFailed = true; - ex.printStackTrace(); - fail("Unexpected exception: " + ex); + public void threadUnexpectedException(Throwable t) { + threadRecordFailure(t); + t.printStackTrace(); + if (t instanceof RuntimeException) + throw (RuntimeException) t; + else if (t instanceof Error) + throw (Error) t; + else { + AssertionFailedError afe = + new AssertionFailedError("unexpected exception: " + t); + t.initCause(t); + throw afe; + } } /** - * Wait out termination of a thread pool or fail doing so + * Waits out termination of a thread pool or fails doing so. */ public void joinPool(ExecutorService exec) { try { exec.shutdown(); - assertTrue(exec.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue("ExecutorService did not terminate in a timely manner", + exec.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } catch (SecurityException ok) { // Allowed in case test doesn't have privs } catch (InterruptedException ie) { @@ -343,36 +410,20 @@ public class JSR166TestCase extends Test /** - * fail with message "should throw exception" + * Fails with message "should throw exception". */ public void shouldThrow() { fail("Should throw exception"); } /** - * fail with message "should throw " + exceptionName + * Fails with message "should throw " + exceptionName. */ public void shouldThrow(String exceptionName) { fail("Should throw " + exceptionName); } /** - * fail with message "Unexpected exception" - */ - public void unexpectedException() { - fail("Unexpected exception"); - } - - /** - * fail with message "Unexpected exception", with argument - */ - public void unexpectedException(Throwable ex) { - ex.printStackTrace(); - fail("Unexpected exception: " + ex); - } - - - /** * The number of elements to place in collections, arrays, etc. */ public static final int SIZE = 20; @@ -483,7 +534,7 @@ public class JSR166TestCase extends Test } /** - * Sleep until the timeout has elapsed, or interrupted. + * Sleeps until the timeout has elapsed, or interrupted. * Does NOT throw InterruptedException. */ void sleepTillInterrupted(long timeoutMillis) { @@ -493,14 +544,33 @@ public class JSR166TestCase extends Test } /** - * Returns a new started Thread running the given runnable. + * Returns a new started daemon Thread running the given runnable. */ Thread newStartedThread(Runnable runnable) { Thread t = new Thread(runnable); + t.setDaemon(true); t.start(); return t; } + /** + * Waits for the specified time (in milliseconds) for the thread + * to terminate (using {@link Thread#join(long)}), else interrupts + * the thread (in the hope that it may terminate later) and fails. + */ + void awaitTermination(Thread t, long timeoutMillis) { + try { + t.join(timeoutMillis); + } catch (InterruptedException ie) { + threadUnexpectedException(ie); + } finally { + if (t.isAlive()) { + t.interrupt(); + fail("Test timed out"); + } + } + } + // Some convenient Runnable classes public abstract class CheckedRunnable implements Runnable { @@ -577,12 +647,13 @@ public class JSR166TestCase extends Test return realCall(); } catch (Throwable t) { threadUnexpectedException(t); + return null; } - return null; } } - public abstract class CheckedInterruptedCallable implements Callable { + public abstract class CheckedInterruptedCallable + implements Callable { protected abstract T realCall() throws Throwable; public final T call() { @@ -663,12 +734,6 @@ public class JSR166TestCase extends Test } } - public class SmallInterruptedRunnable extends CheckedInterruptedRunnable { - protected void realRun() throws InterruptedException { - Thread.sleep(SMALL_DELAY_MS); - } - } - public class MediumRunnable extends CheckedRunnable { protected void realRun() throws Throwable { Thread.sleep(MEDIUM_DELAY_MS); @@ -754,6 +819,36 @@ public class JSR166TestCase extends Test } } + /** + * Analog of CheckedRunnable for RecursiveAction + */ + public abstract class CheckedRecursiveAction extends RecursiveAction { + protected abstract void realCompute() throws Throwable; + + public final void compute() { + try { + realCompute(); + } catch (Throwable t) { + threadUnexpectedException(t); + } + } + } + + /** + * Analog of CheckedCallable for RecursiveTask + */ + public abstract class CheckedRecursiveTask extends RecursiveTask { + protected abstract T realCompute() throws Throwable; + + public final T compute() { + try { + return realCompute(); + } catch (Throwable t) { + threadUnexpectedException(t); + return null; + } + } + } /** * For use as RejectedExecutionHandler in constructors