ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/FutureTaskTest.java
(Generate patch)

Comparing jsr166/src/test/tck/FutureTaskTest.java (file contents):
Revision 1.17 by jsr166, Sat Nov 21 10:25:05 2009 UTC vs.
Revision 1.27 by jsr166, Sat Jun 18 14:16:42 2011 UTC

# Line 1 | Line 1
1   /*
2   * Written by Doug Lea with assistance from members of JCP JSR-166
3   * Expert Group and released to the public domain, as explained at
4 < * http://creativecommons.org/licenses/publicdomain
4 > * http://creativecommons.org/publicdomain/zero/1.0/
5   * Other contributors include Andrew Wright, Jeffrey Hayes,
6   * Pat Fisher, Mike Judd.
7   */
8  
9   import junit.framework.*;
10 < import java.util.concurrent.*;
10 > import java.util.concurrent.Callable;
11 > import java.util.concurrent.CancellationException;
12 > import java.util.concurrent.CountDownLatch;
13 > import java.util.concurrent.ExecutionException;
14 > import java.util.concurrent.Future;
15 > import java.util.concurrent.FutureTask;
16 > import java.util.concurrent.TimeoutException;
17   import static java.util.concurrent.TimeUnit.MILLISECONDS;
18 + import static java.util.concurrent.TimeUnit.SECONDS;
19   import java.util.*;
20  
21   public class FutureTaskTest extends JSR166TestCase {
22  
23      public static void main(String[] args) {
24 <        junit.textui.TestRunner.run (suite());
24 >        junit.textui.TestRunner.run(suite());
25      }
26      public static Test suite() {
27          return new TestSuite(FutureTaskTest.class);
28      }
29  
30 +    void checkNotDone(Future<?> f) {
31 +        assertFalse(f.isDone());
32 +        assertFalse(f.isCancelled());
33 +    }
34 +
35 +    <T> void checkCompletedNormally(Future<T> f, T expected) {
36 +        assertTrue(f.isDone());
37 +        assertFalse(f.isCancelled());
38 +
39 +        try {
40 +            assertSame(expected, f.get());
41 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
42 +        try {
43 +            assertSame(expected, f.get(5L, SECONDS));
44 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
45 +
46 +        assertFalse(f.cancel(false));
47 +        assertFalse(f.cancel(true));
48 +    }
49 +
50 +    void checkCancelled(Future<?> f) {
51 +        assertTrue(f.isDone());
52 +        assertTrue(f.isCancelled());
53 +
54 +        try {
55 +            f.get();
56 +            shouldThrow();
57 +        } catch (CancellationException success) {
58 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
59 +
60 +        try {
61 +            f.get(5L, SECONDS);
62 +            shouldThrow();
63 +        } catch (CancellationException success) {
64 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
65 +
66 +        assertFalse(f.cancel(false));
67 +        assertFalse(f.cancel(true));
68 +    }
69 +
70 +    void checkCompletedAbnormally(Future<?> f, Throwable t) {
71 +        assertTrue(f.isDone());
72 +        assertFalse(f.isCancelled());
73 +
74 +        try {
75 +            f.get();
76 +            shouldThrow();
77 +        } catch (ExecutionException success) {
78 +            assertSame(t, success.getCause());
79 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
80 +
81 +        try {
82 +            f.get(5L, SECONDS);
83 +            shouldThrow();
84 +        } catch (ExecutionException success) {
85 +            assertSame(t, success.getCause());
86 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
87 +
88 +        assertFalse(f.cancel(false));
89 +        assertFalse(f.cancel(true));
90 +    }
91 +
92      /**
93       * Subclass to expose protected methods
94       */
# Line 57 | Line 126 | public class FutureTaskTest extends JSR1
126          FutureTask task = new FutureTask(new NoOpCallable());
127          task.run();
128          assertTrue(task.isDone());
129 <        assertFalse(task.isCancelled());
129 >        checkCompletedNormally(task, Boolean.TRUE);
130      }
131  
132      /**
# Line 66 | Line 135 | public class FutureTaskTest extends JSR1
135      public void testRunAndReset() {
136          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
137          assertTrue(task.runAndReset());
138 <        assertFalse(task.isDone());
138 >        checkNotDone(task);
139      }
140  
141      /**
# Line 76 | Line 145 | public class FutureTaskTest extends JSR1
145          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
146          assertTrue(task.cancel(false));
147          assertFalse(task.runAndReset());
148 <        assertTrue(task.isDone());
80 <        assertTrue(task.isCancelled());
148 >        checkCancelled(task);
149      }
150  
83
84
151      /**
152       * setting value causes get to return it
153       */
154      public void testSet() throws Exception {
155          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
156          task.set(one);
157 <        assertEquals(task.get(), one);
157 >        assertSame(task.get(), one);
158 >        checkCompletedNormally(task, one);
159      }
160  
161      /**
# Line 103 | Line 170 | public class FutureTaskTest extends JSR1
170              shouldThrow();
171          } catch (ExecutionException success) {
172              assertSame(success.getCause(), nse);
173 +            checkCompletedAbnormally(task, nse);
174          }
175      }
176  
177      /**
178 <     *  Cancelling before running succeeds
178 >     * Cancelling before running succeeds
179       */
180      public void testCancelBeforeRun() {
181          FutureTask task = new FutureTask(new NoOpCallable());
182          assertTrue(task.cancel(false));
183          task.run();
184 <        assertTrue(task.isDone());
117 <        assertTrue(task.isCancelled());
184 >        checkCancelled(task);
185      }
186  
187      /**
# Line 124 | Line 191 | public class FutureTaskTest extends JSR1
191          FutureTask task = new FutureTask(new NoOpCallable());
192          assertTrue(task.cancel(true));
193          task.run();
194 <        assertTrue(task.isDone());
128 <        assertTrue(task.isCancelled());
194 >        checkCancelled(task);
195      }
196  
197      /**
# Line 135 | Line 201 | public class FutureTaskTest extends JSR1
201          FutureTask task = new FutureTask(new NoOpCallable());
202          task.run();
203          assertFalse(task.cancel(false));
204 <        assertTrue(task.isDone());
139 <        assertFalse(task.isCancelled());
204 >        checkCompletedNormally(task, Boolean.TRUE);
205      }
206  
207      /**
208       * cancel(true) interrupts a running task
209       */
210      public void testCancelInterrupt() throws InterruptedException {
211 +        final CountDownLatch threadStarted = new CountDownLatch(1);
212          final FutureTask task =
213 <            new FutureTask(new CheckedInterruptedCallable<Object>() {
214 <                public Object realCall() throws InterruptedException {
215 <                    Thread.sleep(SMALL_DELAY_MS);
216 <                    return Boolean.TRUE;
213 >            new FutureTask(new CheckedCallable<Object>() {
214 >                public Object realCall() {
215 >                    threadStarted.countDown();
216 >                    long t0 = System.nanoTime();
217 >                    for (;;) {
218 >                        if (Thread.interrupted())
219 >                            return Boolean.TRUE;
220 >                        if (millisElapsedSince(t0) > MEDIUM_DELAY_MS)
221 >                            fail("interrupt not delivered");
222 >                        Thread.yield();
223 >                    }
224                  }});
225  
226 <        Thread t = new Thread(task);
227 <        t.start();
155 <        Thread.sleep(SHORT_DELAY_MS);
226 >        Thread t = newStartedThread(task);
227 >        threadStarted.await();
228          assertTrue(task.cancel(true));
229 <        t.join();
230 <        assertTrue(task.isDone());
231 <        assertTrue(task.isCancelled());
229 >        checkCancelled(task);
230 >        awaitTermination(t, MEDIUM_DELAY_MS);
231 >        checkCancelled(task);
232      }
233  
162
234      /**
235       * cancel(false) does not interrupt a running task
236       */
237      public void testCancelNoInterrupt() throws InterruptedException {
238 +        final CountDownLatch threadStarted = new CountDownLatch(1);
239 +        final CountDownLatch cancelled = new CountDownLatch(1);
240 +        final FutureTask<Boolean> task =
241 +            new FutureTask<Boolean>(new CheckedCallable<Boolean>() {
242 +                public Boolean realCall() throws InterruptedException {
243 +                    threadStarted.countDown();
244 +                    cancelled.await(MEDIUM_DELAY_MS, MILLISECONDS);
245 +                    assertFalse(Thread.interrupted());
246 +                    return Boolean.TRUE;
247 +                }});
248 +
249 +        Thread t = newStartedThread(task);
250 +        threadStarted.await();
251 +        assertTrue(task.cancel(false));
252 +        checkCancelled(task);
253 +        cancelled.countDown();
254 +        awaitTermination(t, MEDIUM_DELAY_MS);
255 +        checkCancelled(task);
256 +    }
257 +
258 +    /**
259 +     * run in one thread causes get in another thread to retrieve value
260 +     */
261 +    public void testGetRun() throws InterruptedException {
262 +        final CountDownLatch threadStarted = new CountDownLatch(1);
263 +
264          final FutureTask task =
265              new FutureTask(new CheckedCallable<Object>() {
266                  public Object realCall() throws InterruptedException {
170                    Thread.sleep(MEDIUM_DELAY_MS);
267                      return Boolean.TRUE;
268                  }});
269  
270 <        Thread t = new Thread(task);
271 <        t.start();
272 <        Thread.sleep(SHORT_DELAY_MS);
273 <        assertTrue(task.cancel(false));
274 <        t.join();
275 <        assertTrue(task.isDone());
276 <        assertTrue(task.isCancelled());
270 >        Thread t = newStartedThread(new CheckedRunnable() {
271 >            public void realRun() throws Exception {
272 >                threadStarted.countDown();
273 >                assertSame(Boolean.TRUE, task.get());
274 >            }});
275 >
276 >        threadStarted.await();
277 >        checkNotDone(task);
278 >        assertTrue(t.isAlive());
279 >        task.run();
280 >        checkCompletedNormally(task, Boolean.TRUE);
281 >        awaitTermination(t, MEDIUM_DELAY_MS);
282      }
283  
284      /**
285       * set in one thread causes get in another thread to retrieve value
286       */
287 <    public void testGet1() throws InterruptedException {
288 <        final FutureTask ft =
287 >    public void testGetSet() throws InterruptedException {
288 >        final CountDownLatch threadStarted = new CountDownLatch(1);
289 >
290 >        final PublicFutureTask task =
291 >            new PublicFutureTask(new CheckedCallable<Object>() {
292 >                public Object realCall() throws InterruptedException {
293 >                    return Boolean.TRUE;
294 >                }});
295 >
296 >        Thread t = newStartedThread(new CheckedRunnable() {
297 >            public void realRun() throws Exception {
298 >                threadStarted.countDown();
299 >                assertSame(Boolean.FALSE, task.get());
300 >            }});
301 >
302 >        threadStarted.await();
303 >        checkNotDone(task);
304 >        assertTrue(t.isAlive());
305 >        task.set(Boolean.FALSE);
306 >        checkCompletedNormally(task, Boolean.FALSE);
307 >        awaitTermination(t, MEDIUM_DELAY_MS);
308 >    }
309 >
310 >    /**
311 >     * run in one thread causes timed get in another thread to retrieve value
312 >     */
313 >    public void testTimedGetRun() throws InterruptedException {
314 >        final CountDownLatch threadStarted = new CountDownLatch(1);
315 >
316 >        final FutureTask task =
317              new FutureTask(new CheckedCallable<Object>() {
318                  public Object realCall() throws InterruptedException {
319                      return Boolean.TRUE;
320                  }});
321 <        Thread t = new Thread(new CheckedRunnable() {
321 >
322 >        Thread t = newStartedThread(new CheckedRunnable() {
323              public void realRun() throws Exception {
324 <                assertSame(Boolean.TRUE, ft.get());
324 >                threadStarted.countDown();
325 >                assertSame(Boolean.TRUE,
326 >                           task.get(MEDIUM_DELAY_MS, MILLISECONDS));
327              }});
328  
329 <        assertFalse(ft.isDone());
330 <        assertFalse(ft.isCancelled());
331 <        t.start();
332 <        Thread.sleep(SHORT_DELAY_MS);
333 <        ft.run();
334 <        t.join();
203 <        assertTrue(ft.isDone());
204 <        assertFalse(ft.isCancelled());
329 >        threadStarted.await();
330 >        checkNotDone(task);
331 >        assertTrue(t.isAlive());
332 >        task.run();
333 >        checkCompletedNormally(task, Boolean.TRUE);
334 >        awaitTermination(t, MEDIUM_DELAY_MS);
335      }
336  
337      /**
338       * set in one thread causes timed get in another thread to retrieve value
339       */
340 <    public void testTimedGet1() throws InterruptedException {
341 <        final FutureTask ft =
342 <            new FutureTask(new CheckedCallable<Object>() {
340 >    public void testTimedGetSet() throws InterruptedException {
341 >        final CountDownLatch threadStarted = new CountDownLatch(1);
342 >
343 >        final PublicFutureTask task =
344 >            new PublicFutureTask(new CheckedCallable<Object>() {
345                  public Object realCall() throws InterruptedException {
346                      return Boolean.TRUE;
347                  }});
348 <        Thread t = new Thread(new CheckedRunnable() {
348 >
349 >        Thread t = newStartedThread(new CheckedRunnable() {
350              public void realRun() throws Exception {
351 <                assertSame(Boolean.TRUE, ft.get(SMALL_DELAY_MS, MILLISECONDS));
351 >                threadStarted.countDown();
352 >                assertSame(Boolean.FALSE,
353 >                           task.get(MEDIUM_DELAY_MS, MILLISECONDS));
354              }});
355  
356 <        assertFalse(ft.isDone());
357 <        assertFalse(ft.isCancelled());
358 <        t.start();
359 <        Thread.sleep(SHORT_DELAY_MS);
360 <        ft.run();
361 <        t.join();
227 <        assertTrue(ft.isDone());
228 <        assertFalse(ft.isCancelled());
356 >        threadStarted.await();
357 >        checkNotDone(task);
358 >        assertTrue(t.isAlive());
359 >        task.set(Boolean.FALSE);
360 >        checkCompletedNormally(task, Boolean.FALSE);
361 >        awaitTermination(t, MEDIUM_DELAY_MS);
362      }
363  
364      /**
365 <     *  Cancelling a task causes timed get in another thread to throw CancellationException
365 >     * Cancelling a task causes timed get in another thread to throw
366 >     * CancellationException
367       */
368      public void testTimedGet_Cancellation() throws InterruptedException {
369 <        final FutureTask ft =
369 >        final CountDownLatch threadStarted = new CountDownLatch(2);
370 >        final FutureTask task =
371              new FutureTask(new CheckedInterruptedCallable<Object>() {
372                  public Object realCall() throws InterruptedException {
373 <                    Thread.sleep(SMALL_DELAY_MS);
373 >                    threadStarted.countDown();
374 >                    delay(LONG_DELAY_MS);
375                      return Boolean.TRUE;
376                  }});
377  
378          Thread t1 = new ThreadShouldThrow(CancellationException.class) {
379              public void realRun() throws Exception {
380 <                ft.get(MEDIUM_DELAY_MS, MILLISECONDS);
380 >                threadStarted.countDown();
381 >                task.get(MEDIUM_DELAY_MS, MILLISECONDS);
382              }};
383 <        Thread t2 = new Thread(ft);
383 >        Thread t2 = new Thread(task);
384          t1.start();
385          t2.start();
386 <        Thread.sleep(SHORT_DELAY_MS);
387 <        ft.cancel(true);
388 <        t1.join();
389 <        t2.join();
386 >        threadStarted.await();
387 >        task.cancel(true);
388 >        awaitTermination(t1, MEDIUM_DELAY_MS);
389 >        awaitTermination(t2, MEDIUM_DELAY_MS);
390 >        checkCancelled(task);
391      }
392  
393      /**
394 <     * Cancelling a task causes get in another thread to throw CancellationException
394 >     * Cancelling a task causes get in another thread to throw
395 >     * CancellationException
396       */
397      public void testGet_Cancellation() throws InterruptedException {
398 <        final FutureTask ft =
398 >        final CountDownLatch threadStarted = new CountDownLatch(2);
399 >        final FutureTask task =
400              new FutureTask(new CheckedInterruptedCallable<Object>() {
401                  public Object realCall() throws InterruptedException {
402 <                    Thread.sleep(SMALL_DELAY_MS);
402 >                    threadStarted.countDown();
403 >                    delay(LONG_DELAY_MS);
404                      return Boolean.TRUE;
405                  }});
406 +
407          Thread t1 = new ThreadShouldThrow(CancellationException.class) {
408              public void realRun() throws Exception {
409 <                ft.get();
409 >                threadStarted.countDown();
410 >                task.get();
411              }};
412 <
270 <        Thread t2 = new Thread(ft);
412 >        Thread t2 = new Thread(task);
413          t1.start();
414          t2.start();
415 <        Thread.sleep(SHORT_DELAY_MS);
416 <        ft.cancel(true);
417 <        t1.join();
418 <        t2.join();
415 >        threadStarted.await();
416 >        task.cancel(true);
417 >        awaitTermination(t1, MEDIUM_DELAY_MS);
418 >        awaitTermination(t2, MEDIUM_DELAY_MS);
419 >        checkCancelled(task);
420      }
421  
279
422      /**
423       * A runtime exception in task causes get to throw ExecutionException
424       */
425      public void testGet_ExecutionException() throws InterruptedException {
426 <        final FutureTask ft = new FutureTask(new Callable() {
426 >        final FutureTask task = new FutureTask(new Callable() {
427              public Object call() {
428                  return 5/0;
429              }});
430  
431 <        ft.run();
431 >        task.run();
432          try {
433 <            ft.get();
433 >            task.get();
434              shouldThrow();
435          } catch (ExecutionException success) {
436              assertTrue(success.getCause() instanceof ArithmeticException);
437 +            checkCompletedAbnormally(task, success.getCause());
438          }
439      }
440  
441      /**
442 <     *  A runtime exception in task causes timed get to throw ExecutionException
442 >     * A runtime exception in task causes timed get to throw ExecutionException
443       */
444      public void testTimedGet_ExecutionException2() throws Exception {
445 <        final FutureTask ft = new FutureTask(new Callable() {
445 >        final FutureTask task = new FutureTask(new Callable() {
446              public Object call() {
447                  return 5/0;
448              }});
449  
450 <        ft.run();
450 >        task.run();
451          try {
452 <            ft.get(SHORT_DELAY_MS, MILLISECONDS);
452 >            task.get(SHORT_DELAY_MS, MILLISECONDS);
453              shouldThrow();
454          } catch (ExecutionException success) {
455              assertTrue(success.getCause() instanceof ArithmeticException);
456 +            checkCompletedAbnormally(task, success.getCause());
457          }
458      }
459  
316
460      /**
461       * Interrupting a waiting get causes it to throw InterruptedException
462       */
463      public void testGet_InterruptedException() throws InterruptedException {
464 <        final FutureTask ft = new FutureTask(new NoOpCallable());
465 <        Thread t = new Thread(new CheckedInterruptedRunnable() {
464 >        final CountDownLatch threadStarted = new CountDownLatch(1);
465 >        final FutureTask task = new FutureTask(new NoOpCallable());
466 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
467              public void realRun() throws Exception {
468 <                ft.get();
468 >                threadStarted.countDown();
469 >                task.get();
470              }});
471  
472 <        t.start();
328 <        Thread.sleep(SHORT_DELAY_MS);
472 >        threadStarted.await();
473          t.interrupt();
474 <        t.join();
474 >        awaitTermination(t, MEDIUM_DELAY_MS);
475 >        checkNotDone(task);
476      }
477  
478      /**
479 <     *  Interrupting a waiting timed get causes it to throw InterruptedException
479 >     * Interrupting a waiting timed get causes it to throw InterruptedException
480       */
481      public void testTimedGet_InterruptedException2() throws InterruptedException {
482 <        final FutureTask ft = new FutureTask(new NoOpCallable());
483 <        Thread t = new Thread(new CheckedInterruptedRunnable() {
482 >        final CountDownLatch threadStarted = new CountDownLatch(1);
483 >        final FutureTask task = new FutureTask(new NoOpCallable());
484 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
485              public void realRun() throws Exception {
486 <                ft.get(LONG_DELAY_MS,MILLISECONDS);
486 >                threadStarted.countDown();
487 >                task.get(LONG_DELAY_MS, MILLISECONDS);
488              }});
489  
490 <        t.start();
344 <        Thread.sleep(SHORT_DELAY_MS);
490 >        threadStarted.await();
491          t.interrupt();
492 <        t.join();
492 >        awaitTermination(t, MEDIUM_DELAY_MS);
493 >        checkNotDone(task);
494      }
495  
496      /**
# Line 351 | Line 498 | public class FutureTaskTest extends JSR1
498       */
499      public void testGet_TimeoutException() throws Exception {
500          try {
501 <            FutureTask ft = new FutureTask(new NoOpCallable());
502 <            ft.get(1,MILLISECONDS);
501 >            FutureTask task = new FutureTask(new NoOpCallable());
502 >            task.get(1, MILLISECONDS);
503              shouldThrow();
504          } catch (TimeoutException success) {}
505      }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines