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.26 by jsr166, Tue May 31 16:16:23 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  
151  
84
152      /**
153       * setting value causes get to return it
154       */
155      public void testSet() throws Exception {
156          PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
157          task.set(one);
158 <        assertEquals(task.get(), one);
158 >        assertSame(task.get(), one);
159 >        checkCompletedNormally(task, one);
160      }
161  
162      /**
# Line 103 | Line 171 | public class FutureTaskTest extends JSR1
171              shouldThrow();
172          } catch (ExecutionException success) {
173              assertSame(success.getCause(), nse);
174 +            checkCompletedAbnormally(task, nse);
175          }
176      }
177  
178      /**
179 <     *  Cancelling before running succeeds
179 >     * Cancelling before running succeeds
180       */
181      public void testCancelBeforeRun() {
182          FutureTask task = new FutureTask(new NoOpCallable());
183          assertTrue(task.cancel(false));
184          task.run();
185 <        assertTrue(task.isDone());
117 <        assertTrue(task.isCancelled());
185 >        checkCancelled(task);
186      }
187  
188      /**
# Line 124 | Line 192 | public class FutureTaskTest extends JSR1
192          FutureTask task = new FutureTask(new NoOpCallable());
193          assertTrue(task.cancel(true));
194          task.run();
195 <        assertTrue(task.isDone());
128 <        assertTrue(task.isCancelled());
195 >        checkCancelled(task);
196      }
197  
198      /**
# Line 135 | Line 202 | public class FutureTaskTest extends JSR1
202          FutureTask task = new FutureTask(new NoOpCallable());
203          task.run();
204          assertFalse(task.cancel(false));
205 <        assertTrue(task.isDone());
139 <        assertFalse(task.isCancelled());
205 >        checkCompletedNormally(task, Boolean.TRUE);
206      }
207  
208      /**
209       * cancel(true) interrupts a running task
210       */
211      public void testCancelInterrupt() throws InterruptedException {
212 +        final CountDownLatch threadStarted = new CountDownLatch(1);
213          final FutureTask task =
214 <            new FutureTask(new CheckedInterruptedCallable<Object>() {
215 <                public Object realCall() throws InterruptedException {
216 <                    Thread.sleep(SMALL_DELAY_MS);
217 <                    return Boolean.TRUE;
214 >            new FutureTask(new CheckedCallable<Object>() {
215 >                public Object realCall() {
216 >                    threadStarted.countDown();
217 >                    long t0 = System.nanoTime();
218 >                    for (;;) {
219 >                        if (Thread.interrupted())
220 >                            return Boolean.TRUE;
221 >                        if (millisElapsedSince(t0) > MEDIUM_DELAY_MS)
222 >                            fail("interrupt not delivered");
223 >                        Thread.yield();
224 >                    }
225                  }});
226  
227 <        Thread t = new Thread(task);
228 <        t.start();
155 <        Thread.sleep(SHORT_DELAY_MS);
227 >        Thread t = newStartedThread(task);
228 >        threadStarted.await();
229          assertTrue(task.cancel(true));
230 <        t.join();
231 <        assertTrue(task.isDone());
232 <        assertTrue(task.isCancelled());
230 >        checkCancelled(task);
231 >        awaitTermination(t, MEDIUM_DELAY_MS);
232 >        checkCancelled(task);
233      }
234  
162
235      /**
236       * cancel(false) does not interrupt a running task
237       */
238      public void testCancelNoInterrupt() throws InterruptedException {
239 +        final CountDownLatch threadStarted = new CountDownLatch(1);
240 +        final CountDownLatch cancelled = new CountDownLatch(1);
241 +        final FutureTask<Boolean> task =
242 +            new FutureTask<Boolean>(new CheckedCallable<Boolean>() {
243 +                public Boolean realCall() throws InterruptedException {
244 +                    threadStarted.countDown();
245 +                    cancelled.await(MEDIUM_DELAY_MS, MILLISECONDS);
246 +                    assertFalse(Thread.interrupted());
247 +                    return Boolean.TRUE;
248 +                }});
249 +
250 +        Thread t = newStartedThread(task);
251 +        threadStarted.await();
252 +        assertTrue(task.cancel(false));
253 +        checkCancelled(task);
254 +        cancelled.countDown();
255 +        awaitTermination(t, MEDIUM_DELAY_MS);
256 +        checkCancelled(task);
257 +    }
258 +
259 +    /**
260 +     * run in one thread causes get in another thread to retrieve value
261 +     */
262 +    public void testGetRun() throws InterruptedException {
263 +        final CountDownLatch threadStarted = new CountDownLatch(1);
264 +
265          final FutureTask task =
266              new FutureTask(new CheckedCallable<Object>() {
267                  public Object realCall() throws InterruptedException {
170                    Thread.sleep(MEDIUM_DELAY_MS);
268                      return Boolean.TRUE;
269                  }});
270  
271 <        Thread t = new Thread(task);
272 <        t.start();
273 <        Thread.sleep(SHORT_DELAY_MS);
274 <        assertTrue(task.cancel(false));
275 <        t.join();
276 <        assertTrue(task.isDone());
277 <        assertTrue(task.isCancelled());
271 >        Thread t = newStartedThread(new CheckedRunnable() {
272 >            public void realRun() throws Exception {
273 >                threadStarted.countDown();
274 >                assertSame(Boolean.TRUE, task.get());
275 >            }});
276 >
277 >        threadStarted.await();
278 >        checkNotDone(task);
279 >        assertTrue(t.isAlive());
280 >        task.run();
281 >        checkCompletedNormally(task, Boolean.TRUE);
282 >        awaitTermination(t, MEDIUM_DELAY_MS);
283      }
284  
285      /**
286       * set in one thread causes get in another thread to retrieve value
287       */
288 <    public void testGet1() throws InterruptedException {
289 <        final FutureTask ft =
288 >    public void testGetSet() throws InterruptedException {
289 >        final CountDownLatch threadStarted = new CountDownLatch(1);
290 >
291 >        final PublicFutureTask task =
292 >            new PublicFutureTask(new CheckedCallable<Object>() {
293 >                public Object realCall() throws InterruptedException {
294 >                    return Boolean.TRUE;
295 >                }});
296 >
297 >        Thread t = newStartedThread(new CheckedRunnable() {
298 >            public void realRun() throws Exception {
299 >                threadStarted.countDown();
300 >                assertSame(Boolean.FALSE, task.get());
301 >            }});
302 >
303 >        threadStarted.await();
304 >        checkNotDone(task);
305 >        assertTrue(t.isAlive());
306 >        task.set(Boolean.FALSE);
307 >        checkCompletedNormally(task, Boolean.FALSE);
308 >        awaitTermination(t, MEDIUM_DELAY_MS);
309 >    }
310 >
311 >    /**
312 >     * run in one thread causes timed get in another thread to retrieve value
313 >     */
314 >    public void testTimedGetRun() throws InterruptedException {
315 >        final CountDownLatch threadStarted = new CountDownLatch(1);
316 >
317 >        final FutureTask task =
318              new FutureTask(new CheckedCallable<Object>() {
319                  public Object realCall() throws InterruptedException {
320                      return Boolean.TRUE;
321                  }});
322 <        Thread t = new Thread(new CheckedRunnable() {
322 >
323 >        Thread t = newStartedThread(new CheckedRunnable() {
324              public void realRun() throws Exception {
325 <                assertSame(Boolean.TRUE, ft.get());
325 >                threadStarted.countDown();
326 >                assertSame(Boolean.TRUE,
327 >                           task.get(MEDIUM_DELAY_MS, MILLISECONDS));
328              }});
329  
330 <        assertFalse(ft.isDone());
331 <        assertFalse(ft.isCancelled());
332 <        t.start();
333 <        Thread.sleep(SHORT_DELAY_MS);
334 <        ft.run();
335 <        t.join();
203 <        assertTrue(ft.isDone());
204 <        assertFalse(ft.isCancelled());
330 >        threadStarted.await();
331 >        checkNotDone(task);
332 >        assertTrue(t.isAlive());
333 >        task.run();
334 >        checkCompletedNormally(task, Boolean.TRUE);
335 >        awaitTermination(t, MEDIUM_DELAY_MS);
336      }
337  
338      /**
339       * set in one thread causes timed get in another thread to retrieve value
340       */
341 <    public void testTimedGet1() throws InterruptedException {
342 <        final FutureTask ft =
343 <            new FutureTask(new CheckedCallable<Object>() {
341 >    public void testTimedGetSet() throws InterruptedException {
342 >        final CountDownLatch threadStarted = new CountDownLatch(1);
343 >
344 >        final PublicFutureTask task =
345 >            new PublicFutureTask(new CheckedCallable<Object>() {
346                  public Object realCall() throws InterruptedException {
347                      return Boolean.TRUE;
348                  }});
349 <        Thread t = new Thread(new CheckedRunnable() {
349 >
350 >        Thread t = newStartedThread(new CheckedRunnable() {
351              public void realRun() throws Exception {
352 <                assertSame(Boolean.TRUE, ft.get(SMALL_DELAY_MS, MILLISECONDS));
352 >                threadStarted.countDown();
353 >                assertSame(Boolean.FALSE,
354 >                           task.get(MEDIUM_DELAY_MS, MILLISECONDS));
355              }});
356  
357 <        assertFalse(ft.isDone());
358 <        assertFalse(ft.isCancelled());
359 <        t.start();
360 <        Thread.sleep(SHORT_DELAY_MS);
361 <        ft.run();
362 <        t.join();
227 <        assertTrue(ft.isDone());
228 <        assertFalse(ft.isCancelled());
357 >        threadStarted.await();
358 >        checkNotDone(task);
359 >        assertTrue(t.isAlive());
360 >        task.set(Boolean.FALSE);
361 >        checkCompletedNormally(task, Boolean.FALSE);
362 >        awaitTermination(t, MEDIUM_DELAY_MS);
363      }
364  
365      /**
366 <     *  Cancelling a task causes timed get in another thread to throw CancellationException
366 >     * Cancelling a task causes timed get in another thread to throw
367 >     * CancellationException
368       */
369      public void testTimedGet_Cancellation() throws InterruptedException {
370 <        final FutureTask ft =
370 >        final CountDownLatch threadStarted = new CountDownLatch(2);
371 >        final FutureTask task =
372              new FutureTask(new CheckedInterruptedCallable<Object>() {
373                  public Object realCall() throws InterruptedException {
374 <                    Thread.sleep(SMALL_DELAY_MS);
374 >                    threadStarted.countDown();
375 >                    delay(LONG_DELAY_MS);
376                      return Boolean.TRUE;
377                  }});
378  
379          Thread t1 = new ThreadShouldThrow(CancellationException.class) {
380              public void realRun() throws Exception {
381 <                ft.get(MEDIUM_DELAY_MS, MILLISECONDS);
381 >                threadStarted.countDown();
382 >                task.get(MEDIUM_DELAY_MS, MILLISECONDS);
383              }};
384 <        Thread t2 = new Thread(ft);
384 >        Thread t2 = new Thread(task);
385          t1.start();
386          t2.start();
387 <        Thread.sleep(SHORT_DELAY_MS);
388 <        ft.cancel(true);
389 <        t1.join();
390 <        t2.join();
387 >        threadStarted.await();
388 >        task.cancel(true);
389 >        awaitTermination(t1, MEDIUM_DELAY_MS);
390 >        awaitTermination(t2, MEDIUM_DELAY_MS);
391 >        checkCancelled(task);
392      }
393  
394      /**
395 <     * Cancelling a task causes get in another thread to throw CancellationException
395 >     * Cancelling a task causes get in another thread to throw
396 >     * CancellationException
397       */
398      public void testGet_Cancellation() throws InterruptedException {
399 <        final FutureTask ft =
399 >        final CountDownLatch threadStarted = new CountDownLatch(2);
400 >        final FutureTask task =
401              new FutureTask(new CheckedInterruptedCallable<Object>() {
402                  public Object realCall() throws InterruptedException {
403 <                    Thread.sleep(SMALL_DELAY_MS);
403 >                    threadStarted.countDown();
404 >                    delay(LONG_DELAY_MS);
405                      return Boolean.TRUE;
406                  }});
407 +
408          Thread t1 = new ThreadShouldThrow(CancellationException.class) {
409              public void realRun() throws Exception {
410 <                ft.get();
410 >                threadStarted.countDown();
411 >                task.get();
412              }};
413 <
270 <        Thread t2 = new Thread(ft);
413 >        Thread t2 = new Thread(task);
414          t1.start();
415          t2.start();
416 <        Thread.sleep(SHORT_DELAY_MS);
417 <        ft.cancel(true);
418 <        t1.join();
419 <        t2.join();
416 >        threadStarted.await();
417 >        task.cancel(true);
418 >        awaitTermination(t1, MEDIUM_DELAY_MS);
419 >        awaitTermination(t2, MEDIUM_DELAY_MS);
420 >        checkCancelled(task);
421      }
422  
423  
# Line 281 | Line 425 | public class FutureTaskTest extends JSR1
425       * A runtime exception in task causes get to throw ExecutionException
426       */
427      public void testGet_ExecutionException() throws InterruptedException {
428 <        final FutureTask ft = new FutureTask(new Callable() {
428 >        final FutureTask task = new FutureTask(new Callable() {
429              public Object call() {
430                  return 5/0;
431              }});
432  
433 <        ft.run();
433 >        task.run();
434          try {
435 <            ft.get();
435 >            task.get();
436              shouldThrow();
437          } catch (ExecutionException success) {
438              assertTrue(success.getCause() instanceof ArithmeticException);
439 +            checkCompletedAbnormally(task, success.getCause());
440          }
441      }
442  
443      /**
444 <     *  A runtime exception in task causes timed get to throw ExecutionException
444 >     * A runtime exception in task causes timed get to throw ExecutionException
445       */
446      public void testTimedGet_ExecutionException2() throws Exception {
447 <        final FutureTask ft = new FutureTask(new Callable() {
447 >        final FutureTask task = new FutureTask(new Callable() {
448              public Object call() {
449                  return 5/0;
450              }});
451  
452 <        ft.run();
452 >        task.run();
453          try {
454 <            ft.get(SHORT_DELAY_MS, MILLISECONDS);
454 >            task.get(SHORT_DELAY_MS, MILLISECONDS);
455              shouldThrow();
456          } catch (ExecutionException success) {
457              assertTrue(success.getCause() instanceof ArithmeticException);
458 +            checkCompletedAbnormally(task, success.getCause());
459          }
460      }
461  
# Line 318 | Line 464 | public class FutureTaskTest extends JSR1
464       * Interrupting a waiting get causes it to throw InterruptedException
465       */
466      public void testGet_InterruptedException() throws InterruptedException {
467 <        final FutureTask ft = new FutureTask(new NoOpCallable());
468 <        Thread t = new Thread(new CheckedInterruptedRunnable() {
467 >        final CountDownLatch threadStarted = new CountDownLatch(1);
468 >        final FutureTask task = new FutureTask(new NoOpCallable());
469 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
470              public void realRun() throws Exception {
471 <                ft.get();
471 >                threadStarted.countDown();
472 >                task.get();
473              }});
474  
475 <        t.start();
328 <        Thread.sleep(SHORT_DELAY_MS);
475 >        threadStarted.await();
476          t.interrupt();
477 <        t.join();
477 >        awaitTermination(t, MEDIUM_DELAY_MS);
478 >        checkNotDone(task);
479      }
480  
481      /**
482 <     *  Interrupting a waiting timed get causes it to throw InterruptedException
482 >     * Interrupting a waiting timed get causes it to throw InterruptedException
483       */
484      public void testTimedGet_InterruptedException2() throws InterruptedException {
485 <        final FutureTask ft = new FutureTask(new NoOpCallable());
486 <        Thread t = new Thread(new CheckedInterruptedRunnable() {
485 >        final CountDownLatch threadStarted = new CountDownLatch(1);
486 >        final FutureTask task = new FutureTask(new NoOpCallable());
487 >        Thread t = newStartedThread(new CheckedInterruptedRunnable() {
488              public void realRun() throws Exception {
489 <                ft.get(LONG_DELAY_MS,MILLISECONDS);
489 >                threadStarted.countDown();
490 >                task.get(LONG_DELAY_MS, MILLISECONDS);
491              }});
492  
493 <        t.start();
344 <        Thread.sleep(SHORT_DELAY_MS);
493 >        threadStarted.await();
494          t.interrupt();
495 <        t.join();
495 >        awaitTermination(t, MEDIUM_DELAY_MS);
496 >        checkNotDone(task);
497      }
498  
499      /**
# Line 351 | Line 501 | public class FutureTaskTest extends JSR1
501       */
502      public void testGet_TimeoutException() throws Exception {
503          try {
504 <            FutureTask ft = new FutureTask(new NoOpCallable());
505 <            ft.get(1,MILLISECONDS);
504 >            FutureTask task = new FutureTask(new NoOpCallable());
505 >            task.get(1, MILLISECONDS);
506              shouldThrow();
507          } catch (TimeoutException success) {}
508      }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines