/* * Copyright (C) 2009 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.util.concurrent; import junit.framework.TestCase; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Test case for {@link ListenableFutureTask}. * * @author Sven Mawson */ public class ListenableFutureTaskTest extends TestCase { private ExecutorService exec; protected final CountDownLatch runLatch = new CountDownLatch(1); protected final CountDownLatch taskLatch = new CountDownLatch(1); protected final CountDownLatch listenerLatch = new CountDownLatch(1); protected volatile boolean throwException = false; protected final ListenableFutureTask<Integer> task = ListenableFutureTask.create(new Callable<Integer>() { @Override public Integer call() throws Exception { runLatch.countDown(); taskLatch.await(); if (throwException) { throw new IllegalStateException("Fail"); } return 25; } }); @Override protected void setUp() throws Exception { super.setUp(); exec = Executors.newCachedThreadPool(); task.addListener(new Runnable() { @Override public void run() { listenerLatch.countDown(); } }, MoreExecutors.sameThreadExecutor()); } @Override protected void tearDown() throws Exception { if (exec != null) { exec.shutdown(); } super.tearDown(); } public void testListenerDoesNotRunUntilTaskCompletes() throws Exception { // Test default state of not started. assertEquals(1, listenerLatch.getCount()); assertFalse(task.isDone()); assertFalse(task.isCancelled()); // Start the task to put it in the RUNNING state. Have to use a separate // thread because the task will block on the task latch after unblocking // the run latch. exec.execute(task); runLatch.await(); assertEquals(1, listenerLatch.getCount()); assertFalse(task.isDone()); assertFalse(task.isCancelled()); // Finish the task by unblocking the task latch. Then wait for the // listener to be called by blocking on the listener latch. taskLatch.countDown(); assertEquals(25, task.get().intValue()); assertTrue(listenerLatch.await(5, TimeUnit.SECONDS)); assertTrue(task.isDone()); assertFalse(task.isCancelled()); } public void testListenerCalledOnException() throws Exception { throwException = true; // Start up the task and unblock the latch to finish the task. exec.execute(task); runLatch.await(); taskLatch.countDown(); try { task.get(5, TimeUnit.SECONDS); fail("Should have propagated the failure."); } catch (ExecutionException e) { assertEquals(IllegalStateException.class, e.getCause().getClass()); } assertTrue(listenerLatch.await(5, TimeUnit.SECONDS)); assertTrue(task.isDone()); assertFalse(task.isCancelled()); } public void testListenerCalledOnCancelFromNotRunning() throws Exception { task.cancel(false); assertTrue(task.isDone()); assertTrue(task.isCancelled()); assertEquals(1, runLatch.getCount()); // Wait for the listeners to be called, don't rely on the same-thread exec. listenerLatch.await(5, TimeUnit.SECONDS); assertTrue(task.isDone()); assertTrue(task.isCancelled()); // Make sure we didn't run anything. assertEquals(1, runLatch.getCount()); } public void testListenerCalledOnCancelFromRunning() throws Exception { exec.execute(task); runLatch.await(); // Task has started up, cancel it while it's running. task.cancel(true); assertTrue(task.isDone()); assertTrue(task.isCancelled()); assertEquals(1, taskLatch.getCount()); // Wait for the listeners to be called. listenerLatch.await(5, TimeUnit.SECONDS); assertTrue(task.isDone()); assertTrue(task.isCancelled()); assertEquals(1, taskLatch.getCount()); } }