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