/*
 * 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 junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.atomic.AtomicInteger;

public class ScheduledExecutorSubclassTest extends JSR166TestCase {

    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 {
        CustomExecutor p = new CustomExecutor(1);
        final CountDownLatch done = new CountDownLatch(1);
        final Runnable task = new CheckedRunnable() {
            public void realRun() {
                done.countDown();
            }};
        try {
            p.execute(task);
            assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
        } finally {
            joinPool(p);
        }
    }

    /**
     * delayed schedule of callable successfully executes after delay
     */
    public void testSchedule1() throws Exception {
        CustomExecutor p = new CustomExecutor(1);
        final long startTime = System.nanoTime();
        final CountDownLatch done = new CountDownLatch(1);
        try {
            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());
            assertTrue(done.await(0L, MILLISECONDS));
        } finally {
            joinPool(p);
        }
    }

    /**
     * delayed schedule of runnable successfully executes after delay
     */
    public void testSchedule3() throws Exception {
        CustomExecutor p = new CustomExecutor(1);
        final long startTime = System.nanoTime();
        final CountDownLatch done = new CountDownLatch(1);
        try {
            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());
        } finally {
            joinPool(p);
        }
    }

    /**
     * scheduleAtFixedRate executes runnable after given initial delay
     */
    public void testSchedule4() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        final long startTime = System.nanoTime();
        final CountDownLatch done = new CountDownLatch(1);
        try {
            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);
        } finally {
            joinPool(p);
        }
    }

    /**
     * scheduleWithFixedDelay executes runnable after given initial delay
     */
    public void testSchedule5() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        final long startTime = System.nanoTime();
        final CountDownLatch done = new CountDownLatch(1);
        try {
            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);
        } finally {
            joinPool(p);
        }
    }

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

    /**
     * scheduleAtFixedRate executes series of tasks at given rate
     */
    public void testFixedRateSequence() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        RunnableCounter counter = new RunnableCounter();
        ScheduledFuture h =
            p.scheduleAtFixedRate(counter, 0, 1, MILLISECONDS);
        delay(SMALL_DELAY_MS);
        h.cancel(true);
        int c = counter.count.get();
        // By time scaling conventions, we must have at least
        // an execution per SHORT delay, but no more than one SHORT more
        assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
        assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
        joinPool(p);
    }

    /**
     * scheduleWithFixedDelay executes series of tasks with given period
     */
    public void testFixedDelaySequence() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        RunnableCounter counter = new RunnableCounter();
        ScheduledFuture h =
            p.scheduleWithFixedDelay(counter, 0, 1, MILLISECONDS);
        delay(SMALL_DELAY_MS);
        h.cancel(true);
        int c = counter.count.get();
        assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
        assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
        joinPool(p);
    }

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

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

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

        joinPool(se);
    }

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

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

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

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

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

    /**
     * getCompletedTaskCount increases, but doesn't overestimate,
     * when tasks complete
     */
    public void testGetCompletedTaskCount() throws InterruptedException {
        final ThreadPoolExecutor p = new CustomExecutor(2);
        final CountDownLatch threadStarted = new CountDownLatch(1);
        final CountDownLatch threadProceed = new CountDownLatch(1);
        final CountDownLatch threadDone = new CountDownLatch(1);
        try {
            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();
            }
        } finally {
            joinPool(p);
        }
    }

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

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

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

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

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

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

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

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

    /**
     * isTerminated is false before termination, true after
     */
    public void testIsTerminated() throws InterruptedException {
        final ThreadPoolExecutor p = new CustomExecutor(1);
        final CountDownLatch threadStarted = new CountDownLatch(1);
        final CountDownLatch done = new CountDownLatch(1);
        assertFalse(p.isTerminated());
        try {
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    assertFalse(p.isTerminated());
                    threadStarted.countDown();
                    done.await();
                }});
            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
            assertFalse(p.isTerminating());
            done.countDown();
        } finally {
            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 ThreadPoolExecutor p = new CustomExecutor(1);
        final CountDownLatch threadStarted = new CountDownLatch(1);
        final CountDownLatch done = new CountDownLatch(1);
        try {
            assertFalse(p.isTerminating());
            p.execute(new CheckedRunnable() {
                public void realRun() throws InterruptedException {
                    assertFalse(p.isTerminating());
                    threadStarted.countDown();
                    done.await();
                }});
            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
            assertFalse(p.isTerminating());
            done.countDown();
        } finally {
            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 {
        ScheduledThreadPoolExecutor p = new CustomExecutor(1);
        final CountDownLatch threadStarted = new CountDownLatch(1);
        final CountDownLatch done = new CountDownLatch(1);
        try {
            ScheduledFuture[] tasks = new ScheduledFuture[5];
            for (int i = 0; i < tasks.length; i++) {
                Runnable r = new CheckedRunnable() {
                    public void realRun() throws InterruptedException {
                        threadStarted.countDown();
                        done.await();
                    }};
                tasks[i] = p.schedule(r, 1, MILLISECONDS);
            }
            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
            BlockingQueue<Runnable> q = p.getQueue();
            assertTrue(q.contains(tasks[tasks.length - 1]));
            assertFalse(q.contains(tasks[0]));
        } finally {
            done.countDown();
            joinPool(p);
        }
    }

    /**
     * remove(task) removes queued task, and fails to remove active task
     */
    public void testRemove() throws InterruptedException {
        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
        ScheduledFuture[] tasks = new ScheduledFuture[5];
        final CountDownLatch threadStarted = new CountDownLatch(1);
        final CountDownLatch done = new CountDownLatch(1);
        try {
            for (int i = 0; i < tasks.length; i++) {
                Runnable r = new CheckedRunnable() {
                    public void realRun() throws InterruptedException {
                        threadStarted.countDown();
                        done.await();
                    }};
                tasks[i] = p.schedule(r, 1, MILLISECONDS);
            }
            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
            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]));
        } finally {
            done.countDown();
            joinPool(p);
        }
    }

    /**
     * purge removes cancelled tasks from the queue
     */
    public void testPurge() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        ScheduledFuture[] tasks = new ScheduledFuture[5];
        for (int i = 0; i < tasks.length; i++)
            tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
                                  LONG_DELAY_MS, MILLISECONDS);
        try {
            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) < MEDIUM_DELAY_MS);
            fail("Purge failed to remove cancelled tasks");
        } finally {
            for (ScheduledFuture task : tasks)
                task.cancel(true);
            joinPool(p);
        }
    }

    /**
     * shutdownNow returns a list containing tasks that were not run
     */
    public void testShutdownNow() {
        CustomExecutor p = new CustomExecutor(1);
        for (int i = 0; i < 5; i++)
            p.schedule(new SmallPossiblyInterruptedRunnable(),
                       LONG_DELAY_MS, MILLISECONDS);
        try {
            List<Runnable> l = p.shutdownNow();
            assertTrue(p.isShutdown());
            assertEquals(5, l.size());
        } catch (SecurityException ok) {
            // Allowed in case test doesn't have privs
        } finally {
            joinPool(p);
        }
    }

    /**
     * In default setting, shutdown cancels periodic but not delayed
     * tasks at shutdown
     */
    public void testShutdown1() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());

        ScheduledFuture[] tasks = new ScheduledFuture[5];
        for (int i = 0; i < tasks.length; i++)
            tasks[i] = p.schedule(new NoOpRunnable(),
                                  SHORT_DELAY_MS, MILLISECONDS);
        try { p.shutdown(); } catch (SecurityException ok) { return; }
        BlockingQueue<Runnable> q = p.getQueue();
        for (ScheduledFuture task : tasks) {
            assertFalse(task.isDone());
            assertFalse(task.isCancelled());
            assertTrue(q.contains(task));
        }
        assertTrue(p.isShutdown());
        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
        assertTrue(p.isTerminated());
        for (ScheduledFuture task : tasks) {
            assertTrue(task.isDone());
            assertFalse(task.isCancelled());
        }
    }

    /**
     * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
     * delayed tasks are cancelled at shutdown
     */
    public void testShutdown2() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        p.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
        assertFalse(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
        ScheduledFuture[] tasks = new ScheduledFuture[5];
        for (int i = 0; i < tasks.length; i++)
            tasks[i] = p.schedule(new NoOpRunnable(),
                                  SHORT_DELAY_MS, MILLISECONDS);
        BlockingQueue q = p.getQueue();
        assertEquals(tasks.length, q.size());
        try { p.shutdown(); } catch (SecurityException ok) { return; }
        assertTrue(p.isShutdown());
        assertTrue(q.isEmpty());
        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
        assertTrue(p.isTerminated());
        for (ScheduledFuture task : tasks) {
            assertTrue(task.isDone());
            assertTrue(task.isCancelled());
        }
    }

    /**
     * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
     * periodic tasks are cancelled at shutdown
     */
    public void testShutdown3() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
        p.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
        long initialDelay = LONG_DELAY_MS;
        ScheduledFuture task =
            p.scheduleAtFixedRate(new NoOpRunnable(), initialDelay,
                                  5, MILLISECONDS);
        try { p.shutdown(); } catch (SecurityException ok) { return; }
        assertTrue(p.isShutdown());
        assertTrue(p.getQueue().isEmpty());
        assertTrue(task.isDone());
        assertTrue(task.isCancelled());
        joinPool(p);
    }

    /**
     * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
     * periodic tasks are not cancelled at shutdown
     */
    public void testShutdown4() throws InterruptedException {
        CustomExecutor p = new CustomExecutor(1);
        final CountDownLatch counter = new CountDownLatch(2);
        try {
            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
            assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
            assertTrue(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
            final Runnable r = new CheckedRunnable() {
                public void realRun() {
                    counter.countDown();
                }};
            ScheduledFuture task =
                p.scheduleAtFixedRate(r, 1, 1, MILLISECONDS);
            assertFalse(task.isDone());
            assertFalse(task.isCancelled());
            try { p.shutdown(); } catch (SecurityException ok) { return; }
            assertFalse(task.isCancelled());
            assertFalse(p.isTerminated());
            assertTrue(p.isShutdown());
            assertTrue(counter.await(SMALL_DELAY_MS, MILLISECONDS));
            assertFalse(task.isCancelled());
            assertTrue(task.cancel(false));
            assertTrue(task.isDone());
            assertTrue(task.isCancelled());
            assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
            assertTrue(p.isTerminated());
        }
        finally {
            joinPool(p);
        }
    }

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

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

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

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

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

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

    /**
     * invokeAny(c) throws ExecutionException if no task completes
     */
    public void testInvokeAny4() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        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);
        } finally {
            joinPool(e);
        }
    }

    /**
     * invokeAny(c) returns result of some task
     */
    public void testInvokeAny5() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        try {
            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);
        } finally {
            joinPool(e);
        }
    }

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

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

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

    /**
     * get of invokeAll(c) throws exception on failed task
     */
    public void testInvokeAll4() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        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);
        } finally {
            joinPool(e);
        }
    }

    /**
     * invokeAll(c) returns results of all completed tasks
     */
    public void testInvokeAll5() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        try {
            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());
        } finally {
            joinPool(e);
        }
    }

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

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

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

    /**
     * timed invokeAny(c) throws NPE if c has null elements
     */
    public void testTimedInvokeAny3() throws Exception {
        CountDownLatch latch = new CountDownLatch(1);
        ExecutorService e = new CustomExecutor(2);
        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) {
        } finally {
            latch.countDown();
            joinPool(e);
        }
    }

    /**
     * timed invokeAny(c) throws ExecutionException if no task completes
     */
    public void testTimedInvokeAny4() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        List<Callable<String>> l = new ArrayList<Callable<String>>();
        l.add(new NPETask());
        try {
            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
            shouldThrow();
        } catch (ExecutionException success) {
            assertTrue(success.getCause() instanceof NullPointerException);
        } finally {
            joinPool(e);
        }
    }

    /**
     * timed invokeAny(c) returns result of some task
     */
    public void testTimedInvokeAny5() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        try {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(new StringTask());
            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
            assertSame(TEST_STRING, result);
        } finally {
            joinPool(e);
        }
    }

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

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

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

    /**
     * timed invokeAll(c) throws NPE if c has null elements
     */
    public void testTimedInvokeAll3() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        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) {
        } finally {
            joinPool(e);
        }
    }

    /**
     * get of element of invokeAll(c) throws exception on failed task
     */
    public void testTimedInvokeAll4() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        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);
        } finally {
            joinPool(e);
        }
    }

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

    /**
     * timed invokeAll(c) cancels tasks not completed by timeout
     */
    public void testTimedInvokeAll6() throws Exception {
        ExecutorService e = new CustomExecutor(2);
        try {
            List<Callable<String>> l = new ArrayList<Callable<String>>();
            l.add(new StringTask());
            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
            l.add(new StringTask());
            List<Future<String>> futures =
                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
            assertEquals(l.size(), futures.size());
            for (Future future : futures)
                assertTrue(future.isDone());
            assertFalse(futures.get(0).isCancelled());
            assertTrue(futures.get(1).isCancelled());
        } finally {
            joinPool(e);
        }
    }

}
