Coverage Summary for Class: AbstractListenableFutureTest (com.google.common.util.concurrent.testing)
| Class | Method, % | Line, % |
|---|---|---|
| AbstractListenableFutureTest | 0% (0/8) | 0% (0/59) |
| AbstractListenableFutureTest$1 | 0% (0/2) | 0% (0/7) |
| AbstractListenableFutureTest$2 | 0% (0/2) | 0% (0/6) |
| AbstractListenableFutureTest$3 | 0% (0/2) | 0% (0/2) |
| AbstractListenableFutureTest$4 | 0% (0/2) | 0% (0/6) |
| AbstractListenableFutureTest$5 | 0% (0/2) | 0% (0/2) |
| AbstractListenableFutureTest$6 | 0% (0/2) | 0% (0/2) |
| Total | 0% (0/20) | 0% (0/84) |
1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.google.common.util.concurrent.testing; 18 19 import com.google.common.annotations.Beta; 20 import com.google.common.annotations.GwtIncompatible; 21 import com.google.common.util.concurrent.ListenableFuture; 22 import java.util.concurrent.CancellationException; 23 import java.util.concurrent.CountDownLatch; 24 import java.util.concurrent.ExecutionException; 25 import java.util.concurrent.ExecutorService; 26 import java.util.concurrent.Executors; 27 import java.util.concurrent.Future; 28 import java.util.concurrent.TimeUnit; 29 import java.util.concurrent.TimeoutException; 30 import junit.framework.TestCase; 31 32 /** 33 * Abstract test case parent for anything implementing {@link ListenableFuture}. Tests the two get 34 * methods and the addListener method. 35 * 36 * @author Sven Mawson 37 * @since 10.0 38 */ 39 @Beta 40 @GwtIncompatible 41 public abstract class AbstractListenableFutureTest extends TestCase { 42 43 protected CountDownLatch latch; 44 protected ListenableFuture<Boolean> future; 45 46 @Override 47 protected void setUp() throws Exception { 48 49 // Create a latch and a future that waits on the latch. 50 latch = new CountDownLatch(1); 51 future = createListenableFuture(Boolean.TRUE, null, latch); 52 } 53 54 @Override 55 protected void tearDown() throws Exception { 56 57 // Make sure we have no waiting threads. 58 latch.countDown(); 59 } 60 61 /** Constructs a listenable future with a value available after the latch has counted down. */ 62 protected abstract <V> ListenableFuture<V> createListenableFuture( 63 V value, Exception except, CountDownLatch waitOn); 64 65 /** Tests that the {@link Future#get()} method blocks until a value is available. */ 66 public void testGetBlocksUntilValueAvailable() throws Throwable { 67 68 assertFalse(future.isDone()); 69 assertFalse(future.isCancelled()); 70 71 final CountDownLatch successLatch = new CountDownLatch(1); 72 final Throwable[] badness = new Throwable[1]; 73 74 // Wait on the future in a separate thread. 75 new Thread( 76 new Runnable() { 77 @Override 78 public void run() { 79 try { 80 assertSame(Boolean.TRUE, future.get()); 81 successLatch.countDown(); 82 } catch (Throwable t) { 83 t.printStackTrace(); 84 badness[0] = t; 85 } 86 } 87 }) 88 .start(); 89 90 // Release the future value. 91 latch.countDown(); 92 93 assertTrue(successLatch.await(10, TimeUnit.SECONDS)); 94 95 if (badness[0] != null) { 96 throw badness[0]; 97 } 98 99 assertTrue(future.isDone()); 100 assertFalse(future.isCancelled()); 101 } 102 103 /** Tests that the {@link Future#get(long, TimeUnit)} method times out correctly. */ 104 public void testTimeoutOnGetWorksCorrectly() throws InterruptedException, ExecutionException { 105 106 // The task thread waits for the latch, so we expect a timeout here. 107 try { 108 future.get(20, TimeUnit.MILLISECONDS); 109 fail("Should have timed out trying to get the value."); 110 } catch (TimeoutException expected) { 111 } finally { 112 latch.countDown(); 113 } 114 } 115 116 /** 117 * Tests that a canceled future throws a cancellation exception. 118 * 119 * <p>This method checks the cancel, isCancelled, and isDone methods. 120 */ 121 public void testCanceledFutureThrowsCancellation() throws Exception { 122 123 assertFalse(future.isDone()); 124 assertFalse(future.isCancelled()); 125 126 final CountDownLatch successLatch = new CountDownLatch(1); 127 128 // Run cancellation in a separate thread as an extra thread-safety test. 129 new Thread( 130 new Runnable() { 131 @Override 132 public void run() { 133 try { 134 future.get(); 135 } catch (CancellationException expected) { 136 successLatch.countDown(); 137 } catch (Exception ignored) { 138 // All other errors are ignored, we expect a cancellation. 139 } 140 } 141 }) 142 .start(); 143 144 assertFalse(future.isDone()); 145 assertFalse(future.isCancelled()); 146 147 future.cancel(true); 148 149 assertTrue(future.isDone()); 150 assertTrue(future.isCancelled()); 151 152 assertTrue(successLatch.await(200, TimeUnit.MILLISECONDS)); 153 154 latch.countDown(); 155 } 156 157 public void testListenersNotifiedOnError() throws Exception { 158 final CountDownLatch successLatch = new CountDownLatch(1); 159 final CountDownLatch listenerLatch = new CountDownLatch(1); 160 161 ExecutorService exec = Executors.newCachedThreadPool(); 162 163 future.addListener( 164 new Runnable() { 165 @Override 166 public void run() { 167 listenerLatch.countDown(); 168 } 169 }, 170 exec); 171 172 new Thread( 173 new Runnable() { 174 @Override 175 public void run() { 176 try { 177 future.get(); 178 } catch (CancellationException expected) { 179 successLatch.countDown(); 180 } catch (Exception ignored) { 181 // No success latch count down. 182 } 183 } 184 }) 185 .start(); 186 187 future.cancel(true); 188 189 assertTrue(future.isCancelled()); 190 assertTrue(future.isDone()); 191 192 assertTrue(successLatch.await(200, TimeUnit.MILLISECONDS)); 193 assertTrue(listenerLatch.await(200, TimeUnit.MILLISECONDS)); 194 195 latch.countDown(); 196 197 exec.shutdown(); 198 exec.awaitTermination(100, TimeUnit.MILLISECONDS); 199 } 200 201 /** 202 * Tests that all listeners complete, even if they were added before or after the future was 203 * finishing. Also acts as a concurrency test to make sure the locking is done correctly when a 204 * future is finishing so that no listeners can be lost. 205 */ 206 public void testAllListenersCompleteSuccessfully() 207 throws InterruptedException, ExecutionException { 208 209 ExecutorService exec = Executors.newCachedThreadPool(); 210 211 int listenerCount = 20; 212 final CountDownLatch listenerLatch = new CountDownLatch(listenerCount); 213 214 // Test that listeners added both before and after the value is available 215 // get called correctly. 216 for (int i = 0; i < 20; i++) { 217 218 // Right in the middle start up a thread to close the latch. 219 if (i == 10) { 220 new Thread( 221 new Runnable() { 222 @Override 223 public void run() { 224 latch.countDown(); 225 } 226 }) 227 .start(); 228 } 229 230 future.addListener( 231 new Runnable() { 232 @Override 233 public void run() { 234 listenerLatch.countDown(); 235 } 236 }, 237 exec); 238 } 239 240 assertSame(Boolean.TRUE, future.get()); 241 // Wait for the listener latch to complete. 242 listenerLatch.await(500, TimeUnit.MILLISECONDS); 243 244 exec.shutdown(); 245 exec.awaitTermination(500, TimeUnit.MILLISECONDS); 246 } 247 }