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