1 /* 2 * Copyright (C) 2009 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import static com.google.common.util.concurrent.MoreExecutors.directExecutor; 20 21 import junit.framework.TestCase; 22 23 import java.util.concurrent.Callable; 24 import java.util.concurrent.CountDownLatch; 25 import java.util.concurrent.ExecutionException; 26 import java.util.concurrent.ExecutorService; 27 import java.util.concurrent.Executors; 28 import java.util.concurrent.TimeUnit; 29 30 /** 31 * Test case for {@link ListenableFutureTask}. 32 * 33 * @author Sven Mawson 34 */ 35 public class ListenableFutureTaskTest extends TestCase { 36 37 private ExecutorService exec; 38 39 protected final CountDownLatch runLatch = new CountDownLatch(1); 40 protected final CountDownLatch taskLatch = new CountDownLatch(1); 41 protected final CountDownLatch listenerLatch = new CountDownLatch(1); 42 43 protected volatile boolean throwException = false; 44 45 protected final ListenableFutureTask<Integer> task = 46 ListenableFutureTask.create(new Callable<Integer>() { 47 @Override 48 public Integer call() throws Exception { 49 runLatch.countDown(); 50 taskLatch.await(); 51 if (throwException) { 52 throw new IllegalStateException("Fail"); 53 } 54 return 25; 55 } 56 }); 57 58 @Override 59 protected void setUp() throws Exception { 60 super.setUp(); 61 62 exec = Executors.newCachedThreadPool(); 63 64 task.addListener(new Runnable() { 65 @Override 66 public void run() { 67 listenerLatch.countDown(); 68 } 69 }, directExecutor()); 70 } 71 72 @Override 73 protected void tearDown() throws Exception { 74 if (exec != null) { 75 exec.shutdown(); 76 } 77 78 super.tearDown(); 79 } 80 81 public void testListenerDoesNotRunUntilTaskCompletes() throws Exception { 82 83 // Test default state of not started. 84 assertEquals(1, listenerLatch.getCount()); 85 assertFalse(task.isDone()); 86 assertFalse(task.isCancelled()); 87 88 // Start the task to put it in the RUNNING state. Have to use a separate 89 // thread because the task will block on the task latch after unblocking 90 // the run latch. 91 exec.execute(task); 92 runLatch.await(); 93 assertEquals(1, listenerLatch.getCount()); 94 assertFalse(task.isDone()); 95 assertFalse(task.isCancelled()); 96 97 // Finish the task by unblocking the task latch. Then wait for the 98 // listener to be called by blocking on the listener latch. 99 taskLatch.countDown(); 100 assertEquals(25, task.get().intValue()); 101 assertTrue(listenerLatch.await(5, TimeUnit.SECONDS)); 102 assertTrue(task.isDone()); 103 assertFalse(task.isCancelled()); 104 } 105 106 public void testListenerCalledOnException() throws Exception { 107 throwException = true; 108 109 // Start up the task and unblock the latch to finish the task. 110 exec.execute(task); 111 runLatch.await(); 112 taskLatch.countDown(); 113 114 try { 115 task.get(5, TimeUnit.SECONDS); 116 fail("Should have propagated the failure."); 117 } catch (ExecutionException e) { 118 assertEquals(IllegalStateException.class, e.getCause().getClass()); 119 } 120 121 assertTrue(listenerLatch.await(5, TimeUnit.SECONDS)); 122 assertTrue(task.isDone()); 123 assertFalse(task.isCancelled()); 124 } 125 126 public void testListenerCalledOnCancelFromNotRunning() throws Exception { 127 task.cancel(false); 128 assertTrue(task.isDone()); 129 assertTrue(task.isCancelled()); 130 assertEquals(1, runLatch.getCount()); 131 132 // Wait for the listeners to be called, don't rely on the same-thread exec. 133 listenerLatch.await(5, TimeUnit.SECONDS); 134 assertTrue(task.isDone()); 135 assertTrue(task.isCancelled()); 136 137 // Make sure we didn't run anything. 138 assertEquals(1, runLatch.getCount()); 139 } 140 141 public void testListenerCalledOnCancelFromRunning() throws Exception { 142 exec.execute(task); 143 runLatch.await(); 144 145 // Task has started up, cancel it while it's running. 146 task.cancel(true); 147 assertTrue(task.isDone()); 148 assertTrue(task.isCancelled()); 149 assertEquals(1, taskLatch.getCount()); 150 151 // Wait for the listeners to be called. 152 listenerLatch.await(5, TimeUnit.SECONDS); 153 assertTrue(task.isDone()); 154 assertTrue(task.isCancelled()); 155 assertEquals(1, taskLatch.getCount()); 156 } 157 } 158