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/publicdomain/zero/1.0/
5  * Other contributors include Andrew Wright, Jeffrey Hayes,
6  * Pat Fisher, Mike Judd.
7  */
8 
9 package jsr166;
10 
11 import junit.framework.*;
12 import java.util.*;
13 import java.util.concurrent.*;
14 import java.util.concurrent.atomic.AtomicBoolean;
15 import static java.util.concurrent.TimeUnit.MILLISECONDS;
16 import java.security.*;
17 
18 public class AbstractExecutorServiceTest extends JSR166TestCase {
19 
20     /**
21      * A no-frills implementation of AbstractExecutorService, designed
22      * to test the submit methods only.
23      */
24     static class DirectExecutorService extends AbstractExecutorService {
execute(Runnable r)25         public void execute(Runnable r) { r.run(); }
shutdown()26         public void shutdown() { shutdown = true; }
shutdownNow()27         public List<Runnable> shutdownNow() {
28             shutdown = true;
29             return Collections.EMPTY_LIST;
30         }
isShutdown()31         public boolean isShutdown() { return shutdown; }
isTerminated()32         public boolean isTerminated() { return isShutdown(); }
awaitTermination(long timeout, TimeUnit unit)33         public boolean awaitTermination(long timeout, TimeUnit unit) {
34             return isShutdown();
35         }
36         private volatile boolean shutdown = false;
37     }
38 
39     /**
40      * execute(runnable) runs it to completion
41      */
testExecuteRunnable()42     public void testExecuteRunnable() throws Exception {
43         ExecutorService e = new DirectExecutorService();
44         final AtomicBoolean done = new AtomicBoolean(false);
45         CheckedRunnable task = new CheckedRunnable() {
46             public void realRun() {
47                 done.set(true);
48             }};
49         Future<?> future = e.submit(task);
50         assertNull(future.get());
51         assertNull(future.get(0, MILLISECONDS));
52         assertTrue(done.get());
53         assertTrue(future.isDone());
54         assertFalse(future.isCancelled());
55     }
56 
57     /**
58      * Completed submit(callable) returns result
59      */
testSubmitCallable()60     public void testSubmitCallable() throws Exception {
61         ExecutorService e = new DirectExecutorService();
62         Future<String> future = e.submit(new StringTask());
63         String result = future.get();
64         assertSame(TEST_STRING, result);
65     }
66 
67     /**
68      * Completed submit(runnable) returns successfully
69      */
testSubmitRunnable()70     public void testSubmitRunnable() throws Exception {
71         ExecutorService e = new DirectExecutorService();
72         Future<?> future = e.submit(new NoOpRunnable());
73         future.get();
74         assertTrue(future.isDone());
75     }
76 
77     /**
78      * Completed submit(runnable, result) returns result
79      */
testSubmitRunnable2()80     public void testSubmitRunnable2() throws Exception {
81         ExecutorService e = new DirectExecutorService();
82         Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
83         String result = future.get();
84         assertSame(TEST_STRING, result);
85     }
86 
87     /**
88      * A submitted privileged action runs to completion
89      */
testSubmitPrivilegedAction()90     public void testSubmitPrivilegedAction() throws Exception {
91         Runnable r = new CheckedRunnable() {
92             public void realRun() throws Exception {
93                 ExecutorService e = new DirectExecutorService();
94                 Future future = e.submit(Executors.callable(new PrivilegedAction() {
95                     public Object run() {
96                         return TEST_STRING;
97                     }}));
98 
99                 assertSame(TEST_STRING, future.get());
100             }};
101 
102         runWithPermissions(r,
103                            new RuntimePermission("getClassLoader"),
104                            new RuntimePermission("setContextClassLoader"),
105                            new RuntimePermission("modifyThread"));
106     }
107 
108     /**
109      * A submitted privileged exception action runs to completion
110      */
testSubmitPrivilegedExceptionAction()111     public void testSubmitPrivilegedExceptionAction() throws Exception {
112         Runnable r = new CheckedRunnable() {
113             public void realRun() throws Exception {
114                 ExecutorService e = new DirectExecutorService();
115                 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
116                     public Object run() {
117                         return TEST_STRING;
118                     }}));
119 
120                 assertSame(TEST_STRING, future.get());
121             }};
122 
123         runWithPermissions(r);
124     }
125 
126     /**
127      * A submitted failed privileged exception action reports exception
128      */
testSubmitFailedPrivilegedExceptionAction()129     public void testSubmitFailedPrivilegedExceptionAction() throws Exception {
130         Runnable r = new CheckedRunnable() {
131             public void realRun() throws Exception {
132                 ExecutorService e = new DirectExecutorService();
133                 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
134                     public Object run() throws Exception {
135                         throw new IndexOutOfBoundsException();
136                     }}));
137 
138                 try {
139                     future.get();
140                     shouldThrow();
141                 } catch (ExecutionException success) {
142                     assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
143                 }}};
144 
145         runWithPermissions(r);
146     }
147 
148     /**
149      * execute(null runnable) throws NPE
150      */
testExecuteNullRunnable()151     public void testExecuteNullRunnable() {
152         try {
153             ExecutorService e = new DirectExecutorService();
154             e.submit((Runnable) null);
155             shouldThrow();
156         } catch (NullPointerException success) {}
157     }
158 
159     /**
160      * submit(null callable) throws NPE
161      */
testSubmitNullCallable()162     public void testSubmitNullCallable() {
163         try {
164             ExecutorService e = new DirectExecutorService();
165             e.submit((Callable) null);
166             shouldThrow();
167         } catch (NullPointerException success) {}
168     }
169 
170     /**
171      * submit(callable).get() throws InterruptedException if interrupted
172      */
testInterruptedSubmit()173     public void testInterruptedSubmit() throws InterruptedException {
174         final CountDownLatch submitted    = new CountDownLatch(1);
175         final CountDownLatch quittingTime = new CountDownLatch(1);
176         final ExecutorService p
177             = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,
178                                      new ArrayBlockingQueue<Runnable>(10));
179         final Callable<Void> awaiter = new CheckedCallable<Void>() {
180             public Void realCall() throws InterruptedException {
181                 quittingTime.await();
182                 return null;
183             }};
184         try {
185             Thread t = new Thread(new CheckedInterruptedRunnable() {
186                 public void realRun() throws Exception {
187                     Future<Void> future = p.submit(awaiter);
188                     submitted.countDown();
189                     future.get();
190                 }});
191             t.start();
192             submitted.await();
193             t.interrupt();
194             t.join();
195         } finally {
196             quittingTime.countDown();
197             joinPool(p);
198         }
199     }
200 
201     /**
202      * get of submit(callable) throws ExecutionException if callable
203      * throws exception
204      */
testSubmitEE()205     public void testSubmitEE() throws InterruptedException {
206         ThreadPoolExecutor p =
207             new ThreadPoolExecutor(1, 1,
208                                    60, TimeUnit.SECONDS,
209                                    new ArrayBlockingQueue<Runnable>(10));
210 
211         Callable c = new Callable() {
212             public Object call() { throw new ArithmeticException(); }};
213 
214         try {
215             p.submit(c).get();
216             shouldThrow();
217         } catch (ExecutionException success) {
218             assertTrue(success.getCause() instanceof ArithmeticException);
219         }
220         joinPool(p);
221     }
222 
223     /**
224      * invokeAny(null) throws NPE
225      */
testInvokeAny1()226     public void testInvokeAny1() throws Exception {
227         ExecutorService e = new DirectExecutorService();
228         try {
229             e.invokeAny(null);
230             shouldThrow();
231         } catch (NullPointerException success) {
232         } finally {
233             joinPool(e);
234         }
235     }
236 
237     /**
238      * invokeAny(empty collection) throws IAE
239      */
testInvokeAny2()240     public void testInvokeAny2() throws Exception {
241         ExecutorService e = new DirectExecutorService();
242         try {
243             e.invokeAny(new ArrayList<Callable<String>>());
244             shouldThrow();
245         } catch (IllegalArgumentException success) {
246         } finally {
247             joinPool(e);
248         }
249     }
250 
251     /**
252      * invokeAny(c) throws NPE if c has null elements
253      */
testInvokeAny3()254     public void testInvokeAny3() throws Exception {
255         ExecutorService e = new DirectExecutorService();
256         List<Callable<Long>> l = new ArrayList<Callable<Long>>();
257         l.add(new Callable<Long>() {
258             public Long call() { throw new ArithmeticException(); }});
259         l.add(null);
260         try {
261             e.invokeAny(l);
262             shouldThrow();
263         } catch (NullPointerException success) {
264         } finally {
265             joinPool(e);
266         }
267     }
268 
269     /**
270      * invokeAny(c) throws ExecutionException if no task in c completes
271      */
testInvokeAny4()272     public void testInvokeAny4() throws InterruptedException {
273         ExecutorService e = new DirectExecutorService();
274         List<Callable<String>> l = new ArrayList<Callable<String>>();
275         l.add(new NPETask());
276         try {
277             e.invokeAny(l);
278             shouldThrow();
279         } catch (ExecutionException success) {
280             assertTrue(success.getCause() instanceof NullPointerException);
281         } finally {
282             joinPool(e);
283         }
284     }
285 
286     /**
287      * invokeAny(c) returns result of some task in c if at least one completes
288      */
testInvokeAny5()289     public void testInvokeAny5() throws Exception {
290         ExecutorService e = new DirectExecutorService();
291         try {
292             List<Callable<String>> l = new ArrayList<Callable<String>>();
293             l.add(new StringTask());
294             l.add(new StringTask());
295             String result = e.invokeAny(l);
296             assertSame(TEST_STRING, result);
297         } finally {
298             joinPool(e);
299         }
300     }
301 
302     /**
303      * invokeAll(null) throws NPE
304      */
testInvokeAll1()305     public void testInvokeAll1() throws InterruptedException {
306         ExecutorService e = new DirectExecutorService();
307         try {
308             e.invokeAll(null);
309             shouldThrow();
310         } catch (NullPointerException success) {
311         } finally {
312             joinPool(e);
313         }
314     }
315 
316     /**
317      * invokeAll(empty collection) returns empty collection
318      */
testInvokeAll2()319     public void testInvokeAll2() throws InterruptedException {
320         ExecutorService e = new DirectExecutorService();
321         try {
322             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
323             assertTrue(r.isEmpty());
324         } finally {
325             joinPool(e);
326         }
327     }
328 
329     /**
330      * invokeAll(c) throws NPE if c has null elements
331      */
testInvokeAll3()332     public void testInvokeAll3() throws InterruptedException {
333         ExecutorService e = new DirectExecutorService();
334         List<Callable<String>> l = new ArrayList<Callable<String>>();
335         l.add(new StringTask());
336         l.add(null);
337         try {
338             e.invokeAll(l);
339             shouldThrow();
340         } catch (NullPointerException success) {
341         } finally {
342             joinPool(e);
343         }
344     }
345 
346     /**
347      * get of returned element of invokeAll(c) throws exception on failed task
348      */
testInvokeAll4()349     public void testInvokeAll4() throws Exception {
350         ExecutorService e = new DirectExecutorService();
351         try {
352             List<Callable<String>> l = new ArrayList<Callable<String>>();
353             l.add(new NPETask());
354             List<Future<String>> futures = e.invokeAll(l);
355             assertEquals(1, futures.size());
356             try {
357                 futures.get(0).get();
358                 shouldThrow();
359             } catch (ExecutionException success) {
360                 assertTrue(success.getCause() instanceof NullPointerException);
361             }
362         } finally {
363             joinPool(e);
364         }
365     }
366 
367     /**
368      * invokeAll(c) returns results of all completed tasks in c
369      */
testInvokeAll5()370     public void testInvokeAll5() throws Exception {
371         ExecutorService e = new DirectExecutorService();
372         try {
373             List<Callable<String>> l = new ArrayList<Callable<String>>();
374             l.add(new StringTask());
375             l.add(new StringTask());
376             List<Future<String>> futures = e.invokeAll(l);
377             assertEquals(2, futures.size());
378             for (Future<String> future : futures)
379                 assertSame(TEST_STRING, future.get());
380         } finally {
381             joinPool(e);
382         }
383     }
384 
385     /**
386      * timed invokeAny(null) throws NPE
387      */
testTimedInvokeAny1()388     public void testTimedInvokeAny1() throws Exception {
389         ExecutorService e = new DirectExecutorService();
390         try {
391             e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
392             shouldThrow();
393         } catch (NullPointerException success) {
394         } finally {
395             joinPool(e);
396         }
397     }
398 
399     /**
400      * timed invokeAny(null time unit) throws NPE
401      */
testTimedInvokeAnyNullTimeUnit()402     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
403         ExecutorService e = new DirectExecutorService();
404         List<Callable<String>> l = new ArrayList<Callable<String>>();
405         l.add(new StringTask());
406         try {
407             e.invokeAny(l, MEDIUM_DELAY_MS, null);
408             shouldThrow();
409         } catch (NullPointerException success) {
410         } finally {
411             joinPool(e);
412         }
413     }
414 
415     /**
416      * timed invokeAny(empty collection) throws IAE
417      */
testTimedInvokeAny2()418     public void testTimedInvokeAny2() throws Exception {
419         ExecutorService e = new DirectExecutorService();
420         try {
421             e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
422             shouldThrow();
423         } catch (IllegalArgumentException success) {
424         } finally {
425             joinPool(e);
426         }
427     }
428 
429     /**
430      * timed invokeAny(c) throws NPE if c has null elements
431      */
testTimedInvokeAny3()432     public void testTimedInvokeAny3() throws Exception {
433         ExecutorService e = new DirectExecutorService();
434         List<Callable<Long>> l = new ArrayList<Callable<Long>>();
435         l.add(new Callable<Long>() {
436             public Long call() { throw new ArithmeticException(); }});
437         l.add(null);
438         try {
439             e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
440             shouldThrow();
441         } catch (NullPointerException success) {
442         } finally {
443             joinPool(e);
444         }
445     }
446 
447     /**
448      * timed invokeAny(c) throws ExecutionException if no task completes
449      */
testTimedInvokeAny4()450     public void testTimedInvokeAny4() throws Exception {
451         ExecutorService e = new DirectExecutorService();
452         List<Callable<String>> l = new ArrayList<Callable<String>>();
453         l.add(new NPETask());
454         try {
455             e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
456             shouldThrow();
457         } catch (ExecutionException success) {
458             assertTrue(success.getCause() instanceof NullPointerException);
459         } finally {
460             joinPool(e);
461         }
462     }
463 
464     /**
465      * timed invokeAny(c) returns result of some task in c
466      */
testTimedInvokeAny5()467     public void testTimedInvokeAny5() throws Exception {
468         ExecutorService e = new DirectExecutorService();
469         try {
470             List<Callable<String>> l = new ArrayList<Callable<String>>();
471             l.add(new StringTask());
472             l.add(new StringTask());
473             String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
474             assertSame(TEST_STRING, result);
475         } finally {
476             joinPool(e);
477         }
478     }
479 
480     /**
481      * timed invokeAll(null) throws NPE
482      */
testTimedInvokeAll1()483     public void testTimedInvokeAll1() throws InterruptedException {
484         ExecutorService e = new DirectExecutorService();
485         try {
486             e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
487             shouldThrow();
488         } catch (NullPointerException success) {
489         } finally {
490             joinPool(e);
491         }
492     }
493 
494     /**
495      * timed invokeAll(null time unit) throws NPE
496      */
testTimedInvokeAllNullTimeUnit()497     public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
498         ExecutorService e = new DirectExecutorService();
499         List<Callable<String>> l = new ArrayList<Callable<String>>();
500         l.add(new StringTask());
501         try {
502             e.invokeAll(l, MEDIUM_DELAY_MS, null);
503             shouldThrow();
504         } catch (NullPointerException success) {
505         } finally {
506             joinPool(e);
507         }
508     }
509 
510     /**
511      * timed invokeAll(empty collection) returns empty collection
512      */
testTimedInvokeAll2()513     public void testTimedInvokeAll2() throws InterruptedException {
514         ExecutorService e = new DirectExecutorService();
515         try {
516             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
517             assertTrue(r.isEmpty());
518         } finally {
519             joinPool(e);
520         }
521     }
522 
523     /**
524      * timed invokeAll(c) throws NPE if c has null elements
525      */
testTimedInvokeAll3()526     public void testTimedInvokeAll3() throws InterruptedException {
527         ExecutorService e = new DirectExecutorService();
528         List<Callable<String>> l = new ArrayList<Callable<String>>();
529         l.add(new StringTask());
530         l.add(null);
531         try {
532             e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
533             shouldThrow();
534         } catch (NullPointerException success) {
535         } finally {
536             joinPool(e);
537         }
538     }
539 
540     /**
541      * get of returned element of invokeAll(c) throws exception on failed task
542      */
testTimedInvokeAll4()543     public void testTimedInvokeAll4() throws Exception {
544         ExecutorService e = new DirectExecutorService();
545         try {
546             List<Callable<String>> l = new ArrayList<Callable<String>>();
547             l.add(new NPETask());
548             List<Future<String>> futures =
549                 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
550             assertEquals(1, futures.size());
551             try {
552                 futures.get(0).get();
553                 shouldThrow();
554             } catch (ExecutionException success) {
555                 assertTrue(success.getCause() instanceof NullPointerException);
556             }
557         } finally {
558             joinPool(e);
559         }
560     }
561 
562     /**
563      * timed invokeAll(c) returns results of all completed tasks in c
564      */
testTimedInvokeAll5()565     public void testTimedInvokeAll5() throws Exception {
566         ExecutorService e = new DirectExecutorService();
567         try {
568             List<Callable<String>> l = new ArrayList<Callable<String>>();
569             l.add(new StringTask());
570             l.add(new StringTask());
571             List<Future<String>> futures =
572                 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
573             assertEquals(2, futures.size());
574             for (Future<String> future : futures)
575                 assertSame(TEST_STRING, future.get());
576         } finally {
577             joinPool(e);
578         }
579     }
580 
581     /**
582      * timed invokeAll cancels tasks not completed by timeout
583      */
testTimedInvokeAll6()584     public void testTimedInvokeAll6() throws InterruptedException {
585         ExecutorService e = new DirectExecutorService();
586         try {
587             List<Callable<String>> l = new ArrayList<Callable<String>>();
588             l.add(new StringTask());
589             l.add(Executors.callable(possiblyInterruptedRunnable(2 * SHORT_DELAY_MS), TEST_STRING));
590             l.add(new StringTask());
591             List<Future<String>> futures =
592                 e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
593             assertEquals(l.size(), futures.size());
594             for (Future future : futures)
595                 assertTrue(future.isDone());
596             assertFalse(futures.get(0).isCancelled());
597             assertFalse(futures.get(1).isCancelled());
598             assertTrue(futures.get(2).isCancelled());
599         } finally {
600             joinPool(e);
601         }
602     }
603 
604 }
605