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.9 by jsr166, Tue Dec 1 06:47:14 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.*;
7   import static java.util.concurrent.TimeUnit.MILLISECONDS;
8 < import java.util.concurrent.atomic.*;
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(ScheduledExecutorSubclassTest.class);
# Line 36 | 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  
51
77      public class CustomExecutor extends ScheduledThreadPoolExecutor {
78  
79          protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
# Line 58 | 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 73 | Line 98 | public class ScheduledExecutorSubclassTe
98  
99      }
100  
76
77
101      /**
102       * execute successfully executes a runnable
103       */
104      public void testExecute() throws InterruptedException {
105 <        TrackedShortRunnable runnable =new TrackedShortRunnable();
106 <        CustomExecutor p1 = new CustomExecutor(1);
107 <        p1.execute(runnable);
108 <        assertFalse(runnable.done);
109 <        Thread.sleep(SHORT_DELAY_MS);
110 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
111 <        Thread.sleep(MEDIUM_DELAY_MS);
112 <        assertTrue(runnable.done);
90 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
91 <        joinPool(p1);
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 >        }
113      }
114  
94
115      /**
116       * delayed schedule of callable successfully executes after delay
117       */
118      public void testSchedule1() throws Exception {
119 <        TrackedCallable callable = new TrackedCallable();
120 <        CustomExecutor p1 = new CustomExecutor(1);
121 <        Future f = p1.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
122 <        assertFalse(callable.done);
123 <        Thread.sleep(MEDIUM_DELAY_MS);
124 <        assertTrue(callable.done);
125 <        assertEquals(Boolean.TRUE, f.get());
126 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
127 <        joinPool(p1);
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() throws InterruptedException {
139 <        TrackedShortRunnable runnable = new TrackedShortRunnable();
140 <        CustomExecutor p1 = new CustomExecutor(1);
141 <        p1.schedule(runnable, SMALL_DELAY_MS, MILLISECONDS);
142 <        Thread.sleep(SHORT_DELAY_MS);
143 <        assertFalse(runnable.done);
144 <        Thread.sleep(MEDIUM_DELAY_MS);
145 <        assertTrue(runnable.done);
146 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
147 <        joinPool(p1);
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() throws InterruptedException {
159 <        TrackedShortRunnable runnable = new TrackedShortRunnable();
160 <        CustomExecutor p1 = new CustomExecutor(1);
161 <        ScheduledFuture h = p1.scheduleAtFixedRate(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, MILLISECONDS);
162 <        assertFalse(runnable.done);
163 <        Thread.sleep(MEDIUM_DELAY_MS);
164 <        assertTrue(runnable.done);
165 <        h.cancel(true);
166 <        joinPool(p1);
167 <    }
168 <
169 <    static class RunnableCounter implements Runnable {
170 <        AtomicInteger count = new AtomicInteger(0);
171 <        public void run() { count.getAndIncrement(); }
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  
177      /**
178       * scheduleWithFixedDelay executes runnable after given initial delay
179       */
180      public void testSchedule5() throws InterruptedException {
181 <        TrackedShortRunnable runnable = new TrackedShortRunnable();
182 <        CustomExecutor p1 = new CustomExecutor(1);
183 <        ScheduledFuture h = p1.scheduleWithFixedDelay(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, MILLISECONDS);
184 <        assertFalse(runnable.done);
185 <        Thread.sleep(MEDIUM_DELAY_MS);
186 <        assertTrue(runnable.done);
187 <        h.cancel(true);
188 <        joinPool(p1);
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
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 <        CustomExecutor p1 = new CustomExecutor(1);
211 <        RunnableCounter counter = new RunnableCounter();
212 <        ScheduledFuture h =
213 <            p1.scheduleAtFixedRate(counter, 0, 1, MILLISECONDS);
214 <        Thread.sleep(SMALL_DELAY_MS);
215 <        h.cancel(true);
216 <        int c = counter.count.get();
217 <        // By time scaling conventions, we must have at least
218 <        // an execution per SHORT delay, but no more than one SHORT more
219 <        assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
220 <        assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
221 <        joinPool(p1);
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
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 <        CustomExecutor p1 = new CustomExecutor(1);
240 <        RunnableCounter counter = new RunnableCounter();
241 <        ScheduledFuture h =
242 <            p1.scheduleWithFixedDelay(counter, 0, 1, MILLISECONDS);
243 <        Thread.sleep(SMALL_DELAY_MS);
244 <        h.cancel(true);
245 <        int c = counter.count.get();
246 <        assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
247 <        assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
248 <        joinPool(p1);
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  
192
279      /**
280 <     *  execute (null) throws NPE
280 >     * execute(null) throws NPE
281       */
282      public void testExecuteNull() throws InterruptedException {
283 <        CustomExecutor se = new CustomExecutor(1);
284 <        try {
285 <            se.execute(null);
286 <            shouldThrow();
287 <        } catch (NullPointerException success) {}
288 <        joinPool(se);
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 >        }
290      }
291  
292      /**
293 <     * schedule (null) throws NPE
293 >     * schedule(null) throws NPE
294       */
295      public void testScheduleNull() throws InterruptedException {
296 <        CustomExecutor se = new CustomExecutor(1);
297 <        try {
298 <            TrackedCallable callable = null;
299 <            Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
300 <            shouldThrow();
301 <        } catch (NullPointerException success) {}
302 <        joinPool(se);
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 >        }
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, 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          }
231
232        joinPool(se);
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, 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          }
248        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, MILLISECONDS);
347 <             shouldThrow();
348 <         } catch (RejectedExecutionException success) {
349 <         } catch (SecurityException ok) {
350 <         }
351 <         joinPool(se);
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 >        }
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, 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          }
280        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, 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          }
296        joinPool(se);
384      }
385  
386      /**
387 <     *  getActiveCount increases but doesn't overestimate, when a
388 <     *  thread becomes active
387 >     * getActiveCount increases but doesn't overestimate, when a
388 >     * thread becomes active
389       */
390      public void testGetActiveCount() throws InterruptedException {
391 <        CustomExecutor p2 = new CustomExecutor(2);
392 <        assertEquals(0, p2.getActiveCount());
393 <        p2.execute(new SmallRunnable());
394 <        Thread.sleep(SHORT_DELAY_MS);
395 <        assertEquals(1, p2.getActiveCount());
396 <        joinPool(p2);
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 >        }
405      }
406  
407      /**
408 <     *    getCompletedTaskCount increases, but doesn't overestimate,
409 <     *   when tasks complete
408 >     * getCompletedTaskCount increases, but doesn't overestimate,
409 >     * when tasks complete
410       */
411      public void testGetCompletedTaskCount() throws InterruptedException {
412 <        CustomExecutor p2 = new CustomExecutor(2);
413 <        assertEquals(0, p2.getCompletedTaskCount());
414 <        p2.execute(new SmallRunnable());
415 <        Thread.sleep(MEDIUM_DELAY_MS);
416 <        assertEquals(1, p2.getCompletedTaskCount());
417 <        joinPool(p2);
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 >        }
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);
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
449 >     * getLargestPoolSize increases, but doesn't overestimate, when
450 >     * multiple threads active
451       */
452      public void testGetLargestPoolSize() throws InterruptedException {
453 <        CustomExecutor p2 = new CustomExecutor(2);
454 <        assertEquals(0, p2.getLargestPoolSize());
455 <        p2.execute(new SmallRunnable());
456 <        p2.execute(new SmallRunnable());
457 <        Thread.sleep(SHORT_DELAY_MS);
458 <        assertEquals(2, p2.getLargestPoolSize());
459 <        joinPool(p2);
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() {
477 <        CustomExecutor p1 = new CustomExecutor(1);
478 <        assertEquals(0, p1.getPoolSize());
479 <        p1.execute(new SmallRunnable());
480 <        assertEquals(1, p1.getPoolSize());
481 <        joinPool(p1);
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
494 >     * getTaskCount increases, but doesn't overestimate, when tasks
495 >     * submitted
496       */
497      public void testGetTaskCount() throws InterruptedException {
498 <        CustomExecutor p1 = new CustomExecutor(1);
499 <        assertEquals(0, p1.getTaskCount());
500 <        for (int i = 0; i < 5; i++)
501 <            p1.execute(new SmallRunnable());
502 <        Thread.sleep(SHORT_DELAY_MS);
503 <        assertEquals(5, p1.getTaskCount());
504 <        joinPool(p1);
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(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 {
405 <            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 <        CustomExecutor p1 = new CustomExecutor(1);
570 <        try {
571 <            assertFalse(p1.isShutdown());
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          }
417        finally {
418            try { p1.shutdown(); } catch (SecurityException ok) { return; }
419        }
420        assertTrue(p1.isShutdown());
575      }
576  
423
577      /**
578 <     *  isTerminated is false before termination, true after
578 >     * isTerminated is false before termination, true after
579       */
580      public void testIsTerminated() throws InterruptedException {
581 <        CustomExecutor p1 = new CustomExecutor(1);
582 <        try {
583 <            p1.execute(new SmallRunnable());
584 <        } finally {
585 <            try { p1.shutdown(); } catch (SecurityException ok) { return; }
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          }
434        assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
435        assertTrue(p1.isTerminated());
599      }
600  
601      /**
602 <     *  isTerminating is not true when running or when terminated
602 >     * isTerminating is not true when running or when terminated
603       */
604      public void testIsTerminating() throws InterruptedException {
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 <        assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
614 <        assertTrue(p1.isTerminated());
615 <        assertFalse(p1.isTerminating());
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() throws InterruptedException {
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, MILLISECONDS);
634 <        }
635 <        try {
636 <            Thread.sleep(SHORT_DELAY_MS);
637 <            BlockingQueue<Runnable> q = p1.getQueue();
638 <            assertTrue(q.contains(tasks[4]));
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]));
469        } finally {
470            joinPool(p1);
647          }
648      }
649  
# Line 475 | Line 651 | public class ScheduledExecutorSubclassTe
651       * remove(task) removes queued task, and fails to remove active task
652       */
653      public void testRemove() throws InterruptedException {
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, MILLISECONDS);
658 <        }
659 <        try {
660 <            Thread.sleep(SHORT_DELAY_MS);
661 <            BlockingQueue<Runnable> q = p1.getQueue();
662 <            assertFalse(p1.remove((Runnable)tasks[0]));
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]));
495        } finally {
496            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() throws InterruptedException {
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, MILLISECONDS);
689 <        }
690 <        try {
691 <            int max = 5;
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 <            }
523 <            assertTrue(k < SMALL_DELAY_MS);
524 <        } finally {
525 <            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, 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() throws InterruptedException {
752 <        CustomExecutor p1 = new CustomExecutor(1);
753 <        assertTrue(p1.getExecuteExistingDelayedTasksAfterShutdownPolicy());
754 <        assertFalse(p1.getContinueExistingPeriodicTasksAfterShutdownPolicy());
755 <
756 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
757 <        for (int i = 0; i < 5; i++)
758 <            tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, MILLISECONDS);
759 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
760 <        BlockingQueue q = p1.getQueue();
761 <        for (Iterator it = q.iterator(); it.hasNext();) {
762 <            ScheduledFuture t = (ScheduledFuture)it.next();
763 <            assertFalse(t.isCancelled());
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 >            queuedTasks = p.shutdownNow();
765 >        } catch (SecurityException ok) {
766 >            return; // Allowed in case test doesn't have privs
767          }
768 <        assertTrue(p1.isShutdown());
769 <        Thread.sleep(SMALL_DELAY_MS);
770 <        for (int i = 0; i < 5; ++i) {
771 <            assertTrue(tasks[i].isDone());
772 <            assertFalse(tasks[i].isCancelled());
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 <    }
779 <
573 <
574 <    /**
575 <     * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
576 <     * delayed tasks are cancelled at shutdown
577 <     */
578 <    public void testShutDown2() throws InterruptedException {
579 <        CustomExecutor p1 = new CustomExecutor(1);
580 <        p1.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
581 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
582 <        for (int i = 0; i < 5; i++)
583 <            tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, MILLISECONDS);
584 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
585 <        assertTrue(p1.isShutdown());
586 <        BlockingQueue q = p1.getQueue();
587 <        assertTrue(q.isEmpty());
588 <        Thread.sleep(SMALL_DELAY_MS);
589 <        assertTrue(p1.isTerminated());
590 <    }
591 <
592 <
593 <    /**
594 <     * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
595 <     * periodic tasks are not cancelled at shutdown
596 <     */
597 <    public void testShutDown3() throws InterruptedException {
598 <        CustomExecutor p1 = new CustomExecutor(1);
599 <        p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
600 <        ScheduledFuture task =
601 <            p1.scheduleAtFixedRate(new NoOpRunnable(), 5, 5, MILLISECONDS);
602 <        try { p1.shutdown(); } catch (SecurityException ok) { return; }
603 <        assertTrue(p1.isShutdown());
604 <        BlockingQueue q = p1.getQueue();
605 <        assertTrue(q.isEmpty());
606 <        Thread.sleep(SHORT_DELAY_MS);
607 <        assertTrue(p1.isTerminated());
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() throws InterruptedException {
787 <        CustomExecutor p1 = new CustomExecutor(1);
788 <        try {
789 <            p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
790 <            ScheduledFuture task =
791 <                p1.scheduleAtFixedRate(new NoOpRunnable(), 1, 1, 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());
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() throws Exception {
879 <        ExecutorService e = new CustomExecutor(2);
880 <        try {
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);
646        } finally {
647            joinPool(e);
884          }
885      }
886  
# Line 652 | Line 888 | public class ScheduledExecutorSubclassTe
888       * completed submit of runnable returns successfully
889       */
890      public void testSubmitRunnable() throws Exception {
891 <        ExecutorService e = new CustomExecutor(2);
892 <        try {
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());
660        } finally {
661            joinPool(e);
896          }
897      }
898  
# Line 666 | Line 900 | public class ScheduledExecutorSubclassTe
900       * completed submit of (runnable, result) returns result
901       */
902      public void testSubmitRunnable2() throws Exception {
903 <        ExecutorService e = new CustomExecutor(2);
904 <        try {
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);
674        } finally {
675            joinPool(e);
908          }
909      }
910  
# Line 680 | Line 912 | public class ScheduledExecutorSubclassTe
912       * invokeAny(null) throws NPE
913       */
914      public void testInvokeAny1() throws Exception {
915 <        ExecutorService e = new CustomExecutor(2);
916 <        try {
917 <            e.invokeAny(null);
918 <            shouldThrow();
919 <        } catch (NullPointerException success) {
920 <        } finally {
689 <            joinPool(e);
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  
# Line 694 | Line 925 | public class ScheduledExecutorSubclassTe
925       * invokeAny(empty collection) throws IAE
926       */
927      public void testInvokeAny2() throws Exception {
928 <        ExecutorService e = new CustomExecutor(2);
929 <        try {
930 <            e.invokeAny(new ArrayList<Callable<String>>());
931 <            shouldThrow();
932 <        } catch (IllegalArgumentException success) {
933 <        } finally {
703 <            joinPool(e);
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  
# Line 709 | Line 939 | public class ScheduledExecutorSubclassTe
939       */
940      public void testInvokeAny3() throws Exception {
941          final CountDownLatch latch = new CountDownLatch(1);
942 <        ExecutorService e = new CustomExecutor(2);
943 <        try {
944 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
945 <            l.add(new Callable<String>() {
716 <                      public String call() {
717 <                          try {
718 <                              latch.await();
719 <                          } catch (InterruptedException quittingTime) {}
720 <                          return TEST_STRING;
721 <                      }});
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 <            shouldThrow();
949 <        } catch (NullPointerException success) {
950 <        } finally {
947 >            try {
948 >                e.invokeAny(l);
949 >                shouldThrow();
950 >            } catch (NullPointerException success) {}
951              latch.countDown();
728            joinPool(e);
952          }
953      }
954  
# Line 733 | Line 956 | public class ScheduledExecutorSubclassTe
956       * invokeAny(c) throws ExecutionException if no task completes
957       */
958      public void testInvokeAny4() throws Exception {
959 <        ExecutorService e = new CustomExecutor(2);
960 <        try {
961 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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 <            shouldThrow();
965 <        } catch (ExecutionException success) {
966 <            assertTrue(success.getCause() instanceof NullPointerException);
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  
# Line 750 | Line 973 | public class ScheduledExecutorSubclassTe
973       * invokeAny(c) returns result of some task
974       */
975      public void testInvokeAny5() throws Exception {
976 <        ExecutorService e = new CustomExecutor(2);
977 <        try {
978 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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);
760        } finally {
761            joinPool(e);
983          }
984      }
985  
# Line 766 | Line 987 | public class ScheduledExecutorSubclassTe
987       * invokeAll(null) throws NPE
988       */
989      public void testInvokeAll1() throws Exception {
990 <        ExecutorService e = new CustomExecutor(2);
991 <        try {
992 <            e.invokeAll(null);
993 <            shouldThrow();
994 <        } catch (NullPointerException success) {
995 <        } finally {
775 <            joinPool(e);
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  
# Line 780 | Line 1000 | public class ScheduledExecutorSubclassTe
1000       * invokeAll(empty collection) returns empty collection
1001       */
1002      public void testInvokeAll2() throws Exception {
1003 <        ExecutorService e = new CustomExecutor(2);
1004 <        try {
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());
787        } finally {
788            joinPool(e);
1007          }
1008      }
1009  
# Line 793 | Line 1011 | public class ScheduledExecutorSubclassTe
1011       * invokeAll(c) throws NPE if c has null elements
1012       */
1013      public void testInvokeAll3() throws Exception {
1014 <        ExecutorService e = new CustomExecutor(2);
1015 <        try {
1016 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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 <            shouldThrow();
1021 <        } catch (NullPointerException success) {
1022 <        } finally {
805 <            joinPool(e);
1019 >            try {
1020 >                e.invokeAll(l);
1021 >                shouldThrow();
1022 >            } catch (NullPointerException success) {}
1023          }
1024      }
1025  
# Line 810 | Line 1027 | public class ScheduledExecutorSubclassTe
1027       * get of invokeAll(c) throws exception on failed task
1028       */
1029      public void testInvokeAll4() throws Exception {
1030 <        ExecutorService e = new CustomExecutor(2);
1031 <        try {
1032 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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 (Future<String> future : result)
1037 <                future.get();
1038 <            shouldThrow();
1039 <        } catch (ExecutionException success) {
1040 <            assertTrue(success.getCause() instanceof NullPointerException);
1041 <        } finally {
825 <            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  
# Line 830 | Line 1046 | public class ScheduledExecutorSubclassTe
1046       * invokeAll(c) returns results of all completed tasks
1047       */
1048      public void testInvokeAll5() throws Exception {
1049 <        ExecutorService e = new CustomExecutor(2);
1050 <        try {
1051 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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 (Future<String> future : result)
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());
842        } finally {
843            joinPool(e);
1058          }
1059      }
1060  
# Line 848 | Line 1062 | public class ScheduledExecutorSubclassTe
1062       * timed invokeAny(null) throws NPE
1063       */
1064      public void testTimedInvokeAny1() throws Exception {
1065 <        ExecutorService e = new CustomExecutor(2);
1066 <        try {
1067 <            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
1068 <            shouldThrow();
1069 <        } catch (NullPointerException success) {
1070 <        } finally {
857 <            joinPool(e);
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  
# Line 862 | Line 1075 | public class ScheduledExecutorSubclassTe
1075       * timed invokeAny(,,null) throws NPE
1076       */
1077      public void testTimedInvokeAnyNullTimeUnit() throws Exception {
1078 <        ExecutorService e = new CustomExecutor(2);
1079 <        try {
1080 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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 <            shouldThrow();
1084 <        } catch (NullPointerException success) {
1085 <        } finally {
873 <            joinPool(e);
1082 >            try {
1083 >                e.invokeAny(l, MEDIUM_DELAY_MS, null);
1084 >                shouldThrow();
1085 >            } catch (NullPointerException success) {}
1086          }
1087      }
1088  
# Line 878 | Line 1090 | public class ScheduledExecutorSubclassTe
1090       * timed invokeAny(empty collection) throws IAE
1091       */
1092      public void testTimedInvokeAny2() throws Exception {
1093 <        ExecutorService e = new CustomExecutor(2);
1094 <        try {
1095 <            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1096 <            shouldThrow();
1097 <        } catch (IllegalArgumentException success) {
1098 <        } finally {
887 <            joinPool(e);
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  
# Line 892 | Line 1103 | public class ScheduledExecutorSubclassTe
1103       * timed invokeAny(c) throws NPE if c has null elements
1104       */
1105      public void testTimedInvokeAny3() throws Exception {
1106 <        final CountDownLatch latch = new CountDownLatch(1);
1107 <        ExecutorService e = new CustomExecutor(2);
1108 <        try {
1109 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
1110 <            l.add(new Callable<String>() {
900 <                      public String call() {
901 <                          try {
902 <                              latch.await();
903 <                          } catch (InterruptedException quittingTime) {}
904 <                          return TEST_STRING;
905 <                      }});
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, MILLISECONDS);
1113 <            shouldThrow();
1114 <        } catch (NullPointerException success) {
1115 <        } finally {
1112 >            try {
1113 >                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1114 >                shouldThrow();
1115 >            } catch (NullPointerException success) {}
1116              latch.countDown();
912            joinPool(e);
1117          }
1118      }
1119  
# Line 917 | Line 1121 | public class ScheduledExecutorSubclassTe
1121       * timed invokeAny(c) throws ExecutionException if no task completes
1122       */
1123      public void testTimedInvokeAny4() throws Exception {
1124 <        ExecutorService e = new CustomExecutor(2);
1125 <        try {
1126 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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, MILLISECONDS);
1130 <            shouldThrow();
1131 <        } catch (ExecutionException success) {
1132 <            assertTrue(success.getCause() instanceof NullPointerException);
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  
# Line 934 | Line 1140 | public class ScheduledExecutorSubclassTe
1140       * timed invokeAny(c) returns result of some task
1141       */
1142      public void testTimedInvokeAny5() throws Exception {
1143 <        ExecutorService e = new CustomExecutor(2);
1144 <        try {
1145 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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, MILLISECONDS);
1149 >            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1150              assertSame(TEST_STRING, result);
1151 <        } finally {
945 <            joinPool(e);
1151 >            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1152          }
1153      }
1154  
# Line 950 | Line 1156 | public class ScheduledExecutorSubclassTe
1156       * timed invokeAll(null) throws NPE
1157       */
1158      public void testTimedInvokeAll1() throws Exception {
1159 <        ExecutorService e = new CustomExecutor(2);
1160 <        try {
1161 <            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
1162 <            shouldThrow();
1163 <        } catch (NullPointerException success) {
1164 <        } finally {
959 <            joinPool(e);
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  
# Line 964 | Line 1169 | public class ScheduledExecutorSubclassTe
1169       * timed invokeAll(,,null) throws NPE
1170       */
1171      public void testTimedInvokeAllNullTimeUnit() throws Exception {
1172 <        ExecutorService e = new CustomExecutor(2);
1173 <        try {
1174 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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 <            shouldThrow();
1178 <        } catch (NullPointerException success) {
1179 <        } finally {
975 <            joinPool(e);
1176 >            try {
1177 >                e.invokeAll(l, MEDIUM_DELAY_MS, null);
1178 >                shouldThrow();
1179 >            } catch (NullPointerException success) {}
1180          }
1181      }
1182  
# Line 980 | Line 1184 | public class ScheduledExecutorSubclassTe
1184       * timed invokeAll(empty collection) returns empty collection
1185       */
1186      public void testTimedInvokeAll2() throws Exception {
1187 <        ExecutorService e = new CustomExecutor(2);
1188 <        try {
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());
987        } finally {
988            joinPool(e);
1191          }
1192      }
1193  
# Line 993 | Line 1195 | public class ScheduledExecutorSubclassTe
1195       * timed invokeAll(c) throws NPE if c has null elements
1196       */
1197      public void testTimedInvokeAll3() throws Exception {
1198 <        ExecutorService e = new CustomExecutor(2);
1199 <        try {
1200 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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, MILLISECONDS);
1204 <            shouldThrow();
1205 <        } catch (NullPointerException success) {
1206 <        } finally {
1005 <            joinPool(e);
1203 >            try {
1204 >                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1205 >                shouldThrow();
1206 >            } catch (NullPointerException success) {}
1207          }
1208      }
1209  
# Line 1010 | Line 1211 | public class ScheduledExecutorSubclassTe
1211       * get of element of invokeAll(c) throws exception on failed task
1212       */
1213      public void testTimedInvokeAll4() throws Exception {
1214 <        ExecutorService e = new CustomExecutor(2);
1215 <        try {
1216 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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, MILLISECONDS);
1219 <            assertEquals(1, result.size());
1220 <            for (Future<String> future : result)
1221 <                future.get();
1222 <            shouldThrow();
1223 <        } catch (ExecutionException success) {
1224 <            assertTrue(success.getCause() instanceof NullPointerException);
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  
# Line 1030 | Line 1231 | public class ScheduledExecutorSubclassTe
1231       * timed invokeAll(c) returns results of all completed tasks
1232       */
1233      public void testTimedInvokeAll5() throws Exception {
1234 <        ExecutorService e = new CustomExecutor(2);
1235 <        try {
1236 <            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
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, MILLISECONDS);
1240 <            assertEquals(2, result.size());
1241 <            for (Future<String> future : result)
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());
1042        } finally {
1043            joinPool(e);
1244          }
1245      }
1246  
# Line 1048 | Line 1248 | public class ScheduledExecutorSubclassTe
1248       * timed invokeAll(c) cancels tasks not completed by timeout
1249       */
1250      public void testTimedInvokeAll6() throws Exception {
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, 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 <        } finally {
1269 <            joinPool(e);
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  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines