[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.22, Sun Nov 28 20:20:00 2010 UTC revision 1.52, Sun Jul 22 21:04:56 2018 UTC
# Line 1  Line 1 
1  /*  /*
2   * Written by Doug Lea with assistance from members of JCP JSR-166   * Written by Doug Lea with assistance from members of JCP JSR-166
3   * Expert Group and released to the public domain, as explained at   * Expert Group and released to the public domain, as explained at
4   * http://creativecommons.org/licenses/publicdomain   * http://creativecommons.org/publicdomain/zero/1.0/
5   * Other contributors include Andrew Wright, Jeffrey Hayes,   * Other contributors include Andrew Wright, Jeffrey Hayes,
6   * Pat Fisher, Mike Judd.   * Pat Fisher, Mike Judd.
7   */   */
8    
 import junit.framework.*;  
 import java.util.concurrent.*;  
9  import static java.util.concurrent.TimeUnit.MILLISECONDS;  import static java.util.concurrent.TimeUnit.MILLISECONDS;
10  import static java.util.concurrent.TimeUnit.SECONDS;  import static java.util.concurrent.TimeUnit.NANOSECONDS;
11  import java.util.*;  
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.Test;
27    import junit.framework.TestSuite;
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) {      void checkNotDone(Future<?> f) {
80          assertFalse(f.isDone());          assertFalse(f.isDone());
81          assertFalse(f.isCancelled());          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      <T> void checkCompletedNormally(Future<T> f, T expected) {      void checkIsRunning(Future<?> f) {
91          assertTrue(f.isDone());          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());          assertFalse(f.isCancelled());
110    
111            T v1 = null, v2 = null;
112          try {          try {
113              assertSame(expected, f.get());              v1 = f.get();
114          } catch (Throwable fail) { threadUnexpectedException(fail); }              v2 = f.get(randomTimeout(), randomTimeUnit());
         try {  
             assertSame(expected, f.get(5L, SECONDS));  
115          } catch (Throwable fail) { threadUnexpectedException(fail); }          } catch (Throwable fail) { threadUnexpectedException(fail); }
116            assertSame(expectedValue, v1);
117          assertFalse(f.cancel(false));          assertSame(expectedValue, v2);
         assertFalse(f.cancel(true));  
118      }      }
119    
120      void checkCancelled(Future<?> f) {      void checkCancelled(Future<?> f) {
121          assertTrue(f.isDone());          checkIsDone(f);
122          assertTrue(f.isCancelled());          assertTrue(f.isCancelled());
123    
124          try {          try {
# Line 52  Line 128 
128          } catch (Throwable fail) { threadUnexpectedException(fail); }          } catch (Throwable fail) { threadUnexpectedException(fail); }
129    
130          try {          try {
131              f.get(5L, SECONDS);              f.get(randomTimeout(), randomTimeUnit());
132              shouldThrow();              shouldThrow();
133          } catch (CancellationException success) {          } catch (CancellationException success) {
134          } catch (Throwable fail) { threadUnexpectedException(fail); }          } catch (Throwable fail) { threadUnexpectedException(fail); }
135        }
136    
137          assertFalse(f.cancel(false));      void tryToConfuseDoneTask(PublicFutureTask pf) {
138          assertFalse(f.cancel(true));          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) {      void checkCompletedAbnormally(Future<?> f, Throwable t) {
146          assertTrue(f.isDone());          checkIsDone(f);
147          assertFalse(f.isCancelled());          assertFalse(f.isCancelled());
148    
149          try {          try {
# Line 73  Line 154 
154          } catch (Throwable fail) { threadUnexpectedException(fail); }          } catch (Throwable fail) { threadUnexpectedException(fail); }
155    
156          try {          try {
157              f.get(5L, SECONDS);              f.get(randomTimeout(), randomTimeUnit());
158              shouldThrow();              shouldThrow();
159          } catch (ExecutionException success) {          } catch (ExecutionException success) {
160              assertSame(t, success.getCause());              assertSame(t, success.getCause());
161          } catch (Throwable fail) { threadUnexpectedException(fail); }          } catch (Throwable fail) { threadUnexpectedException(fail); }
   
         assertFalse(f.cancel(false));  
         assertFalse(f.cancel(true));  
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 runAndReset() { return super.runAndReset(); }          private final AtomicInteger doneCount = new AtomicInteger(0);
170          public void set(Object x) { super.set(x); }          private final AtomicInteger runAndResetCount = new AtomicInteger(0);
171          public void setException(Throwable t) { super.setException(t); }          private final AtomicInteger setCount = new AtomicInteger(0);
172            private final AtomicInteger setExceptionCount = new AtomicInteger(0);
173            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      }      }
# Line 117  Line 254 
254       * isDone is true when a task completes       * isDone is true when a task completes
255       */       */
256      public void testIsDone() {      public void testIsDone() {
257          FutureTask task = new FutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
258            assertFalse(task.isDone());
259          task.run();          task.run();
260          assertTrue(task.isDone());          assertTrue(task.isDone());
261          checkCompletedNormally(task, Boolean.TRUE);          checkCompletedNormally(task, Boolean.TRUE);
262            assertEquals(1, task.runCount());
263      }      }
264    
265      /**      /**
# Line 128  Line 267 
267       */       */
268      public void testRunAndReset() {      public void testRunAndReset() {
269          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
270            for (int i = 0; i < 3; i++) {
271          assertTrue(task.runAndReset());          assertTrue(task.runAndReset());
272          checkNotDone(task);          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       * runAndReset after cancellation fails       * runAndReset after cancellation fails
282       */       */
283      public void testResetAfterCancel() {      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                for (int i = 0; i < 3; i++) {
288          assertFalse(task.runAndReset());          assertFalse(task.runAndReset());
289                    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);          checkCancelled(task);
296      }      }
297        }
298    
299      /**      /**
300       * setting value causes get to return it       * setting value causes get to return it
# Line 149  Line 302 
302      public void testSet() throws Exception {      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          assertSame(task.get(), one);          for (int i = 0; i < 3; i++) {
306                assertSame(one, task.get());
307                assertSame(one, task.get(LONG_DELAY_MS, MILLISECONDS));
308                assertEquals(1, task.setCount());
309            }
310            tryToConfuseDoneTask(task);
311          checkCompletedNormally(task, one);          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() throws Exception {      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) {          } catch (ExecutionException success) {
327              assertSame(success.getCause(), nse);              assertSame(nse, success.getCause());
328              checkCompletedAbnormally(task, nse);              checkCompletedAbnormally(task, nse);
329          }          }
330    
331            try {
332                task.get(LONG_DELAY_MS, MILLISECONDS);
333                shouldThrow();
334            } catch (ExecutionException success) {
335                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            assertEquals(0, task.runCount());
354            assertEquals(0, task.setCount());
355            assertEquals(0, task.setExceptionCount());
356            assertTrue(task.isCancelled());
357            assertTrue(task.isDone());
358            tryToConfuseDoneTask(task);
359            assertEquals(0, task.runCount());
360          checkCancelled(task);          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            assertEquals(0, task.runCount());
371            assertEquals(0, task.setCount());
372            assertEquals(0, task.setExceptionCount());
373            assertTrue(task.isCancelled());
374            assertTrue(task.isDone());
375            tryToConfuseDoneTask(task);
376            assertEquals(0, task.runCount());
377          checkCancelled(task);          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            assertEquals(1, task.runCount());
388            assertEquals(1, task.setCount());
389            assertEquals(0, task.setExceptionCount());
390            tryToConfuseDoneTask(task);
391          checkCompletedNormally(task, Boolean.TRUE);          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 testCancelInterrupt() throws InterruptedException {      public void testCancelAfterRun2() {
399          final CountDownLatch threadStarted = new CountDownLatch(1);          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
400          final FutureTask task =          task.run();
401              new FutureTask(new CheckedCallable<Object>() {          assertFalse(task.cancel(true));
402                  public Object realCall() {          assertEquals(1, task.runCount());
403                      threadStarted.countDown();          assertEquals(1, task.setCount());
404                      long t0 = System.nanoTime();          assertEquals(0, task.setExceptionCount());
405                      for (;;) {          tryToConfuseDoneTask(task);
406                          if (Thread.interrupted())          checkCompletedNormally(task, Boolean.TRUE);
407                              return Boolean.TRUE;          assertEquals(1, task.runCount());
                         if (millisElapsedSince(t0) > MEDIUM_DELAY_MS)  
                             fail("interrupt not delivered");  
                         Thread.yield();  
408                      }                      }
409    
410        /**
411         * cancel(true) interrupts a running task that subsequently succeeds
412         */
413        public void testCancelInterrupt() {
414            final CountDownLatch pleaseCancel = new CountDownLatch(1);
415            final PublicFutureTask task =
416                new PublicFutureTask(new CheckedRunnable() {
417                    public void realRun() {
418                        pleaseCancel.countDown();
419                        try {
420                            delay(LONG_DELAY_MS);
421                            shouldThrow();
422                        } catch (InterruptedException success) {}
423                        assertFalse(Thread.interrupted());
424                  }});                  }});
425    
426          Thread t = newStartedThread(task);          Thread t = newStartedThread(task);
427          threadStarted.await();          await(pleaseCancel);
428          assertTrue(task.cancel(true));          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);          checkCancelled(task);
437          awaitTermination(t, MEDIUM_DELAY_MS);      }
438    
439        /**
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    
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();
462    
463            await(pleaseCancel);
464            try {
465                task.cancel(true);
466                shouldThrow();
467            } catch (SecurityException expected) {}
468    
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());
472            assertTrue(task.isDone());
473            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);          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() throws InterruptedException {      public void testCancelNoInterrupt() {
518          final CountDownLatch threadStarted = new CountDownLatch(1);          final CountDownLatch pleaseCancel = new CountDownLatch(1);
519          final CountDownLatch cancelled = new CountDownLatch(1);          final CountDownLatch cancelled = new CountDownLatch(1);
520          final FutureTask<Boolean> task =          final PublicFutureTask task =
521              new FutureTask<Boolean>(new CheckedCallable<Boolean>() {              new PublicFutureTask(new CheckedCallable<Boolean>() {
522                  public Boolean realCall() throws InterruptedException {                  public Boolean realCall() {
523                      threadStarted.countDown();                      pleaseCancel.countDown();
524                      cancelled.await(MEDIUM_DELAY_MS, MILLISECONDS);                      await(cancelled);
525                      assertFalse(Thread.interrupted());                      assertFalse(Thread.interrupted());
526                      return Boolean.TRUE;                      return Boolean.TRUE;
527                  }});                  }});
528    
529          Thread t = newStartedThread(task);          Thread t = newStartedThread(task);
530          threadStarted.await();          await(pleaseCancel);
531          assertTrue(task.cancel(false));          assertTrue(task.cancel(false));
532          checkCancelled(task);          assertTrue(task.isCancelled());
533          cancelled.countDown();          cancelled.countDown();
534          awaitTermination(t, MEDIUM_DELAY_MS);          awaitTermination(t);
535            assertEquals(1, task.runCount());
536            assertEquals(1, task.setCount());
537            assertEquals(0, task.setExceptionCount());
538            tryToConfuseDoneTask(task);
539          checkCancelled(task);          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() throws InterruptedException {      public void testGetRun() {
546          final FutureTask task =          final CountDownLatch pleaseRun = new CountDownLatch(2);
547              new FutureTask(new CheckedCallable<Object>() {  
548                  public Object realCall() throws InterruptedException {          final PublicFutureTask task =
549                      return Boolean.TRUE;              new PublicFutureTask(new CheckedCallable<Object>() {
550                    public Object realCall() {
551                        return two;
552                  }});                  }});
         checkNotDone(task);  
553    
554          Thread t = newStartedThread(new CheckedRunnable() {          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 {              public void realRun() throws Exception {
562                  assertSame(Boolean.TRUE, task.get());                  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();          task.run();
571          checkCompletedNormally(task, Boolean.TRUE);          checkCompletedNormally(task, two);
572          awaitTermination(t, MEDIUM_DELAY_MS);          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() throws InterruptedException {      public void testGetSet() {
585          final FutureTask task =          final CountDownLatch pleaseSet = new CountDownLatch(2);
586              new FutureTask(new CheckedCallable<Object>() {  
587            final PublicFutureTask task =
588                new PublicFutureTask(new CheckedCallable<Object>() {
589                  public Object realCall() throws InterruptedException {                  public Object realCall() throws InterruptedException {
590                      return Boolean.TRUE;                      return two;
591                  }});                  }});
         checkNotDone(task);  
592    
593          Thread t = newStartedThread(new CheckedRunnable() {          Thread t1 = newStartedThread(new CheckedRunnable() {
594              public void realRun() throws Exception {              public void realRun() throws Exception {
595                  assertSame(Boolean.TRUE, task.get(SMALL_DELAY_MS, MILLISECONDS));                  pleaseSet.countDown();
596                    assertSame(two, task.get());
597              }});              }});
598    
599          task.run();          Thread t2 = newStartedThread(new CheckedRunnable() {
600          checkCompletedNormally(task, Boolean.TRUE);              public void realRun() throws Exception {
601          awaitTermination(t, MEDIUM_DELAY_MS);                  pleaseSet.countDown();
602      }                  assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS));
   
     /**  
      * Cancelling a task causes timed get in another thread to throw  
      * CancellationException  
      */  
     public void testTimedGet_Cancellation() throws InterruptedException {  
         final CountDownLatch threadStarted = new CountDownLatch(2);  
         final FutureTask task =  
             new FutureTask(new CheckedInterruptedCallable<Object>() {  
                 public Object realCall() throws InterruptedException {  
                     threadStarted.countDown();  
                     Thread.sleep(LONG_DELAY_MS);  
                     return Boolean.TRUE;  
603                  }});                  }});
604    
605          Thread t1 = new ThreadShouldThrow(CancellationException.class) {          await(pleaseSet);
606              public void realRun() throws Exception {          checkNotDone(task);
607                  threadStarted.countDown();          assertTrue(t1.isAlive());
608                  task.get(MEDIUM_DELAY_MS, MILLISECONDS);          assertTrue(t2.isAlive());
609              }};          task.set(two);
610          Thread t2 = new Thread(task);          assertEquals(0, task.runCount());
611          t1.start();          assertEquals(1, task.setCount());
612          t2.start();          assertEquals(0, task.setExceptionCount());
613          threadStarted.await();          tryToConfuseDoneTask(task);
614          task.cancel(true);          checkCompletedNormally(task, two);
615          awaitTermination(t1, MEDIUM_DELAY_MS);          awaitTermination(t1);
616          awaitTermination(t2, MEDIUM_DELAY_MS);          awaitTermination(t2);
         checkCancelled(task);  
617      }      }
618    
619      /**      /**
620       * Cancelling a task causes get in another thread to throw       * Cancelling a task causes timed get in another thread to throw
621       * CancellationException       * CancellationException
622       */       */
623      public void testGet_Cancellation() throws InterruptedException {      public void testTimedGet_Cancellation() {
624          final CountDownLatch threadStarted = new CountDownLatch(2);          testTimedGet_Cancellation(false);
625          final FutureTask task =      }
626              new FutureTask(new CheckedInterruptedCallable<Object>() {      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 {                  public Object realCall() throws InterruptedException {
635                      threadStarted.countDown();                  pleaseCancel.countDown();
636                      Thread.sleep(LONG_DELAY_MS);                  if (mayInterruptIfRunning) {
637                      return Boolean.TRUE;                      try {
638                  }});                          delay(2*LONG_DELAY_MS);
639                        } catch (InterruptedException success) {}
640                    } else {
641                        await(cancelled);
642                    }
643                    return two;
644                }};
645            final PublicFutureTask task = new PublicFutureTask(callable);
646    
647          Thread t1 = new ThreadShouldThrow(CancellationException.class) {          Thread t1 = new ThreadShouldThrow(CancellationException.class) {
648              public void realRun() throws Exception {              public void realRun() throws Exception {
649                  threadStarted.countDown();                      pleaseCancel.countDown();
650                  task.get();                  task.get();
651              }};              }};
652          Thread t2 = new Thread(task);          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          threadStarted.await();          Thread t3 = newStartedThread(task);
660          task.cancel(true);          await(pleaseCancel);
661          awaitTermination(t1, MEDIUM_DELAY_MS);          checkIsRunning(task);
662          awaitTermination(t2, MEDIUM_DELAY_MS);          task.cancel(mayInterruptIfRunning);
663            checkCancelled(task);
664            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);          checkCancelled(task);
673      }      }
674    
   
