--- jsr166/src/test/tck/JSR166TestCase.java 2018/04/10 18:09:58 1.244
+++ jsr166/src/test/tck/JSR166TestCase.java 2019/08/11 22:29:26 1.256
@@ -117,13 +117,21 @@ import junit.framework.TestSuite;
*
*
*
- * - All assertions in code running in generated threads must use
- * the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link
- * #threadAssertEquals}, or {@link #threadAssertNull}, (not
- * {@code fail}, {@code assertTrue}, etc.) It is OK (but not
- * particularly recommended) for other code to use these forms too.
- * Only the most typically used JUnit assertion methods are defined
- * this way, but enough to live with.
+ *
- All code not running in the main test thread (manually spawned threads
+ * or the common fork join pool) must be checked for failure (and completion!).
+ * Mechanisms that can be used to ensure this are:
+ *
+ * - Signalling via a synchronizer like AtomicInteger or CountDownLatch
+ * that the task completed normally, which is checked before returning from
+ * the test method in the main thread.
+ *
- Using the forms {@link #threadFail}, {@link #threadAssertTrue},
+ * or {@link #threadAssertNull}, (not {@code fail}, {@code assertTrue}, etc.)
+ * Only the most typically used JUnit assertion methods are defined
+ * this way, but enough to live with.
+ *
- Recording failure explicitly using {@link #threadUnexpectedException}
+ * or {@link #threadRecordFailure}.
+ *
- Using a wrapper like CheckedRunnable that uses one the mechanisms above.
+ *
*
* - If you override {@link #setUp} or {@link #tearDown}, make sure
* to invoke {@code super.setUp} and {@code super.tearDown} within
@@ -280,8 +288,9 @@ public class JSR166TestCase extends Test
// Avoid spurious reports with enormous runsPerTest.
// A single test case run should never take more than 1 second.
// But let's cap it at the high end too ...
- final int timeoutMinutes =
- Math.min(15, Math.max(runsPerTest / 60, 1));
+ final int timeoutMinutesMin = Math.max(runsPerTest / 60, 1)
+ * Math.max((int) delayFactor, 1);
+ final int timeoutMinutes = Math.min(15, timeoutMinutesMin);
for (TestCase lastTestCase = currentTestCase;;) {
try { MINUTES.sleep(timeoutMinutes); }
catch (InterruptedException unexpected) { break; }
@@ -452,6 +461,12 @@ public class JSR166TestCase extends Test
public static boolean atLeastJava9() { return JAVA_CLASS_VERSION >= 53.0; }
public static boolean atLeastJava10() { return JAVA_CLASS_VERSION >= 54.0; }
public static boolean atLeastJava11() { return JAVA_CLASS_VERSION >= 55.0; }
+ public static boolean atLeastJava12() { return JAVA_CLASS_VERSION >= 56.0; }
+ public static boolean atLeastJava13() { return JAVA_CLASS_VERSION >= 57.0; }
+ public static boolean atLeastJava14() { return JAVA_CLASS_VERSION >= 58.0; }
+ public static boolean atLeastJava15() { return JAVA_CLASS_VERSION >= 59.0; }
+ public static boolean atLeastJava16() { return JAVA_CLASS_VERSION >= 60.0; }
+ public static boolean atLeastJava17() { return JAVA_CLASS_VERSION >= 61.0; }
/**
* Collects all JSR166 unit tests as one suite.
@@ -503,6 +518,7 @@ public class JSR166TestCase extends Test
ExecutorsTest.suite(),
ExecutorCompletionServiceTest.suite(),
FutureTaskTest.suite(),
+ HashtableTest.suite(),
LinkedBlockingDequeTest.suite(),
LinkedBlockingQueueTest.suite(),
LinkedListTest.suite(),
@@ -542,6 +558,7 @@ public class JSR166TestCase extends Test
"HashMapTest",
"LinkedBlockingDeque8Test",
"LinkedBlockingQueue8Test",
+ "LinkedHashMapTest",
"LongAccumulatorTest",
"LongAdderTest",
"SplittableRandomTest",
@@ -668,6 +685,13 @@ public class JSR166TestCase extends Test
static TimeUnit randomTimeUnit() { return RANDOM_TIMEUNIT; }
/**
+ * Returns a random boolean; a "coin flip".
+ */
+ static boolean randomBoolean() {
+ return ThreadLocalRandom.current().nextBoolean();
+ }
+
+ /**
* Returns the shortest timed delay. This can be scaled up for
* slow machines using the jsr166.delay.factor system property,
* or via jtreg's -timeoutFactor: flag.
@@ -1291,22 +1315,33 @@ public class JSR166TestCase extends Test
/**
* Spin-waits up to the specified number of milliseconds for the given
* thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
+ * @param waitingForGodot if non-null, an additional condition to satisfy
*/
- void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) {
- long startTime = 0L;
- 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)
+ void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis,
+ Callable waitingForGodot) {
+ for (long startTime = 0L;;) {
+ switch (thread.getState()) {
+ default: break;
+ case BLOCKED: case WAITING: case TIMED_WAITING:
+ try {
+ if (waitingForGodot == null || waitingForGodot.call())
+ return;
+ } catch (Throwable fail) { threadUnexpectedException(fail); }
+ break;
+ case TERMINATED:
fail("Unexpected thread termination");
- else if (startTime == 0L)
+ }
+
+ if (startTime == 0L)
startTime = System.nanoTime();
else if (millisElapsedSince(startTime) > timeoutMillis) {
- threadAssertTrue(thread.isAlive());
- fail("timed out waiting for thread to enter wait state");
+ assertTrue(thread.isAlive());
+ if (waitingForGodot == null
+ || thread.getState() == Thread.State.RUNNABLE)
+ fail("timed out waiting for thread to enter wait state");
+ else
+ fail("timed out waiting for condition, thread state="
+ + thread.getState());
}
Thread.yield();
}
@@ -1314,32 +1349,10 @@ public class JSR166TestCase extends Test
/**
* Spin-waits up to the specified number of milliseconds for the given
- * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING,
- * and additionally satisfy the given condition.
+ * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
*/
- void waitForThreadToEnterWaitState(
- Thread thread, long timeoutMillis, Callable waitingForGodot) {
- long startTime = 0L;
- for (;;) {
- Thread.State s = thread.getState();
- if (s == Thread.State.BLOCKED ||
- s == Thread.State.WAITING ||
- s == Thread.State.TIMED_WAITING) {
- try {
- if (waitingForGodot.call())
- return;
- } catch (Throwable fail) { threadUnexpectedException(fail); }
- }
- else if (s == Thread.State.TERMINATED)
- fail("Unexpected thread termination");
- else if (startTime == 0L)
- startTime = System.nanoTime();
- else if (millisElapsedSince(startTime) > timeoutMillis) {
- threadAssertTrue(thread.isAlive());
- fail("timed out waiting for thread to enter wait state");
- }
- Thread.yield();
- }
+ void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) {
+ waitForThreadToEnterWaitState(thread, timeoutMillis, null);
}
/**
@@ -1347,7 +1360,7 @@ public class JSR166TestCase extends Test
* enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
*/
void waitForThreadToEnterWaitState(Thread thread) {
- waitForThreadToEnterWaitState(thread, LONG_DELAY_MS);
+ waitForThreadToEnterWaitState(thread, LONG_DELAY_MS, null);
}
/**
@@ -1355,8 +1368,8 @@ public class JSR166TestCase extends Test
* enter a wait state: BLOCKED, WAITING, or TIMED_WAITING,
* and additionally satisfy the given condition.
*/
- void waitForThreadToEnterWaitState(
- Thread thread, Callable waitingForGodot) {
+ void waitForThreadToEnterWaitState(Thread thread,
+ Callable waitingForGodot) {
waitForThreadToEnterWaitState(thread, LONG_DELAY_MS, waitingForGodot);
}
@@ -1388,9 +1401,11 @@ public class JSR166TestCase extends Test
*/
void checkTimedGet(Future f, T expectedValue, long timeoutMillis) {
long startTime = System.nanoTime();
+ T actual = null;
try {
- assertEquals(expectedValue, f.get(timeoutMillis, MILLISECONDS));
+ actual = f.get(timeoutMillis, MILLISECONDS);
} catch (Throwable fail) { threadUnexpectedException(fail); }
+ assertEquals(expectedValue, actual);
if (millisElapsedSince(startTime) > timeoutMillis/2)
throw new AssertionError("timed get did not return promptly");
}
@@ -1462,11 +1477,12 @@ public class JSR166TestCase extends Test
public final void run() {
try {
realRun();
- threadShouldThrow(exceptionClass.getSimpleName());
} catch (Throwable t) {
if (! exceptionClass.isInstance(t))
threadUnexpectedException(t);
+ return;
}
+ threadShouldThrow(exceptionClass.getSimpleName());
}
}
@@ -1476,12 +1492,13 @@ public class JSR166TestCase extends Test
public final void run() {
try {
realRun();
- threadShouldThrow("InterruptedException");
} catch (InterruptedException success) {
threadAssertFalse(Thread.interrupted());
+ return;
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
+ threadShouldThrow("InterruptedException");
}
}
@@ -1493,26 +1510,8 @@ public class JSR166TestCase extends Test
return realCall();
} catch (Throwable fail) {
threadUnexpectedException(fail);
- return null;
- }
- }
- }
-
- public abstract class CheckedInterruptedCallable
- implements Callable {
- protected abstract T realCall() throws Throwable;
-
- public final T call() {
- try {
- T result = realCall();
- threadShouldThrow("InterruptedException");
- return result;
- } catch (InterruptedException success) {
- threadAssertFalse(Thread.interrupted());
- } catch (Throwable fail) {
- threadUnexpectedException(fail);
}
- return null;
+ throw new AssertionError("unreached");
}
}
@@ -1569,13 +1568,15 @@ public class JSR166TestCase extends Test
}
public void await(CountDownLatch latch, long timeoutMillis) {
+ boolean timedOut = false;
try {
- if (!latch.await(timeoutMillis, MILLISECONDS))
- fail("timed out waiting for CountDownLatch for "
- + (timeoutMillis/1000) + " sec");
+ timedOut = !latch.await(timeoutMillis, MILLISECONDS);
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
+ if (timedOut)
+ fail("timed out waiting for CountDownLatch for "
+ + (timeoutMillis/1000) + " sec");
}
public void await(CountDownLatch latch) {
@@ -1583,13 +1584,15 @@ public class JSR166TestCase extends Test
}
public void await(Semaphore semaphore) {
+ boolean timedOut = false;
try {
- if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS))
- fail("timed out waiting for Semaphore for "
- + (LONG_DELAY_MS/1000) + " sec");
+ timedOut = !semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS);
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
+ if (timedOut)
+ fail("timed out waiting for Semaphore for "
+ + (LONG_DELAY_MS/1000) + " sec");
}
public void await(CyclicBarrier barrier) {
@@ -1623,14 +1626,6 @@ public class JSR166TestCase extends Test
public String call() { throw new NullPointerException(); }
}
- public class SmallPossiblyInterruptedRunnable extends CheckedRunnable {
- protected void realRun() {
- try {
- delay(SMALL_DELAY_MS);
- } catch (InterruptedException ok) {}
- }
- }
-
public Runnable possiblyInterruptedRunnable(final long timeoutMillis) {
return new CheckedRunnable() {
protected void realRun() {
@@ -1686,8 +1681,8 @@ public class JSR166TestCase extends Test
return realCompute();
} catch (Throwable fail) {
threadUnexpectedException(fail);
- return null;
}
+ throw new AssertionError("unreached");
}
}
@@ -1764,28 +1759,27 @@ public class JSR166TestCase extends Test
}
}
- void assertImmutable(final Object o) {
+ void assertImmutable(Object o) {
if (o instanceof Collection) {
assertThrows(
UnsupportedOperationException.class,
- new Runnable() { public void run() {
- ((Collection) o).add(null);}});
+ () -> ((Collection) o).add(null));
}
}
@SuppressWarnings("unchecked")
T serialClone(T o) {
+ T clone = null;
try {
ObjectInputStream ois = new ObjectInputStream
(new ByteArrayInputStream(serialBytes(o)));
- T clone = (T) ois.readObject();
- if (o == clone) assertImmutable(o);
- assertSame(o.getClass(), clone.getClass());
- return clone;
+ clone = (T) ois.readObject();
} catch (Throwable fail) {
threadUnexpectedException(fail);
- return null;
}
+ if (o == clone) assertImmutable(o);
+ else assertSame(o.getClass(), clone.getClass());
+ return clone;
}
/**
@@ -1804,7 +1798,7 @@ public class JSR166TestCase extends Test
(new ByteArrayInputStream(bos.toByteArray()));
T clone = (T) ois.readObject();
if (o == clone) assertImmutable(o);
- assertSame(o.getClass(), clone.getClass());
+ else assertSame(o.getClass(), clone.getClass());
return clone;
}
@@ -1829,8 +1823,8 @@ public class JSR166TestCase extends Test
}
public void assertThrows(Class extends Throwable> expectedExceptionClass,
- Runnable... throwingActions) {
- for (Runnable throwingAction : throwingActions) {
+ Action... throwingActions) {
+ for (Action throwingAction : throwingActions) {
boolean threw = false;
try { throwingAction.run(); }
catch (Throwable t) {