--- jsr166/src/test/tck/JSR166TestCase.java 2019/09/08 16:08:56 1.267 +++ jsr166/src/test/tck/JSR166TestCase.java 2021/01/26 13:33:06 1.272 @@ -49,6 +49,7 @@ import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.management.ManagementFactory; +import java.lang.management.LockInfo; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.lang.reflect.Constructor; @@ -73,6 +74,7 @@ import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.PropertyPermission; +import java.util.Queue; import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; @@ -149,6 +151,11 @@ import junit.framework.TestSuite; * but even so, if there is ever any doubt, they can all be increased * in one spot to rerun tests on slower platforms. * + * Class Item is used for elements of collections and related + * purposes. Many tests rely on themir keys being equal to ints. To + * check these, methods mustEqual, mustContain, etc adapt the JUnit + * assert methods to intercept ints. + * *
  • All threads generated must be joined inside each test case * method (or {@code fail} to do so) before returning from the * method. The {@code joinPool} method can be used to do this when @@ -243,6 +250,9 @@ public class JSR166TestCase extends Test } } + private static final ThreadMXBean THREAD_MXBEAN + = ManagementFactory.getThreadMXBean(); + /** * The scaling factor to apply to standard delays used in tests. * May be initialized from any of: @@ -700,6 +710,14 @@ public class JSR166TestCase extends Test /** * Returns a random element from given choices. */ + T chooseRandomly(List choices) { + return choices.get(ThreadLocalRandom.current().nextInt(choices.size())); + } + + /** + * Returns a random element from given choices. + */ + @SuppressWarnings("unchecked") T chooseRandomly(T... choices) { return choices[ThreadLocalRandom.current().nextInt(choices.length)]; } @@ -1130,9 +1148,8 @@ public class JSR166TestCase extends Test } } - ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); System.err.println("------ stacktrace dump start ------"); - for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) + for (ThreadInfo info : THREAD_MXBEAN.dumpAllThreads(true, true)) if (threadOfInterest(info)) System.err.print(info); System.err.println("------ stacktrace dump end ------"); @@ -1161,17 +1178,28 @@ public class JSR166TestCase extends Test } /** + * Returns the thread's blocker's class name, if any, else null. + */ + String blockerClassName(Thread thread) { + ThreadInfo threadInfo; LockInfo lockInfo; + if ((threadInfo = THREAD_MXBEAN.getThreadInfo(thread.getId(), 0)) != null + && (lockInfo = threadInfo.getLockInfo()) != null) + return lockInfo.getClassName(); + return null; + } + + /** * Checks that future.get times out, with the default timeout of * {@code timeoutMillis()}. */ - void assertFutureTimesOut(Future future) { + void assertFutureTimesOut(Future future) { assertFutureTimesOut(future, timeoutMillis()); } /** * Checks that future.get times out, with the given millisecond timeout. */ - void assertFutureTimesOut(Future future, long timeoutMillis) { + void assertFutureTimesOut(Future future, long timeoutMillis) { long startTime = System.nanoTime(); try { future.get(timeoutMillis, MILLISECONDS); @@ -1179,8 +1207,9 @@ public class JSR166TestCase extends Test } catch (TimeoutException success) { } catch (Exception fail) { threadUnexpectedException(fail); - } finally { future.cancel(true); } + } assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + assertFalse(future.isDone()); } /** @@ -1205,28 +1234,137 @@ public class JSR166TestCase extends Test /** * The number of elements to place in collections, arrays, etc. + * Must be at least ten; */ - public static final int SIZE = 20; + public static final int SIZE = 32; - // Some convenient Integer constants - - public static final Integer zero = new Integer(0); - public static final Integer one = new Integer(1); - public static final Integer two = new Integer(2); - public static final Integer three = new Integer(3); - public static final Integer four = new Integer(4); - public static final Integer five = new Integer(5); - public static final Integer six = new Integer(6); - public static final Integer seven = new Integer(7); - public static final Integer eight = new Integer(8); - public static final Integer nine = new Integer(9); - public static final Integer m1 = new Integer(-1); - public static final Integer m2 = new Integer(-2); - public static final Integer m3 = new Integer(-3); - public static final Integer m4 = new Integer(-4); - public static final Integer m5 = new Integer(-5); - public static final Integer m6 = new Integer(-6); - public static final Integer m10 = new Integer(-10); + static Item[] seqItems(int size) { + Item[] s = new Item[size]; + for (int i = 0; i < size; ++i) + s[i] = new Item(i); + return s; + } + static Item[] negativeSeqItems(int size) { + Item[] s = new Item[size]; + for (int i = 0; i < size; ++i) + s[i] = new Item(-i); + return s; + } + + // Many tests rely on defaultItems all being sequential nonnegative + public static final Item[] defaultItems = seqItems(SIZE); + + static Item itemFor(int i) { // check cache for defaultItems + Item[] items = defaultItems; + return (i >= 0 && i < items.length) ? items[i] : new Item(i); + } + + public static final Item zero = defaultItems[0]; + public static final Item one = defaultItems[1]; + public static final Item two = defaultItems[2]; + public static final Item three = defaultItems[3]; + public static final Item four = defaultItems[4]; + public static final Item five = defaultItems[5]; + public static final Item six = defaultItems[6]; + public static final Item seven = defaultItems[7]; + public static final Item eight = defaultItems[8]; + public static final Item nine = defaultItems[9]; + public static final Item ten = defaultItems[10]; + + public static final Item[] negativeItems = negativeSeqItems(SIZE); + + public static final Item minusOne = negativeItems[1]; + public static final Item minusTwo = negativeItems[2]; + public static final Item minusThree = negativeItems[3]; + public static final Item minusFour = negativeItems[4]; + public static final Item minusFive = negativeItems[5]; + public static final Item minusSix = negativeItems[6]; + public static final Item minusSeven = negativeItems[7]; + public static final Item minusEight = negativeItems[8]; + public static final Item minusNone = negativeItems[9]; + public static final Item minusTen = negativeItems[10]; + + // elements expected to be missing + public static final Item fortytwo = new Item(42); + public static final Item eightysix = new Item(86); + public static final Item ninetynine = new Item(99); + + // Interop across Item, int + + static void mustEqual(Item x, Item y) { + if (x != y) + assertEquals(x.value, y.value); + } + static void mustEqual(Item x, int y) { + assertEquals(x.value, y); + } + static void mustEqual(int x, Item y) { + assertEquals(x, y.value); + } + static void mustEqual(int x, int y) { + assertEquals(x, y); + } + static void mustEqual(Object x, Object y) { + if (x != y) + assertEquals(x, y); + } + static void mustEqual(int x, Object y) { + if (y instanceof Item) + assertEquals(x, ((Item)y).value); + else fail(); + } + static void mustEqual(Object x, int y) { + if (x instanceof Item) + assertEquals(((Item)x).value, y); + else fail(); + } + static void mustEqual(boolean x, boolean y) { + assertEquals(x, y); + } + static void mustEqual(long x, long y) { + assertEquals(x, y); + } + static void mustEqual(double x, double y) { + assertEquals(x, y); + } + static void mustContain(Collection c, int i) { + assertTrue(c.contains(itemFor(i))); + } + static void mustContain(Collection c, Item i) { + assertTrue(c.contains(i)); + } + static void mustNotContain(Collection c, int i) { + assertFalse(c.contains(itemFor(i))); + } + static void mustNotContain(Collection c, Item i) { + assertFalse(c.contains(i)); + } + static void mustRemove(Collection c, int i) { + assertTrue(c.remove(itemFor(i))); + } + static void mustRemove(Collection c, Item i) { + assertTrue(c.remove(i)); + } + static void mustNotRemove(Collection c, int i) { + Item[] items = defaultItems; + Item x = (i >= 0 && i < items.length) ? items[i] : new Item(i); + assertFalse(c.remove(x)); + } + static void mustNotRemove(Collection c, Item i) { + assertFalse(c.remove(i)); + } + static void mustAdd(Collection c, int i) { + assertTrue(c.add(itemFor(i))); + } + static void mustAdd(Collection c, Item i) { + assertTrue(c.add(i)); + } + static void mustOffer(Queue c, int i) { + assertTrue(c.offer(itemFor(i))); + } + static void mustOffer(Queue c, Item i) { + assertTrue(c.offer(i)); + } /** * Runs Runnable r with a security policy that permits precisely @@ -1459,6 +1597,14 @@ public class JSR166TestCase extends Test } /** + * Returns a new started daemon Thread running the given action, + * wrapped in a CheckedRunnable. + */ + Thread newStartedThread(Action action) { + return newStartedThread(checkedRunnable(action)); + } + + /** * 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. @@ -1505,6 +1651,13 @@ public class JSR166TestCase extends Test } } + Runnable checkedRunnable(Action action) { + return new CheckedRunnable() { + public void realRun() throws Throwable { + action.run(); + }}; + } + public abstract class ThreadShouldThrow extends Thread { protected abstract void realRun() throws Throwable; @@ -1559,7 +1712,7 @@ public class JSR166TestCase extends Test public void run() {} } - public static class NoOpCallable implements Callable { + public static class NoOpCallable implements Callable { public Object call() { return Boolean.TRUE; } } @@ -1743,7 +1896,7 @@ public class JSR166TestCase extends Test public int await() { try { - return super.await(2 * LONG_DELAY_MS, MILLISECONDS); + return super.await(LONGER_DELAY_MS, MILLISECONDS); } catch (TimeoutException timedOut) { throw new AssertionError("timed out"); } catch (Exception fail) { @@ -1752,7 +1905,7 @@ public class JSR166TestCase extends Test } } - void checkEmpty(BlockingQueue q) { + void checkEmpty(BlockingQueue q) { try { assertTrue(q.isEmpty()); assertEquals(0, q.size()); @@ -1799,6 +1952,7 @@ public class JSR166TestCase extends Test } } + @SuppressWarnings("unchecked") void assertImmutable(Object o) { if (o instanceof Collection) { assertThrows( @@ -1948,7 +2102,7 @@ public class JSR166TestCase extends Test shouldThrow(); } catch (NullPointerException success) {} try { - es.submit((Callable) null); + es.submit((Callable) null); shouldThrow(); } catch (NullPointerException success) {} @@ -1960,7 +2114,7 @@ public class JSR166TestCase extends Test shouldThrow(); } catch (NullPointerException success) {} try { - ses.schedule((Callable) null, + ses.schedule((Callable) null, randomTimeout(), randomTimeUnit()); shouldThrow(); } catch (NullPointerException success) {} @@ -2119,7 +2273,7 @@ public class JSR166TestCase extends Test else { assertEquals(x.isEmpty(), y.isEmpty()); assertEquals(x.size(), y.size()); - assertEquals(new HashSet(x), new HashSet(y)); + assertEquals(new HashSet(x), new HashSet(y)); if (x instanceof Deque) { assertTrue(Arrays.equals(x.toArray(), y.toArray())); assertTrue(Arrays.equals(x.toArray(new Object[0]),