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