1package org.junit.runners;
2
3import static org.junit.internal.runners.rules.RuleFieldValidator.CLASS_RULE_VALIDATOR;
4
5import java.lang.annotation.Annotation;
6import java.lang.reflect.Method;
7import java.util.ArrayList;
8import java.util.Collections;
9import java.util.Comparator;
10import java.util.Iterator;
11import java.util.List;
12
13import org.junit.AfterClass;
14import org.junit.BeforeClass;
15import org.junit.ClassRule;
16import org.junit.Rule;
17import org.junit.internal.AssumptionViolatedException;
18import org.junit.internal.runners.model.EachTestNotifier;
19import org.junit.internal.runners.statements.RunAfters;
20import org.junit.internal.runners.statements.RunBefores;
21import org.junit.rules.RunRules;
22import org.junit.rules.TestRule;
23import org.junit.runner.Description;
24import org.junit.runner.Runner;
25import org.junit.runner.manipulation.Filter;
26import org.junit.runner.manipulation.Filterable;
27import org.junit.runner.manipulation.NoTestsRemainException;
28import org.junit.runner.manipulation.Sortable;
29import org.junit.runner.manipulation.Sorter;
30import org.junit.runner.notification.RunNotifier;
31import org.junit.runner.notification.StoppedByUserException;
32import org.junit.runners.model.FrameworkMethod;
33import org.junit.runners.model.InitializationError;
34import org.junit.runners.model.MultipleFailureException;
35import org.junit.runners.model.RunnerScheduler;
36import org.junit.runners.model.Statement;
37import org.junit.runners.model.TestClass;
38
39/**
40 * Provides most of the functionality specific to a Runner that implements a
41 * "parent node" in the test tree, with children defined by objects of some data
42 * type {@code T}. (For {@link BlockJUnit4ClassRunner}, {@code T} is
43 * {@link Method} . For {@link Suite}, {@code T} is {@link Class}.) Subclasses
44 * must implement finding the children of the node, describing each child, and
45 * running each child. ParentRunner will filter and sort children, handle
46 * {@code @BeforeClass} and {@code @AfterClass} methods,
47 * handle annotated {@link ClassRule}s, create a composite
48 * {@link Description}, and run children sequentially.
49 */
50public abstract class ParentRunner<T> extends Runner implements Filterable,
51		Sortable {
52	private final TestClass fTestClass;
53
54	private Sorter fSorter= Sorter.NULL;
55
56	private List<T> fFilteredChildren= null;
57
58	private RunnerScheduler fScheduler= new RunnerScheduler() {
59		public void schedule(Runnable childStatement) {
60			childStatement.run();
61		}
62
63		public void finished() {
64			// do nothing
65		}
66	};
67
68	/**
69	 * Constructs a new {@code ParentRunner} that will run {@code @TestClass}
70	 * @throws InitializationError
71	 */
72	protected ParentRunner(Class<?> testClass) throws InitializationError {
73		fTestClass= new TestClass(testClass);
74		validate();
75	}
76
77	//
78	// Must be overridden
79	//
80
81	/**
82	 * Returns a list of objects that define the children of this Runner.
83	 */
84	protected abstract List<T> getChildren();
85
86	/**
87	 * Returns a {@link Description} for {@code child}, which can be assumed to
88	 * be an element of the list returned by {@link ParentRunner#getChildren()}
89	 */
90	protected abstract Description describeChild(T child);
91
92	/**
93	 * Runs the test corresponding to {@code child}, which can be assumed to be
94	 * an element of the list returned by {@link ParentRunner#getChildren()}.
95	 * Subclasses are responsible for making sure that relevant test events are
96	 * reported through {@code notifier}
97	 */
98	protected abstract void runChild(T child, RunNotifier notifier);
99
100	//
101	// May be overridden
102	//
103
104	/**
105	 * Adds to {@code errors} a throwable for each problem noted with the test class (available from {@link #getTestClass()}).
106	 * Default implementation adds an error for each method annotated with
107	 * {@code @BeforeClass} or {@code @AfterClass} that is not
108	 * {@code public static void} with no arguments.
109	 */
110	protected void collectInitializationErrors(List<Throwable> errors) {
111		validatePublicVoidNoArgMethods(BeforeClass.class, true, errors);
112		validatePublicVoidNoArgMethods(AfterClass.class, true, errors);
113		validateClassRules(errors);
114	}
115
116	/**
117	 * Adds to {@code errors} if any method in this class is annotated with
118	 * {@code annotation}, but:
119	 * <ul>
120	 * <li>is not public, or
121	 * <li>takes parameters, or
122	 * <li>returns something other than void, or
123	 * <li>is static (given {@code isStatic is false}), or
124	 * <li>is not static (given {@code isStatic is true}).
125	 */
126	protected void validatePublicVoidNoArgMethods(Class<? extends Annotation> annotation,
127			boolean isStatic, List<Throwable> errors) {
128		List<FrameworkMethod> methods= getTestClass().getAnnotatedMethods(annotation);
129
130		for (FrameworkMethod eachTestMethod : methods)
131			eachTestMethod.validatePublicVoidNoArg(isStatic, errors);
132	}
133
134	private void validateClassRules(List<Throwable> errors) {
135		CLASS_RULE_VALIDATOR.validate(getTestClass(), errors);
136	}
137
138	/**
139	 * Constructs a {@code Statement} to run all of the tests in the test class. Override to add pre-/post-processing.
140	 * Here is an outline of the implementation:
141	 * <ul>
142	 * <li>Call {@link #runChild(Object, RunNotifier)} on each object returned by {@link #getChildren()} (subject to any imposed filter and sort).</li>
143	 * <li>ALWAYS run all non-overridden {@code @BeforeClass} methods on this class
144	 * and superclasses before the previous step; if any throws an
145	 * Exception, stop execution and pass the exception on.
146	 * <li>ALWAYS run all non-overridden {@code @AfterClass} methods on this class
147	 * and superclasses before any of the previous steps; all AfterClass methods are
148	 * always executed: exceptions thrown by previous steps are combined, if
149	 * necessary, with exceptions from AfterClass methods into a
150	 * {@link MultipleFailureException}.
151	 * </ul>
152	 * @param notifier
153	 * @return {@code Statement}
154	 */
155	protected Statement classBlock(final RunNotifier notifier) {
156		Statement statement= childrenInvoker(notifier);
157		statement= withBeforeClasses(statement);
158		statement= withAfterClasses(statement);
159		statement= withClassRules(statement);
160		return statement;
161	}
162
163	/**
164	 * Returns a {@link Statement}: run all non-overridden {@code @BeforeClass} methods on this class
165	 * and superclasses before executing {@code statement}; if any throws an
166	 * Exception, stop execution and pass the exception on.
167	 */
168	protected Statement withBeforeClasses(Statement statement) {
169		List<FrameworkMethod> befores= fTestClass
170				.getAnnotatedMethods(BeforeClass.class);
171		return befores.isEmpty() ? statement :
172			new RunBefores(statement, befores, null);
173	}
174
175	/**
176	 * Returns a {@link Statement}: run all non-overridden {@code @AfterClass} methods on this class
177	 * and superclasses before executing {@code statement}; all AfterClass methods are
178	 * always executed: exceptions thrown by previous steps are combined, if
179	 * necessary, with exceptions from AfterClass methods into a
180	 * {@link MultipleFailureException}.
181	 */
182	protected Statement withAfterClasses(Statement statement) {
183		List<FrameworkMethod> afters= fTestClass
184				.getAnnotatedMethods(AfterClass.class);
185		return afters.isEmpty() ? statement :
186			new RunAfters(statement, afters, null);
187	}
188
189	/**
190	 * Returns a {@link Statement}: apply all
191	 * static fields assignable to {@link TestRule}
192	 * annotated with {@link ClassRule}.
193	 *
194	 * @param statement
195	 *            the base statement
196	 * @return a RunRules statement if any class-level {@link Rule}s are
197	 *         found, or the base statement
198	 */
199	private Statement withClassRules(Statement statement) {
200		List<TestRule> classRules= classRules();
201		return classRules.isEmpty() ? statement :
202		    new RunRules(statement, classRules, getDescription());
203	}
204
205	/**
206	 * @return the {@code ClassRule}s that can transform the block that runs
207	 *         each method in the tested class.
208	 */
209	protected List<TestRule> classRules() {
210		return fTestClass.getAnnotatedFieldValues(null, ClassRule.class, TestRule.class);
211	}
212
213	/**
214	 * Returns a {@link Statement}: Call {@link #runChild(Object, RunNotifier)}
215	 * on each object returned by {@link #getChildren()} (subject to any imposed
216	 * filter and sort)
217	 */
218	protected Statement childrenInvoker(final RunNotifier notifier) {
219		return new Statement() {
220			@Override
221			public void evaluate() {
222				runChildren(notifier);
223			}
224		};
225	}
226
227	private void runChildren(final RunNotifier notifier) {
228		for (final T each : getFilteredChildren())
229 			fScheduler.schedule(new Runnable() {
230				public void run() {
231					ParentRunner.this.runChild(each, notifier);
232				}
233			});
234		fScheduler.finished();
235	}
236
237	/**
238	 * Returns a name used to describe this Runner
239	 */
240	protected String getName() {
241		return fTestClass.getName();
242	}
243
244	//
245	// Available for subclasses
246	//
247
248	/**
249	 * Returns a {@link TestClass} object wrapping the class to be executed.
250	 */
251	public final TestClass getTestClass() {
252		return fTestClass;
253	}
254
255	/**
256	 * Runs a {@link Statement} that represents a leaf (aka atomic) test.
257	 */
258	protected final void runLeaf(Statement statement, Description description,
259			RunNotifier notifier) {
260		EachTestNotifier eachNotifier= new EachTestNotifier(notifier, description);
261		eachNotifier.fireTestStarted();
262		try {
263		    statement.evaluate();
264		} catch (AssumptionViolatedException e) {
265			eachNotifier.addFailedAssumption(e);
266		} catch (Throwable e) {
267			eachNotifier.addFailure(e);
268		} finally {
269			eachNotifier.fireTestFinished();
270		}
271	}
272
273	/**
274	 * @return the annotations that should be attached to this runner's
275	 * description.
276	 */
277	protected Annotation[] getRunnerAnnotations() {
278		return fTestClass.getAnnotations();
279	}
280
281	//
282	// Implementation of Runner
283	//
284
285	@Override
286	public Description getDescription() {
287		Description description= Description.createSuiteDescription(getName(),
288				getRunnerAnnotations());
289		for (T child : getFilteredChildren())
290			description.addChild(describeChild(child));
291		return description;
292	}
293
294	@Override
295	public void run(final RunNotifier notifier) {
296		EachTestNotifier testNotifier= new EachTestNotifier(notifier,
297				getDescription());
298		try {
299			Statement statement= classBlock(notifier);
300			statement.evaluate();
301		} catch (AssumptionViolatedException e) {
302			testNotifier.fireTestIgnored();
303		} catch (StoppedByUserException e) {
304			throw e;
305		} catch (Throwable e) {
306			testNotifier.addFailure(e);
307		}
308	}
309
310	//
311	// Implementation of Filterable and Sortable
312	//
313
314	public void filter(Filter filter) throws NoTestsRemainException {
315		for (Iterator<T> iter = getFilteredChildren().iterator(); iter.hasNext(); ) {
316			T each = iter.next();
317			if (shouldRun(filter, each))
318				try {
319					filter.apply(each);
320				} catch (NoTestsRemainException e) {
321					iter.remove();
322				}
323			else
324				iter.remove();
325		}
326	    if (getFilteredChildren().isEmpty()) {
327	        throw new NoTestsRemainException();
328	    }
329	}
330
331	public void sort(Sorter sorter) {
332		fSorter= sorter;
333		for (T each : getFilteredChildren())
334			sortChild(each);
335		Collections.sort(getFilteredChildren(), comparator());
336	}
337
338	//
339	// Private implementation
340	//
341
342	private void validate() throws InitializationError {
343		List<Throwable> errors= new ArrayList<Throwable>();
344		collectInitializationErrors(errors);
345		if (!errors.isEmpty())
346			throw new InitializationError(errors);
347	}
348
349	private List<T> getFilteredChildren() {
350		if (fFilteredChildren == null)
351			fFilteredChildren = new ArrayList<T>(getChildren());
352		return fFilteredChildren;
353	}
354
355	private void sortChild(T child) {
356		fSorter.apply(child);
357	}
358
359	private boolean shouldRun(Filter filter, T each) {
360		return filter.shouldRun(describeChild(each));
361	}
362
363	private Comparator<? super T> comparator() {
364		return new Comparator<T>() {
365			public int compare(T o1, T o2) {
366				return fSorter.compare(describeChild(o1), describeChild(o2));
367			}
368		};
369	}
370
371	/**
372	 * Sets a scheduler that determines the order and parallelization
373	 * of children.  Highly experimental feature that may change.
374	 */
375	public void setScheduler(RunnerScheduler scheduler) {
376		this.fScheduler = scheduler;
377	}
378}
379