< prev index next >
test/jdk/java/util/concurrent/tck/JSR166TestCase.java
Print this page
8225490: Miscellaneous changes imported from jsr166 CVS 2019-09
Reviewed-by: martin, alanb
*** 309,324 ****
// Instrumentation to debug very rare, but very annoying hung test runs.
static volatile TestCase currentTestCase;
// static volatile int currentRun = 0;
static {
! Runnable checkForWedgedTest = new Runnable() { public void run() {
// 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));
for (TestCase lastTestCase = currentTestCase;;) {
try { MINUTES.sleep(timeoutMinutes); }
catch (InterruptedException unexpected) { break; }
if (lastTestCase == currentTestCase) {
System.err.printf(
--- 309,325 ----
// Instrumentation to debug very rare, but very annoying hung test runs.
static volatile TestCase currentTestCase;
// static volatile int currentRun = 0;
static {
! Runnable wedgedTestDetector = new Runnable() { public void run() {
// 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 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; }
if (lastTestCase == currentTestCase) {
System.err.printf(
*** 334,344 ****
// one stack dump is probably enough; more would be spam
break;
}
lastTestCase = currentTestCase;
}}};
! Thread thread = new Thread(checkForWedgedTest, "checkForWedgedTest");
thread.setDaemon(true);
thread.start();
}
// public static String cpuModel() {
--- 335,345 ----
// one stack dump is probably enough; more would be spam
break;
}
lastTestCase = currentTestCase;
}}};
! Thread thread = new Thread(wedgedTestDetector, "WedgedTestDetector");
thread.setDaemon(true);
thread.start();
}
// public static String cpuModel() {
*** 378,388 ****
if (elapsedMillis < profileThreshold)
break;
// Never report first run of any test; treat it as a
// warmup run, notably to trigger all needed classloading,
if (i > 0)
! System.out.printf("%n%s: %d%n", toString(), elapsedMillis);
}
}
/**
* Runs all JSR166 unit tests using junit.textui.TestRunner.
--- 379,389 ----
if (elapsedMillis < profileThreshold)
break;
// Never report first run of any test; treat it as a
// warmup run, notably to trigger all needed classloading,
if (i > 0)
! System.out.printf("%s: %d%n", toString(), elapsedMillis);
}
}
/**
* Runs all JSR166 unit tests using junit.textui.TestRunner.
*** 681,690 ****
--- 682,697 ----
public static long SHORT_DELAY_MS;
public static long SMALL_DELAY_MS;
public static long MEDIUM_DELAY_MS;
public static long LONG_DELAY_MS;
+ /**
+ * A delay significantly longer than LONG_DELAY_MS.
+ * Use this in a thread that is waited for via awaitTermination(Thread).
+ */
+ public static long LONGER_DELAY_MS;
+
private static final long RANDOM_TIMEOUT;
private static final long RANDOM_EXPIRED_TIMEOUT;
private static final TimeUnit RANDOM_TIMEUNIT;
static {
ThreadLocalRandom rnd = ThreadLocalRandom.current();
*** 709,718 ****
--- 716,739 ----
* Returns a random non-null TimeUnit.
*/
static TimeUnit randomTimeUnit() { return RANDOM_TIMEUNIT; }
/**
+ * Returns a random boolean; a "coin flip".
+ */
+ static boolean randomBoolean() {
+ return ThreadLocalRandom.current().nextBoolean();
+ }
+
+ /**
+ * Returns a random element from given choices.
+ */
+ <T> T chooseRandomly(T... choices) {
+ return choices[ThreadLocalRandom.current().nextInt(choices.length)];
+ }
+
+ /**
* 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.
* http://openjdk.java.net/jtreg/command-help.html
*/
*** 726,735 ****
--- 747,757 ----
protected void setDelays() {
SHORT_DELAY_MS = getShortDelay();
SMALL_DELAY_MS = SHORT_DELAY_MS * 5;
MEDIUM_DELAY_MS = SHORT_DELAY_MS * 10;
LONG_DELAY_MS = SHORT_DELAY_MS * 200;
+ LONGER_DELAY_MS = 2 * LONG_DELAY_MS;
}
private static final long TIMEOUT_DELAY_MS
= (long) (12.0 * Math.cbrt(delayFactor));
*** 764,775 ****
* failure is recorded; subsequent calls to this method from within
* the same test have no effect.
*/
public void threadRecordFailure(Throwable t) {
System.err.println(t);
dumpTestThreads();
- threadFailure.compareAndSet(null, t);
}
public void setUp() {
setDelays();
}
--- 786,797 ----
* failure is recorded; subsequent calls to this method from within
* the same test have no effect.
*/
public void threadRecordFailure(Throwable t) {
System.err.println(t);
+ if (threadFailure.compareAndSet(null, t))
dumpTestThreads();
}
public void setUp() {
setDelays();
}
*** 1086,1095 ****
--- 1108,1150 ----
threadUnexpectedException(ex);
}
}
}
+ /** Returns true if thread info might be useful in a thread dump. */
+ static boolean threadOfInterest(ThreadInfo info) {
+ final String name = info.getThreadName();
+ String lockName;
+ if (name == null)
+ return true;
+ if (name.equals("Signal Dispatcher")
+ || name.equals("WedgedTestDetector"))
+ return false;
+ if (name.equals("Reference Handler")) {
+ // Reference Handler stacktrace changed in JDK-8156500
+ StackTraceElement[] stackTrace; String methodName;
+ if ((stackTrace = info.getStackTrace()) != null
+ && stackTrace.length > 0
+ && (methodName = stackTrace[0].getMethodName()) != null
+ && methodName.equals("waitForReferencePendingList"))
+ return false;
+ // jdk8 Reference Handler stacktrace
+ if ((lockName = info.getLockName()) != null
+ && lockName.startsWith("java.lang.ref"))
+ return false;
+ }
+ if ((name.equals("Finalizer") || name.equals("Common-Cleaner"))
+ && (lockName = info.getLockName()) != null
+ && lockName.startsWith("java.lang.ref"))
+ return false;
+ if (name.startsWith("ForkJoinPool.commonPool-worker")
+ && (lockName = info.getLockName()) != null
+ && lockName.startsWith("java.util.concurrent.ForkJoinPool"))
+ return false;
+ return true;
+ }
+
/**
* A debugging tool to print stack traces of most threads, as jstack does.
* Uninteresting threads are filtered out.
*/
static void dumpTestThreads() {
*** 1102,1128 ****
}
}
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
System.err.println("------ stacktrace dump start ------");
! for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
! final String name = info.getThreadName();
! String lockName;
! if ("Signal Dispatcher".equals(name))
! continue;
! if ("Reference Handler".equals(name)
! && (lockName = info.getLockName()) != null
! && lockName.startsWith("java.lang.ref.Reference$Lock"))
! continue;
! if ("Finalizer".equals(name)
! && (lockName = info.getLockName()) != null
! && lockName.startsWith("java.lang.ref.ReferenceQueue$Lock"))
! continue;
! if ("checkForWedgedTest".equals(name))
! continue;
System.err.print(info);
- }
System.err.println("------ stacktrace dump end ------");
if (sm != null) System.setSecurityManager(sm);
}
--- 1157,1169 ----
}
}
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
System.err.println("------ stacktrace dump start ------");
! for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true))
! if (threadOfInterest(info))
System.err.print(info);
System.err.println("------ stacktrace dump end ------");
if (sm != null) System.setSecurityManager(sm);
}
*** 1391,1421 ****
Callable<Boolean> waitingForGodot) {
waitForThreadToEnterWaitState(thread, LONG_DELAY_MS, waitingForGodot);
}
/**
* Returns the number of milliseconds since time given by
* startNanoTime, which must have been previously returned from a
* call to {@link System#nanoTime()}.
*/
static long millisElapsedSince(long startNanoTime) {
return NANOSECONDS.toMillis(System.nanoTime() - startNanoTime);
}
- // void assertTerminatesPromptly(long timeoutMillis, Runnable r) {
- // long startTime = System.nanoTime();
- // try {
- // r.run();
- // } catch (Throwable fail) { threadUnexpectedException(fail); }
- // if (millisElapsedSince(startTime) > timeoutMillis/2)
- // throw new AssertionError("did not return promptly");
- // }
-
- // void assertTerminatesPromptly(Runnable r) {
- // assertTerminatesPromptly(LONG_DELAY_MS/2, r);
- // }
-
/**
* Checks that timed f.get() returns the expected value, and does not
* wait for the timeout to elapse before returning.
*/
<T> void checkTimedGet(Future<T> f, T expectedValue, long timeoutMillis) {
--- 1432,1463 ----
Callable<Boolean> waitingForGodot) {
waitForThreadToEnterWaitState(thread, LONG_DELAY_MS, waitingForGodot);
}
/**
+ * Spin-waits up to LONG_DELAY_MS milliseconds for the current thread to
+ * be interrupted. Clears the interrupt status before returning.
+ */
+ void awaitInterrupted() {
+ for (long startTime = 0L; !Thread.interrupted(); ) {
+ if (startTime == 0L)
+ startTime = System.nanoTime();
+ else if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+ fail("timed out waiting for thread interrupt");
+ 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()}.
*/
static long millisElapsedSince(long startNanoTime) {
return NANOSECONDS.toMillis(System.nanoTime() - startNanoTime);
}
/**
* Checks that timed f.get() returns the expected value, and does not
* wait for the timeout to elapse before returning.
*/
<T> void checkTimedGet(Future<T> f, T expectedValue, long timeoutMillis) {
*** 1446,1464 ****
/**
* 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 fail) {
threadUnexpectedException(fail);
} finally {
! if (t.getState() != Thread.State.TERMINATED) {
! t.interrupt();
! threadFail("timed out waiting for thread to terminate");
}
}
}
/**
--- 1488,1512 ----
/**
* 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 thread, long timeoutMillis) {
try {
! thread.join(timeoutMillis);
} catch (InterruptedException fail) {
threadUnexpectedException(fail);
+ }
+ if (thread.getState() != Thread.State.TERMINATED) {
+ String detail = String.format(
+ "timed out waiting for thread to terminate, thread=%s, state=%s" ,
+ thread, thread.getState());
+ try {
+ threadFail(detail);
} finally {
! // Interrupt thread __after__ having reported its stack trace
! thread.interrupt();
}
}
}
/**
< prev index next >