--- jsr166/src/test/tck/FutureTaskTest.java 2003/09/07 20:39:11 1.2 +++ jsr166/src/test/tck/FutureTaskTest.java 2009/11/16 05:30:07 1.14 @@ -1,132 +1,237 @@ /* - * 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/licenses/publicdomain + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ import junit.framework.*; import java.util.concurrent.*; +import java.util.*; -public class FutureTaskTest extends TestCase { +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); } - private static long SHORT_DELAY_MS = 100; - private static long MEDIUM_DELAY_MS = 1000; - private static long LONG_DELAY_MS = 10000; + /** + * Subclass to expose protected methods + */ + static class PublicFutureTask extends FutureTask { + public PublicFutureTask(Callable r) { super(r); } + public boolean runAndReset() { return super.runAndReset(); } + public void set(Object x) { super.set(x); } + public void setException(Throwable t) { super.setException(t); } + } - public void testIsDone(){ - FutureTask task = new FutureTask( new Callable() { - public Object call() { return Boolean.TRUE; } }); + /** + * Creating a future with a null callable throws NPE + */ + public void testConstructor() { + try { + FutureTask task = new FutureTask(null); + shouldThrow(); + } + catch (NullPointerException success) { + } + } + + /** + * creating a future with null runnable fails + */ + public void testConstructor2() { + try { + FutureTask task = new FutureTask(null, Boolean.TRUE); + shouldThrow(); + } + 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()); } + /** + * runAndReset of a non-cancelled task succeeds + */ + public void testRunAndReset() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + assertTrue(task.runAndReset()); + assertFalse(task.isDone()); + } + + /** + * runAndReset after cancellation fails + */ + public void testResetAfterCancel() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + assertTrue(task.cancel(false)); + assertFalse(task.runAndReset()); + assertTrue(task.isDone()); + assertTrue(task.isCancelled()); + } + + + + /** + * setting value causes get to return it + */ + public void testSet() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + task.set(one); + try { + assertEquals(task.get(), one); + } + catch (Exception e) { + unexpectedException(); + } + } + + /** + * setException causes get to throw ExecutionException + */ + public void testSetException() { + 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(); + } + } + + /** + * Cancelling before running succeeds + */ public void testCancelBeforeRun() { - FutureTask task = new FutureTask( new Callable() { - public Object call() { return Boolean.TRUE; } }); + FutureTask task = new FutureTask( new NoOpCallable()); assertTrue(task.cancel(false)); task.run(); assertTrue(task.isDone()); assertTrue(task.isCancelled()); } + /** + * Cancel(true) before run succeeds + */ public void testCancelBeforeRun2() { - FutureTask task = new FutureTask( new Callable() { - public Object call() { return Boolean.TRUE; } }); + FutureTask task = new FutureTask( new NoOpCallable()); assertTrue(task.cancel(true)); task.run(); assertTrue(task.isDone()); assertTrue(task.isCancelled()); } + /** + * cancel of a completed task fails + */ public void testCancelAfterRun() { - FutureTask task = new FutureTask( new Callable() { - public Object call() { return Boolean.TRUE; } }); + FutureTask task = new FutureTask( new NoOpCallable()); task.run(); assertFalse(task.cancel(false)); assertTrue(task.isDone()); assertFalse(task.isCancelled()); } - public void testCancelInterrupt(){ + /** + * cancel(true) interrupts a running task + */ + public void testCancelInterrupt() { FutureTask task = new FutureTask( new Callable() { public Object call() { try { - Thread.sleep(SHORT_DELAY_MS* 2); - fail("should throw"); + Thread.sleep(MEDIUM_DELAY_MS); + threadShouldThrow(); } catch (InterruptedException success) {} return Boolean.TRUE; } }); Thread t = new Thread(task); t.start(); - - try{ + + try { Thread.sleep(SHORT_DELAY_MS); assertTrue(task.cancel(true)); t.join(); assertTrue(task.isDone()); assertTrue(task.isCancelled()); - } catch(InterruptedException e){ - fail("unexpected exception"); + } catch (InterruptedException e) { + unexpectedException(); } } - public void testCancelNoInterrupt(){ + /** + * cancel(false) does not interrupt a running task + */ + public void testCancelNoInterrupt() { FutureTask task = new FutureTask( new Callable() { public Object call() { try { - Thread.sleep(SHORT_DELAY_MS* 2); + Thread.sleep(MEDIUM_DELAY_MS); } catch (InterruptedException success) { - fail("should not interrupt"); + threadFail("should not interrupt"); } return Boolean.TRUE; } }); Thread t = new Thread(task); t.start(); - - try{ + + try { Thread.sleep(SHORT_DELAY_MS); assertTrue(task.cancel(false)); t.join(); assertTrue(task.isDone()); assertTrue(task.isCancelled()); - } catch(InterruptedException e){ - fail("unexpected exception"); + } catch (InterruptedException e) { + unexpectedException(); } } + /** + * 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{ + final FutureTask ft = new FutureTask(new Callable() { + public Object call() { + try { Thread.sleep(MEDIUM_DELAY_MS); - } catch(InterruptedException e){ - fail("unexpected exception"); + } catch (InterruptedException e) { + threadUnexpectedException(); } return Boolean.TRUE; } }); - Thread t = new Thread(new Runnable(){ - public void run(){ - try{ + Thread t = new Thread(new Runnable() { + public void run() { + try { ft.get(); - } catch(Exception e){ - fail("unexpected exception"); + } catch (Exception e) { + threadUnexpectedException(); } } }); - try{ + try { assertFalse(ft.isDone()); assertFalse(ft.isCancelled()); t.start(); @@ -135,34 +240,37 @@ public class FutureTaskTest extends Test t.join(); assertTrue(ft.isDone()); assertFalse(ft.isCancelled()); - } catch(InterruptedException e){ - fail("unexpected exception"); + } catch (InterruptedException e) { + unexpectedException(); - } + } } + /** + * 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{ + final FutureTask ft = new FutureTask(new Callable() { + public Object call() { + try { Thread.sleep(MEDIUM_DELAY_MS); - } catch(InterruptedException e){ - fail("unexpected exception"); + } catch (InterruptedException e) { + threadUnexpectedException(); } return Boolean.TRUE; } }); - Thread t = new Thread(new Runnable(){ - public void run(){ - try{ + Thread t = new Thread(new Runnable() { + public void run() { + try { ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); - } catch(TimeoutException success) { - } catch(Exception e){ - fail("unexpected exception"); + } catch (TimeoutException success) { + } catch (Exception e) { + threadUnexpectedException(); } } }); - try{ + try { assertFalse(ft.isDone()); assertFalse(ft.isCancelled()); t.start(); @@ -170,131 +278,146 @@ public class FutureTaskTest extends Test t.join(); assertTrue(ft.isDone()); assertFalse(ft.isCancelled()); - } catch(InterruptedException e){ - fail("unexpected exception"); - - } - } + } catch (InterruptedException e) { + unexpectedException(); + } + } - public void testGet_Cancellation(){ - final FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ - try{ - Thread.sleep(MEDIUM_DELAY_MS); - } catch(InterruptedException e){ - fail("unexpected exception"); + /** + * 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; + return Boolean.TRUE; } }); try { - Thread.sleep(SHORT_DELAY_MS); - Thread t = new Thread(new Runnable(){ - public void run(){ - try{ - ft.get(); - fail("should throw"); - } catch(CancellationException success){ - } - catch(Exception e){ - fail("unexpected exception"); - } + 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(); + } } }); - t.start(); + Thread t2 = new Thread(ft); + t1.start(); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); ft.cancel(true); - t.join(); - } catch(InterruptedException success){ - fail("unexpected exception"); + t1.join(); + t2.join(); + } catch (InterruptedException ie) { + unexpectedException(); } } - - public void testGet_Cancellation2(){ - final FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ - try{ - Thread.sleep(SHORT_DELAY_MS); - } catch(InterruptedException e) { - fail("unexpected exception"); + + /** + * 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) { } - return Boolean.TRUE; + return Boolean.TRUE; } }); - try{ - Thread.sleep(100); - Thread t = new Thread(new Runnable(){ - public void run(){ - try{ - ft.get(3 * SHORT_DELAY_MS, TimeUnit.MILLISECONDS); - fail("should throw"); - } catch(CancellationException success) {} - catch(Exception e){ - fail("unexpected exception"); - } + try { + Thread t1 = new Thread(new Runnable() { + public void run() { + try { + ft.get(); + threadShouldThrow(); + } catch (CancellationException success) { + } + catch (Exception e) { + threadUnexpectedException(); + } } }); - t.start(); - Thread.sleep(SHORT_DELAY_MS); + Thread t2 = new Thread(ft); + t1.start(); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); ft.cancel(true); - Thread.sleep(SHORT_DELAY_MS); - t.join(); - } catch(InterruptedException ie){ - fail("unexpected exception"); + t1.join(); + t2.join(); + } catch (InterruptedException success) { + unexpectedException(); } } - public void testGet_ExecutionException(){ - final FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ + + /** + * 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{ + try { ft.run(); ft.get(); - fail("should throw"); - } catch(ExecutionException success){ + shouldThrow(); + } catch (ExecutionException success) { } - catch(Exception e){ - fail("unexpected exception"); + catch (Exception e) { + unexpectedException(); } } - - public void testTimedGet_ExecutionException2(){ - final FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ + + /** + * 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{ + try { ft.run(); ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); - fail("should throw"); - } catch(ExecutionException success) { - } catch(TimeoutException success) { } // unlikely but OK - catch(Exception e){ - fail("unexpected exception"); + shouldThrow(); + } catch (ExecutionException success) { + } catch (TimeoutException success) { } // unlikely but OK + catch (Exception e) { + unexpectedException(); } } - - public void testGet_InterruptedException(){ - final FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ - return new Object(); - } - }); - Thread t = new Thread(new Runnable(){ - public void run(){ - try{ + + /** + * Interrupting a waiting get causes it to throw InterruptedException + */ + public void testGet_InterruptedException() { + final FutureTask ft = new FutureTask(new NoOpCallable()); + Thread t = new Thread(new Runnable() { + public void run() { + try { ft.get(); - fail("should throw"); - } catch(InterruptedException success){ - } catch(Exception e){ - fail("unexpected exception"); + threadShouldThrow(); + } catch (InterruptedException success) { + } catch (Exception e) { + threadUnexpectedException(); } } }); @@ -303,25 +426,24 @@ public class FutureTaskTest extends Test Thread.sleep(SHORT_DELAY_MS); t.interrupt(); t.join(); - } catch(Exception e){ - fail("unexpected exception"); + } catch (Exception e) { + unexpectedException(); } } - public void testTimedGet_InterruptedException2(){ - final FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ - return new Object(); - } - }); - Thread t = new Thread(new Runnable(){ - public void run(){ - try{ - ft.get(100,TimeUnit.SECONDS); - fail("should throw"); - } catch(InterruptedException success){} - catch(Exception e){ - fail("unexpected exception"); + /** + * Interrupting a waiting timed 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(); } } }); @@ -330,26 +452,23 @@ public class FutureTaskTest extends Test Thread.sleep(SHORT_DELAY_MS); t.interrupt(); t.join(); - } catch(Exception e){ - fail("unexpected exception"); + } catch (Exception e) { + unexpectedException(); } } - - public void testGet_TimeoutException(){ - FutureTask ft = new FutureTask(new Callable(){ - public Object call(){ - return new Object(); - } - }); - try{ + + /** + * A timed out timed get throws TimeoutException + */ + public void testGet_TimeoutException() { + try { + FutureTask ft = new FutureTask(new NoOpCallable()); ft.get(1,TimeUnit.MILLISECONDS); - fail("should throw"); - } catch(TimeoutException success){} - catch(Exception success){ - fail("unexpected exception"); + shouldThrow(); + } catch (TimeoutException success) {} + catch (Exception success) { + unexpectedException(); } - - } - + }