001package org.junit.runners;
002
003import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_METHOD_VALIDATOR;
004import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
005
006import java.util.ArrayList;
007import java.util.List;
008import java.util.concurrent.ConcurrentHashMap;
009import java.util.concurrent.ConcurrentMap;
010import java.util.concurrent.TimeUnit;
011
012import org.junit.After;
013import org.junit.Before;
014import org.junit.Ignore;
015import org.junit.Rule;
016import org.junit.Test;
017import org.junit.Test.None;
018import org.junit.internal.runners.model.ReflectiveCallable;
019import org.junit.internal.runners.statements.ExpectException;
020import org.junit.internal.runners.statements.Fail;
021import org.junit.internal.runners.statements.FailOnTimeout;
022import org.junit.internal.runners.statements.InvokeMethod;
023import org.junit.internal.runners.statements.RunAfters;
024import org.junit.internal.runners.statements.RunBefores;
025import org.junit.rules.MethodRule;
026import org.junit.rules.TestRule;
027import org.junit.runner.Description;
028import org.junit.runner.notification.RunNotifier;
029import org.junit.runners.model.FrameworkMember;
030import org.junit.runners.model.FrameworkMethod;
031import org.junit.runners.model.InitializationError;
032import org.junit.runners.model.MemberValueConsumer;
033import org.junit.runners.model.MultipleFailureException;
034import org.junit.runners.model.Statement;
035import org.junit.runners.model.TestClass;
036import org.junit.validator.PublicClassValidator;
037import 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 */
063public 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}