--- jsr166/src/test/tck/JSR166TestCase.java 2017/05/14 00:37:42 1.226 +++ jsr166/src/test/tck/JSR166TestCase.java 2018/01/23 22:56:37 1.240 @@ -76,24 +76,29 @@ import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveTask; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.Semaphore; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; -import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestResult; @@ -439,18 +444,11 @@ public class JSR166TestCase extends Test } } - public static boolean atLeastJava6() { return JAVA_CLASS_VERSION >= 50.0; } - public static boolean atLeastJava7() { return JAVA_CLASS_VERSION >= 51.0; } - public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; } - public static boolean atLeastJava9() { - return JAVA_CLASS_VERSION >= 53.0 - // As of 2015-09, java9 still uses 52.0 class file version - || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?(9|[0-9][0-9])$"); - } - public static boolean atLeastJava10() { - return JAVA_CLASS_VERSION >= 54.0 - || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?[0-9][0-9]$"); - } + public static boolean atLeastJava6() { return JAVA_CLASS_VERSION >= 50.0; } + public static boolean atLeastJava7() { return JAVA_CLASS_VERSION >= 51.0; } + public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; } + public static boolean atLeastJava9() { return JAVA_CLASS_VERSION >= 53.0; } + public static boolean atLeastJava10() { return JAVA_CLASS_VERSION >= 54.0; } /** * Collects all JSR166 unit tests as one suite. @@ -538,6 +536,7 @@ public class JSR166TestCase extends Test "DoubleAdderTest", "ForkJoinPool8Test", "ForkJoinTask8Test", + "HashMapTest", "LinkedBlockingDeque8Test", "LinkedBlockingQueue8Test", "LongAccumulatorTest", @@ -638,6 +637,33 @@ public class JSR166TestCase extends Test public static long MEDIUM_DELAY_MS; public static long LONG_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(); + long[] timeouts = { Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE }; + RANDOM_TIMEOUT = timeouts[rnd.nextInt(timeouts.length)]; + RANDOM_EXPIRED_TIMEOUT = timeouts[rnd.nextInt(3)]; + TimeUnit[] timeUnits = TimeUnit.values(); + RANDOM_TIMEUNIT = timeUnits[rnd.nextInt(timeUnits.length)]; + } + + /** + * Returns a timeout for use when any value at all will do. + */ + static long randomTimeout() { return RANDOM_TIMEOUT; } + + /** + * Returns a timeout that means "no waiting", i.e. not positive. + */ + static long randomExpiredTimeout() { return RANDOM_EXPIRED_TIMEOUT; } + + /** + * Returns a random non-null TimeUnit. + */ + static TimeUnit randomTimeUnit() { return RANDOM_TIMEUNIT; } + /** * Returns the shortest timed delay. This can be scaled up for * slow machines using the jsr166.delay.factor system property, @@ -706,7 +732,7 @@ public class JSR166TestCase extends Test String msg = toString() + ": " + String.format(format, args); System.err.println(msg); dumpTestThreads(); - throw new AssertionFailedError(msg); + throw new AssertionError(msg); } /** @@ -727,12 +753,8 @@ public class JSR166TestCase extends Test throw (RuntimeException) t; else if (t instanceof Exception) throw (Exception) t; - else { - AssertionFailedError afe = - new AssertionFailedError(t.toString()); - afe.initCause(t); - throw afe; - } + else + throw new AssertionError(t.toString(), t); } if (Thread.interrupted()) @@ -766,83 +788,83 @@ public class JSR166TestCase extends Test /** * Just like fail(reason), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadFail(String reason) { try { fail(reason); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; + } catch (AssertionError fail) { + threadRecordFailure(fail); + throw fail; } } /** * Just like assertTrue(b), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadAssertTrue(boolean b) { try { assertTrue(b); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; + } catch (AssertionError fail) { + threadRecordFailure(fail); + throw fail; } } /** * Just like assertFalse(b), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadAssertFalse(boolean b) { try { assertFalse(b); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; + } catch (AssertionError fail) { + threadRecordFailure(fail); + throw fail; } } /** * Just like assertNull(x), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadAssertNull(Object x) { try { assertNull(x); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; + } catch (AssertionError fail) { + threadRecordFailure(fail); + throw fail; } } /** * Just like assertEquals(x, y), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadAssertEquals(long x, long y) { try { assertEquals(x, y); - } catch (AssertionFailedError t) { - threadRecordFailure(t); - throw t; + } catch (AssertionError fail) { + threadRecordFailure(fail); + throw fail; } } /** * Just like assertEquals(x, y), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadAssertEquals(Object x, Object y) { try { assertEquals(x, y); - } catch (AssertionFailedError fail) { + } catch (AssertionError fail) { threadRecordFailure(fail); throw fail; } catch (Throwable fail) { @@ -852,13 +874,13 @@ public class JSR166TestCase extends Test /** * Just like assertSame(x, y), but additionally recording (using - * threadRecordFailure) any AssertionFailedError thrown, so that - * the current testcase will fail. + * threadRecordFailure) any AssertionError thrown, so that the + * current testcase will fail. */ public void threadAssertSame(Object x, Object y) { try { assertSame(x, y); - } catch (AssertionFailedError fail) { + } catch (AssertionError fail) { threadRecordFailure(fail); throw fail; } @@ -880,8 +902,8 @@ public class JSR166TestCase extends Test /** * Records the given exception using {@link #threadRecordFailure}, - * then rethrows the exception, wrapping it in an - * AssertionFailedError if necessary. + * then rethrows the exception, wrapping it in an AssertionError + * if necessary. */ public void threadUnexpectedException(Throwable t) { threadRecordFailure(t); @@ -890,12 +912,8 @@ public class JSR166TestCase extends Test throw (RuntimeException) t; else if (t instanceof Error) throw (Error) t; - else { - AssertionFailedError afe = - new AssertionFailedError("unexpected exception: " + t); - afe.initCause(t); - throw afe; - } + else + throw new AssertionError("unexpected exception: " + t, t); } /** @@ -1066,12 +1084,12 @@ public class JSR166TestCase extends Test * Checks that thread eventually enters the expected blocked thread state. */ void assertThreadBlocks(Thread thread, Thread.State expected) { - // always sleep at least 1 ms, avoiding transitional states - // with high probability + // always sleep at least 1 ms, with high probability avoiding + // transitory states for (long retries = LONG_DELAY_MS * 3 / 4; retries-->0; ) { try { delay(1); } catch (InterruptedException fail) { - fail("Unexpected InterruptedException"); + throw new AssertionError("Unexpected InterruptedException", fail); } Thread.State s = thread.getState(); if (s == expected) @@ -1083,49 +1101,6 @@ public class JSR166TestCase extends Test } /** - * Checks that thread does not terminate within the default - * millisecond delay of {@code timeoutMillis()}. - */ - void assertThreadStaysAlive(Thread thread) { - assertThreadStaysAlive(thread, timeoutMillis()); - } - - /** - * Checks that thread does not terminate within the given millisecond delay. - */ - void assertThreadStaysAlive(Thread thread, long millis) { - try { - // No need to optimize the failing case via Thread.join. - delay(millis); - assertTrue(thread.isAlive()); - } catch (InterruptedException fail) { - threadFail("Unexpected InterruptedException"); - } - } - - /** - * Checks that the threads do not terminate within the default - * millisecond delay of {@code timeoutMillis()}. - */ - void assertThreadsStayAlive(Thread... threads) { - assertThreadsStayAlive(timeoutMillis(), threads); - } - - /** - * Checks that the threads do not terminate within the given millisecond delay. - */ - void assertThreadsStayAlive(long millis, Thread... threads) { - try { - // No need to optimize the failing case via Thread.join. - delay(millis); - for (Thread thread : threads) - assertTrue(thread.isAlive()); - } catch (InterruptedException fail) { - threadFail("Unexpected InterruptedException"); - } - } - - /** * Checks that future.get times out, with the default timeout of * {@code timeoutMillis()}. */ @@ -1300,16 +1275,13 @@ public class JSR166TestCase extends Test /** * Sleeps until the given time has elapsed. - * Throws AssertionFailedError if interrupted. + * Throws AssertionError if interrupted. */ static void sleep(long millis) { try { delay(millis); } catch (InterruptedException fail) { - AssertionFailedError afe = - new AssertionFailedError("Unexpected InterruptedException"); - afe.initCause(fail); - throw afe; + throw new AssertionError("Unexpected InterruptedException", fail); } } @@ -1400,7 +1372,7 @@ public class JSR166TestCase extends Test // r.run(); // } catch (Throwable fail) { threadUnexpectedException(fail); } // if (millisElapsedSince(startTime) > timeoutMillis/2) -// throw new AssertionFailedError("did not return promptly"); +// throw new AssertionError("did not return promptly"); // } // void assertTerminatesPromptly(Runnable r) { @@ -1417,7 +1389,7 @@ public class JSR166TestCase extends Test assertEquals(expectedValue, f.get(timeoutMillis, MILLISECONDS)); } catch (Throwable fail) { threadUnexpectedException(fail); } if (millisElapsedSince(startTime) > timeoutMillis/2) - throw new AssertionFailedError("timed get did not return promptly"); + throw new AssertionError("timed get did not return promptly"); } void checkTimedGet(Future f, T expectedValue) { @@ -1659,7 +1631,7 @@ public class JSR166TestCase extends Test // long startTime = System.nanoTime(); // while (!flag.get()) { // if (millisElapsedSince(startTime) > timeoutMillis) -// throw new AssertionFailedError("timed out"); +// throw new AssertionError("timed out"); // Thread.yield(); // } // } @@ -1668,28 +1640,6 @@ public class JSR166TestCase extends Test public String call() { throw new NullPointerException(); } } - public static class CallableOne implements Callable { - public Integer call() { return one; } - } - - public class ShortRunnable extends CheckedRunnable { - protected void realRun() throws Throwable { - delay(SHORT_DELAY_MS); - } - } - - public class ShortInterruptedRunnable extends CheckedInterruptedRunnable { - protected void realRun() throws InterruptedException { - delay(SHORT_DELAY_MS); - } - } - - public class SmallRunnable extends CheckedRunnable { - protected void realRun() throws Throwable { - delay(SMALL_DELAY_MS); - } - } - public class SmallPossiblyInterruptedRunnable extends CheckedRunnable { protected void realRun() { try { @@ -1698,25 +1648,6 @@ public class JSR166TestCase extends Test } } - public class SmallCallable extends CheckedCallable { - protected Object realCall() throws InterruptedException { - delay(SMALL_DELAY_MS); - return Boolean.TRUE; - } - } - - public class MediumRunnable extends CheckedRunnable { - protected void realRun() throws Throwable { - delay(MEDIUM_DELAY_MS); - } - } - - public class MediumInterruptedRunnable extends CheckedInterruptedRunnable { - protected void realRun() throws InterruptedException { - delay(MEDIUM_DELAY_MS); - } - } - public Runnable possiblyInterruptedRunnable(final long timeoutMillis) { return new CheckedRunnable() { protected void realRun() { @@ -1726,22 +1657,6 @@ public class JSR166TestCase extends Test }}; } - public class MediumPossiblyInterruptedRunnable extends CheckedRunnable { - protected void realRun() { - try { - delay(MEDIUM_DELAY_MS); - } catch (InterruptedException ok) {} - } - } - - public class LongPossiblyInterruptedRunnable extends CheckedRunnable { - protected void realRun() { - try { - delay(LONG_DELAY_MS); - } catch (InterruptedException ok) {} - } - } - /** * For use as ThreadFactory in constructors */ @@ -1755,59 +1670,6 @@ public class JSR166TestCase extends Test 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 { - delay(timeoutMillis); - done = true; - } catch (InterruptedException ok) {} - } - }; - } - - public static class TrackedShortRunnable implements Runnable { - public volatile boolean done = false; - public void run() { - try { - delay(SHORT_DELAY_MS); - done = true; - } catch (InterruptedException ok) {} - } - } - - public static class TrackedSmallRunnable implements Runnable { - public volatile boolean done = false; - public void run() { - try { - delay(SMALL_DELAY_MS); - done = true; - } catch (InterruptedException ok) {} - } - } - - public static class TrackedMediumRunnable implements Runnable { - public volatile boolean done = false; - public void run() { - try { - delay(MEDIUM_DELAY_MS); - done = true; - } catch (InterruptedException ok) {} - } - } - - public static class TrackedLongRunnable implements Runnable { - public volatile boolean done = false; - public void run() { - try { - delay(LONG_DELAY_MS); - done = true; - } catch (InterruptedException ok) {} - } - } - public static class TrackedNoOpRunnable implements Runnable { public volatile boolean done = false; public void run() { @@ -1815,17 +1677,6 @@ public class JSR166TestCase extends Test } } - public static class TrackedCallable implements Callable { - public volatile boolean done = false; - public Object call() { - try { - delay(SMALL_DELAY_MS); - done = true; - } catch (InterruptedException ok) {} - return Boolean.TRUE; - } - } - /** * Analog of CheckedRunnable for RecursiveAction */ @@ -1867,7 +1718,7 @@ public class JSR166TestCase extends Test /** * A CyclicBarrier that uses timed await and fails with - * AssertionFailedErrors instead of throwing checked exceptions. + * AssertionErrors instead of throwing checked exceptions. */ public static class CheckedBarrier extends CyclicBarrier { public CheckedBarrier(int parties) { super(parties); } @@ -1876,12 +1727,9 @@ public class JSR166TestCase extends Test try { return super.await(2 * LONG_DELAY_MS, MILLISECONDS); } catch (TimeoutException timedOut) { - throw new AssertionFailedError("timed out"); + throw new AssertionError("timed out"); } catch (Exception fail) { - AssertionFailedError afe = - new AssertionFailedError("Unexpected exception: " + fail); - afe.initCause(fail); - throw afe; + throw new AssertionError("Unexpected exception: " + fail, fail); } } } @@ -1892,7 +1740,7 @@ public class JSR166TestCase extends Test assertEquals(0, q.size()); assertNull(q.peek()); assertNull(q.poll()); - assertNull(q.poll(0, MILLISECONDS)); + assertNull(q.poll(randomExpiredTimeout(), randomTimeUnit())); assertEquals(q.toString(), "[]"); assertTrue(Arrays.equals(q.toArray(), new Object[0])); assertFalse(q.iterator().hasNext()); @@ -2004,14 +1852,11 @@ public class JSR166TestCase extends Test try { throwingAction.run(); } catch (Throwable t) { threw = true; - if (!expectedExceptionClass.isInstance(t)) { - AssertionFailedError afe = - new AssertionFailedError - ("Expected " + expectedExceptionClass.getName() + - ", got " + t.getClass().getName()); - afe.initCause(t); - threadUnexpectedException(afe); - } + if (!expectedExceptionClass.isInstance(t)) + throw new AssertionError( + "Expected " + expectedExceptionClass.getName() + + ", got " + t.getClass().getName(), + t); } if (!threw) shouldThrow(expectedExceptionClass.getName()); @@ -2043,4 +1888,188 @@ public class JSR166TestCase extends Test static void shuffle(T[] array) { Collections.shuffle(Arrays.asList(array), ThreadLocalRandom.current()); } + + /** + * Returns the same String as would be returned by {@link + * Object#toString}, whether or not the given object's class + * overrides toString(). + * + * @see System#identityHashCode + */ + static String identityString(Object x) { + return x.getClass().getName() + + "@" + Integer.toHexString(System.identityHashCode(x)); + } + + // --- Shared assertions for Executor tests --- + + /** + * Returns maximum number of tasks that can be submitted to given + * pool (with bounded queue) before saturation (when submission + * throws RejectedExecutionException). + */ + static final int saturatedSize(ThreadPoolExecutor pool) { + BlockingQueue q = pool.getQueue(); + return pool.getMaximumPoolSize() + q.size() + q.remainingCapacity(); + } + + @SuppressWarnings("FutureReturnValueIgnored") + void assertNullTaskSubmissionThrowsNullPointerException(Executor e) { + try { + e.execute((Runnable) null); + shouldThrow(); + } catch (NullPointerException success) {} + + if (! (e instanceof ExecutorService)) return; + ExecutorService es = (ExecutorService) e; + try { + es.submit((Runnable) null); + shouldThrow(); + } catch (NullPointerException success) {} + try { + es.submit((Runnable) null, Boolean.TRUE); + shouldThrow(); + } catch (NullPointerException success) {} + try { + es.submit((Callable) null); + shouldThrow(); + } catch (NullPointerException success) {} + + if (! (e instanceof ScheduledExecutorService)) return; + ScheduledExecutorService ses = (ScheduledExecutorService) e; + try { + ses.schedule((Runnable) null, + randomTimeout(), randomTimeUnit()); + shouldThrow(); + } catch (NullPointerException success) {} + try { + ses.schedule((Callable) null, + randomTimeout(), randomTimeUnit()); + shouldThrow(); + } catch (NullPointerException success) {} + try { + ses.scheduleAtFixedRate((Runnable) null, + randomTimeout(), LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + try { + ses.scheduleWithFixedDelay((Runnable) null, + randomTimeout(), LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + + void setRejectedExecutionHandler( + ThreadPoolExecutor p, RejectedExecutionHandler handler) { + p.setRejectedExecutionHandler(handler); + assertSame(handler, p.getRejectedExecutionHandler()); + } + + void assertTaskSubmissionsAreRejected(ThreadPoolExecutor p) { + final RejectedExecutionHandler savedHandler = p.getRejectedExecutionHandler(); + final long savedTaskCount = p.getTaskCount(); + final long savedCompletedTaskCount = p.getCompletedTaskCount(); + final int savedQueueSize = p.getQueue().size(); + final boolean stock = (p.getClass().getClassLoader() == null); + + Runnable r = () -> {}; + Callable c = () -> Boolean.TRUE; + + class Recorder implements RejectedExecutionHandler { + public volatile Runnable r = null; + public volatile ThreadPoolExecutor p = null; + public void reset() { r = null; p = null; } + public void rejectedExecution(Runnable r, ThreadPoolExecutor p) { + assertNull(this.r); + assertNull(this.p); + this.r = r; + this.p = p; + } + } + + // check custom handler is invoked exactly once per task + Recorder recorder = new Recorder(); + setRejectedExecutionHandler(p, recorder); + for (int i = 2; i--> 0; ) { + recorder.reset(); + p.execute(r); + if (stock && p.getClass() == ThreadPoolExecutor.class) + assertSame(r, recorder.r); + assertSame(p, recorder.p); + + recorder.reset(); + assertFalse(p.submit(r).isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + + recorder.reset(); + assertFalse(p.submit(r, Boolean.TRUE).isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + + recorder.reset(); + assertFalse(p.submit(c).isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + + if (p instanceof ScheduledExecutorService) { + ScheduledExecutorService s = (ScheduledExecutorService) p; + ScheduledFuture future; + + recorder.reset(); + future = s.schedule(r, randomTimeout(), randomTimeUnit()); + assertFalse(future.isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + + recorder.reset(); + future = s.schedule(c, randomTimeout(), randomTimeUnit()); + assertFalse(future.isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + + recorder.reset(); + future = s.scheduleAtFixedRate(r, randomTimeout(), LONG_DELAY_MS, MILLISECONDS); + assertFalse(future.isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + + recorder.reset(); + future = s.scheduleWithFixedDelay(r, randomTimeout(), LONG_DELAY_MS, MILLISECONDS); + assertFalse(future.isDone()); + if (stock) assertTrue(!((FutureTask) recorder.r).isDone()); + assertSame(p, recorder.p); + } + } + + // Checking our custom handler above should be sufficient, but + // we add some integration tests of standard handlers. + final AtomicReference thread = new AtomicReference<>(); + final Runnable setThread = () -> thread.set(Thread.currentThread()); + + setRejectedExecutionHandler(p, new ThreadPoolExecutor.AbortPolicy()); + try { + p.execute(setThread); + shouldThrow(); + } catch (RejectedExecutionException success) {} + assertNull(thread.get()); + + setRejectedExecutionHandler(p, new ThreadPoolExecutor.DiscardPolicy()); + p.execute(setThread); + assertNull(thread.get()); + + setRejectedExecutionHandler(p, new ThreadPoolExecutor.CallerRunsPolicy()); + p.execute(setThread); + if (p.isShutdown()) + assertNull(thread.get()); + else + assertSame(Thread.currentThread(), thread.get()); + + setRejectedExecutionHandler(p, savedHandler); + + // check that pool was not perturbed by handlers + assertEquals(savedTaskCount, p.getTaskCount()); + assertEquals(savedCompletedTaskCount, p.getCompletedTaskCount()); + assertEquals(savedQueueSize, p.getQueue().size()); + } }