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    }