[cvs] / jsr166 / src / test / tck / FutureTaskTest.java Repository:
ViewVC logotype

Diff of /jsr166/src/test/tck/FutureTaskTest.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.7, Fri Sep 26 15:33:13 2003 UTC revision 1.52, Sun Jul 22 21:04:56 2018 UTC
# Line 1  Line 1 
1  /*  /*
2   * Written by members of JCP JSR-166 Expert Group and released to the   * Written by Doug Lea with assistance from members of JCP JSR-166
3   * public domain. Use, modify, and redistribute this code in any way   * Expert Group and released to the public domain, as explained at
4   * without acknowledgement. Other contributors include Andrew Wright,   * http://creativecommons.org/publicdomain/zero/1.0/
5   * Jeffrey Hayes, Pat Fischer, Mike Judd.   * Other contributors include Andrew Wright, Jeffrey Hayes,
6   */   * Pat Fisher, Mike Judd.
7     */
8    
9    import static java.util.concurrent.TimeUnit.MILLISECONDS;
10    import static java.util.concurrent.TimeUnit.NANOSECONDS;
11    
12    import java.util.ArrayList;
13    import java.util.List;
14    import java.util.NoSuchElementException;
15    import java.util.concurrent.Callable;
16    import java.util.concurrent.CancellationException;
17    import java.util.concurrent.CountDownLatch;
18    import java.util.concurrent.ExecutionException;
19    import java.util.concurrent.Executors;
20    import java.util.concurrent.ExecutorService;
21    import java.util.concurrent.Future;
22    import java.util.concurrent.FutureTask;
23    import java.util.concurrent.TimeoutException;
24    import java.util.concurrent.atomic.AtomicInteger;
25    
26  import junit.framework.*;  import junit.framework.Test;
27  import java.util.concurrent.*;  import junit.framework.TestSuite;
 import java.util.*;  
