Created
June 9, 2016 13:10
-
-
Save havardh/5d4fc0c9bca35337070bf1f2f8342384 to your computer and use it in GitHub Desktop.
Concurrent test helper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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