--- jsr166/src/test/tck/JSR166TestCase.java 2010/10/06 02:58:04 1.59 +++ jsr166/src/test/tck/JSR166TestCase.java 2010/11/29 07:39:53 1.73 @@ -7,10 +7,13 @@ */ import junit.framework.*; +import java.util.Arrays; +import java.util.NoSuchElementException; import java.util.PropertyPermission; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; @@ -96,6 +99,42 @@ public class JSR166TestCase extends Test private static final boolean useSecurityManager = Boolean.getBoolean("jsr166.useSecurityManager"); + protected static final boolean expensiveTests = + Boolean.getBoolean("jsr166.expensiveTests"); + + /** + * If true, report on stdout all "slow" tests, that is, ones that + * take more than profileThreshold milliseconds to execute. + */ + private static final boolean profileTests = + Boolean.getBoolean("jsr166.profileTests"); + + /** + * The number of milliseconds that tests are permitted for + * execution without being reported, when profileTests is set. + */ + private static final long profileThreshold = + Long.getLong("jsr166.profileThreshold", 100); + + protected void runTest() throws Throwable { + if (profileTests) + runTestProfiled(); + else + super.runTest(); + } + + protected void runTestProfiled() throws Throwable { + long t0 = System.nanoTime(); + try { + super.runTest(); + } finally { + long elapsedMillis = + (System.nanoTime() - t0) / (1000L * 1000L); + if (elapsedMillis >= profileThreshold) + System.out.printf("%n%s: %d%n", toString(), elapsedMillis); + } + } + /** * Runs all JSR166 unit tests using junit.textui.TestRunner */ @@ -116,78 +155,88 @@ public class JSR166TestCase extends Test System.exit(0); } + public static TestSuite newTestSuite(Object... suiteOrClasses) { + TestSuite suite = new TestSuite(); + for (Object suiteOrClass : suiteOrClasses) { + if (suiteOrClass instanceof TestSuite) + suite.addTest((TestSuite) suiteOrClass); + else if (suiteOrClass instanceof Class) + suite.addTest(new TestSuite((Class) suiteOrClass)); + else + throw new ClassCastException("not a test suite or class"); + } + return suite; + } + /** - * Collects all JSR166 unit tests as one suite + * Collects all JSR166 unit tests as one suite. */ public static Test suite() { - TestSuite suite = new TestSuite("JSR166 Unit Tests"); - - 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; + return newTestSuite( + ForkJoinPoolTest.suite(), + ForkJoinTaskTest.suite(), + RecursiveActionTest.suite(), + RecursiveTaskTest.suite(), + LinkedTransferQueueTest.suite(), + PhaserTest.suite(), + ThreadLocalRandomTest.suite(), + AbstractExecutorServiceTest.suite(), + AbstractQueueTest.suite(), + AbstractQueuedSynchronizerTest.suite(), + AbstractQueuedLongSynchronizerTest.suite(), + ArrayBlockingQueueTest.suite(), + ArrayDequeTest.suite(), + AtomicBooleanTest.suite(), + AtomicIntegerArrayTest.suite(), + AtomicIntegerFieldUpdaterTest.suite(), + AtomicIntegerTest.suite(), + AtomicLongArrayTest.suite(), + AtomicLongFieldUpdaterTest.suite(), + AtomicLongTest.suite(), + AtomicMarkableReferenceTest.suite(), + AtomicReferenceArrayTest.suite(), + AtomicReferenceFieldUpdaterTest.suite(), + AtomicReferenceTest.suite(), + AtomicStampedReferenceTest.suite(), + ConcurrentHashMapTest.suite(), + ConcurrentLinkedDequeTest.suite(), + ConcurrentLinkedQueueTest.suite(), + ConcurrentSkipListMapTest.suite(), + ConcurrentSkipListSubMapTest.suite(), + ConcurrentSkipListSetTest.suite(), + ConcurrentSkipListSubSetTest.suite(), + CopyOnWriteArrayListTest.suite(), + CopyOnWriteArraySetTest.suite(), + CountDownLatchTest.suite(), + CyclicBarrierTest.suite(), + DelayQueueTest.suite(), + EntryTest.suite(), + ExchangerTest.suite(), + ExecutorsTest.suite(), + ExecutorCompletionServiceTest.suite(), + FutureTaskTest.suite(), + LinkedBlockingDequeTest.suite(), + LinkedBlockingQueueTest.suite(), + LinkedListTest.suite(), + LockSupportTest.suite(), + PriorityBlockingQueueTest.suite(), + PriorityQueueTest.suite(), + ReentrantLockTest.suite(), + ReentrantReadWriteLockTest.suite(), + ScheduledExecutorTest.suite(), + ScheduledExecutorSubclassTest.suite(), + SemaphoreTest.suite(), + SynchronousQueueTest.suite(), + SystemTest.suite(), + ThreadLocalTest.suite(), + ThreadPoolExecutorTest.suite(), + ThreadPoolExecutorSubclassTest.suite(), + ThreadTest.suite(), + TimeUnitTest.suite(), + TreeMapTest.suite(), + TreeSetTest.suite(), + TreeSubMapTest.suite(), + TreeSubSetTest.suite()); } @@ -213,7 +262,7 @@ public class JSR166TestCase extends Test SHORT_DELAY_MS = getShortDelay(); 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 * 200; } /** @@ -242,7 +291,7 @@ public class JSR166TestCase extends Test * earlier by threadRecordFailure. */ public void tearDown() throws Exception { - Throwable t = threadFailure.get(); + Throwable t = threadFailure.getAndSet(null); if (t != null) { if (t instanceof Error) throw (Error) t; @@ -400,7 +449,7 @@ public class JSR166TestCase extends Test try { exec.shutdown(); assertTrue("ExecutorService did not terminate in a timely manner", - exec.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + exec.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS)); } catch (SecurityException ok) { // Allowed in case test doesn't have privs } catch (InterruptedException ie) { @@ -534,6 +583,21 @@ public class JSR166TestCase extends Test } /** + * Sleeps until the given time has elapsed. + * Throws AssertionFailedError if interrupted. + */ + void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException ie) { + AssertionFailedError afe = + new AssertionFailedError("Unexpected InterruptedException"); + afe.initCause(ie); + throw afe; + } + } + + /** * Sleeps until the timeout has elapsed, or interrupted. * Does NOT throw InterruptedException. */ @@ -544,6 +608,38 @@ public class JSR166TestCase extends Test } /** + * Waits up to the specified number of milliseconds for the given + * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING. + */ + void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) { + long timeoutNanos = timeoutMillis * 1000L * 1000L; + long t0 = System.nanoTime(); + for (;;) { + Thread.State s = thread.getState(); + if (s == Thread.State.BLOCKED || + s == Thread.State.WAITING || + s == Thread.State.TIMED_WAITING) + return; + else if (s == Thread.State.TERMINATED) + fail("Unexpected thread termination"); + else if (System.nanoTime() - t0 > timeoutNanos) { + threadAssertTrue(thread.isAlive()); + return; + } + Thread.yield(); + } + } + + /** + * Returns the number of milliseconds since time given by + * startNanoTime, which must have been previously returned from a + * call to {@link System.nanoTime()}. + */ + long millisElapsedSince(long startNanoTime) { + return NANOSECONDS.toMillis(System.nanoTime() - startNanoTime); + } + + /** * Returns a new started daemon Thread running the given runnable. */ Thread newStartedThread(Runnable runnable) { @@ -685,7 +781,7 @@ public class JSR166TestCase extends Test public Callable latchAwaitingStringTask(final CountDownLatch latch) { return new CheckedCallable() { - public String realCall() { + protected String realCall() { try { latch.await(); } catch (InterruptedException quittingTime) {} @@ -693,6 +789,13 @@ public class JSR166TestCase extends Test }}; } + public Runnable awaiter(final CountDownLatch latch) { + return new CheckedRunnable() { + public void realRun() throws InterruptedException { + latch.await(); + }}; + } + public static class NPETask implements Callable { public String call() { throw new NullPointerException(); } } @@ -746,6 +849,15 @@ public class JSR166TestCase extends Test } } + public Runnable possiblyInterruptedRunnable(final long timeoutMillis) { + return new CheckedRunnable() { + protected void realRun() { + try { + Thread.sleep(timeoutMillis); + } catch (InterruptedException ok) {} + }}; + } + public class MediumPossiblyInterruptedRunnable extends CheckedRunnable { protected void realRun() { try { @@ -771,10 +883,37 @@ public class JSR166TestCase extends Test } } + public interface TrackedRunnable extends Runnable { + boolean isDone(); + } + + public static TrackedRunnable trackedRunnable(final long timeoutMillis) { + return new TrackedRunnable() { + private volatile boolean done = false; + public boolean isDone() { return done; } + public void run() { + try { + Thread.sleep(timeoutMillis); + done = true; + } catch (InterruptedException ok) {} + } + }; + } + public static class TrackedShortRunnable implements Runnable { public volatile boolean done = false; public void run() { try { + Thread.sleep(SHORT_DELAY_MS); + done = true; + } catch (InterruptedException ok) {} + } + } + + public static class TrackedSmallRunnable implements Runnable { + public volatile boolean done = false; + public void run() { + try { Thread.sleep(SMALL_DELAY_MS); done = true; } catch (InterruptedException ok) {} @@ -858,4 +997,50 @@ public class JSR166TestCase extends Test ThreadPoolExecutor executor) {} } + /** + * A CyclicBarrier that fails with AssertionFailedErrors instead + * of throwing checked exceptions. + */ + public class CheckedBarrier extends CyclicBarrier { + public CheckedBarrier(int parties) { super(parties); } + + public int await() { + try { + return super.await(); + } catch (Exception e) { + AssertionFailedError afe = + new AssertionFailedError("Unexpected exception: " + e); + afe.initCause(e); + throw afe; + } + } + } + + public void checkEmpty(BlockingQueue q) { + try { + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertNull(q.peek()); + assertNull(q.poll()); + assertNull(q.poll(0, MILLISECONDS)); + assertEquals(q.toString(), "[]"); + assertTrue(Arrays.equals(q.toArray(), new Object[0])); + assertFalse(q.iterator().hasNext()); + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + q.iterator().next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } catch (InterruptedException ie) { + threadUnexpectedException(ie); + } + } + }