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