Home | History | Annotate | Download | only in concurrent
      1 /*
      2  * Copyright (C) 2008 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 com.google.common.util.concurrent.testing.MockFutureListener;
     20 
     21 import junit.framework.TestCase;
     22 
     23 import java.util.concurrent.TimeUnit;
     24 import java.util.concurrent.TimeoutException;
     25 
     26 /**
     27  * Unit tests for any listenable future that chains other listenable futures.
     28  * Unit tests need only override buildChainingFuture and getSuccessfulResult,
     29  * but they can add custom tests as needed.
     30  *
     31  * @author Nishant Thakkar
     32  */
     33 public abstract class AbstractChainedListenableFutureTest<T> extends TestCase {
     34   protected static final int EXCEPTION_DATA = -1;
     35   protected static final int VALID_INPUT_DATA = 1;
     36   protected static final Exception EXCEPTION = new Exception("Test exception");
     37 
     38   protected SettableFuture<Integer> inputFuture;
     39   protected ListenableFuture<T> resultFuture;
     40   protected MockFutureListener listener;
     41 
     42   @Override
     43   protected void setUp() throws Exception {
     44     super.setUp();
     45 
     46     inputFuture = SettableFuture.create();
     47     resultFuture = buildChainingFuture(inputFuture);
     48     listener = new MockFutureListener(resultFuture);
     49 
     50   }
     51 
     52   public void testFutureGetBeforeCallback() throws Exception {
     53     // Verify that get throws a timeout exception before the callback is called.
     54     try {
     55       resultFuture.get(1L, TimeUnit.MILLISECONDS);
     56       fail("The data is not yet ready, so a TimeoutException is expected");
     57     } catch (TimeoutException expected) {}
     58   }
     59 
     60   public void testFutureGetThrowsWrappedException() throws Exception {
     61     inputFuture.setException(EXCEPTION);
     62     listener.assertException(EXCEPTION);
     63   }
     64 
     65   public void testFutureGetThrowsWrappedError() throws Exception {
     66     Error error = new Error();
     67     try {
     68       inputFuture.setException(error);
     69       fail("Expected an Error to be thrown");  // COV_NF_LINE
     70     } catch (Error expected) {
     71       assertSame(error, expected);
     72     }
     73 
     74     // Verify that get throws an ExecutionException, caused by an Error, when
     75     // the callback is called.
     76     listener.assertException(error);
     77   }
     78 
     79   public void testAddListenerAfterCallback() throws Throwable {
     80     inputFuture.set(VALID_INPUT_DATA);
     81 
     82     listener.assertSuccess(getSuccessfulResult());
     83   }
     84 
     85   public void testFutureBeforeCallback() throws Throwable {
     86     inputFuture.set(VALID_INPUT_DATA);
     87 
     88     listener.assertSuccess(getSuccessfulResult());
     89   }
     90 
     91   /**
     92    * Override to return a chaining listenableFuture that returns the result of
     93    * getSuccessfulResult() when inputFuture returns VALID_INPUT_DATA, and sets
     94    * the exception to EXCEPTION in all other cases.
     95    */
     96   protected abstract ListenableFuture<T> buildChainingFuture(
     97       ListenableFuture<Integer> inputFuture);
     98 
     99   /**
    100    * Override to return the result when VALID_INPUT_DATA is passed in to
    101    * the chaining listenableFuture
    102    */
    103   protected abstract T getSuccessfulResult();
    104 }
    105