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