001package org.junit.runners;
002
003import static org.junit.internal.runners.rules.RuleFieldValidator.CLASS_RULE_METHOD_VALIDATOR;
004import static org.junit.internal.runners.rules.RuleFieldValidator.CLASS_RULE_VALIDATOR;
005
006import java.lang.annotation.Annotation;
007import java.lang.reflect.Method;
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.Comparator;
011import java.util.Iterator;
012import java.util.List;
013
014import org.junit.AfterClass;
015import org.junit.BeforeClass;
016import org.junit.ClassRule;
017import org.junit.Rule;
018import org.junit.internal.AssumptionViolatedException;
019import org.junit.internal.runners.model.EachTestNotifier;
020import org.junit.internal.runners.statements.RunAfters;
021import org.junit.internal.runners.statements.RunBefores;
022import org.junit.rules.RunRules;
023import org.junit.rules.TestRule;
024import org.junit.runner.Description;
025import org.junit.runner.Runner;
026import org.junit.runner.manipulation.Filter;
027import org.junit.runner.manipulation.Filterable;
028import org.junit.runner.manipulation.NoTestsRemainException;
029import org.junit.runner.manipulation.Sortable;
030import org.junit.runner.manipulation.Sorter;
031import org.junit.runner.notification.RunNotifier;
032import org.junit.runner.notification.StoppedByUserException;
033import org.junit.runners.model.FrameworkMethod;
034import org.junit.runners.model.InitializationError;
035import org.junit.runners.model.MultipleFailureException;
036import org.junit.runners.model.RunnerScheduler;
037import org.junit.runners.model.Statement;
038import org.junit.runners.model.TestClass;
039
040/**
041 * Provides most of the functionality specific to a Runner that implements a
042 * "parent node" in the test tree, with children defined by objects of some data
043 * type {@code T}. (For {@link BlockJUnit4ClassRunner}, {@code T} is
044 * {@link Method} . For {@link Suite}, {@code T} is {@link Class}.) Subclasses
045 * must implement finding the children of the node, describing each child, and
046 * running each child. ParentRunner will filter and sort children, handle
047 * {@code @BeforeClass} and {@code @AfterClass} methods,
048 * handle annotated {@link ClassRule}s, create a composite
049 * {@link Description}, and run children sequentially.
050 *
051 * @since 4.5
052 */
053public abstract class ParentRunner<T> extends Runner implements Filterable,
054        Sortable {
055    private final TestClass fTestClass;
056
057    private Sorter fSorter = Sorter.NULL;
058
059    private List<T> fFilteredChildren = null;
060
061    private RunnerScheduler fScheduler = new RunnerScheduler() {
062        public void schedule(Runnable childStatement) {
063            childStatement.run();
064        }
065
066        public void finished() {
067            // do nothing
068        }
069    };
070
071    /**
072     * Constructs a new {@code ParentRunner} that will run {@code @TestClass}
073     */
074    protected ParentRunner(Class<?> testClass) throws InitializationError {
075        fTestClass = new TestClass(testClass);
076        validate();
077    }
078
079    //
080    // Must be overridden
081    //
082
083    /**
084     * Returns a list of objects that define the children of this Runner.
085     */
086    protected abstract List<T> getChildren();
087
088    /**
089     * Returns a {@link Description} for {@code child}, which can be assumed to
090     * be an element of the list returned by {@link ParentRunner#getChildren()}
091     */
092    protected abstract Description describeChild(T child);
093
094    /**
095     * Runs the test corresponding to {@code child}, which can be assumed to be
096     * an element of the list returned by {@link ParentRunner#getChildren()}.
097     * Subclasses are responsible for making sure that relevant test events are
098     * reported through {@code notifier}
099     */
100    protected abstract void runChild(T child, RunNotifier notifier);
101
102    //
103    // May be overridden
104    //
105
106    /**
107     * Adds to {@code errors} a throwable for each problem noted with the test class (available from {@link #getTestClass()}).
108     * Default implementation adds an error for each method annotated with
109     * {@code @BeforeClass} or {@code @AfterClass} that is not
110     * {@code public static void} with no arguments.
111     */
112    protected void collectInitializationErrors(List<Throwable> errors) {
113        validatePublicVoidNoArgMethods(BeforeClass.class, true, errors);
114        validatePublicVoidNoArgMethods(AfterClass.class, true, errors);
115        validateClassRules(errors);
116    }
117
118    /**
119     * Adds to {@code errors} if any method in this class is annotated with
120     * {@code annotation}, but:
121     * <ul>
122     * <li>is not public, or
123     * <li>takes parameters, or
124     * <li>returns something other than void, or
125     * <li>is static (given {@code isStatic is false}), or
126     * <li>is not static (given {@code isStatic is true}).
127     */
128    protected void validatePublicVoidNoArgMethods(Class<? extends Annotation> annotation,
129            boolean isStatic, List<Throwable> errors) {
130        List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(annotation);
131
132        for (FrameworkMethod eachTestMethod : methods) {
133            eachTestMethod.validatePublicVoidNoArg(isStatic, errors);
134        }
135    }
136
137    private void validateClassRules(List<Throwable> errors) {
138        CLASS_RULE_VALIDATOR.validate(getTestClass(), errors);
139        CLASS_RULE_METHOD_VALIDATOR.validate(getTestClass(), errors);
140    }
141
142    /**
143     * Constructs a {@code Statement} to run all of the tests in the test class. Override to add pre-/post-processing.
144     * Here is an outline of the implementation:
145     * <ul>
146     * <li>Call {@link #runChild(Object, RunNotifier)} on each object returned by {@link #getChildren()} (subject to any imposed filter and sort).</li>
147     * <li>ALWAYS run all non-overridden {@code @BeforeClass} methods on this class
148     * and superclasses before the previous step; if any throws an
149     * Exception, stop execution and pass the exception on.
150     * <li>ALWAYS run all non-overridden {@code @AfterClass} methods on this class
151     * and superclasses before any of the previous steps; all AfterClass methods are
152     * always executed: exceptions thrown by previous steps are combined, if
153     * necessary, with exceptions from AfterClass methods into a
154     * {@link MultipleFailureException}.
155     * </ul>
156     *
157     * @return {@code Statement}
158     */
159    protected Statement classBlock(final RunNotifier notifier) {
160        Statement statement = childrenInvoker(notifier);
161        statement = withBeforeClasses(statement);
162        statement = withAfterClasses(statement);
163        statement = withClassRules(statement);
164        return statement;
165    }
166
167    /**
168     * Returns a {@link Statement}: run all non-overridden {@code @BeforeClass} methods on this class
169     * and superclasses before executing {@code statement}; if any throws an
170     * Exception, stop execution and pass the exception on.
171     */
172    protected Statement withBeforeClasses(Statement statement) {
173        List<FrameworkMethod> befores = fTestClass
174                .getAnnotatedMethods(BeforeClass.class);
175        return befores.isEmpty() ? statement :
176                new RunBefores(statement, befores, null);
177    }
178
179    /**
180     * Returns a {@link Statement}: run all non-overridden {@code @AfterClass} methods on this class
181     * and superclasses before executing {@code statement}; all AfterClass methods are
182     * always executed: exceptions thrown by previous steps are combined, if
183     * necessary, with exceptions from AfterClass methods into a
184     * {@link MultipleFailureException}.
185     */
186    protected Statement withAfterClasses(Statement statement) {
187        List<FrameworkMethod> afters = fTestClass
188                .getAnnotatedMethods(AfterClass.class);
189        return afters.isEmpty() ? statement :
190                new RunAfters(statement, afters, null);
191    }
192
193    /**
194     * Returns a {@link Statement}: apply all
195     * static fields assignable to {@link TestRule}
196     * annotated with {@link ClassRule}.
197     *
198     * @param statement the base statement
199     * @return a RunRules statement if any class-level {@link Rule}s are
200     *         found, or the base statement
201     */
202    private Statement withClassRules(Statement statement) {
203        List<TestRule> classRules = classRules();
204        return classRules.isEmpty() ? statement :
205                new RunRules(statement, classRules, getDescription());
206    }
207
208    /**
209     * @return the {@code ClassRule}s that can transform the block that runs
210     *         each method in the tested class.
211     */
212    protected List<TestRule> classRules() {
213        List<TestRule> result = fTestClass.getAnnotatedMethodValues(null, ClassRule.class, TestRule.class);
214
215        result.addAll(fTestClass.getAnnotatedFieldValues(null, ClassRule.class, TestRule.class));
216
217        return result;
218    }
219
220    /**
221     * Returns a {@link Statement}: Call {@link #runChild(Object, RunNotifier)}
222     * on each object returned by {@link #getChildren()} (subject to any imposed
223     * filter and sort)
224     */
225    protected Statement childrenInvoker(final RunNotifier notifier) {
226        return new Statement() {
227            @Override
228            public void evaluate() {
229                runChildren(notifier);
230            }
231        };
232    }
233
234    private void runChildren(final RunNotifier notifier) {
235        for (final T each : getFilteredChildren()) {
236            fScheduler.schedule(new Runnable() {
237                public void run() {
238                    ParentRunner.this.runChild(each, notifier);
239                }
240            });
241        }
242        fScheduler.finished();
243    }
244
245    /**
246     * Returns a name used to describe this Runner
247     */
248    protected String getName() {
249        return fTestClass.getName();
250    }
251
252    //
253    // Available for subclasses
254    //
255
256    /**
257     * Returns a {@link TestClass} object wrapping the class to be executed.
258     */
259    public final TestClass getTestClass() {
260        return fTestClass;
261    }
262
263    /**
264     * Runs a {@link Statement} that represents a leaf (aka atomic) test.
265     */
266    protected final void runLeaf(Statement statement, Description description,
267            RunNotifier notifier) {
268        EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
269        eachNotifier.fireTestStarted();
270        try {
271            statement.evaluate();
272        } catch (AssumptionViolatedException e) {
273            eachNotifier.addFailedAssumption(e);
274        } catch (Throwable e) {
275            eachNotifier.addFailure(e);
276        } finally {
277            eachNotifier.fireTestFinished();
278        }
279    }
280
281    /**
282     * @return the annotations that should be attached to this runner's
283     *         description.
284     */
285    protected Annotation[] getRunnerAnnotations() {
286        return fTestClass.getAnnotations();
287    }
288
289    //
290    // Implementation of Runner
291    //
292
293    @Override
294    public Description getDescription() {
295        Description description = Description.createSuiteDescription(getName(),
296                getRunnerAnnotations());
297        for (T child : getFilteredChildren()) {
298            description.addChild(describeChild(child));
299        }
300        return description;
301    }
302
303    @Override
304    public void run(final RunNotifier notifier) {
305        EachTestNotifier testNotifier = new EachTestNotifier(notifier,
306                getDescription());
307        try {
308            Statement statement = classBlock(notifier);
309            statement.evaluate();
310        } catch (AssumptionViolatedException e) {
311            testNotifier.fireTestIgnored();
312        } catch (StoppedByUserException e) {
313            throw e;
314        } catch (Throwable e) {
315            testNotifier.addFailure(e);
316        }
317    }
318
319    //
320    // Implementation of Filterable and Sortable
321    //
322
323    public void filter(Filter filter) throws NoTestsRemainException {
324        for (Iterator<T> iter = getFilteredChildren().iterator(); iter.hasNext(); ) {
325            T each = iter.next();
326            if (shouldRun(filter, each)) {
327                try {
328                    filter.apply(each);
329                } catch (NoTestsRemainException e) {
330                    iter.remove();
331                }
332            } else {
333                iter.remove();
334            }
335        }
336        if (getFilteredChildren().isEmpty()) {
337            throw new NoTestsRemainException();
338        }
339    }
340
341    public void sort(Sorter sorter) {
342        fSorter = sorter;
343        for (T each : getFilteredChildren()) {
344            sortChild(each);
345        }
346        Collections.sort(getFilteredChildren(), comparator());
347    }
348
349    //
350    // Private implementation
351    //
352
353    private void validate() throws InitializationError {
354        List<Throwable> errors = new ArrayList<Throwable>();
355        collectInitializationErrors(errors);
356        if (!errors.isEmpty()) {
357            throw new InitializationError(errors);
358        }
359    }
360
361    private List<T> getFilteredChildren() {
362        if (fFilteredChildren == null) {
363            fFilteredChildren = new ArrayList<T>(getChildren());
364        }
365        return fFilteredChildren;
366    }
367
368    private void sortChild(T child) {
369        fSorter.apply(child);
370    }
371
372    private boolean shouldRun(Filter filter, T each) {
373        return filter.shouldRun(describeChild(each));
374    }
375
376    private Comparator<? super T> comparator() {
377        return new Comparator<T>() {
378            public int compare(T o1, T o2) {
379                return fSorter.compare(describeChild(o1), describeChild(o2));
380            }
381        };
382    }
383
384    /**
385     * Sets a scheduler that determines the order and parallelization
386     * of children.  Highly experimental feature that may change.
387     */
388    public void setScheduler(RunnerScheduler scheduler) {
389        this.fScheduler = scheduler;
390    }
391}