--- jsr166/src/test/tck/FutureTaskTest.java 2003/09/26 15:33:13 1.7 +++ jsr166/src/test/tck/FutureTaskTest.java 2011/03/15 19:47:06 1.24 @@ -1,21 +1,86 @@ /* - * Written by members of JCP JSR-166 Expert Group and released to the - * public domain. Use, modify, and redistribute this code in any way - * without acknowledgement. Other contributors include Andrew Wright, - * Jeffrey Hayes, Pat Fischer, Mike Judd. + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ import junit.framework.*; import java.util.concurrent.*; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import java.util.*; public class FutureTaskTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run (suite()); + junit.textui.TestRunner.run(suite()); } public static Test suite() { - return new TestSuite(FutureTaskTest.class); + return new TestSuite(FutureTaskTest.class); + } + + void checkNotDone(Future f) { + assertFalse(f.isDone()); + assertFalse(f.isCancelled()); + } + + void checkCompletedNormally(Future f, T expected) { + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + + try { + assertSame(expected, f.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertSame(expected, f.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + assertFalse(f.cancel(false)); + assertFalse(f.cancel(true)); + } + + void checkCancelled(Future f) { + assertTrue(f.isDone()); + assertTrue(f.isCancelled()); + + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + assertFalse(f.cancel(false)); + assertFalse(f.cancel(true)); + } + + void checkCompletedAbnormally(Future f, Throwable t) { + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + assertFalse(f.cancel(false)); + assertFalse(f.cancel(true)); } /** @@ -23,9 +88,7 @@ public class FutureTaskTest extends JSR1 */ static class PublicFutureTask extends FutureTask { public PublicFutureTask(Callable r) { super(r); } - public boolean reset() { return super.reset(); } - public void setCancelled() { super.setCancelled(); } - public void setDone() { super.setDone(); } + public boolean runAndReset() { return super.runAndReset(); } public void set(Object x) { super.set(x); } public void setException(Throwable t) { super.setException(t); } } @@ -37,9 +100,7 @@ public class FutureTaskTest extends JSR1 try { FutureTask task = new FutureTask(null); shouldThrow(); - } - catch(NullPointerException success) { - } + } catch (NullPointerException success) {} } /** @@ -49,449 +110,395 @@ public class FutureTaskTest extends JSR1 try { FutureTask task = new FutureTask(null, Boolean.TRUE); shouldThrow(); - } - catch(NullPointerException success) { - } + } catch (NullPointerException success) {} } /** * isDone is true when a task completes */ public void testIsDone() { - FutureTask task = new FutureTask( new NoOpCallable()); - task.run(); - assertTrue(task.isDone()); - assertFalse(task.isCancelled()); + FutureTask task = new FutureTask(new NoOpCallable()); + task.run(); + assertTrue(task.isDone()); + checkCompletedNormally(task, Boolean.TRUE); } /** - * reset of a done task succeeds and changes status to not done + * runAndReset of a non-cancelled task succeeds */ - public void testReset() { + public void testRunAndReset() { PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); - task.run(); - assertTrue(task.isDone()); - assertTrue(task.reset()); - assertFalse(task.isDone()); + assertTrue(task.runAndReset()); + checkNotDone(task); } /** - * Resetting after cancellation fails + * runAndReset after cancellation fails */ public void testResetAfterCancel() { PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); assertTrue(task.cancel(false)); - task.run(); - assertTrue(task.isDone()); - assertTrue(task.isCancelled()); - assertFalse(task.reset()); + assertFalse(task.runAndReset()); + checkCancelled(task); } - /** - * setDone of new task causes isDone to be true - */ - public void testSetDone() { - PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); - task.setDone(); - assertTrue(task.isDone()); - assertFalse(task.isCancelled()); - } - - /** - * setCancelled of a new task causes isCancelled to be true - */ - public void testSetCancelled() { - PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); - assertTrue(task.cancel(false)); - task.setCancelled(); - assertTrue(task.isDone()); - assertTrue(task.isCancelled()); - } /** - * setting value gauses get to return it + * setting value causes get to return it */ - public void testSet() { + public void testSet() throws Exception { PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); task.set(one); - try { - assertEquals(task.get(), one); - } - catch(Exception e) { - unexpectedException(); - } + assertSame(task.get(), one); + checkCompletedNormally(task, one); } /** * setException causes get to throw ExecutionException */ - public void testSetException() { + public void testSetException() throws Exception { Exception nse = new NoSuchElementException(); PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); task.setException(nse); try { Object x = task.get(); shouldThrow(); - } - catch(ExecutionException ee) { - Throwable cause = ee.getCause(); - assertEquals(cause, nse); - } - catch(Exception e) { - unexpectedException(); + } catch (ExecutionException success) { + assertSame(success.getCause(), nse); + checkCompletedAbnormally(task, nse); } } /** - * Cancelling before running succeeds + * Cancelling before running succeeds */ public void testCancelBeforeRun() { - FutureTask task = new FutureTask( new NoOpCallable()); + FutureTask task = new FutureTask(new NoOpCallable()); assertTrue(task.cancel(false)); - task.run(); - assertTrue(task.isDone()); - assertTrue(task.isCancelled()); + task.run(); + checkCancelled(task); } /** * Cancel(true) before run succeeds */ public void testCancelBeforeRun2() { - FutureTask task = new FutureTask( new NoOpCallable()); + FutureTask task = new FutureTask(new NoOpCallable()); assertTrue(task.cancel(true)); - task.run(); - assertTrue(task.isDone()); - assertTrue(task.isCancelled()); + task.run(); + checkCancelled(task); } /** * cancel of a completed task fails */ public void testCancelAfterRun() { - FutureTask task = new FutureTask( new NoOpCallable()); - task.run(); + FutureTask task = new FutureTask(new NoOpCallable()); + task.run(); assertFalse(task.cancel(false)); - assertTrue(task.isDone()); - assertFalse(task.isCancelled()); + checkCompletedNormally(task, Boolean.TRUE); } /** * cancel(true) interrupts a running task */ - public void testCancelInterrupt() { - FutureTask task = new FutureTask( new Callable() { - public Object call() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - threadShouldThrow(); + public void testCancelInterrupt() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + final FutureTask task = + new FutureTask(new CheckedCallable() { + public Object realCall() { + threadStarted.countDown(); + long t0 = System.nanoTime(); + for (;;) { + if (Thread.interrupted()) + return Boolean.TRUE; + if (millisElapsedSince(t0) > MEDIUM_DELAY_MS) + fail("interrupt not delivered"); + Thread.yield(); } - catch (InterruptedException success) {} - return Boolean.TRUE; - } }); - Thread t = new Thread(task); - t.start(); - - try { - Thread.sleep(SHORT_DELAY_MS); - assertTrue(task.cancel(true)); - t.join(); - assertTrue(task.isDone()); - assertTrue(task.isCancelled()); - } catch(InterruptedException e){ - unexpectedException(); - } - } + }}); + Thread t = newStartedThread(task); + threadStarted.await(); + assertTrue(task.cancel(true)); + checkCancelled(task); + awaitTermination(t, MEDIUM_DELAY_MS); + checkCancelled(task); + } /** * cancel(false) does not interrupt a running task */ - public void testCancelNoInterrupt() { - FutureTask task = new FutureTask( new Callable() { - public Object call() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - } - catch (InterruptedException success) { - threadFail("should not interrupt"); - } + public void testCancelNoInterrupt() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch cancelled = new CountDownLatch(1); + final FutureTask task = + new FutureTask(new CheckedCallable() { + public Boolean realCall() throws InterruptedException { + threadStarted.countDown(); + cancelled.await(MEDIUM_DELAY_MS, MILLISECONDS); + assertFalse(Thread.interrupted()); return Boolean.TRUE; - } }); - Thread t = new Thread(task); - t.start(); - - try { - Thread.sleep(SHORT_DELAY_MS); - assertTrue(task.cancel(false)); - t.join(); - assertTrue(task.isDone()); - assertTrue(task.isCancelled()); - } catch(InterruptedException e){ - unexpectedException(); - } + }}); + + Thread t = newStartedThread(task); + threadStarted.await(); + assertTrue(task.cancel(false)); + checkCancelled(task); + cancelled.countDown(); + awaitTermination(t, MEDIUM_DELAY_MS); + checkCancelled(task); + } + + /** + * run in one thread causes get in another thread to retrieve value + */ + public void testGetRun() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + + final FutureTask task = + new FutureTask(new CheckedCallable() { + public Object realCall() throws InterruptedException { + return Boolean.TRUE; + }}); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + assertSame(Boolean.TRUE, task.get()); + }}); + + threadStarted.await(); + checkNotDone(task); + assertTrue(t.isAlive()); + task.run(); + checkCompletedNormally(task, Boolean.TRUE); + awaitTermination(t, MEDIUM_DELAY_MS); } /** * set in one thread causes get in another thread to retrieve value */ - public void testGet1() { - final FutureTask ft = new FutureTask(new Callable() { - public Object call() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - } catch(InterruptedException e){ - threadUnexpectedException(); - } + public void testGetSet() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + + final PublicFutureTask task = + new PublicFutureTask(new CheckedCallable() { + public Object realCall() throws InterruptedException { return Boolean.TRUE; - } - }); - Thread t = new Thread(new Runnable() { - public void run() { - try { - ft.get(); - } catch(Exception e){ - threadUnexpectedException(); - } - } - }); - try { - assertFalse(ft.isDone()); - assertFalse(ft.isCancelled()); - t.start(); - Thread.sleep(SHORT_DELAY_MS); - ft.run(); - t.join(); - assertTrue(ft.isDone()); - assertFalse(ft.isCancelled()); - } catch(InterruptedException e){ - unexpectedException(); + }}); - } + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + assertSame(Boolean.FALSE, task.get()); + }}); + + threadStarted.await(); + checkNotDone(task); + assertTrue(t.isAlive()); + task.set(Boolean.FALSE); + checkCompletedNormally(task, Boolean.FALSE); + awaitTermination(t, MEDIUM_DELAY_MS); + } + + /** + * run in one thread causes timed get in another thread to retrieve value + */ + public void testTimedGetRun() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + + final FutureTask task = + new FutureTask(new CheckedCallable() { + public Object realCall() throws InterruptedException { + return Boolean.TRUE; + }}); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + assertSame(Boolean.TRUE, + task.get(MEDIUM_DELAY_MS, MILLISECONDS)); + }}); + + threadStarted.await(); + checkNotDone(task); + assertTrue(t.isAlive()); + task.run(); + checkCompletedNormally(task, Boolean.TRUE); + awaitTermination(t, MEDIUM_DELAY_MS); } /** * set in one thread causes timed get in another thread to retrieve value */ - public void testTimedGet1() { - final FutureTask ft = new FutureTask(new Callable() { - public Object call() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - } catch(InterruptedException e){ - threadUnexpectedException(); - } + public void testTimedGetSet() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + + final PublicFutureTask task = + new PublicFutureTask(new CheckedCallable() { + public Object realCall() throws InterruptedException { return Boolean.TRUE; - } - }); - Thread t = new Thread(new Runnable() { - public void run() { - try { - ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); - } catch(TimeoutException success) { - } catch(Exception e){ - threadUnexpectedException(); - } - } - }); - try { - assertFalse(ft.isDone()); - assertFalse(ft.isCancelled()); - t.start(); - ft.run(); - t.join(); - assertTrue(ft.isDone()); - assertFalse(ft.isCancelled()); - } catch(InterruptedException e){ - unexpectedException(); - - } + }}); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + assertSame(Boolean.FALSE, + task.get(MEDIUM_DELAY_MS, MILLISECONDS)); + }}); + + threadStarted.await(); + checkNotDone(task); + assertTrue(t.isAlive()); + task.set(Boolean.FALSE); + checkCompletedNormally(task, Boolean.FALSE); + awaitTermination(t, MEDIUM_DELAY_MS); } /** - * Cancelling a task causes timed get in another thread to throw CancellationException - */ - public void testTimedGet_Cancellation() { - final FutureTask ft = new FutureTask(new Callable() { - public Object call() { - try { - Thread.sleep(SMALL_DELAY_MS); - threadShouldThrow(); - } catch(InterruptedException e) { - } - return Boolean.TRUE; - } - }); - try { - Thread t1 = new Thread(new Runnable() { - public void run() { - try { - ft.get(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); - threadShouldThrow(); - } catch(CancellationException success) {} - catch(Exception e){ - threadUnexpectedException(); - } - } - }); - Thread t2 = new Thread(ft); - t1.start(); - t2.start(); - Thread.sleep(SHORT_DELAY_MS); - ft.cancel(true); - t1.join(); - t2.join(); - } catch(InterruptedException ie){ - unexpectedException(); - } + * Cancelling a task causes timed get in another thread to throw + * CancellationException + */ + public void testTimedGet_Cancellation() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(2); + final FutureTask task = + new FutureTask(new CheckedInterruptedCallable() { + public Object realCall() throws InterruptedException { + threadStarted.countDown(); + Thread.sleep(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); } /** - * Cancelling a task causes get in another thread to throw CancellationException - */ - public void testGet_Cancellation() { - final FutureTask ft = new FutureTask(new Callable() { - public Object call() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - threadShouldThrow(); - } catch(InterruptedException e){ - } + * Cancelling a task causes get in another thread to throw + * CancellationException + */ + public void testGet_Cancellation() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(2); + final FutureTask task = + new FutureTask(new CheckedInterruptedCallable() { + public Object realCall() throws InterruptedException { + threadStarted.countDown(); + Thread.sleep(LONG_DELAY_MS); return Boolean.TRUE; - } - }); - try { - Thread t1 = new Thread(new Runnable() { - public void run() { - try { - ft.get(); - threadShouldThrow(); - } catch(CancellationException success){ - } - catch(Exception e){ - threadUnexpectedException(); - } - } - }); - Thread t2 = new Thread(ft); - t1.start(); - t2.start(); - Thread.sleep(SHORT_DELAY_MS); - ft.cancel(true); - t1.join(); - t2.join(); - } catch(InterruptedException success){ - unexpectedException(); - } + }}); + + Thread t1 = new ThreadShouldThrow(CancellationException.class) { + public void realRun() throws Exception { + threadStarted.countDown(); + task.get(); + }}; + 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); } - + /** * A runtime exception in task causes get to throw ExecutionException */ - public void testGet_ExecutionException() { - final FutureTask ft = new FutureTask(new Callable() { - public Object call() { - int i = 5/0; - return Boolean.TRUE; - } - }); - try { - ft.run(); - ft.get(); - shouldThrow(); - } catch(ExecutionException success){ + public void testGet_ExecutionException() throws InterruptedException { + final FutureTask task = new FutureTask(new Callable() { + public Object call() { + return 5/0; + }}); + + task.run(); + try { + task.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof ArithmeticException); + checkCompletedAbnormally(task, success.getCause()); } - catch(Exception e){ - unexpectedException(); - } - } - - /** - * A runtime exception in task causes timed get to throw ExecutionException - */ - public void testTimedGet_ExecutionException2() { - final FutureTask ft = new FutureTask(new Callable() { - public Object call() { - int i = 5/0; - return Boolean.TRUE; - } - }); - try { - ft.run(); - ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); - shouldThrow(); - } catch(ExecutionException success) { - } catch(TimeoutException success) { } // unlikely but OK - catch(Exception e){ - unexpectedException(); - } } - /** - * Interrupting a waiting get causes it to throw InterruptedException + * A runtime exception in task causes timed get to throw ExecutionException */ - public void testGet_InterruptedException() { - final FutureTask ft = new FutureTask(new NoOpCallable()); - Thread t = new Thread(new Runnable() { - public void run() { - try { - ft.get(); - threadShouldThrow(); - } catch(InterruptedException success){ - } catch(Exception e){ - threadUnexpectedException(); - } - } - }); + public void testTimedGet_ExecutionException2() throws Exception { + final FutureTask task = new FutureTask(new Callable() { + public Object call() { + return 5/0; + }}); + + task.run(); try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch(Exception e){ - unexpectedException(); + task.get(SHORT_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof ArithmeticException); + checkCompletedAbnormally(task, success.getCause()); } } + /** - * Interrupting a waiting timed get causes it to throw InterruptedException + * Interrupting a waiting get causes it to throw InterruptedException */ - public void testTimedGet_InterruptedException2() { - final FutureTask ft = new FutureTask(new NoOpCallable()); - Thread t = new Thread(new Runnable() { - public void run() { - try { - ft.get(LONG_DELAY_MS,TimeUnit.MILLISECONDS); - threadShouldThrow(); - } catch(InterruptedException success){} - catch(Exception e){ - threadUnexpectedException(); - } - } - }); - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch(Exception e){ - unexpectedException(); - } + public void testGet_InterruptedException() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + final FutureTask task = new FutureTask(new NoOpCallable()); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + task.get(); + }}); + + threadStarted.await(); + t.interrupt(); + awaitTermination(t, MEDIUM_DELAY_MS); + checkNotDone(task); + } + + /** + * Interrupting a waiting timed get causes it to throw InterruptedException + */ + public void testTimedGet_InterruptedException2() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + final FutureTask task = new FutureTask(new NoOpCallable()); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + task.get(LONG_DELAY_MS, MILLISECONDS); + }}); + + threadStarted.await(); + t.interrupt(); + awaitTermination(t, MEDIUM_DELAY_MS); + checkNotDone(task); } - + /** * A timed out timed get throws TimeoutException */ - public void testGet_TimeoutException() { - try { - FutureTask ft = new FutureTask(new NoOpCallable()); - ft.get(1,TimeUnit.MILLISECONDS); - shouldThrow(); - } catch(TimeoutException success){} - catch(Exception success){ - unexpectedException(); - } + public void testGet_TimeoutException() throws Exception { + try { + FutureTask task = new FutureTask(new NoOpCallable()); + task.get(1, MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) {} } - + }