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.FixMethodOrder;
023    import org.junit.Ignore;
024    import org.junit.Rule;
025    import org.junit.internal.AssumptionViolatedException;
026    import org.junit.internal.runners.model.EachTestNotifier;
027    import org.junit.internal.runners.statements.RunAfters;
028    import org.junit.internal.runners.statements.RunBefores;
029    import org.junit.rules.RunRules;
030    import org.junit.rules.TestRule;
031    import org.junit.runner.Description;
032    import org.junit.runner.Runner;
033    import org.junit.runner.manipulation.Filter;
034    import org.junit.runner.manipulation.Filterable;
035    import org.junit.runner.manipulation.Orderer;
036    import org.junit.runner.manipulation.InvalidOrderingException;
037    import org.junit.runner.manipulation.NoTestsRemainException;
038    import org.junit.runner.manipulation.Orderable;
039    import org.junit.runner.manipulation.Sorter;
040    import org.junit.runner.notification.RunNotifier;
041    import org.junit.runner.notification.StoppedByUserException;
042    import org.junit.runners.model.FrameworkMember;
043    import org.junit.runners.model.FrameworkMethod;
044    import org.junit.runners.model.InitializationError;
045    import org.junit.runners.model.InvalidTestClassError;
046    import org.junit.runners.model.MemberValueConsumer;
047    import org.junit.runners.model.RunnerScheduler;
048    import org.junit.runners.model.Statement;
049    import org.junit.runners.model.TestClass;
050    import org.junit.validator.AnnotationsValidator;
051    import 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     */
066    public 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    }