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