675      /**      /**
676       * A runtime exception in task causes get to throw ExecutionException       * A runtime exception in task causes get to throw ExecutionException
677       */       */
678      public void testGet_ExecutionException() throws InterruptedException {      public void testGet_ExecutionException() throws InterruptedException {
679          final FutureTask task = 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                  return 5/0;                  throw e;
683              }});              }});
684    
685          task.run();          task.run();
686            assertEquals(1, task.runCount());
687            assertEquals(0, task.setCount());
688            assertEquals(1, task.setExceptionCount());
689          try {          try {
690              task.get();              task.get();
691              shouldThrow();              shouldThrow();
692          } catch (ExecutionException success) {          } catch (ExecutionException success) {
693              assertTrue(success.getCause() instanceof ArithmeticException);              assertSame(e, success.getCause());
694                tryToConfuseDoneTask(task);
695              checkCompletedAbnormally(task, success.getCause());              checkCompletedAbnormally(task, success.getCause());
696          }          }
697      }      }
# Line 374  Line 700 
700       * A runtime exception in task causes timed get to throw ExecutionException       * A runtime exception in task causes timed get to throw ExecutionException
701       */       */
702      public void testTimedGet_ExecutionException2() throws Exception {      public void testTimedGet_ExecutionException2() throws Exception {
703          final FutureTask task = 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                  return 5/0;                  throw e;
707              }});              }});
708    
709          task.run();          task.run();
710          try {          try {
711              task.get(SHORT_DELAY_MS, MILLISECONDS);              task.get(LONG_DELAY_MS, MILLISECONDS);
712              shouldThrow();              shouldThrow();
713          } catch (ExecutionException success) {          } catch (ExecutionException success) {
714              assertTrue(success.getCause() instanceof ArithmeticException);              assertSame(e, success.getCause());
715                tryToConfuseDoneTask(task);
716              checkCompletedAbnormally(task, success.getCause());              checkCompletedAbnormally(task, success.getCause());
717          }          }
718      }      }
719    
   
