ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
(Generate patch)

Comparing jsr166/src/test/tck/ScheduledExecutorSubclassTest.java (file contents):
Revision 1.4 by jsr166, Mon Nov 16 05:30:08 2009 UTC vs.
Revision 1.61 by jsr166, Mon Feb 22 23:16:06 2016 UTC

# Line 1 | Line 1
1   /*
2   * Written by Doug Lea with assistance from members of JCP JSR-166
3   * Expert Group and released to the public domain, as explained at
4 < * http://creativecommons.org/licenses/publicdomain
4 > * http://creativecommons.org/publicdomain/zero/1.0/
5   */
6  
7 < import junit.framework.*;
8 < import java.util.*;
9 < import java.util.concurrent.*;
10 < import java.util.concurrent.atomic.*;
7 > import static java.util.concurrent.TimeUnit.MILLISECONDS;
8 > import static java.util.concurrent.TimeUnit.NANOSECONDS;
9 > import static java.util.concurrent.TimeUnit.SECONDS;
10 >
11 > import java.util.ArrayList;
12 > import java.util.HashSet;
13 > import java.util.List;
14 > import java.util.concurrent.BlockingQueue;
15 > import java.util.concurrent.Callable;
16 > import java.util.concurrent.CancellationException;
17 > import java.util.concurrent.CountDownLatch;
18 > import java.util.concurrent.Delayed;
19 > import java.util.concurrent.ExecutionException;
20 > import java.util.concurrent.Executors;
21 > import java.util.concurrent.ExecutorService;
22 > import java.util.concurrent.Future;
23 > import java.util.concurrent.RejectedExecutionException;
24 > import java.util.concurrent.RejectedExecutionHandler;
25 > import java.util.concurrent.RunnableScheduledFuture;
26 > import java.util.concurrent.ScheduledFuture;
27 > import java.util.concurrent.ScheduledThreadPoolExecutor;
28 > import java.util.concurrent.ThreadFactory;
29 > import java.util.concurrent.ThreadPoolExecutor;
30 > import java.util.concurrent.TimeoutException;
31 > import java.util.concurrent.TimeUnit;
32 > import java.util.concurrent.atomic.AtomicBoolean;
33 > import java.util.concurrent.atomic.AtomicInteger;
34 > import java.util.concurrent.atomic.AtomicLong;
35 >
36 > import junit.framework.Test;
37 > import junit.framework.TestSuite;
38  
39   public class ScheduledExecutorSubclassTest extends JSR166TestCase {
40      public static void main(String[] args) {
41 <        junit.textui.TestRunner.run (suite());
41 >        main(suite(), args);
42      }
43      public static Test suite() {
44 <        return new TestSuite(ScheduledExecutorTest.class);
44 >        return new TestSuite(ScheduledExecutorSubclassTest.class);
45      }
46  
47      static class CustomTask<V> implements RunnableScheduledFuture<V> {
# Line 35 | Line 62 | public class ScheduledExecutorSubclassTe
62          }
63          public boolean isCancelled() { return task.isCancelled(); }
64          public boolean isDone() { return task.isDone(); }
65 <        public V get() throws InterruptedException,  ExecutionException {
65 >        public V get() throws InterruptedException, ExecutionException {
66              V v = task.get();
67              assertTrue(ran);
68              return v;
69          }
70 <        public V get(long time, TimeUnit unit) throws InterruptedException,  ExecutionException, TimeoutException {
70 >        public V get(long time, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
71              V v = task.get(time, unit);
72              assertTrue(ran);
73              return v;
74          }
75      }
76  
50
77      public class CustomExecutor extends ScheduledThreadPoolExecutor {
78  
79          protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
# Line 57 | Line 83 | public class ScheduledExecutorSubclassTe
83          protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> c, RunnableScheduledFuture<V> task) {
84              return new CustomTask<V>(task);
85          }
86 <        CustomExecutor(int corePoolSize) { super(corePoolSize);}
86 >        CustomExecutor(int corePoolSize) { super(corePoolSize); }
87          CustomExecutor(int corePoolSize, RejectedExecutionHandler handler) {
88              super(corePoolSize, handler);
89          }
# Line 72 | Line 98 | public class ScheduledExecutorSubclassTe
98  
99      }
100  
75
76
101      /**
102       * execute successfully executes a runnable
103       */
104 <    public void testExecute() {
105 <        try {
106 <            TrackedShortRunnable runnable =new TrackedShortRunnable();
107 <            CustomExecutor p1 = new CustomExecutor(1);
108 <            p1.execute(runnable);
109 <            assertFalse(runnable.done);
110 <            Thread.sleep(SHORT_DELAY_MS);
111 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
88 <            try {
89 <                Thread.sleep(MEDIUM_DELAY_MS);
90 <            } catch (InterruptedException e) {
91 <                unexpectedException();
92 <            }
93 <            assertTrue(runnable.done);
94 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
95 <            joinPool(p1);
96 <        }
97 <        catch (Exception e) {
98 <            unexpectedException();
104 >    public void testExecute() throws InterruptedException {
105 >        final CustomExecutor p = new CustomExecutor(1);
106 >        try (PoolCleaner cleaner = cleaner(p)) {
107 >            final CountDownLatch done = new CountDownLatch(1);
108 >            final Runnable task = new CheckedRunnable() {
109 >                public void realRun() { done.countDown(); }};
110 >            p.execute(task);
111 >            await(done);
112          }
100
113      }
114  
103
115      /**
116       * delayed schedule of callable successfully executes after delay
117       */
118 <    public void testSchedule1() {
119 <        try {
120 <            TrackedCallable callable = new TrackedCallable();
121 <            CustomExecutor p1 = new CustomExecutor(1);
122 <            Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
123 <            assertFalse(callable.done);
124 <            Thread.sleep(MEDIUM_DELAY_MS);
125 <            assertTrue(callable.done);
126 <            assertEquals(Boolean.TRUE, f.get());
127 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
128 <            joinPool(p1);
129 <        } catch (RejectedExecutionException e) {}
130 <        catch (Exception e) {
131 <            e.printStackTrace();
121 <            unexpectedException();
118 >    public void testSchedule1() throws Exception {
119 >        final CountDownLatch done = new CountDownLatch(1);
120 >        final CustomExecutor p = new CustomExecutor(1);
121 >        try (PoolCleaner cleaner = cleaner(p, done)) {
122 >            final long startTime = System.nanoTime();
123 >            Callable task = new CheckedCallable<Boolean>() {
124 >                public Boolean realCall() {
125 >                    done.countDown();
126 >                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
127 >                    return Boolean.TRUE;
128 >                }};
129 >            Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
130 >            assertSame(Boolean.TRUE, f.get());
131 >            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
132          }
133      }
134  
135      /**
136 <     *  delayed schedule of runnable successfully executes after delay
137 <     */
138 <    public void testSchedule3() {
139 <        try {
140 <            TrackedShortRunnable runnable = new TrackedShortRunnable();
141 <            CustomExecutor p1 = new CustomExecutor(1);
142 <            p1.schedule(runnable, SMALL_DELAY_MS, TimeUnit.MILLISECONDS);
143 <            Thread.sleep(SHORT_DELAY_MS);
144 <            assertFalse(runnable.done);
145 <            Thread.sleep(MEDIUM_DELAY_MS);
146 <            assertTrue(runnable.done);
147 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
148 <            joinPool(p1);
149 <        } catch (Exception e) {
150 <            unexpectedException();
136 >     * delayed schedule of runnable successfully executes after delay
137 >     */
138 >    public void testSchedule3() throws Exception {
139 >        final CustomExecutor p = new CustomExecutor(1);
140 >        try (PoolCleaner cleaner = cleaner(p)) {
141 >            final long startTime = System.nanoTime();
142 >            final CountDownLatch done = new CountDownLatch(1);
143 >            Runnable task = new CheckedRunnable() {
144 >                public void realRun() {
145 >                    done.countDown();
146 >                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
147 >                }};
148 >            Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
149 >            await(done);
150 >            assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
151 >            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
152          }
153      }
154  
155      /**
156       * scheduleAtFixedRate executes runnable after given initial delay
157       */
158 <    public void testSchedule4() {
159 <        try {
160 <            TrackedShortRunnable runnable = new TrackedShortRunnable();
161 <            CustomExecutor p1 = new CustomExecutor(1);
162 <            ScheduledFuture h = p1.scheduleAtFixedRate(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
163 <            assertFalse(runnable.done);
164 <            Thread.sleep(MEDIUM_DELAY_MS);
165 <            assertTrue(runnable.done);
166 <            h.cancel(true);
167 <            joinPool(p1);
168 <        } catch (Exception e) {
169 <            unexpectedException();
158 >    public void testSchedule4() throws InterruptedException {
159 >        final CustomExecutor p = new CustomExecutor(1);
160 >        try (PoolCleaner cleaner = cleaner(p)) {
161 >            final long startTime = System.nanoTime();
162 >            final CountDownLatch done = new CountDownLatch(1);
163 >            Runnable task = new CheckedRunnable() {
164 >                public void realRun() {
165 >                    done.countDown();
166 >                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
167 >                }};
168 >            ScheduledFuture f =
169 >                p.scheduleAtFixedRate(task, timeoutMillis(),
170 >                                      LONG_DELAY_MS, MILLISECONDS);
171 >            await(done);
172 >            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
173 >            f.cancel(true);
174          }
175      }
176  
162    static class RunnableCounter implements Runnable {
163        AtomicInteger count = new AtomicInteger(0);
164        public void run() { count.getAndIncrement(); }
165    }
166
177      /**
178       * scheduleWithFixedDelay executes runnable after given initial delay
179       */
180 <    public void testSchedule5() {
181 <        try {
182 <            TrackedShortRunnable runnable = new TrackedShortRunnable();
183 <            CustomExecutor p1 = new CustomExecutor(1);
184 <            ScheduledFuture h = p1.scheduleWithFixedDelay(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
185 <            assertFalse(runnable.done);
186 <            Thread.sleep(MEDIUM_DELAY_MS);
187 <            assertTrue(runnable.done);
188 <            h.cancel(true);
189 <            joinPool(p1);
190 <        } catch (Exception e) {
191 <            unexpectedException();
180 >    public void testSchedule5() throws InterruptedException {
181 >        final CustomExecutor p = new CustomExecutor(1);
182 >        try (PoolCleaner cleaner = cleaner(p)) {
183 >            final long startTime = System.nanoTime();
184 >            final CountDownLatch done = new CountDownLatch(1);
185 >            Runnable task = new CheckedRunnable() {
186 >                public void realRun() {
187 >                    done.countDown();
188 >                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
189 >                }};
190 >            ScheduledFuture f =
191 >                p.scheduleWithFixedDelay(task, timeoutMillis(),
192 >                                         LONG_DELAY_MS, MILLISECONDS);
193 >            await(done);
194 >            assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
195 >            f.cancel(true);
196          }
197      }
198  
199 +    static class RunnableCounter implements Runnable {
200 +        AtomicInteger count = new AtomicInteger(0);
201 +        public void run() { count.getAndIncrement(); }
202 +    }
203 +
204      /**
205 <     * scheduleAtFixedRate executes series of tasks at given rate
206 <     */
207 <    public void testFixedRateSequence() {
208 <        try {
209 <            CustomExecutor p1 = new CustomExecutor(1);
210 <            RunnableCounter counter = new RunnableCounter();
211 <            ScheduledFuture h =
212 <                p1.scheduleAtFixedRate(counter, 0, 1, TimeUnit.MILLISECONDS);
213 <            Thread.sleep(SMALL_DELAY_MS);
214 <            h.cancel(true);
215 <            int c = counter.count.get();
216 <            // By time scaling conventions, we must have at least
217 <            // an execution per SHORT delay, but no more than one SHORT more
218 <            assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
219 <            assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
220 <            joinPool(p1);
221 <        } catch (Exception e) {
222 <            unexpectedException();
205 >     * scheduleAtFixedRate executes series of tasks at given rate.
206 >     * Eventually, it must hold that:
207 >     *   cycles - 1 <= elapsedMillis/delay < cycles
208 >     */
209 >    public void testFixedRateSequence() throws InterruptedException {
210 >        final CustomExecutor p = new CustomExecutor(1);
211 >        try (PoolCleaner cleaner = cleaner(p)) {
212 >            for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
213 >                final long startTime = System.nanoTime();
214 >                final int cycles = 8;
215 >                final CountDownLatch done = new CountDownLatch(cycles);
216 >                final Runnable task = new CheckedRunnable() {
217 >                    public void realRun() { done.countDown(); }};
218 >                final ScheduledFuture periodicTask =
219 >                    p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
220 >                final int totalDelayMillis = (cycles - 1) * delay;
221 >                await(done, totalDelayMillis + LONG_DELAY_MS);
222 >                periodicTask.cancel(true);
223 >                final long elapsedMillis = millisElapsedSince(startTime);
224 >                assertTrue(elapsedMillis >= totalDelayMillis);
225 >                if (elapsedMillis <= cycles * delay)
226 >                    return;
227 >                // else retry with longer delay
228 >            }
229 >            fail("unexpected execution rate");
230          }
231      }
232  
233      /**
234 <     * scheduleWithFixedDelay executes series of tasks with given period
235 <     */
236 <    public void testFixedDelaySequence() {
237 <        try {
238 <            CustomExecutor p1 = new CustomExecutor(1);
239 <            RunnableCounter counter = new RunnableCounter();
240 <            ScheduledFuture h =
241 <                p1.scheduleWithFixedDelay(counter, 0, 1, TimeUnit.MILLISECONDS);
242 <            Thread.sleep(SMALL_DELAY_MS);
243 <            h.cancel(true);
244 <            int c = counter.count.get();
245 <            assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
246 <            assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
247 <            joinPool(p1);
248 <        } catch (Exception e) {
249 <            unexpectedException();
234 >     * scheduleWithFixedDelay executes series of tasks with given period.
235 >     * Eventually, it must hold that each task starts at least delay and at
236 >     * most 2 * delay after the termination of the previous task.
237 >     */
238 >    public void testFixedDelaySequence() throws InterruptedException {
239 >        final CustomExecutor p = new CustomExecutor(1);
240 >        try (PoolCleaner cleaner = cleaner(p)) {
241 >            for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
242 >                final long startTime = System.nanoTime();
243 >                final AtomicLong previous = new AtomicLong(startTime);
244 >                final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
245 >                final int cycles = 8;
246 >                final CountDownLatch done = new CountDownLatch(cycles);
247 >                final int d = delay;
248 >                final Runnable task = new CheckedRunnable() {
249 >                    public void realRun() {
250 >                        long now = System.nanoTime();
251 >                        long elapsedMillis
252 >                            = NANOSECONDS.toMillis(now - previous.get());
253 >                        if (done.getCount() == cycles) { // first execution
254 >                            if (elapsedMillis >= d)
255 >                                tryLongerDelay.set(true);
256 >                        } else {
257 >                            assertTrue(elapsedMillis >= d);
258 >                            if (elapsedMillis >= 2 * d)
259 >                                tryLongerDelay.set(true);
260 >                        }
261 >                        previous.set(now);
262 >                        done.countDown();
263 >                    }};
264 >                final ScheduledFuture periodicTask =
265 >                    p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
266 >                final int totalDelayMillis = (cycles - 1) * delay;
267 >                await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
268 >                periodicTask.cancel(true);
269 >                final long elapsedMillis = millisElapsedSince(startTime);
270 >                assertTrue(elapsedMillis >= totalDelayMillis);
271 >                if (!tryLongerDelay.get())
272 >                    return;
273 >                // else retry with longer delay
274 >            }
275 >            fail("unexpected execution rate");
276          }
277      }
278  
227
279      /**
280 <     *  execute (null) throws NPE
280 >     * execute(null) throws NPE
281       */
282 <    public void testExecuteNull() {
283 <        CustomExecutor se = null;
284 <        try {
285 <            se = new CustomExecutor(1);
286 <            se.execute(null);
287 <            shouldThrow();
288 <        } catch (NullPointerException success) {}
238 <        catch (Exception e) {
239 <            unexpectedException();
282 >    public void testExecuteNull() throws InterruptedException {
283 >        final CustomExecutor p = new CustomExecutor(1);
284 >        try (PoolCleaner cleaner = cleaner(p)) {
285 >            try {
286 >                p.execute(null);
287 >                shouldThrow();
288 >            } catch (NullPointerException success) {}
289          }
241
242        joinPool(se);
290      }
291  
292      /**
293 <     * schedule (null) throws NPE
293 >     * schedule(null) throws NPE
294       */
295 <    public void testScheduleNull() {
296 <        CustomExecutor se = new CustomExecutor(1);
297 <        try {
298 <            TrackedCallable callable = null;
299 <            Future f = se.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
300 <            shouldThrow();
301 <        } catch (NullPointerException success) {}
302 <        catch (Exception e) {
256 <            unexpectedException();
295 >    public void testScheduleNull() throws InterruptedException {
296 >        final CustomExecutor p = new CustomExecutor(1);
297 >        try (PoolCleaner cleaner = cleaner(p)) {
298 >            try {
299 >                TrackedCallable callable = null;
300 >                Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
301 >                shouldThrow();
302 >            } catch (NullPointerException success) {}
303          }
258        joinPool(se);
304      }
305  
306      /**
307       * execute throws RejectedExecutionException if shutdown
308       */
309      public void testSchedule1_RejectedExecutionException() {
310 <        CustomExecutor se = new CustomExecutor(1);
311 <        try {
312 <            se.shutdown();
313 <            se.schedule(new NoOpRunnable(),
314 <                        MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
315 <            shouldThrow();
316 <        } catch (RejectedExecutionException success) {
317 <        } catch (SecurityException ok) {
310 >        final CustomExecutor p = new CustomExecutor(1);
311 >        try (PoolCleaner cleaner = cleaner(p)) {
312 >            try {
313 >                p.shutdown();
314 >                p.schedule(new NoOpRunnable(),
315 >                           MEDIUM_DELAY_MS, MILLISECONDS);
316 >                shouldThrow();
317 >            } catch (RejectedExecutionException success) {
318 >            } catch (SecurityException ok) {}
319          }
274
275        joinPool(se);
276
320      }
321  
322      /**
323       * schedule throws RejectedExecutionException if shutdown
324       */
325      public void testSchedule2_RejectedExecutionException() {
326 <        CustomExecutor se = new CustomExecutor(1);
327 <        try {
328 <            se.shutdown();
329 <            se.schedule(new NoOpCallable(),
330 <                        MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
331 <            shouldThrow();
332 <        } catch (RejectedExecutionException success) {
333 <        } catch (SecurityException ok) {
326 >        final CustomExecutor p = new CustomExecutor(1);
327 >        try (PoolCleaner cleaner = cleaner(p)) {
328 >            try {
329 >                p.shutdown();
330 >                p.schedule(new NoOpCallable(),
331 >                           MEDIUM_DELAY_MS, MILLISECONDS);
332 >                shouldThrow();
333 >            } catch (RejectedExecutionException success) {
334 >            } catch (SecurityException ok) {}
335          }
292        joinPool(se);
336      }
337  
338      /**
339       * schedule callable throws RejectedExecutionException if shutdown
340       */
341 <     public void testSchedule3_RejectedExecutionException() {
342 <         CustomExecutor se = new CustomExecutor(1);
343 <         try {
344 <            se.shutdown();
345 <            se.schedule(new NoOpCallable(),
346 <                        MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
347 <            shouldThrow();
348 <        } catch (RejectedExecutionException success) {
349 <        } catch (SecurityException ok) {
341 >    public void testSchedule3_RejectedExecutionException() {
342 >        final CustomExecutor p = new CustomExecutor(1);
343 >        try (PoolCleaner cleaner = cleaner(p)) {
344 >            try {
345 >                p.shutdown();
346 >                p.schedule(new NoOpCallable(),
347 >                           MEDIUM_DELAY_MS, MILLISECONDS);
348 >                shouldThrow();
349 >            } catch (RejectedExecutionException success) {
350 >            } catch (SecurityException ok) {}
351          }
308         joinPool(se);
352      }
353  
354      /**
355 <     *  scheduleAtFixedRate throws RejectedExecutionException if shutdown
355 >     * scheduleAtFixedRate throws RejectedExecutionException if shutdown
356       */
357      public void testScheduleAtFixedRate1_RejectedExecutionException() {
358 <        CustomExecutor se = new CustomExecutor(1);
359 <        try {
360 <            se.shutdown();
361 <            se.scheduleAtFixedRate(new NoOpRunnable(),
362 <                                   MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
363 <            shouldThrow();
364 <        } catch (RejectedExecutionException success) {
365 <        } catch (SecurityException ok) {
358 >        final CustomExecutor p = new CustomExecutor(1);
359 >        try (PoolCleaner cleaner = cleaner(p)) {
360 >            try {
361 >                p.shutdown();
362 >                p.scheduleAtFixedRate(new NoOpRunnable(),
363 >                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
364 >                shouldThrow();
365 >            } catch (RejectedExecutionException success) {
366 >            } catch (SecurityException ok) {}
367          }
324        joinPool(se);
368      }
369  
370      /**
371       * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
372       */
373      public void testScheduleWithFixedDelay1_RejectedExecutionException() {
374 <        CustomExecutor se = new CustomExecutor(1);
375 <        try {
376 <            se.shutdown();
377 <            se.scheduleWithFixedDelay(new NoOpRunnable(),
378 <                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
379 <            shouldThrow();
380 <        } catch (RejectedExecutionException success) {
381 <        } catch (SecurityException ok) {
374 >        final CustomExecutor p = new CustomExecutor(1);
375 >        try (PoolCleaner cleaner = cleaner(p)) {
376 >            try {
377 >                p.shutdown();
378 >                p.scheduleWithFixedDelay(new NoOpRunnable(),
379 >                                         MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
380 >                shouldThrow();
381 >            } catch (RejectedExecutionException success) {
382 >            } catch (SecurityException ok) {}
383          }
340        joinPool(se);
384      }
385  
386      /**
387 <     *  getActiveCount increases but doesn't overestimate, when a
388 <     *  thread becomes active
389 <     */
390 <    public void testGetActiveCount() {
391 <        CustomExecutor p2 = new CustomExecutor(2);
392 <        assertEquals(0, p2.getActiveCount());
393 <        p2.execute(new SmallRunnable());
394 <        try {
395 <            Thread.sleep(SHORT_DELAY_MS);
396 <        } catch (Exception e) {
397 <            unexpectedException();
387 >     * getActiveCount increases but doesn't overestimate, when a
388 >     * thread becomes active
389 >     */
390 >    public void testGetActiveCount() throws InterruptedException {
391 >        final CountDownLatch done = new CountDownLatch(1);
392 >        final ThreadPoolExecutor p = new CustomExecutor(2);
393 >        try (PoolCleaner cleaner = cleaner(p, done)) {
394 >            final CountDownLatch threadStarted = new CountDownLatch(1);
395 >            assertEquals(0, p.getActiveCount());
396 >            p.execute(new CheckedRunnable() {
397 >                public void realRun() throws InterruptedException {
398 >                    threadStarted.countDown();
399 >                    assertEquals(1, p.getActiveCount());
400 >                    await(done);
401 >                }});
402 >            await(threadStarted);
403 >            assertEquals(1, p.getActiveCount());
404          }
356        assertEquals(1, p2.getActiveCount());
357        joinPool(p2);
405      }
406  
407      /**
408 <     *    getCompletedTaskCount increases, but doesn't overestimate,
409 <     *   when tasks complete
410 <     */
411 <    public void testGetCompletedTaskCount() {
412 <        CustomExecutor p2 = new CustomExecutor(2);
413 <        assertEquals(0, p2.getCompletedTaskCount());
414 <        p2.execute(new SmallRunnable());
415 <        try {
416 <            Thread.sleep(MEDIUM_DELAY_MS);
417 <        } catch (Exception e) {
418 <            unexpectedException();
408 >     * getCompletedTaskCount increases, but doesn't overestimate,
409 >     * when tasks complete
410 >     */
411 >    public void testGetCompletedTaskCount() throws InterruptedException {
412 >        final ThreadPoolExecutor p = new CustomExecutor(2);
413 >        try (PoolCleaner cleaner = cleaner(p)) {
414 >            final CountDownLatch threadStarted = new CountDownLatch(1);
415 >            final CountDownLatch threadProceed = new CountDownLatch(1);
416 >            final CountDownLatch threadDone = new CountDownLatch(1);
417 >            assertEquals(0, p.getCompletedTaskCount());
418 >            p.execute(new CheckedRunnable() {
419 >                public void realRun() throws InterruptedException {
420 >                    threadStarted.countDown();
421 >                    assertEquals(0, p.getCompletedTaskCount());
422 >                    threadProceed.await();
423 >                    threadDone.countDown();
424 >                }});
425 >            await(threadStarted);
426 >            assertEquals(0, p.getCompletedTaskCount());
427 >            threadProceed.countDown();
428 >            threadDone.await();
429 >            long startTime = System.nanoTime();
430 >            while (p.getCompletedTaskCount() != 1) {
431 >                if (millisElapsedSince(startTime) > LONG_DELAY_MS)
432 >                    fail("timed out");
433 >                Thread.yield();
434 >            }
435          }
373        assertEquals(1, p2.getCompletedTaskCount());
374        joinPool(p2);
436      }
437  
438      /**
439 <     *  getCorePoolSize returns size given in constructor if not otherwise set
439 >     * getCorePoolSize returns size given in constructor if not otherwise set
440       */
441      public void testGetCorePoolSize() {
442 <        CustomExecutor p1 = new CustomExecutor(1);
443 <        assertEquals(1, p1.getCorePoolSize());
444 <        joinPool(p1);
445 <    }
446 <
447 <    /**
448 <     *    getLargestPoolSize increases, but doesn't overestimate, when
449 <     *   multiple threads active
450 <     */
451 <    public void testGetLargestPoolSize() {
452 <        CustomExecutor p2 = new CustomExecutor(2);
453 <        assertEquals(0, p2.getLargestPoolSize());
454 <        p2.execute(new SmallRunnable());
455 <        p2.execute(new SmallRunnable());
456 <        try {
457 <            Thread.sleep(SHORT_DELAY_MS);
458 <        } catch (Exception e) {
459 <            unexpectedException();
460 <        }
461 <        assertEquals(2, p2.getLargestPoolSize());
462 <        joinPool(p2);
463 <    }
464 <
465 <    /**
466 <     *   getPoolSize increases, but doesn't overestimate, when threads
467 <     *   become active
468 <     */
469 <    public void testGetPoolSize() {
470 <        CustomExecutor p1 = new CustomExecutor(1);
471 <        assertEquals(0, p1.getPoolSize());
472 <        p1.execute(new SmallRunnable());
473 <        assertEquals(1, p1.getPoolSize());
474 <        joinPool(p1);
475 <    }
476 <
477 <    /**
478 <     *    getTaskCount increases, but doesn't overestimate, when tasks
479 <     *    submitted
480 <     */
481 <    public void testGetTaskCount() {
482 <        CustomExecutor p1 = new CustomExecutor(1);
483 <        assertEquals(0, p1.getTaskCount());
484 <        for (int i = 0; i < 5; i++)
485 <            p1.execute(new SmallRunnable());
486 <        try {
487 <            Thread.sleep(SHORT_DELAY_MS);
488 <        } catch (Exception e) {
489 <            unexpectedException();
442 >        final CustomExecutor p = new CustomExecutor(1);
443 >        try (PoolCleaner cleaner = cleaner(p)) {
444 >            assertEquals(1, p.getCorePoolSize());
445 >        }
446 >    }
447 >
448 >    /**
449 >     * getLargestPoolSize increases, but doesn't overestimate, when
450 >     * multiple threads active
451 >     */
452 >    public void testGetLargestPoolSize() throws InterruptedException {
453 >        final int THREADS = 3;
454 >        final CountDownLatch done = new CountDownLatch(1);
455 >        final ThreadPoolExecutor p = new CustomExecutor(THREADS);
456 >        try (PoolCleaner cleaner = cleaner(p, done)) {
457 >            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
458 >            assertEquals(0, p.getLargestPoolSize());
459 >            for (int i = 0; i < THREADS; i++)
460 >                p.execute(new CheckedRunnable() {
461 >                    public void realRun() throws InterruptedException {
462 >                        threadsStarted.countDown();
463 >                        await(done);
464 >                        assertEquals(THREADS, p.getLargestPoolSize());
465 >                    }});
466 >            await(threadsStarted);
467 >            assertEquals(THREADS, p.getLargestPoolSize());
468 >        }
469 >        assertEquals(THREADS, p.getLargestPoolSize());
470 >    }
471 >
472 >    /**
473 >     * getPoolSize increases, but doesn't overestimate, when threads
474 >     * become active
475 >     */
476 >    public void testGetPoolSize() throws InterruptedException {
477 >        final CountDownLatch done = new CountDownLatch(1);
478 >        final ThreadPoolExecutor p = new CustomExecutor(1);
479 >        try (PoolCleaner cleaner = cleaner(p, done)) {
480 >            final CountDownLatch threadStarted = new CountDownLatch(1);
481 >            assertEquals(0, p.getPoolSize());
482 >            p.execute(new CheckedRunnable() {
483 >                public void realRun() throws InterruptedException {
484 >                    threadStarted.countDown();
485 >                    assertEquals(1, p.getPoolSize());
486 >                    await(done);
487 >                }});
488 >            await(threadStarted);
489 >            assertEquals(1, p.getPoolSize());
490 >        }
491 >    }
492 >
493 >    /**
494 >     * getTaskCount increases, but doesn't overestimate, when tasks
495 >     * submitted
496 >     */
497 >    public void testGetTaskCount() throws InterruptedException {
498 >        final int TASKS = 3;
499 >        final CountDownLatch done = new CountDownLatch(1);
500 >        final ThreadPoolExecutor p = new CustomExecutor(1);
501 >        try (PoolCleaner cleaner = cleaner(p, done)) {
502 >            final CountDownLatch threadStarted = new CountDownLatch(1);
503 >            assertEquals(0, p.getTaskCount());
504 >            assertEquals(0, p.getCompletedTaskCount());
505 >            p.execute(new CheckedRunnable() {
506 >                public void realRun() throws InterruptedException {
507 >                    threadStarted.countDown();
508 >                    await(done);
509 >                }});
510 >            await(threadStarted);
511 >            assertEquals(1, p.getTaskCount());
512 >            assertEquals(0, p.getCompletedTaskCount());
513 >            for (int i = 0; i < TASKS; i++) {
514 >                assertEquals(1 + i, p.getTaskCount());
515 >                p.execute(new CheckedRunnable() {
516 >                    public void realRun() throws InterruptedException {
517 >                        threadStarted.countDown();
518 >                        assertEquals(1 + TASKS, p.getTaskCount());
519 >                        await(done);
520 >                    }});
521 >            }
522 >            assertEquals(1 + TASKS, p.getTaskCount());
523 >            assertEquals(0, p.getCompletedTaskCount());
524          }
525 <        assertEquals(5, p1.getTaskCount());
526 <        joinPool(p1);
525 >        assertEquals(1 + TASKS, p.getTaskCount());
526 >        assertEquals(1 + TASKS, p.getCompletedTaskCount());
527      }
528  
529      /**
530       * getThreadFactory returns factory in constructor if not set
531       */
532      public void testGetThreadFactory() {
533 <        ThreadFactory tf = new SimpleThreadFactory();
534 <        CustomExecutor p = new CustomExecutor(1, tf);
535 <        assertSame(tf, p.getThreadFactory());
536 <        joinPool(p);
533 >        final ThreadFactory threadFactory = new SimpleThreadFactory();
534 >        final CustomExecutor p = new CustomExecutor(1, threadFactory);
535 >        try (PoolCleaner cleaner = cleaner(p)) {
536 >            assertSame(threadFactory, p.getThreadFactory());
537 >        }
538      }
539  
540      /**
541       * setThreadFactory sets the thread factory returned by getThreadFactory
542       */
543      public void testSetThreadFactory() {
544 <        ThreadFactory tf = new SimpleThreadFactory();
545 <        CustomExecutor p = new CustomExecutor(1);
546 <        p.setThreadFactory(tf);
547 <        assertSame(tf, p.getThreadFactory());
548 <        joinPool(p);
544 >        final ThreadFactory threadFactory = new SimpleThreadFactory();
545 >        final CustomExecutor p = new CustomExecutor(1);
546 >        try (PoolCleaner cleaner = cleaner(p)) {
547 >            p.setThreadFactory(threadFactory);
548 >            assertSame(threadFactory, p.getThreadFactory());
549 >        }
550      }
551  
552      /**
553       * setThreadFactory(null) throws NPE
554       */
555      public void testSetThreadFactoryNull() {
556 <        CustomExecutor p = new CustomExecutor(1);
557 <        try {
558 <            p.setThreadFactory(null);
559 <            shouldThrow();
560 <        } catch (NullPointerException success) {
561 <        } finally {
465 <            joinPool(p);
556 >        final CustomExecutor p = new CustomExecutor(1);
557 >        try (PoolCleaner cleaner = cleaner(p)) {
558 >            try {
559 >                p.setThreadFactory(null);
560 >                shouldThrow();
561 >            } catch (NullPointerException success) {}
562          }
563      }
564  
565      /**
566 <     *   is isShutDown is false before shutdown, true after
566 >     * isShutdown is false before shutdown, true after
567       */
568      public void testIsShutdown() {
569 <
570 <        CustomExecutor p1 = new CustomExecutor(1);
571 <        try {
572 <            assertFalse(p1.isShutdown());
573 <        }
478 <        finally {
479 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
569 >        final CustomExecutor p = new CustomExecutor(1);
570 >        try (PoolCleaner cleaner = cleaner(p)) {
571 >            assertFalse(p.isShutdown());
572 >            try { p.shutdown(); } catch (SecurityException ok) { return; }
573 >            assertTrue(p.isShutdown());
574          }
481        assertTrue(p1.isShutdown());
575      }
576  
484
577      /**
578 <     *   isTerminated is false before termination, true after
579 <     */
580 <    public void testIsTerminated() {
581 <        CustomExecutor p1 = new CustomExecutor(1);
582 <        try {
583 <            p1.execute(new SmallRunnable());
584 <        } finally {
585 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
586 <        }
587 <        try {
588 <            assertTrue(p1.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
589 <            assertTrue(p1.isTerminated());
590 <        } catch (Exception e) {
591 <            unexpectedException();
578 >     * isTerminated is false before termination, true after
579 >     */
580 >    public void testIsTerminated() throws InterruptedException {
581 >        final CountDownLatch done = new CountDownLatch(1);
582 >        final ThreadPoolExecutor p = new CustomExecutor(1);
583 >        try (PoolCleaner cleaner = cleaner(p)) {
584 >            final CountDownLatch threadStarted = new CountDownLatch(1);
585 >            p.execute(new CheckedRunnable() {
586 >                public void realRun() throws InterruptedException {
587 >                    assertFalse(p.isTerminated());
588 >                    threadStarted.countDown();
589 >                    await(done);
590 >                }});
591 >            await(threadStarted);
592 >            assertFalse(p.isTerminated());
593 >            assertFalse(p.isTerminating());
594 >            done.countDown();
595 >            try { p.shutdown(); } catch (SecurityException ok) { return; }
596 >            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
597 >            assertTrue(p.isTerminated());
598          }
599      }
600  
601      /**
602 <     *  isTerminating is not true when running or when terminated
603 <     */
604 <    public void testIsTerminating() {
605 <        CustomExecutor p1 = new CustomExecutor(1);
606 <        assertFalse(p1.isTerminating());
607 <        try {
608 <            p1.execute(new SmallRunnable());
609 <            assertFalse(p1.isTerminating());
610 <        } finally {
611 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
612 <        }
613 <        try {
614 <            assertTrue(p1.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
615 <            assertTrue(p1.isTerminated());
616 <            assertFalse(p1.isTerminating());
617 <        } catch (Exception e) {
618 <            unexpectedException();
602 >     * isTerminating is not true when running or when terminated
603 >     */
604 >    public void testIsTerminating() throws InterruptedException {
605 >        final CountDownLatch done = new CountDownLatch(1);
606 >        final ThreadPoolExecutor p = new CustomExecutor(1);
607 >        try (PoolCleaner cleaner = cleaner(p)) {
608 >            final CountDownLatch threadStarted = new CountDownLatch(1);
609 >            assertFalse(p.isTerminating());
610 >            p.execute(new CheckedRunnable() {
611 >                public void realRun() throws InterruptedException {
612 >                    assertFalse(p.isTerminating());
613 >                    threadStarted.countDown();
614 >                    await(done);
615 >                }});
616 >            await(threadStarted);
617 >            assertFalse(p.isTerminating());
618 >            done.countDown();
619 >            try { p.shutdown(); } catch (SecurityException ok) { return; }
620 >            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
621 >            assertTrue(p.isTerminated());
622 >            assertFalse(p.isTerminating());
623          }
624      }
625  
626      /**
627       * getQueue returns the work queue, which contains queued tasks
628       */
629 <    public void testGetQueue() {
630 <        CustomExecutor p1 = new CustomExecutor(1);
631 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
632 <        for (int i = 0; i < 5; i++) {
633 <            tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, TimeUnit.MILLISECONDS);
634 <        }
635 <        try {
636 <            Thread.sleep(SHORT_DELAY_MS);
637 <            BlockingQueue<Runnable> q = p1.getQueue();
638 <            assertTrue(q.contains(tasks[4]));
629 >    public void testGetQueue() throws InterruptedException {
630 >        final CountDownLatch done = new CountDownLatch(1);
631 >        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
632 >        try (PoolCleaner cleaner = cleaner(p, done)) {
633 >            final CountDownLatch threadStarted = new CountDownLatch(1);
634 >            ScheduledFuture[] tasks = new ScheduledFuture[5];
635 >            for (int i = 0; i < tasks.length; i++) {
636 >                Runnable r = new CheckedRunnable() {
637 >                    public void realRun() throws InterruptedException {
638 >                        threadStarted.countDown();
639 >                        await(done);
640 >                    }};
641 >                tasks[i] = p.schedule(r, 1, MILLISECONDS);
642 >            }
643 >            await(threadStarted);
644 >            BlockingQueue<Runnable> q = p.getQueue();
645 >            assertTrue(q.contains(tasks[tasks.length - 1]));
646              assertFalse(q.contains(tasks[0]));
538        } catch (Exception e) {
539            unexpectedException();
540        } finally {
541            joinPool(p1);
647          }
648      }
649  
650      /**
651       * remove(task) removes queued task, and fails to remove active task
652       */
653 <    public void testRemove() {
654 <        CustomExecutor p1 = new CustomExecutor(1);
655 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
656 <        for (int i = 0; i < 5; i++) {
657 <            tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, TimeUnit.MILLISECONDS);
658 <        }
659 <        try {
660 <            Thread.sleep(SHORT_DELAY_MS);
661 <            BlockingQueue<Runnable> q = p1.getQueue();
662 <            assertFalse(p1.remove((Runnable)tasks[0]));
653 >    public void testRemove() throws InterruptedException {
654 >        final CountDownLatch done = new CountDownLatch(1);
655 >        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
656 >        try (PoolCleaner cleaner = cleaner(p, done)) {
657 >            ScheduledFuture[] tasks = new ScheduledFuture[5];
658 >            final CountDownLatch threadStarted = new CountDownLatch(1);
659 >            for (int i = 0; i < tasks.length; i++) {
660 >                Runnable r = new CheckedRunnable() {
661 >                    public void realRun() throws InterruptedException {
662 >                        threadStarted.countDown();
663 >                        await(done);
664 >                    }};
665 >                tasks[i] = p.schedule(r, 1, MILLISECONDS);
666 >            }
667 >            await(threadStarted);
668 >            BlockingQueue<Runnable> q = p.getQueue();
669 >            assertFalse(p.remove((Runnable)tasks[0]));
670              assertTrue(q.contains((Runnable)tasks[4]));
671              assertTrue(q.contains((Runnable)tasks[3]));
672 <            assertTrue(p1.remove((Runnable)tasks[4]));
673 <            assertFalse(p1.remove((Runnable)tasks[4]));
672 >            assertTrue(p.remove((Runnable)tasks[4]));
673 >            assertFalse(p.remove((Runnable)tasks[4]));
674              assertFalse(q.contains((Runnable)tasks[4]));
675              assertTrue(q.contains((Runnable)tasks[3]));
676 <            assertTrue(p1.remove((Runnable)tasks[3]));
676 >            assertTrue(p.remove((Runnable)tasks[3]));
677              assertFalse(q.contains((Runnable)tasks[3]));
566        } catch (Exception e) {
567            unexpectedException();
568        } finally {
569            joinPool(p1);
678          }
679      }
680  
681      /**
682 <     *  purge removes cancelled tasks from the queue
682 >     * purge removes cancelled tasks from the queue
683       */
684 <    public void testPurge() {
685 <        CustomExecutor p1 = new CustomExecutor(1);
686 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
687 <        for (int i = 0; i < 5; i++) {
688 <            tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
689 <        }
690 <        try {
691 <            int max = 5;
684 >    public void testPurge() throws InterruptedException {
685 >        final ScheduledFuture[] tasks = new ScheduledFuture[5];
686 >        final Runnable releaser = new Runnable() { public void run() {
687 >            for (ScheduledFuture task : tasks)
688 >                if (task != null) task.cancel(true); }};
689 >        final CustomExecutor p = new CustomExecutor(1);
690 >        try (PoolCleaner cleaner = cleaner(p, releaser)) {
691 >            for (int i = 0; i < tasks.length; i++)
692 >                tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
693 >                                      LONG_DELAY_MS, MILLISECONDS);
694 >            int max = tasks.length;
695              if (tasks[4].cancel(true)) --max;
696              if (tasks[3].cancel(true)) --max;
697              // There must eventually be an interference-free point at
698              // which purge will not fail. (At worst, when queue is empty.)
699 <            int k;
700 <            for (k = 0; k < SMALL_DELAY_MS; ++k) {
701 <                p1.purge();
702 <                long count = p1.getTaskCount();
703 <                if (count >= 0 && count <= max)
704 <                    break;
705 <                Thread.sleep(1);
706 <            }
596 <            assertTrue(k < SMALL_DELAY_MS);
597 <        } catch (Exception e) {
598 <            unexpectedException();
599 <        } finally {
600 <            joinPool(p1);
699 >            long startTime = System.nanoTime();
700 >            do {
701 >                p.purge();
702 >                long count = p.getTaskCount();
703 >                if (count == max)
704 >                    return;
705 >            } while (millisElapsedSince(startTime) < LONG_DELAY_MS);
706 >            fail("Purge failed to remove cancelled tasks");
707          }
708      }
709  
710      /**
711 <     *  shutDownNow returns a list containing tasks that were not run
712 <     */
713 <    public void testShutDownNow() {
714 <        CustomExecutor p1 = new CustomExecutor(1);
715 <        for (int i = 0; i < 5; i++)
716 <            p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
717 <        List l;
711 >     * shutdownNow returns a list containing tasks that were not run,
712 >     * and those tasks are drained from the queue
713 >     */
714 >    public void testShutdownNow() throws InterruptedException {
715 >        final int poolSize = 2;
716 >        final int count = 5;
717 >        final AtomicInteger ran = new AtomicInteger(0);
718 >        final CustomExecutor p = new CustomExecutor(poolSize);
719 >        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
720 >        Runnable waiter = new CheckedRunnable() { public void realRun() {
721 >            threadsStarted.countDown();
722 >            try {
723 >                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
724 >            } catch (InterruptedException success) {}
725 >            ran.getAndIncrement();
726 >        }};
727 >        for (int i = 0; i < count; i++)
728 >            p.execute(waiter);
729 >        await(threadsStarted);
730 >        assertEquals(poolSize, p.getActiveCount());
731 >        assertEquals(0, p.getCompletedTaskCount());
732 >        final List<Runnable> queuedTasks;
733          try {
734 <            l = p1.shutdownNow();
734 >            queuedTasks = p.shutdownNow();
735          } catch (SecurityException ok) {
736 <            return;
736 >            return; // Allowed in case test doesn't have privs
737          }
738 <        assertTrue(p1.isShutdown());
739 <        assertTrue(l.size() > 0 && l.size() <= 5);
740 <        joinPool(p1);
738 >        assertTrue(p.isShutdown());
739 >        assertTrue(p.getQueue().isEmpty());
740 >        assertEquals(count - poolSize, queuedTasks.size());
741 >        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
742 >        assertTrue(p.isTerminated());
743 >        assertEquals(poolSize, ran.get());
744 >        assertEquals(poolSize, p.getCompletedTaskCount());
745      }
746  
747      /**
748 <     * In default setting, shutdown cancels periodic but not delayed
749 <     * tasks at shutdown
750 <     */
751 <    public void testShutDown1() {
748 >     * shutdownNow returns a list containing tasks that were not run,
749 >     * and those tasks are drained from the queue
750 >     */
751 >    public void testShutdownNow_delayedTasks() throws InterruptedException {
752 >        final CustomExecutor p = new CustomExecutor(1);
753 >        List<ScheduledFuture> tasks = new ArrayList<>();
754 >        for (int i = 0; i < 3; i++) {
755 >            Runnable r = new NoOpRunnable();
756 >            tasks.add(p.schedule(r, 9, SECONDS));
757 >            tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS));
758 >            tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS));
759 >        }
760 >        if (testImplementationDetails)
761 >            assertEquals(new HashSet(tasks), new HashSet(p.getQueue()));
762 >        final List<Runnable> queuedTasks;
763          try {
764 <            CustomExecutor p1 = new CustomExecutor(1);
765 <            assertTrue(p1.getExecuteExistingDelayedTasksAfterShutdownPolicy());
766 <            assertFalse(p1.getContinueExistingPeriodicTasksAfterShutdownPolicy());
631 <
632 <            ScheduledFuture[] tasks = new ScheduledFuture[5];
633 <            for (int i = 0; i < 5; i++)
634 <                tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
635 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
636 <            BlockingQueue q = p1.getQueue();
637 <            for (Iterator it = q.iterator(); it.hasNext();) {
638 <                ScheduledFuture t = (ScheduledFuture)it.next();
639 <                assertFalse(t.isCancelled());
640 <            }
641 <            assertTrue(p1.isShutdown());
642 <            Thread.sleep(SMALL_DELAY_MS);
643 <            for (int i = 0; i < 5; ++i) {
644 <                assertTrue(tasks[i].isDone());
645 <                assertFalse(tasks[i].isCancelled());
646 <            }
647 <
648 <        }
649 <        catch (Exception ex) {
650 <            unexpectedException();
651 <        }
652 <    }
653 <
654 <
655 <    /**
656 <     * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
657 <     * delayed tasks are cancelled at shutdown
658 <     */
659 <    public void testShutDown2() {
660 <        try {
661 <            CustomExecutor p1 = new CustomExecutor(1);
662 <            p1.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
663 <            ScheduledFuture[] tasks = new ScheduledFuture[5];
664 <            for (int i = 0; i < 5; i++)
665 <                tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
666 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
667 <            assertTrue(p1.isShutdown());
668 <            BlockingQueue q = p1.getQueue();
669 <            assertTrue(q.isEmpty());
670 <            Thread.sleep(SMALL_DELAY_MS);
671 <            assertTrue(p1.isTerminated());
672 <        }
673 <        catch (Exception ex) {
674 <            unexpectedException();
675 <        }
676 <    }
677 <
678 <
679 <    /**
680 <     * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
681 <     * periodic tasks are not cancelled at shutdown
682 <     */
683 <    public void testShutDown3() {
684 <        try {
685 <            CustomExecutor p1 = new CustomExecutor(1);
686 <            p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
687 <            ScheduledFuture task =
688 <                p1.scheduleAtFixedRate(new NoOpRunnable(), 5, 5, TimeUnit.MILLISECONDS);
689 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
690 <            assertTrue(p1.isShutdown());
691 <            BlockingQueue q = p1.getQueue();
692 <            assertTrue(q.isEmpty());
693 <            Thread.sleep(SHORT_DELAY_MS);
694 <            assertTrue(p1.isTerminated());
764 >            queuedTasks = p.shutdownNow();
765 >        } catch (SecurityException ok) {
766 >            return; // Allowed in case test doesn't have privs
767          }
768 <        catch (Exception ex) {
769 <            unexpectedException();
768 >        assertTrue(p.isShutdown());
769 >        assertTrue(p.getQueue().isEmpty());
770 >        if (testImplementationDetails)
771 >            assertEquals(new HashSet(tasks), new HashSet(queuedTasks));
772 >        assertEquals(tasks.size(), queuedTasks.size());
773 >        for (ScheduledFuture task : tasks) {
774 >            assertFalse(((CustomTask)task).ran);
775 >            assertFalse(task.isDone());
776 >            assertFalse(task.isCancelled());
777          }
778 +        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
779 +        assertTrue(p.isTerminated());
780      }
781  
782      /**
783 <     * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
784 <     * periodic tasks are cancelled at shutdown
785 <     */
786 <    public void testShutDown4() {
787 <        CustomExecutor p1 = new CustomExecutor(1);
788 <        try {
789 <            p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
790 <            ScheduledFuture task =
791 <                p1.scheduleAtFixedRate(new NoOpRunnable(), 1, 1, TimeUnit.MILLISECONDS);
792 <            assertFalse(task.isCancelled());
793 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
794 <            assertFalse(task.isCancelled());
795 <            assertFalse(p1.isTerminated());
796 <            assertTrue(p1.isShutdown());
797 <            Thread.sleep(SHORT_DELAY_MS);
798 <            assertFalse(task.isCancelled());
799 <            assertTrue(task.cancel(true));
800 <            assertTrue(task.isDone());
801 <            Thread.sleep(SHORT_DELAY_MS);
802 <            assertTrue(p1.isTerminated());
803 <        }
804 <        catch (Exception ex) {
805 <            unexpectedException();
783 >     * By default, periodic tasks are cancelled at shutdown.
784 >     * By default, delayed tasks keep running after shutdown.
785 >     * Check that changing the default values work:
786 >     * - setExecuteExistingDelayedTasksAfterShutdownPolicy
787 >     * - setContinueExistingPeriodicTasksAfterShutdownPolicy
788 >     */
789 >    public void testShutdown_cancellation() throws Exception {
790 >        Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE };
791 >        for (Boolean policy : allBooleans)
792 >    {
793 >        final int poolSize = 2;
794 >        final CustomExecutor p = new CustomExecutor(poolSize);
795 >        final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE);
796 >        final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE);
797 >        final boolean effectiveRemovePolicy = (policy == Boolean.TRUE);
798 >        if (policy != null) {
799 >            p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy);
800 >            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy);
801 >            p.setRemoveOnCancelPolicy(policy);
802 >        }
803 >        assertEquals(effectiveDelayedPolicy,
804 >                     p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
805 >        assertEquals(effectivePeriodicPolicy,
806 >                     p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
807 >        assertEquals(effectiveRemovePolicy,
808 >                     p.getRemoveOnCancelPolicy());
809 >        // Strategy: Wedge the pool with poolSize "blocker" threads
810 >        final AtomicInteger ran = new AtomicInteger(0);
811 >        final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
812 >        final CountDownLatch unblock = new CountDownLatch(1);
813 >        final CountDownLatch periodicLatch1 = new CountDownLatch(2);
814 >        final CountDownLatch periodicLatch2 = new CountDownLatch(2);
815 >        Runnable task = new CheckedRunnable() { public void realRun()
816 >                                                    throws InterruptedException {
817 >            poolBlocked.countDown();
818 >            assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
819 >            ran.getAndIncrement();
820 >        }};
821 >        List<Future<?>> blockers = new ArrayList<>();
822 >        List<Future<?>> periodics = new ArrayList<>();
823 >        List<Future<?>> delayeds = new ArrayList<>();
824 >        for (int i = 0; i < poolSize; i++)
825 >            blockers.add(p.submit(task));
826 >        assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
827 >
828 >        periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1),
829 >                                            1, 1, MILLISECONDS));
830 >        periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
831 >                                               1, 1, MILLISECONDS));
832 >        delayeds.add(p.schedule(task, 1, MILLISECONDS));
833 >
834 >        assertTrue(p.getQueue().containsAll(periodics));
835 >        assertTrue(p.getQueue().containsAll(delayeds));
836 >        try { p.shutdown(); } catch (SecurityException ok) { return; }
837 >        assertTrue(p.isShutdown());
838 >        assertFalse(p.isTerminated());
839 >        for (Future<?> periodic : periodics) {
840 >            assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
841 >            assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
842 >        }
843 >        for (Future<?> delayed : delayeds) {
844 >            assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
845 >            assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
846 >        }
847 >        if (testImplementationDetails) {
848 >            assertEquals(effectivePeriodicPolicy,
849 >                         p.getQueue().containsAll(periodics));
850 >            assertEquals(effectiveDelayedPolicy,
851 >                         p.getQueue().containsAll(delayeds));
852 >        }
853 >        // Release all pool threads
854 >        unblock.countDown();
855 >
856 >        for (Future<?> delayed : delayeds) {
857 >            if (effectiveDelayedPolicy) {
858 >                assertNull(delayed.get());
859 >            }
860          }
861 <        finally {
862 <            joinPool(p1);
861 >        if (effectivePeriodicPolicy) {
862 >            assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS));
863 >            assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS));
864 >            for (Future<?> periodic : periodics) {
865 >                assertTrue(periodic.cancel(false));
866 >                assertTrue(periodic.isCancelled());
867 >                assertTrue(periodic.isDone());
868 >            }
869          }
870 <    }
870 >        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
871 >        assertTrue(p.isTerminated());
872 >        assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
873 >    }}
874  
875      /**
876       * completed submit of callable returns result
877       */
878 <    public void testSubmitCallable() {
879 <        ExecutorService e = new CustomExecutor(2);
880 <        try {
878 >    public void testSubmitCallable() throws Exception {
879 >        final ExecutorService e = new CustomExecutor(2);
880 >        try (PoolCleaner cleaner = cleaner(e)) {
881              Future<String> future = e.submit(new StringTask());
882              String result = future.get();
883              assertSame(TEST_STRING, result);
884          }
741        catch (ExecutionException ex) {
742            unexpectedException();
743        }
744        catch (InterruptedException ex) {
745            unexpectedException();
746        } finally {
747            joinPool(e);
748        }
885      }
886  
887      /**
888       * completed submit of runnable returns successfully
889       */
890 <    public void testSubmitRunnable() {
891 <        ExecutorService e = new CustomExecutor(2);
892 <        try {
890 >    public void testSubmitRunnable() throws Exception {
891 >        final ExecutorService e = new CustomExecutor(2);
892 >        try (PoolCleaner cleaner = cleaner(e)) {
893              Future<?> future = e.submit(new NoOpRunnable());
894              future.get();
895              assertTrue(future.isDone());
896          }
761        catch (ExecutionException ex) {
762            unexpectedException();
763        }
764        catch (InterruptedException ex) {
765            unexpectedException();
766        } finally {
767            joinPool(e);
768        }
897      }
898  
899      /**
900       * completed submit of (runnable, result) returns result
901       */
902 <    public void testSubmitRunnable2() {
903 <        ExecutorService e = new CustomExecutor(2);
904 <        try {
902 >    public void testSubmitRunnable2() throws Exception {
903 >        final ExecutorService e = new CustomExecutor(2);
904 >        try (PoolCleaner cleaner = cleaner(e)) {
905              Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
906              String result = future.get();
907              assertSame(TEST_STRING, result);
908          }
781        catch (ExecutionException ex) {
782            unexpectedException();
783        }
784        catch (InterruptedException ex) {
785            unexpectedException();
786        } finally {
787            joinPool(e);
788        }
909      }
910  
911      /**
912       * invokeAny(null) throws NPE
913       */
914 <    public void testInvokeAny1() {
915 <        ExecutorService e = new CustomExecutor(2);
916 <        try {
917 <            e.invokeAny(null);
918 <        } catch (NullPointerException success) {
919 <        } catch (Exception ex) {
920 <            unexpectedException();
801 <        } finally {
802 <            joinPool(e);
914 >    public void testInvokeAny1() throws Exception {
915 >        final ExecutorService e = new CustomExecutor(2);
916 >        try (PoolCleaner cleaner = cleaner(e)) {
917 >            try {
918 >                e.invokeAny(null);
919 >                shouldThrow();
920 >            } catch (NullPointerException success) {}
921          }
922      }
923  
924      /**
925       * invokeAny(empty collection) throws IAE
926       */
927 <    public void testInvokeAny2() {
928 <        ExecutorService e = new CustomExecutor(2);
929 <        try {
930 <            e.invokeAny(new ArrayList<Callable<String>>());
931 <        } catch (IllegalArgumentException success) {
932 <        } catch (Exception ex) {
933 <            unexpectedException();
816 <        } finally {
817 <            joinPool(e);
927 >    public void testInvokeAny2() throws Exception {
928 >        final ExecutorService e = new CustomExecutor(2);
929 >        try (PoolCleaner cleaner = cleaner(e)) {
930 >            try {
931 >                e.invokeAny(new ArrayList<Callable<String>>());
932 >                shouldThrow();
933 >            } catch (IllegalArgumentException success) {}
934          }
935      }
936  
937      /**
938       * invokeAny(c) throws NPE if c has null elements
939       */
940 <    public void testInvokeAny3() {
941 <        ExecutorService e = new CustomExecutor(2);
942 <        try {
943 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
944 <            l.add(new StringTask());
940 >    public void testInvokeAny3() throws Exception {
941 >        final CountDownLatch latch = new CountDownLatch(1);
942 >        final ExecutorService e = new CustomExecutor(2);
943 >        try (PoolCleaner cleaner = cleaner(e)) {
944 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
945 >            l.add(latchAwaitingStringTask(latch));
946              l.add(null);
947 <            e.invokeAny(l);
948 <        } catch (NullPointerException success) {
949 <        } catch (Exception ex) {
950 <            unexpectedException();
951 <        } finally {
835 <            joinPool(e);
947 >            try {
948 >                e.invokeAny(l);
949 >                shouldThrow();
950 >            } catch (NullPointerException success) {}
951 >            latch.countDown();
952          }
953      }
954  
955      /**
956       * invokeAny(c) throws ExecutionException if no task completes
957       */
958 <    public void testInvokeAny4() {
959 <        ExecutorService e = new CustomExecutor(2);
960 <        try {
961 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
958 >    public void testInvokeAny4() throws Exception {
959 >        final ExecutorService e = new CustomExecutor(2);
960 >        try (PoolCleaner cleaner = cleaner(e)) {
961 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
962              l.add(new NPETask());
963 <            e.invokeAny(l);
964 <        } catch (ExecutionException success) {
965 <        } catch (Exception ex) {
966 <            unexpectedException();
967 <        } finally {
968 <            joinPool(e);
963 >            try {
964 >                e.invokeAny(l);
965 >                shouldThrow();
966 >            } catch (ExecutionException success) {
967 >                assertTrue(success.getCause() instanceof NullPointerException);
968 >            }
969          }
970      }
971  
972      /**
973       * invokeAny(c) returns result of some task
974       */
975 <    public void testInvokeAny5() {
976 <        ExecutorService e = new CustomExecutor(2);
977 <        try {
978 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
975 >    public void testInvokeAny5() throws Exception {
976 >        final ExecutorService e = new CustomExecutor(2);
977 >        try (PoolCleaner cleaner = cleaner(e)) {
978 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
979              l.add(new StringTask());
980              l.add(new StringTask());
981              String result = e.invokeAny(l);
982              assertSame(TEST_STRING, result);
867        } catch (ExecutionException success) {
868        } catch (Exception ex) {
869            unexpectedException();
870        } finally {
871            joinPool(e);
983          }
984      }
985  
986      /**
987       * invokeAll(null) throws NPE
988       */
989 <    public void testInvokeAll1() {
990 <        ExecutorService e = new CustomExecutor(2);
991 <        try {
992 <            e.invokeAll(null);
993 <        } catch (NullPointerException success) {
994 <        } catch (Exception ex) {
995 <            unexpectedException();
885 <        } finally {
886 <            joinPool(e);
989 >    public void testInvokeAll1() throws Exception {
990 >        final ExecutorService e = new CustomExecutor(2);
991 >        try (PoolCleaner cleaner = cleaner(e)) {
992 >            try {
993 >                e.invokeAll(null);
994 >                shouldThrow();
995 >            } catch (NullPointerException success) {}
996          }
997      }
998  
999      /**
1000       * invokeAll(empty collection) returns empty collection
1001       */
1002 <    public void testInvokeAll2() {
1003 <        ExecutorService e = new CustomExecutor(2);
1004 <        try {
1002 >    public void testInvokeAll2() throws Exception {
1003 >        final ExecutorService e = new CustomExecutor(2);
1004 >        try (PoolCleaner cleaner = cleaner(e)) {
1005              List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
1006              assertTrue(r.isEmpty());
898        } catch (Exception ex) {
899            unexpectedException();
900        } finally {
901            joinPool(e);
1007          }
1008      }
1009  
1010      /**
1011       * invokeAll(c) throws NPE if c has null elements
1012       */
1013 <    public void testInvokeAll3() {
1014 <        ExecutorService e = new CustomExecutor(2);
1015 <        try {
1016 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1013 >    public void testInvokeAll3() throws Exception {
1014 >        final ExecutorService e = new CustomExecutor(2);
1015 >        try (PoolCleaner cleaner = cleaner(e)) {
1016 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1017              l.add(new StringTask());
1018              l.add(null);
1019 <            e.invokeAll(l);
1020 <        } catch (NullPointerException success) {
1021 <        } catch (Exception ex) {
1022 <            unexpectedException();
918 <        } finally {
919 <            joinPool(e);
1019 >            try {
1020 >                e.invokeAll(l);
1021 >                shouldThrow();
1022 >            } catch (NullPointerException success) {}
1023          }
1024      }
1025  
1026      /**
1027       * get of invokeAll(c) throws exception on failed task
1028       */
1029 <    public void testInvokeAll4() {
1030 <        ExecutorService e = new CustomExecutor(2);
1031 <        try {
1032 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1029 >    public void testInvokeAll4() throws Exception {
1030 >        final ExecutorService e = new CustomExecutor(2);
1031 >        try (PoolCleaner cleaner = cleaner(e)) {
1032 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1033              l.add(new NPETask());
1034 <            List<Future<String>> result = e.invokeAll(l);
1035 <            assertEquals(1, result.size());
1036 <            for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
1037 <                it.next().get();
1038 <        } catch (ExecutionException success) {
1039 <        } catch (Exception ex) {
1040 <            unexpectedException();
1041 <        } finally {
939 <            joinPool(e);
1034 >            List<Future<String>> futures = e.invokeAll(l);
1035 >            assertEquals(1, futures.size());
1036 >            try {
1037 >                futures.get(0).get();
1038 >                shouldThrow();
1039 >            } catch (ExecutionException success) {
1040 >                assertTrue(success.getCause() instanceof NullPointerException);
1041 >            }
1042          }
1043      }
1044  
1045      /**
1046       * invokeAll(c) returns results of all completed tasks
1047       */
1048 <    public void testInvokeAll5() {
1049 <        ExecutorService e = new CustomExecutor(2);
1050 <        try {
1051 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1048 >    public void testInvokeAll5() throws Exception {
1049 >        final ExecutorService e = new CustomExecutor(2);
1050 >        try (PoolCleaner cleaner = cleaner(e)) {
1051 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1052              l.add(new StringTask());
1053              l.add(new StringTask());
1054 <            List<Future<String>> result = e.invokeAll(l);
1055 <            assertEquals(2, result.size());
1056 <            for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
1057 <                assertSame(TEST_STRING, it.next().get());
956 <        } catch (ExecutionException success) {
957 <        } catch (Exception ex) {
958 <            unexpectedException();
959 <        } finally {
960 <            joinPool(e);
1054 >            List<Future<String>> futures = e.invokeAll(l);
1055 >            assertEquals(2, futures.size());
1056 >            for (Future<String> future : futures)
1057 >                assertSame(TEST_STRING, future.get());
1058          }
1059      }
1060  
1061      /**
1062       * timed invokeAny(null) throws NPE
1063       */
1064 <    public void testTimedInvokeAny1() {
1065 <        ExecutorService e = new CustomExecutor(2);
1066 <        try {
1067 <            e.invokeAny(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1068 <        } catch (NullPointerException success) {
1069 <        } catch (Exception ex) {
1070 <            unexpectedException();
974 <        } finally {
975 <            joinPool(e);
1064 >    public void testTimedInvokeAny1() throws Exception {
1065 >        final ExecutorService e = new CustomExecutor(2);
1066 >        try (PoolCleaner cleaner = cleaner(e)) {
1067 >            try {
1068 >                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
1069 >                shouldThrow();
1070 >            } catch (NullPointerException success) {}
1071          }
1072      }
1073  
1074      /**
1075       * timed invokeAny(,,null) throws NPE
1076       */
1077 <    public void testTimedInvokeAnyNullTimeUnit() {
1078 <        ExecutorService e = new CustomExecutor(2);
1079 <        try {
1080 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1077 >    public void testTimedInvokeAnyNullTimeUnit() throws Exception {
1078 >        final ExecutorService e = new CustomExecutor(2);
1079 >        try (PoolCleaner cleaner = cleaner(e)) {
1080 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1081              l.add(new StringTask());
1082 <            e.invokeAny(l, MEDIUM_DELAY_MS, null);
1083 <        } catch (NullPointerException success) {
1084 <        } catch (Exception ex) {
1085 <            unexpectedException();
991 <        } finally {
992 <            joinPool(e);
1082 >            try {
1083 >                e.invokeAny(l, MEDIUM_DELAY_MS, null);
1084 >                shouldThrow();
1085 >            } catch (NullPointerException success) {}
1086          }
1087      }
1088  
1089      /**
1090       * timed invokeAny(empty collection) throws IAE
1091       */
1092 <    public void testTimedInvokeAny2() {
1093 <        ExecutorService e = new CustomExecutor(2);
1094 <        try {
1095 <            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1096 <        } catch (IllegalArgumentException success) {
1097 <        } catch (Exception ex) {
1098 <            unexpectedException();
1006 <        } finally {
1007 <            joinPool(e);
1092 >    public void testTimedInvokeAny2() throws Exception {
1093 >        final ExecutorService e = new CustomExecutor(2);
1094 >        try (PoolCleaner cleaner = cleaner(e)) {
1095 >            try {
1096 >                e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1097 >                shouldThrow();
1098 >            } catch (IllegalArgumentException success) {}
1099          }
1100      }
1101  
1102      /**
1103       * timed invokeAny(c) throws NPE if c has null elements
1104       */
1105 <    public void testTimedInvokeAny3() {
1106 <        ExecutorService e = new CustomExecutor(2);
1107 <        try {
1108 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1109 <            l.add(new StringTask());
1105 >    public void testTimedInvokeAny3() throws Exception {
1106 >        CountDownLatch latch = new CountDownLatch(1);
1107 >        final ExecutorService e = new CustomExecutor(2);
1108 >        try (PoolCleaner cleaner = cleaner(e)) {
1109 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1110 >            l.add(latchAwaitingStringTask(latch));
1111              l.add(null);
1112 <            e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1113 <        } catch (NullPointerException success) {
1114 <        } catch (Exception ex) {
1115 <            ex.printStackTrace();
1116 <            unexpectedException();
1025 <        } finally {
1026 <            joinPool(e);
1112 >            try {
1113 >                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1114 >                shouldThrow();
1115 >            } catch (NullPointerException success) {}
1116 >            latch.countDown();
1117          }
1118      }
1119  
1120      /**
1121       * timed invokeAny(c) throws ExecutionException if no task completes
1122       */
1123 <    public void testTimedInvokeAny4() {
1124 <        ExecutorService e = new CustomExecutor(2);
1125 <        try {
1126 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1123 >    public void testTimedInvokeAny4() throws Exception {
1124 >        final ExecutorService e = new CustomExecutor(2);
1125 >        try (PoolCleaner cleaner = cleaner(e)) {
1126 >            long startTime = System.nanoTime();
1127 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1128              l.add(new NPETask());
1129 <            e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1130 <        } catch (ExecutionException success) {
1131 <        } catch (Exception ex) {
1132 <            unexpectedException();
1133 <        } finally {
1134 <            joinPool(e);
1129 >            try {
1130 >                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1131 >                shouldThrow();
1132 >            } catch (ExecutionException success) {
1133 >                assertTrue(success.getCause() instanceof NullPointerException);
1134 >            }
1135 >            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1136          }
1137      }
1138  
1139      /**
1140       * timed invokeAny(c) returns result of some task
1141       */
1142 <    public void testTimedInvokeAny5() {
1143 <        ExecutorService e = new CustomExecutor(2);
1144 <        try {
1145 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1142 >    public void testTimedInvokeAny5() throws Exception {
1143 >        final ExecutorService e = new CustomExecutor(2);
1144 >        try (PoolCleaner cleaner = cleaner(e)) {
1145 >            long startTime = System.nanoTime();
1146 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1147              l.add(new StringTask());
1148              l.add(new StringTask());
1149 <            String result = e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1149 >            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1150              assertSame(TEST_STRING, result);
1151 <        } catch (ExecutionException success) {
1059 <        } catch (Exception ex) {
1060 <            unexpectedException();
1061 <        } finally {
1062 <            joinPool(e);
1151 >            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1152          }
1153      }
1154  
1155      /**
1156       * timed invokeAll(null) throws NPE
1157       */
1158 <    public void testTimedInvokeAll1() {
1159 <        ExecutorService e = new CustomExecutor(2);
1160 <        try {
1161 <            e.invokeAll(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1162 <        } catch (NullPointerException success) {
1163 <        } catch (Exception ex) {
1164 <            unexpectedException();
1076 <        } finally {
1077 <            joinPool(e);
1158 >    public void testTimedInvokeAll1() throws Exception {
1159 >        final ExecutorService e = new CustomExecutor(2);
1160 >        try (PoolCleaner cleaner = cleaner(e)) {
1161 >            try {
1162 >                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
1163 >                shouldThrow();
1164 >            } catch (NullPointerException success) {}
1165          }
1166      }
1167  
1168      /**
1169       * timed invokeAll(,,null) throws NPE
1170       */
1171 <    public void testTimedInvokeAllNullTimeUnit() {
1172 <        ExecutorService e = new CustomExecutor(2);
1173 <        try {
1174 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1171 >    public void testTimedInvokeAllNullTimeUnit() throws Exception {
1172 >        final ExecutorService e = new CustomExecutor(2);
1173 >        try (PoolCleaner cleaner = cleaner(e)) {
1174 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1175              l.add(new StringTask());
1176 <            e.invokeAll(l, MEDIUM_DELAY_MS, null);
1177 <        } catch (NullPointerException success) {
1178 <        } catch (Exception ex) {
1179 <            unexpectedException();
1093 <        } finally {
1094 <            joinPool(e);
1176 >            try {
1177 >                e.invokeAll(l, MEDIUM_DELAY_MS, null);
1178 >                shouldThrow();
1179 >            } catch (NullPointerException success) {}
1180          }
1181      }
1182  
1183      /**
1184       * timed invokeAll(empty collection) returns empty collection
1185       */
1186 <    public void testTimedInvokeAll2() {
1187 <        ExecutorService e = new CustomExecutor(2);
1188 <        try {
1189 <            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1186 >    public void testTimedInvokeAll2() throws Exception {
1187 >        final ExecutorService e = new CustomExecutor(2);
1188 >        try (PoolCleaner cleaner = cleaner(e)) {
1189 >            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1190              assertTrue(r.isEmpty());
1106        } catch (Exception ex) {
1107            unexpectedException();
1108        } finally {
1109            joinPool(e);
1191          }
1192      }
1193  
1194      /**
1195       * timed invokeAll(c) throws NPE if c has null elements
1196       */
1197 <    public void testTimedInvokeAll3() {
1198 <        ExecutorService e = new CustomExecutor(2);
1199 <        try {
1200 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1197 >    public void testTimedInvokeAll3() throws Exception {
1198 >        final ExecutorService e = new CustomExecutor(2);
1199 >        try (PoolCleaner cleaner = cleaner(e)) {
1200 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1201              l.add(new StringTask());
1202              l.add(null);
1203 <            e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1204 <        } catch (NullPointerException success) {
1205 <        } catch (Exception ex) {
1206 <            unexpectedException();
1126 <        } finally {
1127 <            joinPool(e);
1203 >            try {
1204 >                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1205 >                shouldThrow();
1206 >            } catch (NullPointerException success) {}
1207          }
1208      }
1209  
1210      /**
1211       * get of element of invokeAll(c) throws exception on failed task
1212       */
1213 <    public void testTimedInvokeAll4() {
1214 <        ExecutorService e = new CustomExecutor(2);
1215 <        try {
1216 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1213 >    public void testTimedInvokeAll4() throws Exception {
1214 >        final ExecutorService e = new CustomExecutor(2);
1215 >        try (PoolCleaner cleaner = cleaner(e)) {
1216 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1217              l.add(new NPETask());
1218 <            List<Future<String>> result = e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1219 <            assertEquals(1, result.size());
1220 <            for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
1221 <                it.next().get();
1222 <        } catch (ExecutionException success) {
1223 <        } catch (Exception ex) {
1224 <            unexpectedException();
1225 <        } finally {
1226 <            joinPool(e);
1218 >            List<Future<String>> futures =
1219 >                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1220 >            assertEquals(1, futures.size());
1221 >            try {
1222 >                futures.get(0).get();
1223 >                shouldThrow();
1224 >            } catch (ExecutionException success) {
1225 >                assertTrue(success.getCause() instanceof NullPointerException);
1226 >            }
1227          }
1228      }
1229  
1230      /**
1231       * timed invokeAll(c) returns results of all completed tasks
1232       */
1233 <    public void testTimedInvokeAll5() {
1234 <        ExecutorService e = new CustomExecutor(2);
1235 <        try {
1236 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1233 >    public void testTimedInvokeAll5() throws Exception {
1234 >        final ExecutorService e = new CustomExecutor(2);
1235 >        try (PoolCleaner cleaner = cleaner(e)) {
1236 >            List<Callable<String>> l = new ArrayList<Callable<String>>();
1237              l.add(new StringTask());
1238              l.add(new StringTask());
1239 <            List<Future<String>> result = e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
1240 <            assertEquals(2, result.size());
1241 <            for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
1242 <                assertSame(TEST_STRING, it.next().get());
1243 <        } catch (ExecutionException success) {
1165 <        } catch (Exception ex) {
1166 <            unexpectedException();
1167 <        } finally {
1168 <            joinPool(e);
1239 >            List<Future<String>> futures =
1240 >                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
1241 >            assertEquals(2, futures.size());
1242 >            for (Future<String> future : futures)
1243 >                assertSame(TEST_STRING, future.get());
1244          }
1245      }
1246  
1247      /**
1248       * timed invokeAll(c) cancels tasks not completed by timeout
1249       */
1250 <    public void testTimedInvokeAll6() {
1251 <        ExecutorService e = new CustomExecutor(2);
1252 <        try {
1253 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1254 <            l.add(new StringTask());
1255 <            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
1256 <            l.add(new StringTask());
1257 <            List<Future<String>> result = e.invokeAll(l, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
1258 <            assertEquals(3, result.size());
1259 <            Iterator<Future<String>> it = result.iterator();
1260 <            Future<String> f1 = it.next();
1261 <            Future<String> f2 = it.next();
1262 <            Future<String> f3 = it.next();
1263 <            assertTrue(f1.isDone());
1264 <            assertTrue(f2.isDone());
1265 <            assertTrue(f3.isDone());
1266 <            assertFalse(f1.isCancelled());
1267 <            assertTrue(f2.isCancelled());
1268 <        } catch (Exception ex) {
1269 <            unexpectedException();
1270 <        } finally {
1271 <            joinPool(e);
1250 >    public void testTimedInvokeAll6() throws Exception {
1251 >        for (long timeout = timeoutMillis();;) {
1252 >            final CountDownLatch done = new CountDownLatch(1);
1253 >            final Callable<String> waiter = new CheckedCallable<String>() {
1254 >                public String realCall() {
1255 >                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
1256 >                    catch (InterruptedException ok) {}
1257 >                    return "1"; }};
1258 >            final ExecutorService p = new CustomExecutor(2);
1259 >            try (PoolCleaner cleaner = cleaner(p, done)) {
1260 >                List<Callable<String>> tasks = new ArrayList<>();
1261 >                tasks.add(new StringTask("0"));
1262 >                tasks.add(waiter);
1263 >                tasks.add(new StringTask("2"));
1264 >                long startTime = System.nanoTime();
1265 >                List<Future<String>> futures =
1266 >                    p.invokeAll(tasks, timeout, MILLISECONDS);
1267 >                assertEquals(tasks.size(), futures.size());
1268 >                assertTrue(millisElapsedSince(startTime) >= timeout);
1269 >                for (Future future : futures)
1270 >                    assertTrue(future.isDone());
1271 >                assertTrue(futures.get(1).isCancelled());
1272 >                try {
1273 >                    assertEquals("0", futures.get(0).get());
1274 >                    assertEquals("2", futures.get(2).get());
1275 >                    break;
1276 >                } catch (CancellationException retryWithLongerTimeout) {
1277 >                    timeout *= 2;
1278 >                    if (timeout >= LONG_DELAY_MS / 2)
1279 >                        fail("expected exactly one task to be cancelled");
1280 >                }
1281 >            }
1282          }
1283      }
1284  
1200
1285   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines