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 junit.framework.TestCase;
     20 
     21 import java.util.concurrent.Callable;
     22 import java.util.concurrent.CountDownLatch;
     23 import java.util.concurrent.ExecutionException;
     24 import java.util.concurrent.ExecutorService;
     25 import java.util.concurrent.Executors;
     26 import java.util.concurrent.TimeUnit;
     27 
     28 /**
     29  * Test case for {@link ListenableFutureTask}.
     30  *
     31  * @author Sven Mawson
     32  */
     33 public class ListenableFutureTaskTest extends TestCase {
     34 
     35   private ExecutorService exec;
     36 
     37   protected final CountDownLatch runLatch = new CountDownLatch(1);
     38   protected final CountDownLatch taskLatch = new CountDownLatch(1);
     39   protected final CountDownLatch listenerLatch = new CountDownLatch(1);
     40 
     41   protected volatile boolean throwException = false;
     42 
     43   protected final ListenableFutureTask<Integer> task =
     44       ListenableFutureTask.create(new Callable<Integer>() {
     45     @Override
     46     public Integer call() throws Exception {
     47       runLatch.countDown();
     48       taskLatch.await();
     49       if (throwException) {
     50         throw new IllegalStateException("Fail");
     51       }
     52       return 25;
     53     }
     54   });
     55 
     56   @Override
     57   protected void setUp() throws Exception {
     58     super.setUp();
     59 
     60     exec = Executors.newCachedThreadPool();
     61 
     62     task.addListener(new Runnable() {
     63       @Override
     64       public void run() {
     65         listenerLatch.countDown();
     66       }
     67     }, MoreExecutors.sameThreadExecutor());
     68   }
     69 
     70   @Override
     71   protected void tearDown() throws Exception {
     72     if (exec != null) {
     73       exec.shutdown();
     74     }
     75 
     76     super.tearDown();
     77   }
     78 
     79   public void testListenerDoesNotRunUntilTaskCompletes() throws Exception {
     80 
     81     // Test default state of not started.
     82     assertEquals(1, listenerLatch.getCount());
     83     assertFalse(task.isDone());
     84     assertFalse(task.isCancelled());
     85 
     86     // Start the task to put it in the RUNNING state.  Have to use a separate
     87     // thread because the task will block on the task latch after unblocking
     88     // the run latch.
     89     exec.execute(task);
     90     runLatch.await();
     91     assertEquals(1, listenerLatch.getCount());
     92     assertFalse(task.isDone());
     93     assertFalse(task.isCancelled());
     94 
     95     // Finish the task by unblocking the task latch.  Then wait for the
     96     // listener to be called by blocking on the listener latch.
     97     taskLatch.countDown();
     98     assertEquals(25, task.get().intValue());
     99     assertTrue(listenerLatch.await(5, TimeUnit.SECONDS));
    100     assertTrue(task.isDone());
    101     assertFalse(task.isCancelled());
    102   }
    103 
    104   public void testListenerCalledOnException() throws Exception {
    105     throwException = true;
    106 
    107     // Start up the task and unblock the latch to finish the task.
    108     exec.execute(task);
    109     runLatch.await();
    110     taskLatch.countDown();
    111 
    112     try {
    113       task.get(5, TimeUnit.SECONDS);
    114       fail("Should have propagated the failure.");
    115     } catch (ExecutionException e) {
    116       assertEquals(IllegalStateException.class, e.getCause().getClass());
    117     }
    118 
    119     assertTrue(listenerLatch.await(5, TimeUnit.SECONDS));
    120     assertTrue(task.isDone());
    121     assertFalse(task.isCancelled());
    122   }
    123 
    124   public void testListenerCalledOnCancelFromNotRunning() throws Exception {
    125     task.cancel(false);
    126     assertTrue(task.isDone());
    127     assertTrue(task.isCancelled());
    128     assertEquals(1, runLatch.getCount());
    129 
    130     // Wait for the listeners to be called, don't rely on the same-thread exec.
    131     listenerLatch.await(5, TimeUnit.SECONDS);
    132     assertTrue(task.isDone());
    133     assertTrue(task.isCancelled());
    134 
    135     // Make sure we didn't run anything.
    136     assertEquals(1, runLatch.getCount());
    137   }
    138 
    139   public void testListenerCalledOnCancelFromRunning() throws Exception {
    140     exec.execute(task);
    141     runLatch.await();
    142 
    143     // Task has started up, cancel it while it's running.
    144     task.cancel(true);
    145     assertTrue(task.isDone());
    146     assertTrue(task.isCancelled());
    147     assertEquals(1, taskLatch.getCount());
    148 
    149     // Wait for the listeners to be called.
    150     listenerLatch.await(5, TimeUnit.SECONDS);
    151     assertTrue(task.isDone());
    152     assertTrue(task.isCancelled());
    153     assertEquals(1, taskLatch.getCount());
    154   }
    155 }
    156