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