720      /**      /**
721       * Interrupting a waiting get causes it to throw InterruptedException       * get is interruptible
722       */       */
723      public void testGet_InterruptedException() throws InterruptedException {      public void testGet_interruptible() {
724          final CountDownLatch threadStarted = new CountDownLatch(1);          final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
725          final FutureTask task = new FutureTask(new NoOpCallable());          final FutureTask task = new FutureTask(new NoOpCallable());
726          Thread t = newStartedThread(new CheckedInterruptedRunnable() {          Thread t = newStartedThread(new CheckedRunnable() {
727              public void realRun() throws Exception {              public void realRun() throws Exception {
728                  threadStarted.countDown();                  Thread.currentThread().interrupt();
729                    try {
730                  task.get();                  task.get();
731                        shouldThrow();
732                    } catch (InterruptedException success) {}
733                    assertFalse(Thread.interrupted());
734    
735                    pleaseInterrupt.countDown();
736                    try {
737                        task.get();
738                        shouldThrow();
739                    } catch (InterruptedException success) {}
740                    assertFalse(Thread.interrupted());
741              }});              }});
742    
743          threadStarted.await();          await(pleaseInterrupt);
744          t.interrupt();          t.interrupt();
745          awaitTermination(t, MEDIUM_DELAY_MS);          awaitTermination(t);
746          checkNotDone(task);          checkNotDone(task);
747      }      }
748    
749      /**      /**
750       * Interrupting a waiting timed get causes it to throw InterruptedException       * timed get is interruptible
751       */       */
752      public void testTimedGet_InterruptedException2() throws InterruptedException {      public void testTimedGet_interruptible() {
753          final CountDownLatch threadStarted = new CountDownLatch(1);          final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
754          final FutureTask task = new FutureTask(new NoOpCallable());          final FutureTask task = new FutureTask(new NoOpCallable());
755          Thread t = newStartedThread(new CheckedInterruptedRunnable() {          Thread t = newStartedThread(new CheckedRunnable() {
756              public void realRun() throws Exception {              public void realRun() throws Exception {
757                  threadStarted.countDown();                  Thread.currentThread().interrupt();
758                  task.get(LONG_DELAY_MS, MILLISECONDS);                  try {
759                        task.get(2*LONG_DELAY_MS, MILLISECONDS);
760                        shouldThrow();
761                    } catch (InterruptedException success) {}
762                    assertFalse(Thread.interrupted());
763    
764                    pleaseInterrupt.countDown();
765                    try {
766                        task.get(2*LONG_DELAY_MS, MILLISECONDS);
767                        shouldThrow();
768                    } catch (InterruptedException success) {}
769                    assertFalse(Thread.interrupted());
770              }});              }});
771    
772          threadStarted.await();          await(pleaseInterrupt);
773          t.interrupt();          t.interrupt();
774          awaitTermination(t, MEDIUM_DELAY_MS);          awaitTermination(t);
775          checkNotDone(task);          checkNotDone(task);
776      }      }
777    
# Line 430  Line 779 
779       * A timed out timed get throws TimeoutException       * A timed out timed get throws TimeoutException
780       */       */
781      public void testGet_TimeoutException() throws Exception {      public void testGet_TimeoutException() throws Exception {
782            FutureTask task = new FutureTask(new NoOpCallable());
783            long startTime = System.nanoTime();
784          try {          try {
785                task.get(timeoutMillis(), MILLISECONDS);
786                shouldThrow();
787            } catch (TimeoutException success) {
788                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
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());              FutureTask task = new FutureTask(new NoOpCallable());
797              task.get(1, MILLISECONDS);          long[] timeouts = { Long.MIN_VALUE, 0L, Long.MAX_VALUE };
798    
799            for (long timeout : timeouts) {
800                try {
801                    task.get(timeout, null);
802                    shouldThrow();
803                } catch (NullPointerException success) {}
804            }
805    
806            task.run();
807    
808            for (long timeout : timeouts) {
809                try {
810                    task.get(timeout, null);
811              shouldThrow();              shouldThrow();
812          } catch (TimeoutException success) {}              } catch (NullPointerException success) {}
813            }
814        }
815    
816        /**
817         * timed get with most negative timeout works correctly (i.e. no
818         * underflow bug)
819         */
820        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 {
828                        task.get(timeout, NANOSECONDS);
829                        shouldThrow();
830                    } catch (TimeoutException success) {
831                    } catch (Throwable fail) {threadUnexpectedException(fail);}}}};
832            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    
884  }  }

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

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8