WrappingExecutorServiceTest.java revision 0888a09821a98ac0680fad765217302858e70fa4
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
17package com.google.common.util.concurrent;
18
19import com.google.common.base.Predicate;
20import com.google.common.base.Predicates;
21import com.google.common.collect.ImmutableList;
22import com.google.common.collect.Iterables;
23import com.google.common.collect.Lists;
24
25import junit.framework.TestCase;
26
27import java.util.Collection;
28import java.util.List;
29import java.util.concurrent.Callable;
30import java.util.concurrent.ExecutionException;
31import java.util.concurrent.ExecutorService;
32import java.util.concurrent.Future;
33import java.util.concurrent.TimeUnit;
34import java.util.concurrent.TimeoutException;
35
36/**
37 * Test for {@link WrappingExecutorService}
38 *
39 * @author Chris Nokleberg
40 */
41public 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