    001    package org.junit.runners;
    002
    003    import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_METHOD_VALIDATOR;
    004    import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
    005
    006    import java.util.ArrayList;
    007    import java.util.List;
    008    import java.util.concurrent.ConcurrentHashMap;
    009    import java.util.concurrent.ConcurrentMap;
    010    import java.util.concurrent.TimeUnit;
    011
    012    import org.junit.After;
    013    import org.junit.Before;
    014    import org.junit.Ignore;
    015    import org.junit.Rule;
    016    import org.junit.Test;
    017    import org.junit.Test.None;
    018    import org.junit.internal.runners.model.ReflectiveCallable;
    019    import org.junit.internal.runners.statements.ExpectException;
    020    import org.junit.internal.runners.statements.Fail;
    021    import org.junit.internal.runners.statements.FailOnTimeout;
    022    import org.junit.internal.runners.statements.InvokeMethod;
    023    import org.junit.internal.runners.statements.RunAfters;
    024    import org.junit.internal.runners.statements.RunBefores;
    025    import org.junit.rules.MethodRule;
    026    import org.junit.rules.TestRule;
    027    import org.junit.runner.Description;
    028    import org.junit.runner.notification.RunNotifier;
    029    import org.junit.runners.model.FrameworkMember;
    030    import org.junit.runners.model.FrameworkMethod;
    031    import org.junit.runners.model.InitializationError;
    032    import org.junit.runners.model.MemberValueConsumer;
    033    import org.junit.runners.model.MultipleFailureException;
    034    import org.junit.runners.model.Statement;
    035    import org.junit.runners.model.TestClass;
    036    import org.junit.validator.PublicClassValidator;
    037    import org.junit.validator.TestClassValidator;
    038
    039    /**
    040     * Implements the JUnit 4 standard test case class model, as defined by the
    041     * annotations in the org.junit package. Many users will never notice this
    042     * class: it is now the default test class runner, but it should have exactly
    043     * the same behavior as the old test class runner ({@code JUnit4ClassRunner}).
    044     * <p>
    045     * BlockJUnit4ClassRunner has advantages for writers of custom JUnit runners
    046     * that are slight changes to the default behavior, however:
    047     *
    048     * <ul>
    049     * <li>It has a much simpler implementation based on {@link Statement}s,
    050     * allowing new operations to be inserted into the appropriate point in the
    051     * execution flow.
    052     *
    053     * <li>It is published, and extension and reuse are encouraged, whereas {@code
    054     * JUnit4ClassRunner} was in an internal package, and is now deprecated.
    055     * </ul>
    056     * <p>
    057     * In turn, in 2009 we introduced {@link Rule}s.  In many cases where extending
    058     * BlockJUnit4ClassRunner was necessary to add new behavior, {@link Rule}s can
    059     * be used, which makes the extension more reusable and composable.
    060     *
    061     * @since 4.5
    062     */
    063    public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> {
    064        private static TestClassValidator PUBLIC_CLASS_VALIDATOR = new PublicClassValidator();
    065
    066        private final ConcurrentMap<FrameworkMethod, Description> methodDescriptions = new ConcurrentHashMap<FrameworkMethod, Description>();
    067
    068        /**
    069         * Creates a BlockJUnit4ClassRunner to run {@code testClass}
    070         *
    071         * @throws InitializationError if the test class is malformed.
    072         */
    073        public BlockJUnit4ClassRunner(Class<?> testClass) throws InitializationError {
    074            super(testClass);
    075        }
    076
    077        /**
    078         * Creates a BlockJUnit4ClassRunner to run {@code testClass}.
    079         *
    080         * @throws InitializationError if the test class is malformed.
    081         * @since 4.13
    082         */
    083        protected BlockJUnit4ClassRunner(TestClass testClass) throws InitializationError {
    084            super(testClass);
    085        }
    086
    087        //
    088        // Implementation of ParentRunner
    089        //
    090
    091        @Override
    092        protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
    093            Description description = describeChild(method);
    094            if (isIgnored(method)) {
    095                notifier.fireTestIgnored(description);
    096            } else {
    097                Statement statement = new Statement() {
    098                    @Override
    099                    public void evaluate() throws Throwable {
    100                        methodBlock(method).evaluate();
    101                    }
    102                };
    103                runLeaf(statement, description, notifier);
    104            }
    105        }
    106
    107        /**
    108         * Evaluates whether {@link FrameworkMethod}s are ignored based on the
    109         * {@link Ignore} annotation.
    110         */
    111        @Override
    112        protected boolean isIgnored(FrameworkMethod child) {
    113            return child.getAnnotation(Ignore.class) != null;
    114        }
    115
    116        @Override
    117        protected Description describeChild(FrameworkMethod method) {
    118            Description description = methodDescriptions.get(method);
    119
    120            if (description == null) {
    121                description = Description.createTestDescription(getTestClass().getJavaClass(),
    122                        testName(method), method.getAnnotations());
    123                methodDescriptions.putIfAbsent(method, description);
    124            }
    125
    126            return description;
    127        }
    128
    129        @Override
    130        protected List<FrameworkMethod> getChildren() {
    131            return computeTestMethods();
    132        }
    133
    134        //
    135        // Override in subclasses
    136        //
    137
    138        /**
    139         * Returns the methods that run tests. Default implementation returns all
    140         * methods annotated with {@code @Test} on this class and superclasses that
    141         * are not overridden.
    142         */
    143        protected List<FrameworkMethod> computeTestMethods() {
    144            return getTestClass().getAnnotatedMethods(Test.class);
    145        }
    146
    147        @Override
    148        protected void collectInitializationErrors(List<Throwable> errors) {
    149            super.collectInitializationErrors(errors);
    150
    151            validatePublicConstructor(errors);
    152            validateNoNonStaticInnerClass(errors);
    153            validateConstructor(errors);
    154            validateInstanceMethods(errors);
    155            validateFields(errors);
    156            validateMethods(errors);
    157        }
    158
    159        private void validatePublicConstructor(List<Throwable> errors) {
    160            if (getTestClass().getJavaClass() != null) {
    161                errors.addAll(PUBLIC_CLASS_VALIDATOR.validateTestClass(getTestClass()));
    162            }
    163        }
    164
    165        protected void validateNoNonStaticInnerClass(List<Throwable> errors) {
    166            if (getTestClass().isANonStaticInnerClass()) {
    167                String gripe = "The inner class " + getTestClass().getName()
    168                        + " is not static.";
    169                errors.add(new Exception(gripe));
    170            }
    171        }
    172
    173        /**
    174         * Adds to {@code errors} if the test class has more than one constructor,
    175         * or if the constructor takes parameters. Override if a subclass requires
    176         * different validation rules.
    177         */
    178        protected void validateConstructor(List<Throwable> errors) {
    179            validateOnlyOneConstructor(errors);
    180            validateZeroArgConstructor(errors);
    181        }
    182
    183        /**
    184         * Adds to {@code errors} if the test class has more than one constructor
    185         * (do not override)
    186         */
    187        protected void validateOnlyOneConstructor(List<Throwable> errors) {
    188            if (!hasOneConstructor()) {
    189                String gripe = "Test class should have exactly one public constructor";
    190                errors.add(new Exception(gripe));
    191            }
    192        }
    193
    194        /**
    195         * Adds to {@code errors} if the test class's single constructor takes
    196         * parameters (do not override)
    197         */
    198        protected void validateZeroArgConstructor(List<Throwable> errors) {
    199            if (!getTestClass().isANonStaticInnerClass()
    200                    && hasOneConstructor()
    201                    && (getTestClass().getOnlyConstructor().getParameterTypes().length != 0)) {
    202                String gripe = "Test class should have exactly one public zero-argument constructor";
    203                errors.add(new Exception(gripe));
    204            }
    205        }
    206
    207        private boolean hasOneConstructor() {
    208            return getTestClass().getJavaClass().getConstructors().length == 1;
    209        }
    210
    211        /**
    212         * Adds to {@code errors} for each method annotated with {@code @Test},
    213         * {@code @Before}, or {@code @After} that is not a public, void instance
    214         * method with no arguments.
    215         * @deprecated
    216         */
    217        @Deprecated
    218        protected void validateInstanceMethods(List<Throwable> errors) {
    219            validatePublicVoidNoArgMethods(After.class, false, errors);
    220            validatePublicVoidNoArgMethods(Before.class, false, errors);
    221            validateTestMethods(errors);
    222
    223            if (computeTestMethods().isEmpty()) {
    224                errors.add(new Exception("No runnable methods"));
    225            }
    226        }
    227
    228        protected void validateFields(List<Throwable> errors) {
    229            RULE_VALIDATOR.validate(getTestClass(), errors);
    230        }
    231
    232        private void validateMethods(List<Throwable> errors) {
    233            RULE_METHOD_VALIDATOR.validate(getTestClass(), errors);
    234        }
    235
    236        /**
    237         * Adds to {@code errors} for each method annotated with {@code @Test}that
    238         * is not a public, void instance method with no arguments.
    239         */
    240        protected void validateTestMethods(List<Throwable> errors) {
    241            validatePublicVoidNoArgMethods(Test.class, false, errors);
    242        }
    243
    244        /**
    245         * Returns a new fixture for running a test. Default implementation executes
    246         * the test class's no-argument constructor (validation should have ensured
    247         * one exists).
    248         */
    249        protected Object createTest() throws Exception {
    250            return getTestClass().getOnlyConstructor().newInstance();
    251        }
    252
    253        /**
    254         * Returns a new fixture to run a particular test {@code method} against.
    255         * Default implementation executes the no-argument {@link #createTest()} method.
    256         *
    257         * @since 4.13
    258         */
    259        protected Object createTest(FrameworkMethod method) throws Exception {
    260            return createTest();
    261        }
    262
    263        /**
    264         * Returns the name that describes {@code method} for {@link Description}s.
    265         * Default implementation is the method's name
    266         */
    267        protected String testName(FrameworkMethod method) {
    268            return method.getName();
    269        }
    270
    271        /**
    272         * Returns a Statement that, when executed, either returns normally if
    273         * {@code method} passes, or throws an exception if {@code method} fails.
    274         *
    275         * Here is an outline of the default implementation:
    276         *
    277         * <ul>
    278         * <li>Invoke {@code method} on the result of {@link #createTest(org.junit.runners.model.FrameworkMethod)}, and
    279         * throw any exceptions thrown by either operation.
    280         * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@link Test#expected()}
    281         * attribute, return normally only if the previous step threw an
    282         * exception of the correct type, and throw an exception otherwise.
    283         * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
    284         * timeout} attribute, throw an exception if the previous step takes more
    285         * than the specified number of milliseconds.
    286         * <li>ALWAYS run all non-overridden {@code @Before} methods on this class
    287         * and superclasses before any of the previous steps; if any throws an
    288         * Exception, stop execution and pass the exception on.
    289         * <li>ALWAYS run all non-overridden {@code @After} methods on this class
    290         * and superclasses after any of the previous steps; all After methods are
    291         * always executed: exceptions thrown by previous steps are combined, if
    292         * necessary, with exceptions from After methods into a
    293         * {@link MultipleFailureException}.
    294         * <li>ALWAYS allow {@code @Rule} fields to modify the execution of the
    295         * above steps. A {@code Rule} may prevent all execution of the above steps,
    296         * or add additional behavior before and after, or modify thrown exceptions.
    297         * For more information, see {@link TestRule}
    298         * </ul>
    299         *
    300         * This can be overridden in subclasses, either by overriding this method,
    301         * or the implementations creating each sub-statement.
    302         */
    303        protected Statement methodBlock(final FrameworkMethod method) {
    304            Object test;
    305            try {
    306                test = new ReflectiveCallable() {
    307                    @Override
    308                    protected Object runReflectiveCall() throws Throwable {
    309                        return createTest(method);
    310                    }
    311                }.run();
    312            } catch (Throwable e) {
    313                return new Fail(e);
    314            }
    315
    316            Statement statement = methodInvoker(method, test);
    317            statement = possiblyExpectingExceptions(method, test, statement);
    318            statement = withPotentialTimeout(method, test, statement);
    319            statement = withBefores(method, test, statement);
    320            statement = withAfters(method, test, statement);
    321            statement = withRules(method, test, statement);
    322            statement = withInterruptIsolation(statement);
    323            return statement;
    324        }
    325
    326        //
    327        // Statement builders
    328        //
    329
    330        /**
    331         * Returns a {@link Statement} that invokes {@code method} on {@code test}
    332         */
    333        protected Statement methodInvoker(FrameworkMethod method, Object test) {
    334            return new InvokeMethod(method, test);
    335        }
    336
    337        /**
    338         * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
    339         * has the {@link Test#expected()} attribute, return normally only if {@code next}
    340         * throws an exception of the correct type, and throw an exception
    341         * otherwise.
    342         */
    343        protected Statement possiblyExpectingExceptions(FrameworkMethod method,
    344                Object test, Statement next) {
    345            Test annotation = method.getAnnotation(Test.class);
    346            Class<? extends Throwable> expectedExceptionClass = getExpectedException(annotation);
    347            return expectedExceptionClass != null ? new ExpectException(next, expectedExceptionClass) : next;
    348        }
    349
    350        /**
    351         * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
    352         * has the {@code timeout} attribute, throw an exception if {@code next}
    353         * takes more than the specified number of milliseconds.
    354         * @deprecated
    355         */
    356        @Deprecated
    357        protected Statement withPotentialTimeout(FrameworkMethod method,
    358                Object test, Statement next) {
    359            long timeout = getTimeout(method.getAnnotation(Test.class));
    360            if (timeout <= 0) {
    361                return next;
    362            }
    363            return FailOnTimeout.builder()
    364                   .withTimeout(timeout, TimeUnit.MILLISECONDS)
    365                   .build(next);
    366        }
    367
    368        /**
    369         * Returns a {@link Statement}: run all non-overridden {@code @Before}
    370         * methods on this class and superclasses before running {@code next}; if
    371         * any throws an Exception, stop execution and pass the exception on.
    372         */
    373        protected Statement withBefores(FrameworkMethod method, Object target,
    374                Statement statement) {
    375            List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
    376                    Before.class);
    377            return befores.isEmpty() ? statement : new RunBefores(statement,
    378                    befores, target);
    379        }
    380
    381        /**
    382         * Returns a {@link Statement}: run all non-overridden {@code @After}
    383         * methods on this class and superclasses before running {@code next}; all
    384         * After methods are always executed: exceptions thrown by previous steps
    385         * are combined, if necessary, with exceptions from After methods into a
    386         * {@link MultipleFailureException}.
    387         */
    388        protected Statement withAfters(FrameworkMethod method, Object target,
    389                Statement statement) {
    390            List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(
    391                    After.class);
    392            return afters.isEmpty() ? statement : new RunAfters(statement, afters,
    393                    target);
    394        }
    395
    396        private Statement withRules(FrameworkMethod method, Object target, Statement statement) {
    397            RuleContainer ruleContainer = new RuleContainer();
    398            CURRENT_RULE_CONTAINER.set(ruleContainer);
    399            try {
    400                List<TestRule> testRules = getTestRules(target);
    401                for (MethodRule each : rules(target)) {
    402                    if (!(each instanceof TestRule && testRules.contains(each))) {
    403                        ruleContainer.add(each);
    404                    }
    405                }
    406                for (TestRule rule : testRules) {
    407                    ruleContainer.add(rule);
    408                }
    409            } finally {
    410                CURRENT_RULE_CONTAINER.remove();
    411            }
    412            return ruleContainer.apply(method, describeChild(method), target, statement);
    413        }
    414
    415        /**
    416         * @param target the test case instance
    417         * @return a list of MethodRules that should be applied when executing this
    418         *         test
    419         */
    420        protected List<MethodRule> rules(Object target) {
    421            RuleCollector<MethodRule> collector = new RuleCollector<MethodRule>();
    422            getTestClass().collectAnnotatedMethodValues(target, Rule.class, MethodRule.class,
    423                    collector);
    424            getTestClass().collectAnnotatedFieldValues(target, Rule.class, MethodRule.class,
    425                    collector);
    426            return collector.result;
    427        }
    428
    429        /**
    430         * @param target the test case instance
    431         * @return a list of TestRules that should be applied when executing this
    432         *         test
    433         */
    434        protected List<TestRule> getTestRules(Object target) {
    435            RuleCollector<TestRule> collector = new RuleCollector<TestRule>();
    436            getTestClass().collectAnnotatedMethodValues(target, Rule.class, TestRule.class, collector);
    437            getTestClass().collectAnnotatedFieldValues(target, Rule.class, TestRule.class, collector);
    438            return collector.result;
    439        }
    440
    441        private Class<? extends Throwable> getExpectedException(Test annotation) {
    442            if (annotation == null || annotation.expected() == None.class) {
    443                return null;
    444            } else {
    445                return annotation.expected();
    446            }
    447        }
    448
    449        private long getTimeout(Test annotation) {
    450            if (annotation == null) {
    451                return 0;
    452            }
    453            return annotation.timeout();
    454        }
    455
    456        private static final ThreadLocal<RuleContainer> CURRENT_RULE_CONTAINER =
    457                new ThreadLocal<RuleContainer>();
    458
    459        private static class RuleCollector<T> implements MemberValueConsumer<T> {
    460            final List<T> result = new ArrayList<T>();
    461
    462            public void accept(FrameworkMember<?> member, T value) {
    463                Rule rule = member.getAnnotation(Rule.class);
    464                if (rule != null) {
    465                    RuleContainer container = CURRENT_RULE_CONTAINER.get();
    466                    if (container != null) {
    467                        container.setOrder(value, rule.order());
    468                    }
    469                }
    470                result.add(value);
    471            }
    472        }
    473    }