28    
29  public class FutureTaskTest extends JSR166TestCase {  public class FutureTaskTest extends JSR166TestCase {
30    
31      public static void main(String[] args) {      public static void main(String[] args) {
32          junit.textui.TestRunner.run (suite());          main(suite(), args);
33      }      }
34      public static Test suite() {      public static Test suite() {
35          return new TestSuite(FutureTaskTest.class);          return new TestSuite(FutureTaskTest.class);
36      }      }
37    
38        void checkIsDone(Future<?> f) {
39            assertTrue(f.isDone());
40            assertFalse(f.cancel(false));
41            assertFalse(f.cancel(true));
42            if (f instanceof PublicFutureTask) {
43                PublicFutureTask pf = (PublicFutureTask) f;
44                assertEquals(1, pf.doneCount());
45                assertFalse(pf.runAndReset());
46                assertEquals(1, pf.doneCount());
47                Object r = null; Object exInfo = null;
48                try {
49                    r = f.get();
50                } catch (CancellationException t) {
51                    exInfo = CancellationException.class;
52                } catch (ExecutionException t) {
53                    exInfo = t.getCause();
54                } catch (Throwable t) {
55                    threadUnexpectedException(t);
56                }
57    
58                // Check that run and runAndReset have no effect.
59                int savedRunCount = pf.runCount();
60                pf.run();
61                pf.runAndReset();
62                assertEquals(savedRunCount, pf.runCount());
63                Object r2 = null;
64                try {
65                    r2 = f.get();
66                } catch (CancellationException t) {
67                    assertSame(exInfo, CancellationException.class);
68                } catch (ExecutionException t) {
69                    assertSame(exInfo, t.getCause());
70                } catch (Throwable t) {
71                    threadUnexpectedException(t);
72                }
73                if (exInfo == null)
74                    assertSame(r, r2);
75                assertTrue(f.isDone());
76            }
77        }
78    
79        void checkNotDone(Future<?> f) {
80            assertFalse(f.isDone());
81            assertFalse(f.isCancelled());
82            if (f instanceof PublicFutureTask) {
83                PublicFutureTask pf = (PublicFutureTask) f;
84                assertEquals(0, pf.doneCount());
85                assertEquals(0, pf.setCount());
86                assertEquals(0, pf.setExceptionCount());
87            }
88        }
89    
90        void checkIsRunning(Future<?> f) {
91            checkNotDone(f);
92            if (f instanceof FutureTask) {
93                FutureTask ft = (FutureTask<?>) f;
94                // Check that run methods do nothing
95                ft.run();
96                if (f instanceof PublicFutureTask) {
97                    PublicFutureTask pf = (PublicFutureTask) f;
98                    int savedRunCount = pf.runCount();
99                    pf.run();
100                    assertFalse(pf.runAndReset());
101                    assertEquals(savedRunCount, pf.runCount());
102                }
103                checkNotDone(f);
104            }
105        }
106    
107        <T> void checkCompletedNormally(Future<T> f, T expectedValue) {
108            checkIsDone(f);
109            assertFalse(f.isCancelled());
110    
111            T v1 = null, v2 = null;
112            try {
113                v1 = f.get();
114                v2 = f.get(randomTimeout(), randomTimeUnit());
115            } catch (Throwable fail) { threadUnexpectedException(fail); }
116            assertSame(expectedValue, v1);
117            assertSame(expectedValue, v2);
118        }
119    
120        void checkCancelled(Future<?> f) {
121            checkIsDone(f);
122            assertTrue(f.isCancelled());
123    
124            try {
125                f.get();
126                shouldThrow();
127            } catch (CancellationException success) {
128            } catch (Throwable fail) { threadUnexpectedException(fail); }
129    
130            try {
131                f.get(randomTimeout(), randomTimeUnit());
132                shouldThrow();
133            } catch (CancellationException success) {
134            } catch (Throwable fail) { threadUnexpectedException(fail); }
135        }
136    
137        void tryToConfuseDoneTask(PublicFutureTask pf) {
138            pf.set(new Object());
139            pf.setException(new Error());
140            for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
141                pf.cancel(mayInterruptIfRunning);
142            }
143        }
144    
145        void checkCompletedAbnormally(Future<?> f, Throwable t) {
146            checkIsDone(f);
147            assertFalse(f.isCancelled());
148    
149            try {
150                f.get();
151                shouldThrow();
152            } catch (ExecutionException success) {
153                assertSame(t, success.getCause());
154            } catch (Throwable fail) { threadUnexpectedException(fail); }
155    
156            try {
157                f.get(randomTimeout(), randomTimeUnit());
158                shouldThrow();
159            } catch (ExecutionException success) {
160                assertSame(t, success.getCause());
161            } catch (Throwable fail) { threadUnexpectedException(fail); }
162        }
163    
164      /**      /**
165       * Subclass to expose protected methods       * Subclass to expose protected methods
166       */       */
167      static class PublicFutureTask extends FutureTask {      static class PublicFutureTask extends FutureTask {
168          public PublicFutureTask(Callable r) { super(r); }          private final AtomicInteger runCount;
169          public boolean reset() { return super.reset(); }          private final AtomicInteger doneCount = new AtomicInteger(0);
170          public void setCancelled() { super.setCancelled(); }          private final AtomicInteger runAndResetCount = new AtomicInteger(0);
171          public void setDone() { super.setDone(); }          private final AtomicInteger setCount = new AtomicInteger(0);
172          public void set(Object x) { super.set(x); }          private final AtomicInteger setExceptionCount = new AtomicInteger(0);
173          public void setException(Throwable t) { super.setException(t); }          public int runCount() { return runCount.get(); }
174            public int doneCount() { return doneCount.get(); }
175            public int runAndResetCount() { return runAndResetCount.get(); }
176            public int setCount() { return setCount.get(); }
177            public int setExceptionCount() { return setExceptionCount.get(); }
178    
179            PublicFutureTask(Runnable runnable) {
180                this(runnable, seven);
181            }
182            PublicFutureTask(Runnable runnable, Object result) {
183                this(runnable, result, new AtomicInteger(0));
184            }
185            private PublicFutureTask(final Runnable runnable, Object result,
186                                     final AtomicInteger runCount) {
187                super(new Runnable() {
188                    public void run() {
189                        runCount.getAndIncrement();
190                        runnable.run();
191                    }}, result);
192                this.runCount = runCount;
193            }
194            PublicFutureTask(Callable callable) {
195                this(callable, new AtomicInteger(0));
196            }
197            private PublicFutureTask(final Callable callable,
198                                     final AtomicInteger runCount) {
199                super(new Callable() {
200                    public Object call() throws Exception {
201                        runCount.getAndIncrement();
202                        return callable.call();
203                    }});
204                this.runCount = runCount;
205            }
206            @Override public void done() {
207                assertTrue(isDone());
208                doneCount.incrementAndGet();
209                super.done();
210            }
211            @Override public boolean runAndReset() {
212                runAndResetCount.incrementAndGet();
213                return super.runAndReset();
214            }
215            @Override public void set(Object x) {
216                setCount.incrementAndGet();
217                super.set(x);
218            }
219            @Override public void setException(Throwable t) {
220                setExceptionCount.incrementAndGet();
221                super.setException(t);
222            }
223        }
224    
225        class Counter extends CheckedRunnable {
226            final AtomicInteger count = new AtomicInteger(0);
227            public int get() { return count.get(); }
228            public void realRun() {
229                count.getAndIncrement();
230            }
231      }      }
232    
233      /**      /**
234       * Creating a future with a null callable throws NPE       * creating a future with a null callable throws NullPointerException
235       */       */
236      public void testConstructor() {      public void testConstructor() {
237          try {          try {
238              FutureTask task = new FutureTask(null);              new FutureTask(null);
239              shouldThrow();              shouldThrow();
240          }          } catch (NullPointerException success) {}
         catch(NullPointerException success) {  
         }  
241      }      }
242    
243      /**      /**
244       * creating a future with null runnable fails       * creating a future with null runnable throws NullPointerException
245       */       */
246      public void testConstructor2() {      public void testConstructor2() {
247          try {          try {
248              FutureTask task = new FutureTask(null, Boolean.TRUE);              new FutureTask(null, Boolean.TRUE);
249              shouldThrow();              shouldThrow();
250          }          } catch (NullPointerException success) {}
         catch(NullPointerException success) {  
         }  
251      }      }
252    
253      /**      /**
254       * isDone is true when a task completes       * isDone is true when a task completes
255       */       */
256      public void testIsDone() {      public void testIsDone() {
         FutureTask task = new FutureTask( new NoOpCallable());  
         task.run();  
         assertTrue(task.isDone());  
         assertFalse(task.isCancelled());  
     }  
   
     /**  
      * reset of a done task succeeds and changes status to not done  
      */  
     public void testReset() {  
257          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
         task.run();  
         assertTrue(task.isDone());  
         assertTrue(task.reset());  
258          assertFalse(task.isDone());          assertFalse(task.isDone());
     }  
   
     /**  
      * Resetting after cancellation fails  
      */  
     public void testResetAfterCancel() {  
         PublicFutureTask task = new PublicFutureTask(new NoOpCallable());  
         assertTrue(task.cancel(false));  
259          task.run();          task.run();
260          assertTrue(task.isDone());          assertTrue(task.isDone());
261          assertTrue(task.isCancelled());          checkCompletedNormally(task, Boolean.TRUE);
262          assertFalse(task.reset());          assertEquals(1, task.runCount());
263      }      }
264    
265      /**      /**
266       * setDone of new task causes isDone to be true       * runAndReset of a non-cancelled task succeeds
267       */       */
268      public void testSetDone() {      public void testRunAndReset() {
269          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
270          task.setDone();          for (int i = 0; i < 3; i++) {
271          assertTrue(task.isDone());              assertTrue(task.runAndReset());
272          assertFalse(task.isCancelled());              checkNotDone(task);
273                assertEquals(i + 1, task.runCount());
274                assertEquals(i + 1, task.runAndResetCount());
275                assertEquals(0, task.setCount());
276                assertEquals(0, task.setExceptionCount());
277            }
278      }      }
279    
280      /**      /**
281       * setCancelled of a new task causes isCancelled to be true       * runAndReset after cancellation fails
282       */       */
283      public void testSetCancelled() {      public void testRunAndResetAfterCancel() {
284            for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
285          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
286          assertTrue(task.cancel(false));              assertTrue(task.cancel(mayInterruptIfRunning));
287          task.setCancelled();              for (int i = 0; i < 3; i++) {
288          assertTrue(task.isDone());                  assertFalse(task.runAndReset());
289          assertTrue(task.isCancelled());                  assertEquals(0, task.runCount());
290                    assertEquals(i + 1, task.runAndResetCount());
291                    assertEquals(0, task.setCount());
292                    assertEquals(0, task.setExceptionCount());
293                }
294                tryToConfuseDoneTask(task);
295                checkCancelled(task);
296            }
297      }      }
298    
299      /**      /**
300       * setting value gauses get to return it       * setting value causes get to return it
301       */       */
302      public void testSet() {      public void testSet() throws Exception {
303          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
304          task.set(one);          task.set(one);
305          try {          for (int i = 0; i < 3; i++) {
306              assertEquals(task.get(), one);              assertSame(one, task.get());
307          }              assertSame(one, task.get(LONG_DELAY_MS, MILLISECONDS));
308          catch(Exception e) {              assertEquals(1, task.setCount());
309              unexpectedException();          }
310          }          tryToConfuseDoneTask(task);
311            checkCompletedNormally(task, one);
312            assertEquals(0, task.runCount());
313      }      }
314    
315      /**      /**
316       * setException causes get to throw ExecutionException       * setException causes get to throw ExecutionException
317       */       */
318      public void testSetException() {      public void testSetException_get() throws Exception {
319          Exception nse = new NoSuchElementException();          Exception nse = new NoSuchElementException();
320          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
321          task.setException(nse);          task.setException(nse);
322    
323          try {          try {
324              Object x = task.get();              task.get();
325              shouldThrow();              shouldThrow();
326            } catch (ExecutionException success) {
327                assertSame(nse, success.getCause());
328                checkCompletedAbnormally(task, nse);
329          }          }
330          catch(ExecutionException ee) {  
331              Throwable cause = ee.getCause();          try {
332              assertEquals(cause, nse);              task.get(LONG_DELAY_MS, MILLISECONDS);
333          }              shouldThrow();
334          catch(Exception e) {          } catch (ExecutionException success) {
335              unexpectedException();              assertSame(nse, success.getCause());
336                checkCompletedAbnormally(task, nse);
337          }          }
338    
339            assertEquals(1, task.setExceptionCount());
340            assertEquals(0, task.setCount());
341            tryToConfuseDoneTask(task);
342            checkCompletedAbnormally(task, nse);
343            assertEquals(0, task.runCount());
344      }      }
345    
346      /**      /**
347       *  Cancelling before running succeeds       * cancel(false) before run succeeds
348       */       */
349      public void testCancelBeforeRun() {      public void testCancelBeforeRun() {
350          FutureTask task = new FutureTask( new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
351          assertTrue(task.cancel(false));          assertTrue(task.cancel(false));
352          task.run();          task.run();
353          assertTrue(task.isDone());          assertEquals(0, task.runCount());
354            assertEquals(0, task.setCount());
355            assertEquals(0, task.setExceptionCount());
356          assertTrue(task.isCancelled());          assertTrue(task.isCancelled());
357            assertTrue(task.isDone());
358            tryToConfuseDoneTask(task);
359            assertEquals(0, task.runCount());
360            checkCancelled(task);
361      }      }
362    
363      /**      /**
364       * Cancel(true) before run succeeds       * cancel(true) before run succeeds
365       */       */
366      public void testCancelBeforeRun2() {      public void testCancelBeforeRun2() {
367          FutureTask task = new FutureTask( new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
368          assertTrue(task.cancel(true));          assertTrue(task.cancel(true));
369          task.run();          task.run();
370          assertTrue(task.isDone());          assertEquals(0, task.runCount());
371            assertEquals(0, task.setCount());
372            assertEquals(0, task.setExceptionCount());
373          assertTrue(task.isCancelled());          assertTrue(task.isCancelled());
374            assertTrue(task.isDone());
375            tryToConfuseDoneTask(task);
376            assertEquals(0, task.runCount());
377            checkCancelled(task);
378      }      }
379    
380      /**      /**
381       * cancel of a completed task fails       * cancel(false) of a completed task fails
382       */       */
383      public void testCancelAfterRun() {      public void testCancelAfterRun() {
384          FutureTask task = new FutureTask( new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
385          task.run();          task.run();
386          assertFalse(task.cancel(false));          assertFalse(task.cancel(false));
387          assertTrue(task.isDone());          assertEquals(1, task.runCount());
388          assertFalse(task.isCancelled());          assertEquals(1, task.setCount());
389            assertEquals(0, task.setExceptionCount());
390            tryToConfuseDoneTask(task);
391            checkCompletedNormally(task, Boolean.TRUE);
392            assertEquals(1, task.runCount());
393      }      }
394    
395      /**      /**
396       * cancel(true) interrupts a running task       * cancel(true) of a completed task fails
397         */
398        public void testCancelAfterRun2() {
399            PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
400            task.run();
401            assertFalse(task.cancel(true));
402            assertEquals(1, task.runCount());
403            assertEquals(1, task.setCount());
404            assertEquals(0, task.setExceptionCount());
405            tryToConfuseDoneTask(task);
406            checkCompletedNormally(task, Boolean.TRUE);
407            assertEquals(1, task.runCount());
408        }
409    
410        /**
411         * cancel(true) interrupts a running task that subsequently succeeds
412       */       */
413      public void testCancelInterrupt() {      public void testCancelInterrupt() {
414          FutureTask task = new FutureTask( new Callable() {          final CountDownLatch pleaseCancel = new CountDownLatch(1);
415                  public Object call() {          final PublicFutureTask task =
416                new PublicFutureTask(new CheckedRunnable() {
417                    public void realRun() {
418                        pleaseCancel.countDown();
419                      try {                      try {
420                          Thread.sleep(MEDIUM_DELAY_MS);                          delay(LONG_DELAY_MS);
421                          threadShouldThrow();                          shouldThrow();
422                        } catch (InterruptedException success) {}
423                        assertFalse(Thread.interrupted());
424                    }});
425    
426            Thread t = newStartedThread(task);
427            await(pleaseCancel);
428            assertTrue(task.cancel(true));
429            assertTrue(task.isCancelled());
430            assertTrue(task.isDone());
431            awaitTermination(t);
432            assertEquals(1, task.runCount());
433            assertEquals(1, task.setCount());
434            assertEquals(0, task.setExceptionCount());
435            tryToConfuseDoneTask(task);
436            checkCancelled(task);
437                      }                      }
438                      catch (InterruptedException success) {}  
439                      return Boolean.TRUE;      /**
440         * cancel(true) tries to interrupt a running task, but
441         * Thread.interrupt throws (simulating a restrictive security
442         * manager)
443         */
444        public void testCancelInterrupt_ThrowsSecurityException() {
445            final CountDownLatch pleaseCancel = new CountDownLatch(1);
446            final CountDownLatch cancelled = new CountDownLatch(1);
447            final PublicFutureTask task =
448                new PublicFutureTask(new CheckedRunnable() {
449                    public void realRun() {
450                        pleaseCancel.countDown();
451                        await(cancelled);
452                        assertFalse(Thread.interrupted());
453                  } });                  } });
454          Thread t = new  Thread(task);  
455            final Thread t = new Thread(task) {
456                // Simulate a restrictive security manager.
457                @Override public void interrupt() {
458                    throw new SecurityException();
459                }};
460            t.setDaemon(true);
461          t.start();          t.start();
462    
463            await(pleaseCancel);
464          try {          try {
465              Thread.sleep(SHORT_DELAY_MS);              task.cancel(true);
466              assertTrue(task.cancel(true));              shouldThrow();
467              t.join();          } catch (SecurityException expected) {}
468              assertTrue(task.isDone());  
469            // We failed to deliver the interrupt, but the world retains
470            // its sanity, as if we had done task.cancel(false)
471              assertTrue(task.isCancelled());              assertTrue(task.isCancelled());
472          } catch(InterruptedException e){          assertTrue(task.isDone());
473              unexpectedException();          assertEquals(1, task.runCount());
474          }          assertEquals(1, task.doneCount());
475            assertEquals(0, task.setCount());
476            assertEquals(0, task.setExceptionCount());
477            cancelled.countDown();
478            awaitTermination(t);
479            assertEquals(1, task.setCount());
480            assertEquals(0, task.setExceptionCount());
481            tryToConfuseDoneTask(task);
482            checkCancelled(task);
483      }      }
484    
485        /**
486         * cancel(true) interrupts a running task that subsequently throws
487         */
488        public void testCancelInterrupt_taskFails() {
489            final CountDownLatch pleaseCancel = new CountDownLatch(1);
490            final PublicFutureTask task =
491                new PublicFutureTask(new Runnable() {
492                    public void run() {
493                        pleaseCancel.countDown();
494                        try {
495                            delay(LONG_DELAY_MS);
496                            threadShouldThrow();
497                        } catch (InterruptedException success) {
498                        } catch (Throwable t) { threadUnexpectedException(t); }
499                        throw new RuntimeException();
500                    }});
501    
502            Thread t = newStartedThread(task);
503            await(pleaseCancel);
504            assertTrue(task.cancel(true));
505            assertTrue(task.isCancelled());
506            awaitTermination(t);
507            assertEquals(1, task.runCount());
508            assertEquals(0, task.setCount());
509            assertEquals(1, task.setExceptionCount());
510            tryToConfuseDoneTask(task);
511            checkCancelled(task);
512        }
513    
514      /**      /**
515       * cancel(false) does not interrupt a running task       * cancel(false) does not interrupt a running task
516       */       */
517      public void testCancelNoInterrupt() {      public void testCancelNoInterrupt() {
518          FutureTask task = new FutureTask( new Callable() {          final CountDownLatch pleaseCancel = new CountDownLatch(1);
519                  public Object call() {          final CountDownLatch cancelled = new CountDownLatch(1);
520                      try {          final PublicFutureTask task =
521                          Thread.sleep(MEDIUM_DELAY_MS);              new PublicFutureTask(new CheckedCallable<Boolean>() {
522                      }                  public Boolean realCall() {
523                      catch (InterruptedException success) {                      pleaseCancel.countDown();
524                          threadFail("should not interrupt");                      await(cancelled);
525                      }                      assertFalse(Thread.interrupted());
526                      return Boolean.TRUE;                      return Boolean.TRUE;
527                  } });                  } });
         Thread t = new  Thread(task);  
         t.start();  
528    
529          try {          Thread t = newStartedThread(task);
530              Thread.sleep(SHORT_DELAY_MS);          await(pleaseCancel);
531              assertTrue(task.cancel(false));              assertTrue(task.cancel(false));
             t.join();  
             assertTrue(task.isDone());  
532              assertTrue(task.isCancelled());              assertTrue(task.isCancelled());
533          } catch(InterruptedException e){          cancelled.countDown();
534              unexpectedException();          awaitTermination(t);
535          }          assertEquals(1, task.runCount());
536            assertEquals(1, task.setCount());
537            assertEquals(0, task.setExceptionCount());
538            tryToConfuseDoneTask(task);
539            checkCancelled(task);
540      }      }
541    
542      /**      /**
543       * set in one thread causes get in another thread to retrieve value       * run in one thread causes get in another thread to retrieve value
544       */       */
545      public void testGet1() {      public void testGetRun() {
546          final FutureTask ft = new FutureTask(new Callable() {          final CountDownLatch pleaseRun = new CountDownLatch(2);
                 public Object call() {  
                     try {  
                         Thread.sleep(MEDIUM_DELAY_MS);  
                     } catch(InterruptedException e){  
                         threadUnexpectedException();  
                     }  
                     return Boolean.TRUE;  
                 }  
         });  
         Thread t = new Thread(new Runnable() {  
                 public void run() {  
                     try {  
                         ft.get();  
                     } catch(Exception e){  
                         threadUnexpectedException();  
                     }  
                 }  
             });  
         try {  
             assertFalse(ft.isDone());  
             assertFalse(ft.isCancelled());  
             t.start();  
             Thread.sleep(SHORT_DELAY_MS);  
             ft.run();  
             t.join();  
             assertTrue(ft.isDone());  
             assertFalse(ft.isCancelled());  
         } catch(InterruptedException e){  
             unexpectedException();  
547    
548          }          final PublicFutureTask task =
549                new PublicFutureTask(new CheckedCallable<Object>() {
550                    public Object realCall() {
551                        return two;
552                    }});
553    
554            Thread t1 = newStartedThread(new CheckedRunnable() {
555                public void realRun() throws Exception {
556                    pleaseRun.countDown();
557                    assertSame(two, task.get());
558                }});
559    
560            Thread t2 = newStartedThread(new CheckedRunnable() {
561                public void realRun() throws Exception {
562                    pleaseRun.countDown();
563                    assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS));
564                }});
565    
566            await(pleaseRun);
567            checkNotDone(task);
568            assertTrue(t1.isAlive());
569            assertTrue(t2.isAlive());
570            task.run();
571            checkCompletedNormally(task, two);
572            assertEquals(1, task.runCount());
573            assertEquals(1, task.setCount());
574            assertEquals(0, task.setExceptionCount());
575            awaitTermination(t1);
576            awaitTermination(t2);
577            tryToConfuseDoneTask(task);
578            checkCompletedNormally(task, two);
579      }      }
580    
581      /**      /**
582       * set in one thread causes timed get in another thread to retrieve value       * set in one thread causes get in another thread to retrieve value
583       */       */
584      public void testTimedGet1() {      public void testGetSet() {
585          final FutureTask ft = new FutureTask(new Callable() {          final CountDownLatch pleaseSet = new CountDownLatch(2);
                 public Object call() {  
                     try {  
                         Thread.sleep(MEDIUM_DELAY_MS);  
                     } catch(InterruptedException e){  
                         threadUnexpectedException();  
                     }  
                     return Boolean.TRUE;  
                 }  
             });  
         Thread t = new Thread(new Runnable() {  
                 public void run() {  
                     try {  
                         ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);  
                     } catch(TimeoutException success) {  
                     } catch(Exception e){  
                         threadUnexpectedException();  
                     }  
                 }  
             });  
         try {  
             assertFalse(ft.isDone());  
             assertFalse(ft.isCancelled());  
             t.start();  
             ft.run();  
             t.join();  
             assertTrue(ft.isDone());  
             assertFalse(ft.isCancelled());  
         } catch(InterruptedException e){  
             unexpectedException();  
586    
587          }          final PublicFutureTask task =
588                new PublicFutureTask(new CheckedCallable<Object>() {
589                    public Object realCall() throws InterruptedException {
590                        return two;
591                    }});
592    
593            Thread t1 = newStartedThread(new CheckedRunnable() {
594                public void realRun() throws Exception {
595                    pleaseSet.countDown();
596                    assertSame(two, task.get());
597                }});
598    
599            Thread t2 = newStartedThread(new CheckedRunnable() {
600                public void realRun() throws Exception {
601                    pleaseSet.countDown();
602                    assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS));
603                }});
604    
605            await(pleaseSet);
606            checkNotDone(task);
607            assertTrue(t1.isAlive());
608            assertTrue(t2.isAlive());
609            task.set(two);
610            assertEquals(0, task.runCount());
611            assertEquals(1, task.setCount());
612            assertEquals(0, task.setExceptionCount());
613            tryToConfuseDoneTask(task);
614            checkCompletedNormally(task, two);
615            awaitTermination(t1);
616            awaitTermination(t2);
617      }      }
618    
619      /**      /**
620       *  Cancelling a task causes timed get in another thread to throw CancellationException       * Cancelling a task causes timed get in another thread to throw
621         * CancellationException
622       */       */
623      public void testTimedGet_Cancellation() {      public void testTimedGet_Cancellation() {
624          final FutureTask ft = new FutureTask(new Callable() {          testTimedGet_Cancellation(false);
                 public Object call() {  
                     try {  
                         Thread.sleep(SMALL_DELAY_MS);  
                         threadShouldThrow();  
                     } catch(InterruptedException e) {  
625                      }                      }
626                      return Boolean.TRUE;      public void testTimedGet_Cancellation_interrupt() {
627            testTimedGet_Cancellation(true);
628                  }                  }
629              });      public void testTimedGet_Cancellation(final boolean mayInterruptIfRunning) {
630            final CountDownLatch pleaseCancel = new CountDownLatch(3);
631            final CountDownLatch cancelled = new CountDownLatch(1);
632            final Callable<Object> callable =
633                new CheckedCallable<Object>() {
634                public Object realCall() throws InterruptedException {
635                    pleaseCancel.countDown();
636                    if (mayInterruptIfRunning) {
637          try {          try {
638              Thread t1 = new Thread(new Runnable() {                          delay(2*LONG_DELAY_MS);
639                      public void run() {                      } catch (InterruptedException success) {}
640                          try {                  } else {
641                              ft.get(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);                      await(cancelled);
                             threadShouldThrow();  
                         } catch(CancellationException success) {}  
                         catch(Exception e){  
                             threadUnexpectedException();  
                         }  
642                      }                      }
643                  });                  return two;
644              Thread t2 = new Thread(ft);              }};
645            final PublicFutureTask task = new PublicFutureTask(callable);
646    
647            Thread t1 = new ThreadShouldThrow(CancellationException.class) {
648                    public void realRun() throws Exception {
649                        pleaseCancel.countDown();
650                        task.get();
651                    }};
652            Thread t2 = new ThreadShouldThrow(CancellationException.class) {
653                    public void realRun() throws Exception {
654                        pleaseCancel.countDown();
655                        task.get(2*LONG_DELAY_MS, MILLISECONDS);
656                    }};
657              t1.start();              t1.start();
658              t2.start();              t2.start();
659              Thread.sleep(SHORT_DELAY_MS);          Thread t3 = newStartedThread(task);
660              ft.cancel(true);          await(pleaseCancel);
661              t1.join();          checkIsRunning(task);
662              t2.join();          task.cancel(mayInterruptIfRunning);
663          } catch(InterruptedException ie){          checkCancelled(task);
664              unexpectedException();          awaitTermination(t1);
665          }          awaitTermination(t2);
666            cancelled.countDown();
667            awaitTermination(t3);
668            assertEquals(1, task.runCount());
669            assertEquals(1, task.setCount());
670            assertEquals(0, task.setExceptionCount());
671            tryToConfuseDoneTask(task);
672            checkCancelled(task);
673      }      }
674    
675      /**      /**
676       * Cancelling a task causes get in another thread to throw CancellationException       * A runtime exception in task causes get to throw ExecutionException
677       */       */
678      public void testGet_Cancellation() {      public void testGet_ExecutionException() throws InterruptedException {
679          final FutureTask ft = new FutureTask(new Callable() {          final ArithmeticException e = new ArithmeticException();
680            final PublicFutureTask task = new PublicFutureTask(new Callable() {
681                  public Object call() {                  public Object call() {
682                    throw e;
683                }});
684    
685            task.run();
686            assertEquals(1, task.runCount());
687            assertEquals(0, task.setCount());
688            assertEquals(1, task.setExceptionCount());
689                      try {                      try {
690                          Thread.sleep(MEDIUM_DELAY_MS);              task.get();
691                          threadShouldThrow();              shouldThrow();
692                      } catch(InterruptedException e){          } catch (ExecutionException success) {
693                      }              assertSame(e, success.getCause());
694                      return Boolean.TRUE;              tryToConfuseDoneTask(task);
695                  }              checkCompletedAbnormally(task, success.getCause());
             });  
         try {  
             Thread t1 = new Thread(new Runnable() {  
                     public void run() {  
                         try {  
                             ft.get();  
                             threadShouldThrow();  
                         } catch(CancellationException success){  
                         }  
                         catch(Exception e){  
                             threadUnexpectedException();  
                         }  
                     }  
                 });  
             Thread t2 = new Thread(ft);  
             t1.start();  
             t2.start();  
             Thread.sleep(SHORT_DELAY_MS);  
             ft.cancel(true);  
             t1.join();  
             t2.join();  
         } catch(InterruptedException success){  
             unexpectedException();  
696          }          }
697      }      }
698    
   
699      /**      /**
700       * A runtime exception in task causes get to throw ExecutionException       * A runtime exception in task causes timed get to throw ExecutionException
701       */       */
702      public void testGet_ExecutionException() {      public void testTimedGet_ExecutionException2() throws Exception {
703          final FutureTask ft = new FutureTask(new Callable() {          final ArithmeticException e = new ArithmeticException();
704            final PublicFutureTask task = new PublicFutureTask(new Callable() {
705                  public Object call() {                  public Object call() {
706                      int i = 5/0;                  throw e;
707                      return Boolean.TRUE;              }});
708                  }  
709              });          task.run();
710          try {          try {
711              ft.run();              task.get(LONG_DELAY_MS, MILLISECONDS);
             ft.get();  
712              shouldThrow();              shouldThrow();
713          } catch(ExecutionException success){          } catch(ExecutionException success){
714          }              assertSame(e, success.getCause());
715          catch(Exception e){              tryToConfuseDoneTask(task);
716              unexpectedException();              checkCompletedAbnormally(task, success.getCause());
717          }          }
718      }      }
719    
720      /**      /**
721       *  A runtime exception in task causes timed get to throw ExecutionException       * get is interruptible
722       */       */
723      public void testTimedGet_ExecutionException2() {      public void testGet_interruptible() {
724          final FutureTask ft = new FutureTask(new Callable() {          final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
725                  public Object call() {          final FutureTask task = new FutureTask(new NoOpCallable());
726                      int i = 5/0;          Thread t = newStartedThread(new CheckedRunnable() {
727                      return Boolean.TRUE;              public void realRun() throws Exception {
728                  }                  Thread.currentThread().interrupt();
             });  
729          try {          try {
730              ft.run();                      task.get();
             ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);  
731              shouldThrow();              shouldThrow();
732          } catch(ExecutionException success) {                  } catch (InterruptedException success) {}
733          } catch(TimeoutException success) { } // unlikely but OK                  assertFalse(Thread.interrupted());
         catch(Exception e){  
             unexpectedException();  
         }  
     }  
734    
735                    pleaseInterrupt.countDown();
736                    try {
737                        task.get();
738                        shouldThrow();
739                    } catch (InterruptedException success) {}
740                    assertFalse(Thread.interrupted());
741                }});
742    
743            await(pleaseInterrupt);
744            t.interrupt();
745            awaitTermination(t);
746            checkNotDone(task);
747        }
748    
749      /**      /**
750       * Interrupting a waiting get causes it to throw InterruptedException       * timed get is interruptible
751       */       */
752      public void testGet_InterruptedException() {      public void testTimedGet_interruptible() {
753          final FutureTask ft = new FutureTask(new NoOpCallable());          final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
754          Thread t = new Thread(new Runnable() {          final FutureTask task = new FutureTask(new NoOpCallable());
755                  public void run() {          Thread t = newStartedThread(new CheckedRunnable() {
756                public void realRun() throws Exception {
757                    Thread.currentThread().interrupt();
758                      try {                      try {
759                          ft.get();                      task.get(2*LONG_DELAY_MS, MILLISECONDS);
760                          threadShouldThrow();                      shouldThrow();
761                      } catch(InterruptedException success){                  } catch (InterruptedException success) {}
762                      } catch(Exception e){                  assertFalse(Thread.interrupted());
763                          threadUnexpectedException();  
764                      }                  pleaseInterrupt.countDown();
                 }  
             });  
765          try {          try {
766              t.start();                      task.get(2*LONG_DELAY_MS, MILLISECONDS);
767              Thread.sleep(SHORT_DELAY_MS);                      shouldThrow();
768                    } catch (InterruptedException success) {}
769                    assertFalse(Thread.interrupted());
770                }});
771    
772            await(pleaseInterrupt);
773              t.interrupt();              t.interrupt();
774              t.join();          awaitTermination(t);
775          } catch(Exception e){          checkNotDone(task);
             unexpectedException();  
         }  
776      }      }
777    
778      /**      /**
779       *  Interrupting a waiting timed get causes it to throw InterruptedException       * A timed out timed get throws TimeoutException
780       */       */
781      public void testTimedGet_InterruptedException2() {      public void testGet_TimeoutException() throws Exception {
782          final FutureTask ft = new FutureTask(new NoOpCallable());          FutureTask task = new FutureTask(new NoOpCallable());
783          Thread t = new Thread(new Runnable() {          long startTime = System.nanoTime();
                 public void run() {  
784                      try {                      try {
785                          ft.get(LONG_DELAY_MS,TimeUnit.MILLISECONDS);              task.get(timeoutMillis(), MILLISECONDS);
786                          threadShouldThrow();              shouldThrow();
787                      } catch(InterruptedException success){}          } catch (TimeoutException success) {
788                      catch(Exception e){              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
                         threadUnexpectedException();  
789                      }                      }
790                  }                  }
791              });  
792        /**
793         * timed get with null TimeUnit throws NullPointerException
794         */
795        public void testGet_NullTimeUnit() throws Exception {
796            FutureTask task = new FutureTask(new NoOpCallable());
797            long[] timeouts = { Long.MIN_VALUE, 0L, Long.MAX_VALUE };
798    
799            for (long timeout : timeouts) {
800          try {          try {
801              t.start();                  task.get(timeout, null);
802              Thread.sleep(SHORT_DELAY_MS);                  shouldThrow();
803              t.interrupt();              } catch (NullPointerException success) {}
804              t.join();          }
805          } catch(Exception e){  
806              unexpectedException();          task.run();
807    
808            for (long timeout : timeouts) {
809                try {
810                    task.get(timeout, null);
811                    shouldThrow();
812                } catch (NullPointerException success) {}
813          }          }
814      }      }
815    
816      /**      /**
817       * A timed out timed get throws TimeoutException       * timed get with most negative timeout works correctly (i.e. no
818         * underflow bug)
819       */       */
820      public void testGet_TimeoutException() {      public void testGet_NegativeInfinityTimeout() throws Exception {
821            final ExecutorService pool = Executors.newFixedThreadPool(10);
822            final Runnable nop = new Runnable() { public void run() {}};
823            final FutureTask<Void> task = new FutureTask<>(nop, null);
824            final List<Future<?>> futures = new ArrayList<>();
825            Runnable r = new Runnable() { public void run() {
826                for (long timeout : new long[] { 0L, -1L, Long.MIN_VALUE }) {
827          try {          try {
828              FutureTask ft = new FutureTask(new NoOpCallable());                      task.get(timeout, NANOSECONDS);
             ft.get(1,TimeUnit.MILLISECONDS);  
829              shouldThrow();              shouldThrow();
830          } catch(TimeoutException success){}                  } catch (TimeoutException success) {
831          catch(Exception success){                  } catch (Throwable fail) {threadUnexpectedException(fail);}}}};
832              unexpectedException();          for (int i = 0; i < 10; i++)
833                futures.add(pool.submit(r));
834            try {
835                joinPool(pool);
836                for (Future<?> future : futures)
837                    checkCompletedNormally(future, null);
838            } finally {
839                task.run();         // last resort to help terminate
840            }
841        }
842    
843        /**
844         * toString indicates current completion state
845         */
846        public void testToString_incomplete() {
847            FutureTask<String> f = new FutureTask<>(() -> "");
848            assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]"));
849            if (testImplementationDetails)
850                assertTrue(f.toString().startsWith(
851                                   identityString(f) + "[Not completed, task ="));
852        }
853    
854        public void testToString_normal() {
855            FutureTask<String> f = new FutureTask<>(() -> "");
856            f.run();
857            assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]"));
858            if (testImplementationDetails)
859                assertEquals(identityString(f) + "[Completed normally]",
860                             f.toString());
861        }
862    
863        public void testToString_exception() {
864            FutureTask<String> f = new FutureTask<>(
865                    () -> { throw new ArithmeticException(); });
866            f.run();
867            assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
868            if (testImplementationDetails)
869                assertTrue(f.toString().startsWith(
870                                   identityString(f) + "[Completed exceptionally: "));
871        }
872    
873        public void testToString_cancelled() {
874            for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
875                FutureTask<String> f = new FutureTask<>(() -> "");
876                assertTrue(f.cancel(mayInterruptIfRunning));
877                assertTrue(f.toString().matches(".*\\[.*Cancelled.*\\]"));
878                if (testImplementationDetails)
879                    assertEquals(identityString(f) + "[Cancelled]",
880                                 f.toString());
881          }          }
882      }      }
883    

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.52

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8