blob: 900bd5d78a54654baef8ae0bd1fe946fff28a0f8 [file] [log] [blame]
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.util.concurrent;
import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
import static com.google.common.util.concurrent.Runnables.doNothing;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import junit.framework.TestCase;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Test for {@link WrappingExecutorService}
*
* @author Chris Nokleberg
*/
public class WrappingExecutorServiceTest extends TestCase {
private static final String RESULT_VALUE = "ran";
// Uninteresting delegations
public void testDelegations() throws InterruptedException {
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
assertFalse(testExecutor.awaitTermination(10, TimeUnit.MILLISECONDS));
mock.assertLastMethodCalled("awaitTermination");
assertFalse(testExecutor.isTerminated());
mock.assertLastMethodCalled("isTerminated");
assertFalse(testExecutor.isShutdown());
mock.assertLastMethodCalled("isShutdown");
testExecutor.shutdown();
mock.assertLastMethodCalled("shutdown");
List<Runnable> list = testExecutor.shutdownNow();
mock.assertLastMethodCalled("shutdownNow");
assertEquals(ImmutableList.of(), list);
}
public void testExecute() {
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
testExecutor.execute(doNothing());
mock.assertLastMethodCalled("execute");
}
public void testSubmit() throws InterruptedException, ExecutionException {
{
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
Future<?> f = testExecutor.submit(doNothing());
mock.assertLastMethodCalled("submit");
f.get();
}
{
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
Future<String> f = testExecutor.submit(doNothing(), RESULT_VALUE);
mock.assertLastMethodCalled("submit");
assertEquals(RESULT_VALUE, f.get());
}
{
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
Callable<String> task = Callables.returning(RESULT_VALUE);
Future<String> f = testExecutor.submit(task);
mock.assertLastMethodCalled("submit");
assertEquals(RESULT_VALUE, f.get());
}
}
public void testInvokeAll() throws InterruptedException, ExecutionException {
List<Callable<String>> tasks = createTasks(3);
{
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
List<Future<String>> futures = testExecutor.invokeAll(tasks);
mock.assertLastMethodCalled("invokeAll");
checkResults(futures);
}
{
MockExecutor mock = new MockExecutor();
TimeUnit unit = TimeUnit.SECONDS;
long timeout = 5;
TestExecutor testExecutor = new TestExecutor(mock);
List<Future<String>> futures = testExecutor.invokeAll(tasks, timeout, unit);
mock.assertMethodWithTimeout("invokeAll", timeout, unit);
checkResults(futures);
}
}
public void testInvokeAny() throws InterruptedException, ExecutionException, TimeoutException {
List<Callable<String>> tasks = createTasks(3);
{
MockExecutor mock = new MockExecutor();
TestExecutor testExecutor = new TestExecutor(mock);
String s = testExecutor.invokeAny(tasks);
assertEquals("ran0", s);
mock.assertLastMethodCalled("invokeAny");
}
{
MockExecutor mock = new MockExecutor();
TimeUnit unit = TimeUnit.SECONDS;
long timeout = 5;
TestExecutor testExecutor = new TestExecutor(mock);
String s = testExecutor.invokeAny(tasks, timeout, unit);
assertEquals(RESULT_VALUE + "0", s);
mock.assertMethodWithTimeout("invokeAny", timeout, unit);
}
}
private static void checkResults(List<Future<String>> futures)
throws InterruptedException, ExecutionException {
for (int i = 0; i < futures.size(); i++) {
assertEquals(RESULT_VALUE + i, futures.get(i).get());
}
}
private static List<Callable<String>> createTasks(int n) {
List<Callable<String>> callables = Lists.newArrayList();
for (int i = 0; i < n; i++) {
callables.add(Callables.returning(RESULT_VALUE + i));
}
return callables;
}
private static final class WrappedCallable<T> implements Callable<T> {
private final Callable<T> delegate;
public WrappedCallable(Callable<T> delegate) {
this.delegate = delegate;
}
@Override
public T call() throws Exception {
return delegate.call();
}
}
private static final class WrappedRunnable implements Runnable {
private final Runnable delegate;
public WrappedRunnable(Runnable delegate) {
this.delegate = delegate;
}
@Override
public void run() {
delegate.run();
}
}
private static final class TestExecutor extends WrappingExecutorService {
public TestExecutor(MockExecutor mock) {
super(mock);
}
@Override
protected <T> Callable<T> wrapTask(Callable<T> callable) {
return new WrappedCallable<T>(callable);
}
@Override protected Runnable wrapTask(Runnable command) {
return new WrappedRunnable(command);
}
}
// TODO: If this test can ever depend on EasyMock or the like, use it instead.
private static final class MockExecutor implements ExecutorService {
private String lastMethodCalled = "";
private long lastTimeoutInMillis = -1;
private ExecutorService inline = newDirectExecutorService();
public void assertLastMethodCalled(String method) {
assertEquals(method, lastMethodCalled);
}
public void assertMethodWithTimeout(String method, long timeout, TimeUnit unit) {
assertLastMethodCalled(method + "Timeout");
assertEquals(unit.toMillis(timeout), lastTimeoutInMillis);
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) {
lastMethodCalled = "awaitTermination";
return false;
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
lastMethodCalled = "invokeAll";
assertTaskWrapped(tasks);
return inline.invokeAll(tasks);
}
@Override
public <T> List<Future<T>> invokeAll(
Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws InterruptedException {
assertTaskWrapped(tasks);
lastMethodCalled = "invokeAllTimeout";
lastTimeoutInMillis = unit.toMillis(timeout);
return inline.invokeAll(tasks, timeout, unit);
}
// Define the invokeAny methods to invoke the first task
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws ExecutionException, InterruptedException {
assertTaskWrapped(tasks);
lastMethodCalled = "invokeAny";
return inline.submit(Iterables.get(tasks, 0)).get();
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws ExecutionException, InterruptedException, TimeoutException {
assertTaskWrapped(tasks);
lastMethodCalled = "invokeAnyTimeout";
lastTimeoutInMillis = unit.toMillis(timeout);
return inline.submit(Iterables.get(tasks, 0)).get(timeout, unit);
}
@Override
public boolean isShutdown() {
lastMethodCalled = "isShutdown";
return false;
}
@Override
public boolean isTerminated() {
lastMethodCalled = "isTerminated";
return false;
}
@Override
public void shutdown() {
lastMethodCalled = "shutdown";
}
@Override
public List<Runnable> shutdownNow() {
lastMethodCalled = "shutdownNow";
return ImmutableList.of();
}
@Override
public <T> Future<T> submit(Callable<T> task) {
lastMethodCalled = "submit";
assertTrue(task instanceof WrappedCallable);
return inline.submit(task);
}
@Override
public Future<?> submit(Runnable task) {
lastMethodCalled = "submit";
assertTrue(task instanceof WrappedRunnable);
return inline.submit(task);
}
@Override
public <T> Future<T> submit(Runnable task, T result) {
lastMethodCalled = "submit";
assertTrue(task instanceof WrappedRunnable);
return inline.submit(task, result);
}
@Override
public void execute(Runnable command) {
lastMethodCalled = "execute";
assertTrue(command instanceof WrappedRunnable);
inline.execute(command);
}
private static <T> void assertTaskWrapped(
Collection<? extends Callable<T>> tasks) {
Predicate<Object> p = Predicates.instanceOf(WrappedCallable.class);
assertTrue(Iterables.all(tasks, p));
}
}
}