Home | History | Annotate | Download | only in concurrent
      1 /*
      2  * Copyright (C) 2011 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 of
      6  * 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;
     18 
     19 import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
     20 import static com.google.common.util.concurrent.Runnables.doNothing;
     21 
     22 import com.google.common.base.Predicate;
     23 import com.google.common.base.Predicates;
     24 import com.google.common.collect.ImmutableList;
     25 import com.google.common.collect.Iterables;
     26 import com.google.common.collect.Lists;
     27 
     28 import junit.framework.TestCase;
     29 
     30 import java.util.Collection;
     31 import java.util.List;
     32 import java.util.concurrent.Callable;
     33 import java.util.concurrent.ExecutionException;
     34 import java.util.concurrent.ExecutorService;
     35 import java.util.concurrent.Future;
     36 import java.util.concurrent.TimeUnit;
     37 import java.util.concurrent.TimeoutException;
     38 
     39 /**
     40  * Test for {@link WrappingExecutorService}
     41  *
     42  * @author Chris Nokleberg
     43  */
     44 public class WrappingExecutorServiceTest extends TestCase {
     45   private static final String RESULT_VALUE = "ran";
     46   // Uninteresting delegations
     47   public void testDelegations() throws InterruptedException {
     48     MockExecutor mock = new MockExecutor();
     49     TestExecutor testExecutor = new TestExecutor(mock);
     50     assertFalse(testExecutor.awaitTermination(10, TimeUnit.MILLISECONDS));
     51     mock.assertLastMethodCalled("awaitTermination");
     52     assertFalse(testExecutor.isTerminated());
     53     mock.assertLastMethodCalled("isTerminated");
     54     assertFalse(testExecutor.isShutdown());
     55     mock.assertLastMethodCalled("isShutdown");
     56     testExecutor.shutdown();
     57     mock.assertLastMethodCalled("shutdown");
     58     List<Runnable> list = testExecutor.shutdownNow();
     59     mock.assertLastMethodCalled("shutdownNow");
     60     assertEquals(ImmutableList.of(), list);
     61   }
     62 
     63   public void testExecute() {
     64     MockExecutor mock = new MockExecutor();
     65     TestExecutor testExecutor = new TestExecutor(mock);
     66     testExecutor.execute(doNothing());
     67     mock.assertLastMethodCalled("execute");
     68   }
     69 
     70   public void testSubmit() throws InterruptedException, ExecutionException {
     71     {
     72       MockExecutor mock = new MockExecutor();
     73       TestExecutor testExecutor = new TestExecutor(mock);
     74       Future<?> f = testExecutor.submit(doNothing());
     75       mock.assertLastMethodCalled("submit");
     76       f.get();
     77     }
     78     {
     79       MockExecutor mock = new MockExecutor();
     80       TestExecutor testExecutor = new TestExecutor(mock);
     81       Future<String> f = testExecutor.submit(doNothing(), RESULT_VALUE);
     82       mock.assertLastMethodCalled("submit");
     83       assertEquals(RESULT_VALUE, f.get());
     84     }
     85     {
     86       MockExecutor mock = new MockExecutor();
     87       TestExecutor testExecutor = new TestExecutor(mock);
     88       Callable<String> task = Callables.returning(RESULT_VALUE);
     89       Future<String> f = testExecutor.submit(task);
     90       mock.assertLastMethodCalled("submit");
     91       assertEquals(RESULT_VALUE, f.get());
     92     }
     93   }
     94 
     95   public void testInvokeAll() throws InterruptedException, ExecutionException {
     96     List<Callable<String>> tasks = createTasks(3);
     97     {
     98       MockExecutor mock = new MockExecutor();
     99       TestExecutor testExecutor = new TestExecutor(mock);
    100       List<Future<String>> futures = testExecutor.invokeAll(tasks);
    101       mock.assertLastMethodCalled("invokeAll");
    102       checkResults(futures);
    103     }
    104     {
    105       MockExecutor mock = new MockExecutor();
    106       TimeUnit unit = TimeUnit.SECONDS;
    107       long timeout = 5;
    108       TestExecutor testExecutor = new TestExecutor(mock);
    109       List<Future<String>> futures = testExecutor.invokeAll(tasks, timeout, unit);
    110       mock.assertMethodWithTimeout("invokeAll", timeout, unit);
    111       checkResults(futures);
    112     }
    113   }
    114 
    115   public void testInvokeAny() throws InterruptedException, ExecutionException, TimeoutException {
    116     List<Callable<String>> tasks = createTasks(3);
    117     {
    118       MockExecutor mock = new MockExecutor();
    119       TestExecutor testExecutor = new TestExecutor(mock);
    120       String s = testExecutor.invokeAny(tasks);
    121       assertEquals("ran0", s);
    122       mock.assertLastMethodCalled("invokeAny");
    123     }
    124     {
    125       MockExecutor mock = new MockExecutor();
    126       TimeUnit unit = TimeUnit.SECONDS;
    127       long timeout = 5;
    128       TestExecutor testExecutor = new TestExecutor(mock);
    129       String s = testExecutor.invokeAny(tasks, timeout, unit);
    130       assertEquals(RESULT_VALUE + "0", s);
    131       mock.assertMethodWithTimeout("invokeAny", timeout, unit);
    132     }
    133   }
    134 
    135   private static void checkResults(List<Future<String>> futures)
    136       throws InterruptedException, ExecutionException {
    137     for (int i = 0; i < futures.size(); i++) {
    138       assertEquals(RESULT_VALUE + i, futures.get(i).get());
    139     }
    140   }
    141 
    142   private static List<Callable<String>> createTasks(int n) {
    143     List<Callable<String>> callables = Lists.newArrayList();
    144     for (int i = 0; i < n; i++) {
    145       callables.add(Callables.returning(RESULT_VALUE + i));
    146     }
    147     return callables;
    148   }
    149 
    150   private static final class WrappedCallable<T> implements Callable<T> {
    151     private final Callable<T> delegate;
    152 
    153     public WrappedCallable(Callable<T> delegate) {
    154       this.delegate = delegate;
    155     }
    156 
    157     @Override
    158     public T call() throws Exception {
    159       return delegate.call();
    160     }
    161   }
    162 
    163   private static final class WrappedRunnable implements Runnable {
    164     private final Runnable delegate;
    165 
    166     public WrappedRunnable(Runnable delegate) {
    167       this.delegate = delegate;
    168     }
    169 
    170     @Override
    171     public void run() {
    172       delegate.run();
    173     }
    174   }
    175 
    176   private static final class TestExecutor extends WrappingExecutorService {
    177     public TestExecutor(MockExecutor mock) {
    178       super(mock);
    179     }
    180 
    181     @Override
    182     protected <T> Callable<T> wrapTask(Callable<T> callable) {
    183       return new WrappedCallable<T>(callable);
    184     }
    185 
    186     @Override protected Runnable wrapTask(Runnable command) {
    187       return new WrappedRunnable(command);
    188     }
    189   }
    190 
    191   // TODO: If this test can ever depend on EasyMock or the like, use it instead.
    192   private static final class MockExecutor implements ExecutorService {
    193     private String lastMethodCalled = "";
    194     private long lastTimeoutInMillis = -1;
    195     private ExecutorService inline = newDirectExecutorService();
    196 
    197     public void assertLastMethodCalled(String method) {
    198       assertEquals(method, lastMethodCalled);
    199     }
    200 
    201     public void assertMethodWithTimeout(String method, long timeout, TimeUnit unit) {
    202       assertLastMethodCalled(method + "Timeout");
    203       assertEquals(unit.toMillis(timeout), lastTimeoutInMillis);
    204     }
    205 
    206     @Override
    207     public boolean awaitTermination(long timeout, TimeUnit unit) {
    208       lastMethodCalled = "awaitTermination";
    209       return false;
    210     }
    211 
    212     @Override
    213     public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
    214         throws InterruptedException {
    215       lastMethodCalled = "invokeAll";
    216       assertTaskWrapped(tasks);
    217       return inline.invokeAll(tasks);
    218     }
    219 
    220     @Override
    221     public <T> List<Future<T>> invokeAll(
    222         Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
    223         throws InterruptedException {
    224       assertTaskWrapped(tasks);
    225       lastMethodCalled = "invokeAllTimeout";
    226       lastTimeoutInMillis = unit.toMillis(timeout);
    227       return inline.invokeAll(tasks, timeout, unit);
    228     }
    229 
    230     // Define the invokeAny methods to invoke the first task
    231     @Override
    232     public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
    233         throws ExecutionException, InterruptedException {
    234       assertTaskWrapped(tasks);
    235       lastMethodCalled = "invokeAny";
    236       return inline.submit(Iterables.get(tasks, 0)).get();
    237     }
    238 
    239     @Override
    240     public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
    241         throws ExecutionException, InterruptedException, TimeoutException {
    242       assertTaskWrapped(tasks);
    243       lastMethodCalled = "invokeAnyTimeout";
    244       lastTimeoutInMillis = unit.toMillis(timeout);
    245       return inline.submit(Iterables.get(tasks, 0)).get(timeout, unit);
    246     }
    247 
    248     @Override
    249     public boolean isShutdown() {
    250       lastMethodCalled = "isShutdown";
    251       return false;
    252     }
    253 
    254     @Override
    255     public boolean isTerminated() {
    256       lastMethodCalled = "isTerminated";
    257       return false;
    258     }
    259 
    260     @Override
    261     public void shutdown() {
    262       lastMethodCalled = "shutdown";
    263     }
    264 
    265     @Override
    266     public List<Runnable> shutdownNow() {
    267       lastMethodCalled = "shutdownNow";
    268       return ImmutableList.of();
    269     }
    270 
    271     @Override
    272     public <T> Future<T> submit(Callable<T> task) {
    273       lastMethodCalled = "submit";
    274       assertTrue(task instanceof WrappedCallable);
    275       return inline.submit(task);
    276     }
    277 
    278     @Override
    279     public Future<?> submit(Runnable task) {
    280       lastMethodCalled = "submit";
    281       assertTrue(task instanceof WrappedRunnable);
    282       return inline.submit(task);
    283     }
    284 
    285     @Override
    286     public <T> Future<T> submit(Runnable task, T result) {
    287       lastMethodCalled = "submit";
    288       assertTrue(task instanceof WrappedRunnable);
    289       return inline.submit(task, result);
    290     }
    291 
    292     @Override
    293     public void execute(Runnable command) {
    294       lastMethodCalled = "execute";
    295       assertTrue(command instanceof WrappedRunnable);
    296       inline.execute(command);
    297     }
    298 
    299     private static <T> void assertTaskWrapped(
    300         Collection<? extends Callable<T>> tasks) {
    301       Predicate<Object> p = Predicates.instanceOf(WrappedCallable.class);
    302       assertTrue(Iterables.all(tasks, p));
    303     }
    304 
    305   }
    306 }
    307