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

Legend:
Removed from v.1.28  
changed lines
  Added in v.1.45

Doug Lea
ViewVC Help
Powered by ViewVC 1.0.8