Home | History | Annotate | Download | only in concurrent
      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