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