1b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpackage org.junit.experimental;
2b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
3b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.ArrayList;
4b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.List;
5b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.concurrent.Callable;
6b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.concurrent.ExecutorService;
7b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.concurrent.Executors;
8b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport java.util.concurrent.Future;
9b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
10b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runner.Computer;
11b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runner.Runner;
12b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.ParentRunner;
13b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.model.InitializationError;
14b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.model.RunnerBuilder;
15b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.model.RunnerScheduler;
16b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
17b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpublic class ParallelComputer extends Computer {
18b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private final boolean fClasses;
19b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
20b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private final boolean fMethods;
21b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
22b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public ParallelComputer(boolean classes, boolean methods) {
23b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		fClasses= classes;
24b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		fMethods= methods;
25b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
26b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
27b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public static Computer classes() {
28b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return new ParallelComputer(true, false);
29b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
30b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
31b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public static Computer methods() {
32b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return new ParallelComputer(false, true);
33b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
34b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
35b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	private static <T> Runner parallelize(Runner runner) {
36b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		if (runner instanceof ParentRunner<?>) {
37b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			((ParentRunner<?>) runner).setScheduler(new RunnerScheduler() {
38b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				private final List<Future<Object>> fResults= new ArrayList<Future<Object>>();
39b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
40b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				private final ExecutorService fService= Executors
41b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						.newCachedThreadPool();
42b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
43b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				public void schedule(final Runnable childStatement) {
44b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot					fResults.add(fService.submit(new Callable<Object>() {
45b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						public Object call() throws Exception {
46b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot							childStatement.run();
47b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot							return null;
48b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						}
49b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot					}));
50b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				}
51b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
52b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				public void finished() {
53b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot					for (Future<Object> each : fResults)
54b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						try {
55b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot							each.get();
56b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						} catch (Exception e) {
57b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot							e.printStackTrace();
58b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						}
59b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				}
60b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			});
61b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		}
62b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return runner;
63b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
64b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
65b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	@Override
66b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public Runner getSuite(RunnerBuilder builder, java.lang.Class<?>[] classes)
67b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			throws InitializationError {
68b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		Runner suite= super.getSuite(builder, classes);
69b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return fClasses ? parallelize(suite) : suite;
70b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
71b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
72b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	@Override
73b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	protected Runner getRunner(RunnerBuilder builder, Class<?> testClass)
74b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			throws Throwable {
75b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		Runner runner= super.getRunner(builder, testClass);
76b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return fMethods ? parallelize(runner) : runner;
77b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
78b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot}
79