001package org.junit.runners;
002
003import static org.junit.internal.Checks.notNull;
004import static org.junit.internal.runners.rules.RuleMemberValidator.CLASS_RULE_METHOD_VALIDATOR;
005import static org.junit.internal.runners.rules.RuleMemberValidator.CLASS_RULE_VALIDATOR;
006
007import java.lang.annotation.Annotation;
008import java.lang.reflect.Method;
009import java.util.ArrayList;
010import java.util.Collections;
011import java.util.Comparator;
012import java.util.Iterator;
013import java.util.LinkedHashMap;
014import java.util.List;
015import java.util.Map;
016import java.util.concurrent.locks.Lock;
017import java.util.concurrent.locks.ReentrantLock;
018
019import org.junit.AfterClass;
020import org.junit.BeforeClass;
021import org.junit.ClassRule;
022import org.junit.FixMethodOrder;
023import org.junit.Ignore;
024import org.junit.Rule;
025import org.junit.internal.AssumptionViolatedException;
026import org.junit.internal.runners.model.EachTestNotifier;
027import org.junit.internal.runners.statements.RunAfters;
028import org.junit.internal.runners.statements.RunBefores;
029import org.junit.rules.RunRules;
030import org.junit.rules.TestRule;
031import org.junit.runner.Description;
032import org.junit.runner.Runner;
033import org.junit.runner.manipulation.Filter;
034import org.junit.runner.manipulation.Filterable;
035import org.junit.runner.manipulation.Orderer;
036import org.junit.runner.manipulation.InvalidOrderingException;
037import org.junit.runner.manipulation.NoTestsRemainException;
038import org.junit.runner.manipulation.Orderable;
039import org.junit.runner.manipulation.Sorter;
040import org.junit.runner.notification.RunNotifier;
041import org.junit.runner.notification.StoppedByUserException;
042import org.junit.runners.model.FrameworkMember;
043import org.junit.runners.model.FrameworkMethod;
044import org.junit.runners.model.InitializationError;
045import org.junit.runners.model.InvalidTestClassError;
046import org.junit.runners.model.MemberValueConsumer;
047import org.junit.runners.model.RunnerScheduler;
048import org.junit.runners.model.Statement;
049import org.junit.runners.model.TestClass;
050import org.junit.validator.AnnotationsValidator;
051import org.junit.validator.TestClassValidator;
052
053/**
054 * Provides most of the functionality specific to a Runner that implements a
055 * "parent node" in the test tree, with children defined by objects of some data
056 * type {@code T}. (For {@link BlockJUnit4ClassRunner}, {@code T} is
057 * {@link Method} . For {@link Suite}, {@code T} is {@link Class}.) Subclasses
058 * must implement finding the children of the node, describing each child, and
059 * running each child. ParentRunner will filter and sort children, handle
060 * {@code @BeforeClass} and {@code @AfterClass} methods,
061 * handle annotated {@link ClassRule}s, create a composite
062 * {@link Description}, and run children sequentially.
063 *
064 * @since 4.5
065 */
066public abstract class ParentRunner<T> extends Runner implements Filterable,
067        Orderable {
068    private static final List<TestClassValidator> VALIDATORS = Collections.<TestClassValidator>singletonList(
069            new AnnotationsValidator());
070
071    private final Lock childrenLock = new ReentrantLock();
072    private final TestClass testClass;
073
074    // Guarded by childrenLock
075    private volatile List<T> filteredChildren = null;
076
077    private volatile RunnerScheduler scheduler = new RunnerScheduler() {
078        public void schedule(Runnable childStatement) {
079            childStatement.run();
080        }
081
082        public void finished() {
083            // do nothing
084        }
085    };
086
087    /**
088     * Constructs a new {@code ParentRunner} that will run {@code @TestClass}
089     */
090    protected ParentRunner(Class<?> testClass) throws InitializationError {
091        this.testClass = createTestClass(testClass);
092        validate();
093    }
094
095   /**
096    * Constructs a new {@code ParentRunner} that will run the {@code TestClass}.
097    *
098    * @since 4.13
099    */
100    protected ParentRunner(TestClass testClass) throws InitializationError {
101       this.testClass = notNull(testClass);
102       validate();
103    }
104
105    /**
106     * @deprecated Please use {@link #ParentRunner(org.junit.runners.model.TestClass)}.
107     * @since 4.12
108     */
109    @Deprecated
110    protected TestClass createTestClass(Class<?> testClass) {
111        return new TestClass(testClass);
112    }
113
114    //
115    // Must be overridden
116    //
117
118    /**
119     * Returns a list of objects that define the children of this Runner.
120     */
121    protected abstract List<T> getChildren();
122
123    /**
124     * Returns a {@link Description} for {@code child}, which can be assumed to
125     * be an element of the list returned by {@link ParentRunner#getChildren()}
126     */
127    protected abstract Description describeChild(T child);
128
129    /**
130     * Runs the test corresponding to {@code child}, which can be assumed to be
131     * an element of the list returned by {@link ParentRunner#getChildren()}.
132     * Subclasses are responsible for making sure that relevant test events are
133     * reported through {@code notifier}
134     */
135    protected abstract void runChild(T child, RunNotifier notifier);
136
137    //
138    // May be overridden
139    //
140
141    /**
142     * Adds to {@code errors} a throwable for each problem noted with the test class (available from {@link #getTestClass()}).
143     * Default implementation adds an error for each method annotated with
144     * {@code @BeforeClass} or {@code @AfterClass} that is not
145     * {@code public static void} with no arguments.
146     */
147    protected void collectInitializationErrors(List<Throwable> errors) {
148        validatePublicVoidNoArgMethods(BeforeClass.class, true, errors);
149        validatePublicVoidNoArgMethods(AfterClass.class, true, errors);
150        validateClassRules(errors);
151        applyValidators(errors);
152    }
153
154    private void applyValidators(List<Throwable> errors) {
155        if (getTestClass().getJavaClass() != null) {
156            for (TestClassValidator each : VALIDATORS) {
157                errors.addAll(each.validateTestClass(getTestClass()));
158            }
159        }
160    }
161
162    /**
163     * Adds to {@code errors} if any method in this class is annotated with
164     * {@code annotation}, but:
165     * <ul>
166     * <li>is not public, or
167     * <li>takes parameters, or
168     * <li>returns something other than void, or
169     * <li>is static (given {@code isStatic is false}), or
170     * <li>is not static (given {@code isStatic is true}).
171     * </ul>
172     */
173    protected void validatePublicVoidNoArgMethods(Class<? extends Annotation> annotation,
174            boolean isStatic, List<Throwable> errors) {
175        List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(annotation);
176
177        for (FrameworkMethod eachTestMethod : methods) {
178            eachTestMethod.validatePublicVoidNoArg(isStatic, errors);
179        }
180    }
181
182    private void validateClassRules(List<Throwable> errors) {
183        CLASS_RULE_VALIDATOR.validate(getTestClass(), errors);
184        CLASS_RULE_METHOD_VALIDATOR.validate(getTestClass(), errors);
185    }
186
187    /**
188     * Constructs a {@code Statement} to run all of the tests in the test class.
189     * Override to add pre-/post-processing. Here is an outline of the
190     * implementation:
191     * <ol>
192     * <li>Determine the children to be run using {@link #getChildren()}
193     * (subject to any imposed filter and sort).</li>
194     * <li>If there are any children remaining after filtering and ignoring,
195     * construct a statement that will:
196     * <ol>
197     * <li>Apply all {@code ClassRule}s on the test-class and superclasses.</li>
198     * <li>Run all non-overridden {@code @BeforeClass} methods on the test-class
199     * and superclasses; if any throws an Exception, stop execution and pass the
200     * exception on.</li>
201     * <li>Run all remaining tests on the test-class.</li>
202     * <li>Run all non-overridden {@code @AfterClass} methods on the test-class
203     * and superclasses: exceptions thrown by previous steps are combined, if
204     * necessary, with exceptions from AfterClass methods into a
205     * {@link org.junit.runners.model.MultipleFailureException}.</li>
206     * </ol>
207     * </li>
208     * </ol>
209     *
210     * @return {@code Statement}
211     */
212    protected Statement classBlock(final RunNotifier notifier) {
213        Statement statement = childrenInvoker(notifier);
214        if (!areAllChildrenIgnored()) {
215            statement = withBeforeClasses(statement);
216            statement = withAfterClasses(statement);
217            statement = withClassRules(statement);
218            statement = withInterruptIsolation(statement);
219        }
220        return statement;
221    }
222
223    private boolean areAllChildrenIgnored() {
224        for (T child : getFilteredChildren()) {
225            if (!isIgnored(child)) {
226                return false;
227            }
228        }
229        return true;
230    }
231
232    /**
233     * Returns a {@link Statement}: run all non-overridden {@code @BeforeClass} methods on this class
234     * and superclasses before executing {@code statement}; if any throws an
235     * Exception, stop execution and pass the exception on.
236     */
237    protected Statement withBeforeClasses(Statement statement) {
238        List<FrameworkMethod> befores = testClass
239                .getAnnotatedMethods(BeforeClass.class);
240        return befores.isEmpty() ? statement :
241                new RunBefores(statement, befores, null);
242    }
243
244    /**
245     * Returns a {@link Statement}: run all non-overridden {@code @AfterClass} methods on this class
246     * and superclasses after executing {@code statement}; all AfterClass methods are
247     * always executed: exceptions thrown by previous steps are combined, if
248     * necessary, with exceptions from AfterClass methods into a
249     * {@link org.junit.runners.model.MultipleFailureException}.
250     */
251    protected Statement withAfterClasses(Statement statement) {
252        List<FrameworkMethod> afters = testClass
253                .getAnnotatedMethods(AfterClass.class);
254        return afters.isEmpty() ? statement :
255                new RunAfters(statement, afters, null);
256    }
257
258    /**
259     * Returns a {@link Statement}: apply all
260     * static fields assignable to {@link TestRule}
261     * annotated with {@link ClassRule}.
262     *
263     * @param statement the base statement
264     * @return a RunRules statement if any class-level {@link Rule}s are
265     *         found, or the base statement
266     */
267    private Statement withClassRules(Statement statement) {
268        List<TestRule> classRules = classRules();
269        return classRules.isEmpty() ? statement :
270                new RunRules(statement, classRules, getDescription());
271    }
272
273    /**
274     * @return the {@code ClassRule}s that can transform the block that runs
275     *         each method in the tested class.
276     */
277    protected List<TestRule> classRules() {
278        ClassRuleCollector collector = new ClassRuleCollector();
279        testClass.collectAnnotatedMethodValues(null, ClassRule.class, TestRule.class, collector);
280        testClass.collectAnnotatedFieldValues(null, ClassRule.class, TestRule.class, collector);
281        return collector.getOrderedRules();
282    }
283
284    /**
285     * Returns a {@link Statement}: Call {@link #runChild(Object, RunNotifier)}
286     * on each object returned by {@link #getChildren()} (subject to any imposed
287     * filter and sort)
288     */
289    protected Statement childrenInvoker(final RunNotifier notifier) {
290        return new Statement() {
291            @Override
292            public void evaluate() {
293                runChildren(notifier);
294            }
295        };
296    }
297
298    /**
299     * @return a {@link Statement}: clears interrupt status of current thread after execution of statement
300     */
301    protected final Statement withInterruptIsolation(final Statement statement) {
302        return new Statement() {
303            @Override
304            public void evaluate() throws Throwable {
305                try {
306                    statement.evaluate();
307                } finally {
308                    Thread.interrupted(); // clearing thread interrupted status for isolation
309                }
310            }
311        };
312    }
313
314    /**
315     * Evaluates whether a child is ignored. The default implementation always
316     * returns <code>false</code>.
317     * 
318     * <p>{@link BlockJUnit4ClassRunner}, for example, overrides this method to
319     * filter tests based on the {@link Ignore} annotation.
320     */
321    protected boolean isIgnored(T child) {
322        return false;
323    }
324
325    private void runChildren(final RunNotifier notifier) {
326        final RunnerScheduler currentScheduler = scheduler;
327        try {
328            for (final T each : getFilteredChildren()) {
329                currentScheduler.schedule(new Runnable() {
330                    public void run() {
331                        ParentRunner.this.runChild(each, notifier);
332                    }
333                });
334            }
335        } finally {
336            currentScheduler.finished();
337        }
338    }
339
340    /**
341     * Returns a name used to describe this Runner
342     */
343    protected String getName() {
344        return testClass.getName();
345    }
346
347    //
348    // Available for subclasses
349    //
350
351    /**
352     * Returns a {@link TestClass} object wrapping the class to be executed.
353     */
354    public final TestClass getTestClass() {
355        return testClass;
356    }
357
358    /**
359     * Runs a {@link Statement} that represents a leaf (aka atomic) test.
360     */
361    protected final void runLeaf(Statement statement, Description description,
362            RunNotifier notifier) {
363        EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
364        eachNotifier.fireTestStarted();
365        try {
366            statement.evaluate();
367        } catch (AssumptionViolatedException e) {
368            eachNotifier.addFailedAssumption(e);
369        } catch (Throwable e) {
370            eachNotifier.addFailure(e);
371        } finally {
372            eachNotifier.fireTestFinished();
373        }
374    }
375
376    /**
377     * @return the annotations that should be attached to this runner's
378     *         description.
379     */
380    protected Annotation[] getRunnerAnnotations() {
381        return testClass.getAnnotations();
382    }
383
384    //
385    // Implementation of Runner
386    //
387
388    @Override
389    public Description getDescription() {
390        Class<?> clazz = getTestClass().getJavaClass();
391        Description description;
392        // if subclass overrides `getName()` then we should use it
393        // to maintain backwards compatibility with JUnit 4.12
394        if (clazz == null || !clazz.getName().equals(getName())) {
395            description = Description.createSuiteDescription(getName(), getRunnerAnnotations());
396        } else {
397            description = Description.createSuiteDescription(clazz, getRunnerAnnotations());
398        }
399
400        for (T child : getFilteredChildren()) {
401            description.addChild(describeChild(child));
402        }
403        return description;
404    }
405
406    @Override
407    public void run(final RunNotifier notifier) {
408        EachTestNotifier testNotifier = new EachTestNotifier(notifier,
409                getDescription());
410        testNotifier.fireTestSuiteStarted();
411        try {
412            Statement statement = classBlock(notifier);
413            statement.evaluate();
414        } catch (AssumptionViolatedException e) {
415            testNotifier.addFailedAssumption(e);
416        } catch (StoppedByUserException e) {
417            throw e;
418        } catch (Throwable e) {
419            testNotifier.addFailure(e);
420        } finally {
421            testNotifier.fireTestSuiteFinished();
422        }
423    }
424
425    //
426    // Implementation of Filterable and Sortable
427    //
428
429    public void filter(Filter filter) throws NoTestsRemainException {
430        childrenLock.lock();
431        try {
432            List<T> children = new ArrayList<T>(getFilteredChildren());
433            for (Iterator<T> iter = children.iterator(); iter.hasNext(); ) {
434                T each = iter.next();
435                if (shouldRun(filter, each)) {
436                    try {
437                        filter.apply(each);
438                    } catch (NoTestsRemainException e) {
439                        iter.remove();
440                    }
441                } else {
442                    iter.remove();
443                }
444            }
445            filteredChildren = Collections.unmodifiableList(children);
446            if (filteredChildren.isEmpty()) {
447                throw new NoTestsRemainException();
448            }
449        } finally {
450            childrenLock.unlock();
451        }
452    }
453
454    public void sort(Sorter sorter) {
455        if (shouldNotReorder()) {
456            return;
457        }
458
459        childrenLock.lock();
460        try {
461            for (T each : getFilteredChildren()) {
462                sorter.apply(each);
463            }
464            List<T> sortedChildren = new ArrayList<T>(getFilteredChildren());
465            Collections.sort(sortedChildren, comparator(sorter));
466            filteredChildren = Collections.unmodifiableList(sortedChildren);
467        } finally {
468            childrenLock.unlock();
469        }
470    }
471
472    /**
473     * Implementation of {@link Orderable#order(Orderer)}.
474     *
475     * @since 4.13
476     */
477    public void order(Orderer orderer) throws InvalidOrderingException {
478        if (shouldNotReorder()) {
479            return;
480        }
481
482        childrenLock.lock();
483        try {
484            List<T> children = getFilteredChildren();
485            // In theory, we could have duplicate Descriptions. De-dup them before ordering,
486            // and add them back at the end.
487            Map<Description, List<T>> childMap = new LinkedHashMap<Description, List<T>>(
488                    children.size());
489            for (T child : children) {
490                Description description = describeChild(child);
491                List<T> childrenWithDescription = childMap.get(description);
492                if (childrenWithDescription == null) {
493                    childrenWithDescription = new ArrayList<T>(1);
494                    childMap.put(description, childrenWithDescription);
495                }
496                childrenWithDescription.add(child);
497                orderer.apply(child);
498            }
499
500            List<Description> inOrder = orderer.order(childMap.keySet());
501
502            children = new ArrayList<T>(children.size());
503            for (Description description : inOrder) {
504                children.addAll(childMap.get(description));
505            }
506            filteredChildren = Collections.unmodifiableList(children);
507        } finally {
508            childrenLock.unlock();
509        }
510    }
511
512    //
513    // Private implementation
514    //
515
516    private boolean shouldNotReorder() {
517        // If the test specifies a specific order, do not reorder.
518        return getDescription().getAnnotation(FixMethodOrder.class) != null;
519    }
520
521    private void validate() throws InitializationError {
522        List<Throwable> errors = new ArrayList<Throwable>();
523        collectInitializationErrors(errors);
524        if (!errors.isEmpty()) {
525            throw new InvalidTestClassError(testClass.getJavaClass(), errors);
526        }
527    }
528
529    private List<T> getFilteredChildren() {
530        if (filteredChildren == null) {
531            childrenLock.lock();
532            try {
533                if (filteredChildren == null) {
534                    filteredChildren = Collections.unmodifiableList(
535                            new ArrayList<T>(getChildren()));
536                }
537            } finally {
538                childrenLock.unlock();
539            }
540        }
541        return filteredChildren;
542    }
543
544    private boolean shouldRun(Filter filter, T each) {
545        return filter.shouldRun(describeChild(each));
546    }
547
548    private Comparator<? super T> comparator(final Sorter sorter) {
549        return new Comparator<T>() {
550            public int compare(T o1, T o2) {
551                return sorter.compare(describeChild(o1), describeChild(o2));
552            }
553        };
554    }
555
556    /**
557     * Sets a scheduler that determines the order and parallelization
558     * of children.  Highly experimental feature that may change.
559     */
560    public void setScheduler(RunnerScheduler scheduler) {
561        this.scheduler = scheduler;
562    }
563
564    private static class ClassRuleCollector implements MemberValueConsumer<TestRule> {
565        final List<RuleContainer.RuleEntry> entries = new ArrayList<RuleContainer.RuleEntry>();
566
567        public void accept(FrameworkMember<?> member, TestRule value) {
568            ClassRule rule = member.getAnnotation(ClassRule.class);
569            entries.add(new RuleContainer.RuleEntry(value, RuleContainer.RuleEntry.TYPE_TEST_RULE,
570                    rule != null ? rule.order() : null));
571        }
572
573        public List<TestRule> getOrderedRules() {
574            Collections.sort(entries, RuleContainer.ENTRY_COMPARATOR);
575            List<TestRule> result = new ArrayList<TestRule>(entries.size());
576            for (RuleContainer.RuleEntry entry : entries) {
577                result.add((TestRule) entry.rule);
578            }
579            return result;
580        }
581    }
582}