/**
* Copyright (c) 2012-2016 André Bargull
* Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms.
*
* <https://github.com/anba/es6draft>
*/
package com.github.anba.es6draft.util;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.runners.Parameterized;
import org.junit.runners.Suite;
import org.junit.runners.model.RunnerScheduler;
/**
* JUnit {@link Suite} implementation similar to {@link Parameterized} with support for multiple
* threads
*
* @see <a href="http://hwellmann.blogspot.de/2009/12/running-parameterized-junit-tests-in.html">
* http://hwellmann.blogspot.de/2009/12/running-parameterized-junit-tests-in.html</a>
*/
public class Parallelized extends Parameterized {
private static final class ThreadPoolScheduler implements RunnerScheduler {
private final ExecutorService executor;
public ThreadPoolScheduler(ExecutorService executor) {
this.executor = executor;
}
@Override
public void finished() {
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public void schedule(Runnable childStatement) {
executor.submit(childStatement);
}
}
public Parallelized(Class<?> klass) throws Throwable {
super(klass);
setScheduler(new ThreadPoolScheduler(createExecutor(klass)));
}
protected ExecutorService createExecutor(Class<?> klass) {
int numThreads = numberOfThreads(klass);
return Executors.newFixedThreadPool(numThreads);
}
protected int numberOfThreads(Class<?> klass) {
Concurrency concurrency = klass.getAnnotation(Concurrency.class);
int threads;
int maxThreads;
float factor;
if (concurrency != null) {
threads = concurrency.threads();
maxThreads = concurrency.maxThreads();
factor = concurrency.factor();
} else {
threads = getDefaultValue(Concurrency.class, "threads", Integer.class);
maxThreads = getDefaultValue(Concurrency.class, "maxThreads", Integer.class);
factor = getDefaultValue(Concurrency.class, "factor", Float.class);
}
threads = threads > 0 ? threads : Runtime.getRuntime().availableProcessors();
maxThreads = Math.max(maxThreads, 1);
factor = Math.max(factor, 0);
return Math.min(Math.max((int) Math.round(threads * factor), 1), maxThreads);
}
private static <T> T getDefaultValue(Class<?> annotation, String methodName, Class<T> valueType) {
assert annotation.isAnnotation();
try {
return valueType.cast(annotation.getMethod(methodName).getDefaultValue());
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}