Skip to content

Instantly share code, notes, and snippets.

@havardh
Created June 9, 2016 13:10
Show Gist options
  • Save havardh/5d4fc0c9bca35337070bf1f2f8342384 to your computer and use it in GitHub Desktop.
Save havardh/5d4fc0c9bca35337070bf1f2f8342384 to your computer and use it in GitHub Desktop.
Concurrent test helper
import static java.util.Arrays.asList;
import static com.google.common.collect.FluentIterable.from;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.google.common.base.Function;
import com.google.common.base.Optional;
public class ConcurrentTestHelper {
public static abstract class Callback {
public abstract void apply();
}
public static void assertThreadSafe(int numberOfThreads, Callback callbacks) throws Exception {
assertThreadSafe(numberOfThreads, new Callback[] {callbacks});
}
public static void assertThreadSafe(Callback ...callbacks) throws Exception{
assertThreadSafe(callbacks.length, callbacks);
}
private static void assertThreadSafe(int numberOfThreads, final Callback...callbacks) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
List<Future<Optional<Exception>>> futureExceptions = createCallables(numberOfThreads, executor, callbacks);
executor.shutdown();
for (Future<Optional<Exception>> exceptionFuture : futureExceptions) {
if (exceptionFuture.get().isPresent()) {
throw exceptionFuture.get().get();
}
}
}
private static List<Future<Optional<Exception>>> createCallables(
int numberOfThreads,
ExecutorService executor,
Callback[] callbacks
) {
List<Callable<Optional<Exception>>> callables = from(asList(callbacks))
.transform(new Function<Callback, Callable<Optional<Exception>>>() {
@Override
public Callable<Optional<Exception>> apply(Callback callback) {
return createCallable(callback);
}
}).toList();
List<Future<Optional<Exception>>> futureExceptions = new ArrayList<>();
if (callables.size() == 1) {
Callable callable = callables.get(0);
for (int i=0; i<numberOfThreads; i++) {
futureExceptions.add(executor.submit(callable));
}
} else {
for (Callable<Optional<Exception>> callable : callables) {
futureExceptions.add(executor.submit(callable));
}
}
return futureExceptions;
}
private static Callable<Optional<Exception>> createCallable(final Callback callback) {
return new Callable<Optional<Exception>>() {
@Override
public Optional<Exception> call() throws Exception {
try {
callback.apply();
return Optional.absent();
} catch (Exception e) {
return Optional.of(e);
}
}
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment