/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package jsr166;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import junit.framework.Test;
import junit.framework.TestSuite;

public class ScheduledExecutorSubclassTest extends JSR166TestCase {
    // android-note: Removed because the CTS runner does a bad job of
    // retrying tests that have suite() declarations.
    //
    // public static void main(String[] args) {
    //     main(suite(), args);
    // }
    // public static Test suite() {
    //     return new TestSuite(ScheduledExecutorSubclassTest.class);
    // }

    static class CustomTask<V> implements RunnableScheduledFuture<V> {
        RunnableScheduledFuture<V> task;
        volatile boolean ran;
        CustomTask(RunnableScheduledFuture<V> t) { task = t; }
        public boolean isPeriodic() { return task.isPeriodic(); }
        public void run() {
            ran = true;
            task.run();
        }
        public long getDelay(TimeUnit unit) { return task.getDelay(unit); }
        public int compareTo(Delayed t) {
            return task.compareTo(((CustomTask)t).task);
        }
        public boolean cancel(boolean mayInterruptIfRunning) {
            return task.cancel(mayInterruptIfRunning);
        }
        public boolean isCancelled() { return task.isCancelled(); }
        public boolean isDone() { return task.isDone(); }
        public V get() throws InterruptedException, ExecutionException {
            V v = task.get();
            assertTrue(ran);
            return v;
        }
        public V get(long time, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            V v = task.get(time, unit);
            assertTrue(ran);
            return v;
        }
    }

    public class CustomExecutor extends ScheduledThreadPoolExecutor {

        protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
            return new CustomTask<V>(task);
        }

        protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> c, RunnableScheduledFuture<V> task) {
            return new CustomTask<V>(task);
        }
        CustomExecutor(int corePoolSize) { super(corePoolSize); }
        CustomExecutor(int corePoolSize, RejectedExecutionHandler handler) {
            super(corePoolSize, handler);
        }

        CustomExecutor(int corePoolSize, ThreadFactory threadFactory) {
            super(corePoolSize, threadFactory);
        }
        CustomExecutor(int corePoolSize, ThreadFactory threadFactory,
                       RejectedExecutionHandler handler) {
            super(corePoolSize, threadFactory, handler);
        }

    }

    /**
     * execute successfully executes a runnable
     */
    public void testExecute() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            final CountDownLatch done = new CountDownLatch(1);
            final Runnable task = new CheckedRunnable() {
                public void realRun() { done.countDown(); }};
            p.execute(task);
            await(done);
        }
    }

    /**
     * delayed schedule of callable successfully executes after delay
     */
    public void testSchedule1() throws Exception {
        final CountDownLatch done = new CountDownLatch(1);
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            final long startTime = System.nanoTime();
            Callable task = new CheckedCallable<Boolean>() {
                public Boolean realCall() {
                    done.countDown();
                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
                    return Boolean.TRUE;
                }};
            Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
            assertSame(Boolean.TRUE, f.get());
            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
        }
    }

    /**
     * delayed schedule of runnable successfully executes after delay
     */
    public void testSchedule3() throws Exception {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            final long startTime = System.nanoTime();
            final CountDownLatch done = new CountDownLatch(1);
            Runnable task = new CheckedRunnable() {
                public void realRun() {
                    done.countDown();
                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
                }};
            Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
            await(done);
            assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
        }
    }

    /**
     * scheduleAtFixedRate executes runnable after given initial delay
     */
    public void testSchedule4() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            final long startTime = System.nanoTime();
            final CountDownLatch done = new CountDownLatch(1);
            Runnable task = new CheckedRunnable() {
                public void realRun() {
                    done.countDown();
                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
                }};
            ScheduledFuture f =
                p.scheduleAtFixedRate(task, timeoutMillis(),
                                      LONG_DELAY_MS, MILLISECONDS);
            await(done);
            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
            f.cancel(true);
        }
    }

    /**
     * scheduleWithFixedDelay executes runnable after given initial delay
     */
    public void testSchedule5() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            final long startTime = System.nanoTime();
            final CountDownLatch done = new CountDownLatch(1);
            Runnable task = new CheckedRunnable() {
                public void realRun() {
                    done.countDown();
                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
                }};
            ScheduledFuture f =
                p.scheduleWithFixedDelay(task, timeoutMillis(),
                                         LONG_DELAY_MS, MILLISECONDS);
            await(done);
            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
            f.cancel(true);
        }
    }

    static class RunnableCounter implements Runnable {
        AtomicInteger count = new AtomicInteger(0);
        public void run() { count.getAndIncrement(); }
    }

    /**
     * scheduleAtFixedRate executes series of tasks at given rate.
     * Eventually, it must hold that:
     *   cycles - 1 <= elapsedMillis/delay < cycles
     */
    public void testFixedRateSequence() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
                final long startTime = System.nanoTime();
                final int cycles = 8;
                final CountDownLatch done = new CountDownLatch(cycles);
                final Runnable task = new CheckedRunnable() {
                    public void realRun() { done.countDown(); }};
                final ScheduledFuture periodicTask =
                    p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
                final int totalDelayMillis = (cycles - 1) * delay;
                await(done, totalDelayMillis + LONG_DELAY_MS);
                periodicTask.cancel(true);
                final long elapsedMillis = millisElapsedSince(startTime);
                assertTrue(elapsedMillis >= totalDelayMillis);
                if (elapsedMillis <= cycles * delay)
                    return;
                // else retry with longer delay
            }
            fail("unexpected execution rate");
        }
    }

    /**
     * scheduleWithFixedDelay executes series of tasks with given period.
     * Eventually, it must hold that each task starts at least delay and at
     * most 2 * delay after the termination of the previous task.
     */
    public void testFixedDelaySequence() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
                final long startTime = System.nanoTime();
                final AtomicLong previous = new AtomicLong(startTime);
                final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
                final int cycles = 8;
                final CountDownLatch done = new CountDownLatch(cycles);
                final int d = delay;
                final Runnable task = new CheckedRunnable() {
                    public void realRun() {
                        long now = System.nanoTime();
                        long elapsedMillis
                            = NANOSECONDS.toMillis(now - previous.get());
                        if (done.getCount() == cycles) { // first execution
                            if (elapsedMillis >= d)
                                tryLongerDelay.set(true);
                        } else {
                            assertTrue(elapsedMillis >= d);
                            if (elapsedMillis >= 2 * d)
                                tryLongerDelay.set(true);
                        }
                        previous.set(now);
                        done.countDown();
                    }};
                final ScheduledFuture periodicTask =
                    p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
                final int totalDelayMillis = (cycles - 1) * delay;
                await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
                periodicTask.cancel(true);
                final long elapsedMillis = millisElapsedSince(startTime);
                assertTrue(elapsedMillis >= totalDelayMillis);
                if (!tryLongerDelay.get())
                    return;
                // else retry with longer delay
            }
            fail("unexpected execution rate");
        }
    }

    /**
     * execute(null) throws NPE
     */
    public void testExecuteNull() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.execute(null);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * schedule(null) throws NPE
     */
    public void testScheduleNull() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                TrackedCallable callable = null;
                Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * execute throws RejectedExecutionException if shutdown
     */
    public void testSchedule1_RejectedExecutionException() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.shutdown();
                p.schedule(new NoOpRunnable(),
                           MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (RejectedExecutionException success) {
            } catch (SecurityException ok) {}
        }
    }

    /**
     * schedule throws RejectedExecutionException if shutdown
     */
    public void testSchedule2_RejectedExecutionException() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.shutdown();
                p.schedule(new NoOpCallable(),
                           MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (RejectedExecutionException success) {
            } catch (SecurityException ok) {}
        }
    }

    /**
     * schedule callable throws RejectedExecutionException if shutdown
     */
    public void testSchedule3_RejectedExecutionException() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.shutdown();
                p.schedule(new NoOpCallable(),
                           MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (RejectedExecutionException success) {
            } catch (SecurityException ok) {}
        }
    }

    /**
     * scheduleAtFixedRate throws RejectedExecutionException if shutdown
     */
    public void testScheduleAtFixedRate1_RejectedExecutionException() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.shutdown();
                p.scheduleAtFixedRate(new NoOpRunnable(),
                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (RejectedExecutionException success) {
            } catch (SecurityException ok) {}
        }
    }

    /**
     * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
     */
    public void testScheduleWithFixedDelay1_RejectedExecutionException() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.shutdown();
                p.scheduleWithFixedDelay(new NoOpRunnable(),
                                         MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (RejectedExecutionException success) {
            } catch (SecurityException ok) {}
        }
    }

    /**
     * getActiveCount increases but doesn't overestimate, when a
     * thread becomes active
     */
    public void testGetActiveCount() throws InterruptedException {
        final CountDownLatch done = new CountDownLatch(1);
        final ThreadPoolExecutor p = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            assertEquals(0, p.getActiveCount());
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    threadStarted.countDown();
                    assertEquals(1, p.getActiveCount());
                    await(done);
                }});
            await(threadStarted);
            assertEquals(1, p.getActiveCount());
        }
    }

    /**
     * getCompletedTaskCount increases, but doesn't overestimate,
     * when tasks complete
     */
    public void testGetCompletedTaskCount() throws InterruptedException {
        final ThreadPoolExecutor p = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(p)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            final CountDownLatch threadProceed = new CountDownLatch(1);
            final CountDownLatch threadDone = new CountDownLatch(1);
            assertEquals(0, p.getCompletedTaskCount());
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    threadStarted.countDown();
                    assertEquals(0, p.getCompletedTaskCount());
                    threadProceed.await();
                    threadDone.countDown();
                }});
            await(threadStarted);
            assertEquals(0, p.getCompletedTaskCount());
            threadProceed.countDown();
            threadDone.await();
            long startTime = System.nanoTime();
            while (p.getCompletedTaskCount() != 1) {
                if (millisElapsedSince(startTime) > LONG_DELAY_MS)
                    fail("timed out");
                Thread.yield();
            }
        }
    }

    /**
     * getCorePoolSize returns size given in constructor if not otherwise set
     */
    public void testGetCorePoolSize() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            assertEquals(1, p.getCorePoolSize());
        }
    }

    /**
     * getLargestPoolSize increases, but doesn't overestimate, when
     * multiple threads active
     */
    public void testGetLargestPoolSize() throws InterruptedException {
        final int THREADS = 3;
        final CountDownLatch done = new CountDownLatch(1);
        final ThreadPoolExecutor p = new CustomExecutor(THREADS);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
            assertEquals(0, p.getLargestPoolSize());
            for (int i = 0; i < THREADS; i++)
                p.execute(new CheckedRunnable() {
                    public void realRun() throws InterruptedException {
                        threadsStarted.countDown();
                        await(done);
                        assertEquals(THREADS, p.getLargestPoolSize());
                    }});
            await(threadsStarted);
            assertEquals(THREADS, p.getLargestPoolSize());
        }
        assertEquals(THREADS, p.getLargestPoolSize());
    }

    /**
     * getPoolSize increases, but doesn't overestimate, when threads
     * become active
     */
    public void testGetPoolSize() throws InterruptedException {
        final CountDownLatch done = new CountDownLatch(1);
        final ThreadPoolExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            assertEquals(0, p.getPoolSize());
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    threadStarted.countDown();
                    assertEquals(1, p.getPoolSize());
                    await(done);
                }});
            await(threadStarted);
            assertEquals(1, p.getPoolSize());
        }
    }

    /**
     * getTaskCount increases, but doesn't overestimate, when tasks
     * submitted
     */
    public void testGetTaskCount() throws InterruptedException {
        final int TASKS = 3;
        final CountDownLatch done = new CountDownLatch(1);
        final ThreadPoolExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            assertEquals(0, p.getTaskCount());
            assertEquals(0, p.getCompletedTaskCount());
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    threadStarted.countDown();
                    await(done);
                }});
            await(threadStarted);
            assertEquals(1, p.getTaskCount());
            assertEquals(0, p.getCompletedTaskCount());
            for (int i = 0; i < TASKS; i++) {
                assertEquals(1 + i, p.getTaskCount());
                p.execute(new CheckedRunnable() {
                    public void realRun() throws InterruptedException {
                        threadStarted.countDown();
                        assertEquals(1 + TASKS, p.getTaskCount());
                        await(done);
                    }});
            }
            assertEquals(1 + TASKS, p.getTaskCount());
            assertEquals(0, p.getCompletedTaskCount());
        }
        assertEquals(1 + TASKS, p.getTaskCount());
        assertEquals(1 + TASKS, p.getCompletedTaskCount());
    }

    /**
     * getThreadFactory returns factory in constructor if not set
     */
    public void testGetThreadFactory() {
        final ThreadFactory threadFactory = new SimpleThreadFactory();
        final CustomExecutor p = new CustomExecutor(1, threadFactory);
        try (PoolCleaner cleaner = cleaner(p)) {
            assertSame(threadFactory, p.getThreadFactory());
        }
    }

    /**
     * setThreadFactory sets the thread factory returned by getThreadFactory
     */
    public void testSetThreadFactory() {
        final ThreadFactory threadFactory = new SimpleThreadFactory();
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            p.setThreadFactory(threadFactory);
            assertSame(threadFactory, p.getThreadFactory());
        }
    }

    /**
     * setThreadFactory(null) throws NPE
     */
    public void testSetThreadFactoryNull() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            try {
                p.setThreadFactory(null);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * isShutdown is false before shutdown, true after
     */
    public void testIsShutdown() {
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            assertFalse(p.isShutdown());
            try { p.shutdown(); } catch (SecurityException ok) { return; }
            assertTrue(p.isShutdown());
        }
    }

    /**
     * isTerminated is false before termination, true after
     */
    public void testIsTerminated() throws InterruptedException {
        final CountDownLatch done = new CountDownLatch(1);
        final ThreadPoolExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    assertFalse(p.isTerminated());
                    threadStarted.countDown();
                    await(done);
                }});
            await(threadStarted);
            assertFalse(p.isTerminated());
            assertFalse(p.isTerminating());
            done.countDown();
            try { p.shutdown(); } catch (SecurityException ok) { return; }
            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
            assertTrue(p.isTerminated());
        }
    }

    /**
     * isTerminating is not true when running or when terminated
     */
    public void testIsTerminating() throws InterruptedException {
        final CountDownLatch done = new CountDownLatch(1);
        final ThreadPoolExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            assertFalse(p.isTerminating());
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    assertFalse(p.isTerminating());
                    threadStarted.countDown();
                    await(done);
                }});
            await(threadStarted);
            assertFalse(p.isTerminating());
            done.countDown();
            try { p.shutdown(); } catch (SecurityException ok) { return; }
            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
            assertTrue(p.isTerminated());
            assertFalse(p.isTerminating());
        }
    }

    /**
     * getQueue returns the work queue, which contains queued tasks
     */
    public void testGetQueue() throws InterruptedException {
        final CountDownLatch done = new CountDownLatch(1);
        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            final CountDownLatch threadStarted = new CountDownLatch(1);
            ScheduledFuture[] tasks = new ScheduledFuture[5];
            for (int i = 0; i < tasks.length; i++) {
                Runnable r = new CheckedRunnable() {
                    public void realRun() throws InterruptedException {
                        threadStarted.countDown();
                        await(done);
                    }};
                tasks[i] = p.schedule(r, 1, MILLISECONDS);
            }
            await(threadStarted);
            BlockingQueue<Runnable> q = p.getQueue();
            assertTrue(q.contains(tasks[tasks.length - 1]));
            assertFalse(q.contains(tasks[0]));
        }
    }

    /**
     * remove(task) removes queued task, and fails to remove active task
     */
    public void testRemove() throws InterruptedException {
        final CountDownLatch done = new CountDownLatch(1);
        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p, done)) {
            ScheduledFuture[] tasks = new ScheduledFuture[5];
            final CountDownLatch threadStarted = new CountDownLatch(1);
            for (int i = 0; i < tasks.length; i++) {
                Runnable r = new CheckedRunnable() {
                    public void realRun() throws InterruptedException {
                        threadStarted.countDown();
                        await(done);
                    }};
                tasks[i] = p.schedule(r, 1, MILLISECONDS);
            }
            await(threadStarted);
            BlockingQueue<Runnable> q = p.getQueue();
            assertFalse(p.remove((Runnable)tasks[0]));
            assertTrue(q.contains((Runnable)tasks[4]));
            assertTrue(q.contains((Runnable)tasks[3]));
            assertTrue(p.remove((Runnable)tasks[4]));
            assertFalse(p.remove((Runnable)tasks[4]));
            assertFalse(q.contains((Runnable)tasks[4]));
            assertTrue(q.contains((Runnable)tasks[3]));
            assertTrue(p.remove((Runnable)tasks[3]));
            assertFalse(q.contains((Runnable)tasks[3]));
        }
    }

    /**
     * purge removes cancelled tasks from the queue
     */
    public void testPurge() throws InterruptedException {
        final ScheduledFuture[] tasks = new ScheduledFuture[5];
        final Runnable releaser = new Runnable() { public void run() {
            for (ScheduledFuture task : tasks)
                if (task != null) task.cancel(true); }};
        final CustomExecutor p = new CustomExecutor(1);
        try (PoolCleaner cleaner = cleaner(p, releaser)) {
            for (int i = 0; i < tasks.length; i++)
                tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
                                      LONG_DELAY_MS, MILLISECONDS);
            int max = tasks.length;
            if (tasks[4].cancel(true)) --max;
            if (tasks[3].cancel(true)) --max;
            // There must eventually be an interference-free point at
            // which purge will not fail. (At worst, when queue is empty.)
            long startTime = System.nanoTime();
            do {
                p.purge();
                long count = p.getTaskCount();
                if (count == max)
                    return;
            } while (millisElapsedSince(startTime) < LONG_DELAY_MS);
            fail("Purge failed to remove cancelled tasks");
        }
    }

    /**
     * shutdownNow returns a list containing tasks that were not run,
     * and those tasks are drained from the queue
     */
    public void testShutdownNow() throws InterruptedException {
        final int poolSize = 2;
        final int count = 5;
        final AtomicInteger ran = new AtomicInteger(0);
        final CustomExecutor p = new CustomExecutor(poolSize);
        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
        Runnable waiter = new CheckedRunnable() { public void realRun() {
            threadsStarted.countDown();
            try {
                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
            } catch (InterruptedException success) {}
            ran.getAndIncrement();
        }};
        for (int i = 0; i < count; i++)
            p.execute(waiter);
        await(threadsStarted);
        assertEquals(poolSize, p.getActiveCount());
        assertEquals(0, p.getCompletedTaskCount());
        final List<Runnable> queuedTasks;
        try {
            queuedTasks = p.shutdownNow();
        } catch (SecurityException ok) {
            return; // Allowed in case test doesn't have privs
        }
        assertTrue(p.isShutdown());
        assertTrue(p.getQueue().isEmpty());
        assertEquals(count - poolSize, queuedTasks.size());
        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
        assertTrue(p.isTerminated());
        assertEquals(poolSize, ran.get());
        assertEquals(poolSize, p.getCompletedTaskCount());
    }

    /**
     * shutdownNow returns a list containing tasks that were not run,
     * and those tasks are drained from the queue
     */
    public void testShutdownNow_delayedTasks() throws InterruptedException {
        final CustomExecutor p = new CustomExecutor(1);
        List<ScheduledFuture> tasks = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Runnable r = new NoOpRunnable();
            tasks.add(p.schedule(r, 9, SECONDS));
            tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS));
            tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS));
        }
        if (testImplementationDetails)
            assertEquals(new HashSet(tasks), new HashSet(p.getQueue()));
        final List<Runnable> queuedTasks;
        try {
            queuedTasks = p.shutdownNow();
        } catch (SecurityException ok) {
            return; // Allowed in case test doesn't have privs
        }
        assertTrue(p.isShutdown());
        assertTrue(p.getQueue().isEmpty());
        if (testImplementationDetails)
            assertEquals(new HashSet(tasks), new HashSet(queuedTasks));
        assertEquals(tasks.size(), queuedTasks.size());
        for (ScheduledFuture task : tasks) {
            assertFalse(((CustomTask)task).ran);
            assertFalse(task.isDone());
            assertFalse(task.isCancelled());
        }
        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
        assertTrue(p.isTerminated());
    }

    /**
     * By default, periodic tasks are cancelled at shutdown.
     * By default, delayed tasks keep running after shutdown.
     * Check that changing the default values work:
     * - setExecuteExistingDelayedTasksAfterShutdownPolicy
     * - setContinueExistingPeriodicTasksAfterShutdownPolicy
     */
    public void testShutdown_cancellation() throws Exception {
        Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE };
        for (Boolean policy : allBooleans)
    {
        final int poolSize = 2;
        final CustomExecutor p = new CustomExecutor(poolSize);
        final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE);
        final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE);
        final boolean effectiveRemovePolicy = (policy == Boolean.TRUE);
        if (policy != null) {
            p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy);
            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy);
            p.setRemoveOnCancelPolicy(policy);
        }
        assertEquals(effectiveDelayedPolicy,
                     p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
        assertEquals(effectivePeriodicPolicy,
                     p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
        assertEquals(effectiveRemovePolicy,
                     p.getRemoveOnCancelPolicy());
        // Strategy: Wedge the pool with poolSize "blocker" threads
        final AtomicInteger ran = new AtomicInteger(0);
        final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
        final CountDownLatch unblock = new CountDownLatch(1);
        final CountDownLatch periodicLatch1 = new CountDownLatch(2);
        final CountDownLatch periodicLatch2 = new CountDownLatch(2);
        Runnable task = new CheckedRunnable() { public void realRun()
                                                    throws InterruptedException {
            poolBlocked.countDown();
            assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
            ran.getAndIncrement();
        }};
        List<Future<?>> blockers = new ArrayList<>();
        List<Future<?>> periodics = new ArrayList<>();
        List<Future<?>> delayeds = new ArrayList<>();
        for (int i = 0; i < poolSize; i++)
            blockers.add(p.submit(task));
        assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));

        periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1),
                                            1, 1, MILLISECONDS));
        periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
                                               1, 1, MILLISECONDS));
        delayeds.add(p.schedule(task, 1, MILLISECONDS));

        assertTrue(p.getQueue().containsAll(periodics));
        assertTrue(p.getQueue().containsAll(delayeds));
        try { p.shutdown(); } catch (SecurityException ok) { return; }
        assertTrue(p.isShutdown());
        assertFalse(p.isTerminated());
        for (Future<?> periodic : periodics) {
            assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
            assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
        }
        for (Future<?> delayed : delayeds) {
            assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
            assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
        }
        if (testImplementationDetails) {
            assertEquals(effectivePeriodicPolicy,
                         p.getQueue().containsAll(periodics));
            assertEquals(effectiveDelayedPolicy,
                         p.getQueue().containsAll(delayeds));
        }
        // Release all pool threads
        unblock.countDown();

        for (Future<?> delayed : delayeds) {
            if (effectiveDelayedPolicy) {
                assertNull(delayed.get());
            }
        }
        if (effectivePeriodicPolicy) {
            assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS));
            assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS));
            for (Future<?> periodic : periodics) {
                assertTrue(periodic.cancel(false));
                assertTrue(periodic.isCancelled());
                assertTrue(periodic.isDone());
            }
        }
        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
        assertTrue(p.isTerminated());
        assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
    }}

    /**
     * completed submit of callable returns result
     */
    public void testSubmitCallable() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            Future<String> future = e.submit(new StringTask());
            String result = future.get();
            assertSame(TEST_STRING, result);
        }
    }

    /**
     * completed submit of runnable returns successfully
     */
    public void testSubmitRunnable() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            Future<?> future = e.submit(new NoOpRunnable());
            future.get();
            assertTrue(future.isDone());
        }
    }

    /**
     * completed submit of (runnable, result) returns result
     */
    public void testSubmitRunnable2() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
            String result = future.get();
            assertSame(TEST_STRING, result);
        }
    }

    /**
     * invokeAny(null) throws NPE
     */
    public void testInvokeAny1() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            try {
                e.invokeAny(null);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * invokeAny(empty collection) throws IAE
     */
    public void testInvokeAny2() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            try {
                e.invokeAny(new ArrayList<Callable<String>>());
                shouldThrow();
            } catch (IllegalArgumentException success) {}
        }
    }

    /**
     * invokeAny(c) throws NPE if c has null elements
     */
    public void testInvokeAny3() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(latchAwaitingStringTask(latch));
            l.add(null);
            try {
                e.invokeAny(l);
                shouldThrow();
            } catch (NullPointerException success) {}
            latch.countDown();
        }
    }

    /**
     * invokeAny(c) throws ExecutionException if no task completes
     */
    public void testInvokeAny4() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new NPETask());
            try {
                e.invokeAny(l);
                shouldThrow();
            } catch (ExecutionException success) {
                assertTrue(success.getCause() instanceof NullPointerException);
            }
        }
    }

    /**
     * invokeAny(c) returns result of some task
     */
    public void testInvokeAny5() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(new StringTask());
            String result = e.invokeAny(l);
            assertSame(TEST_STRING, result);
        }
    }

    /**
     * invokeAll(null) throws NPE
     */
    public void testInvokeAll1() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            try {
                e.invokeAll(null);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * invokeAll(empty collection) returns empty collection
     */
    public void testInvokeAll2() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
            assertTrue(r.isEmpty());
        }
    }

    /**
     * invokeAll(c) throws NPE if c has null elements
     */
    public void testInvokeAll3() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(null);
            try {
                e.invokeAll(l);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * get of invokeAll(c) throws exception on failed task
     */
    public void testInvokeAll4() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new NPETask());
            List<Future<String>> futures = e.invokeAll(l);
            assertEquals(1, futures.size());
            try {
                futures.get(0).get();
                shouldThrow();
            } catch (ExecutionException success) {
                assertTrue(success.getCause() instanceof NullPointerException);
            }
        }
    }

    /**
     * invokeAll(c) returns results of all completed tasks
     */
    public void testInvokeAll5() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(new StringTask());
            List<Future<String>> futures = e.invokeAll(l);
            assertEquals(2, futures.size());
            for (Future<String> future : futures)
                assertSame(TEST_STRING, future.get());
        }
    }

    /**
     * timed invokeAny(null) throws NPE
     */
    public void testTimedInvokeAny1() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            try {
                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * timed invokeAny(,,null) throws NPE
     */
    public void testTimedInvokeAnyNullTimeUnit() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            try {
                e.invokeAny(l, MEDIUM_DELAY_MS, null);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * timed invokeAny(empty collection) throws IAE
     */
    public void testTimedInvokeAny2() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            try {
                e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (IllegalArgumentException success) {}
        }
    }

    /**
     * timed invokeAny(c) throws NPE if c has null elements
     */
    public void testTimedInvokeAny3() throws Exception {
        CountDownLatch latch = new CountDownLatch(1);
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(latchAwaitingStringTask(latch));
            l.add(null);
            try {
                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (NullPointerException success) {}
            latch.countDown();
        }
    }

    /**
     * timed invokeAny(c) throws ExecutionException if no task completes
     */
    public void testTimedInvokeAny4() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            long startTime = System.nanoTime();
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new NPETask());
            try {
                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (ExecutionException success) {
                assertTrue(success.getCause() instanceof NullPointerException);
            }
            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
        }
    }

    /**
     * timed invokeAny(c) returns result of some task
     */
    public void testTimedInvokeAny5() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            long startTime = System.nanoTime();
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(new StringTask());
            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
            assertSame(TEST_STRING, result);
            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
        }
    }

    /**
     * timed invokeAll(null) throws NPE
     */
    public void testTimedInvokeAll1() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            try {
                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * timed invokeAll(,,null) throws NPE
     */
    public void testTimedInvokeAllNullTimeUnit() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            try {
                e.invokeAll(l, MEDIUM_DELAY_MS, null);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * timed invokeAll(empty collection) returns empty collection
     */
    public void testTimedInvokeAll2() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
            assertTrue(r.isEmpty());
        }
    }

    /**
     * timed invokeAll(c) throws NPE if c has null elements
     */
    public void testTimedInvokeAll3() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(null);
            try {
                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
                shouldThrow();
            } catch (NullPointerException success) {}
        }
    }

    /**
     * get of element of invokeAll(c) throws exception on failed task
     */
    public void testTimedInvokeAll4() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new NPETask());
            List<Future<String>> futures =
                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
            assertEquals(1, futures.size());
            try {
                futures.get(0).get();
                shouldThrow();
            } catch (ExecutionException success) {
                assertTrue(success.getCause() instanceof NullPointerException);
            }
        }
    }

    /**
     * timed invokeAll(c) returns results of all completed tasks
     */
    public void testTimedInvokeAll5() throws Exception {
        final ExecutorService e = new CustomExecutor(2);
        try (PoolCleaner cleaner = cleaner(e)) {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(new StringTask());
            List<Future<String>> futures =
                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
            assertEquals(2, futures.size());
            for (Future<String> future : futures)
                assertSame(TEST_STRING, future.get());
        }
    }

    /**
     * timed invokeAll(c) cancels tasks not completed by timeout
     */
    public void testTimedInvokeAll6() throws Exception {
        for (long timeout = timeoutMillis();;) {
            final CountDownLatch done = new CountDownLatch(1);
            final Callable<String> waiter = new CheckedCallable<String>() {
                public String realCall() {
                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
                    catch (InterruptedException ok) {}
                    return "1"; }};
            final ExecutorService p = new CustomExecutor(2);
            try (PoolCleaner cleaner = cleaner(p, done)) {
                List<Callable<String>> tasks = new ArrayList<>();
                tasks.add(new StringTask("0"));
                tasks.add(waiter);
                tasks.add(new StringTask("2"));
                long startTime = System.nanoTime();
                List<Future<String>> futures =
                    p.invokeAll(tasks, timeout, MILLISECONDS);
                assertEquals(tasks.size(), futures.size());
                assertTrue(millisElapsedSince(startTime) >= timeout);
                for (Future future : futures)
                    assertTrue(future.isDone());
                assertTrue(futures.get(1).isCancelled());
                try {
                    assertEquals("0", futures.get(0).get());
                    assertEquals("2", futures.get(2).get());
                    break;
                } catch (CancellationException retryWithLongerTimeout) {
                    timeout *= 2;
                    if (timeout >= LONG_DELAY_MS / 2)
                        fail("expected exactly one task to be cancelled");
                }
            }
        }
    }

}
