package org.oddjob.scheduling; import java.util.concurrent.CancellationException; import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import junit.framework.TestCase; public class JavaExecutorAssumptionsTest extends TestCase { class SimpleRunnable implements Runnable { boolean ran; public void run() { ran = true; } } public void testCancelBeforeRun() throws InterruptedException { ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); SimpleRunnable runnable = new SimpleRunnable(); ScheduledFuture<?> future = executor.schedule( runnable, 1000, TimeUnit.HOURS); Thread.sleep(1); assertTrue(future.getDelay(TimeUnit.MILLISECONDS) < (1000L * 60 * 60 * 1000)); assertEquals(false, future.isCancelled()); assertEquals(false, future.isDone()); future.cancel(true); assertEquals(true, future.isCancelled()); assertEquals(true, future.isDone()); assertEquals(false, runnable.ran); executor.shutdown(); } public void testRunBeforeCancel() throws InterruptedException, ExecutionException { ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); SimpleRunnable runnable = new SimpleRunnable(); Future<?> future = executor.schedule( runnable, 0, TimeUnit.HOURS); future.get(); assertEquals(true, runnable.ran); assertEquals(false, future.isCancelled()); assertEquals(true, future.isDone()); future.cancel(true); assertEquals(false, future.isCancelled()); executor.shutdown(); } class RunUntilInerrupted implements Runnable { Exchanger<Void> exchange = new Exchanger<Void>(); boolean ran; boolean interrupted; public synchronized void run() { ran = true; try { exchange.exchange(null); wait(); } catch (InterruptedException e) { interrupted = true; } try { exchange.exchange(null); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public void testCancelInterrupted() throws InterruptedException, ExecutionException { ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1); RunUntilInerrupted runnable = new RunUntilInerrupted(); Future<?> future = executor.schedule( runnable, 0, TimeUnit.HOURS); assertEquals(false, future.isCancelled()); assertEquals(false, future.isDone()); runnable.exchange.exchange(null); future.cancel(true); try { future.get(); fail("Should cancel."); } catch (CancellationException e) { // expected. } // CancellationException thrown even though the job hasn't actually finished. // need this exchange to wait for the finish. runnable.exchange.exchange(null); assertEquals(true, runnable.ran); assertEquals(true, runnable.interrupted); assertEquals(true, future.isCancelled()); assertEquals(true, future.isDone()); executor.shutdown(); } }