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 }