001/*
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.kuali.rice.test.runners;
018
019import org.apache.commons.beanutils.MethodUtils;
020import org.junit.After;
021import org.junit.AfterClass;
022import org.junit.Before;
023import org.junit.BeforeClass;
024import org.junit.ClassRule;
025import org.junit.Ignore;
026import org.junit.Rule;
027import org.junit.Test;
028import org.junit.internal.AssumptionViolatedException;
029import org.junit.internal.runners.model.EachTestNotifier;
030import org.junit.internal.runners.model.ReflectiveCallable;
031import org.junit.internal.runners.statements.ExpectException;
032import org.junit.internal.runners.statements.Fail;
033import org.junit.internal.runners.statements.FailOnTimeout;
034import org.junit.internal.runners.statements.InvokeMethod;
035import org.junit.internal.runners.statements.RunAfters;
036import org.junit.internal.runners.statements.RunBefores;
037import org.junit.rules.RunRules;
038import org.junit.rules.TestRule;
039import org.junit.runner.Description;
040import org.junit.runner.JUnitCore;
041import org.junit.runner.Result;
042import org.junit.runner.RunWith;
043import org.junit.runner.Runner;
044import org.junit.runner.manipulation.Filter;
045import org.junit.runner.manipulation.Filterable;
046import org.junit.runner.manipulation.NoTestsRemainException;
047import org.junit.runner.manipulation.Sortable;
048import org.junit.runner.manipulation.Sorter;
049import org.junit.runner.notification.Failure;
050import org.junit.runner.notification.RunNotifier;
051import org.junit.runner.notification.StoppedByUserException;
052import org.junit.runners.model.FrameworkMethod;
053import org.junit.runners.model.InitializationError;
054import org.junit.runners.model.RunnerScheduler;
055import org.junit.runners.model.Statement;
056import org.junit.runners.model.TestClass;
057import org.kuali.rice.core.api.util.ShadowingInstrumentableClassLoader;
058import org.kuali.rice.test.MethodAware;
059
060import java.lang.annotation.Annotation;
061import java.lang.reflect.Method;
062import java.util.ArrayList;
063import java.util.Collections;
064import java.util.Comparator;
065import java.util.Iterator;
066import java.util.List;
067
068import static org.junit.internal.runners.rules.RuleMemberValidator.*;
069
070
071/**
072 * A JUnit test {@link org.junit.runner.Runner} which uses a custom classloader with a copy of the classpath and allows
073 * for transformers to be added to the ClassLoader for load-time weaving.
074 *
075 * <p>Useful when writing tests that use JPA with EclipseLink since it depends upon load-time weaving.</p>
076 *
077 * <p>In order to use this class, you must have a {@link BootstrapTest} annotation available somewhere in the hierarchy
078 * of your test class (usually on the same class where the {@link RunWith} annotation is specified which references this
079 * runner class). This informs the runner about a test that it can run to execute any one-time initialization for
080 * the test suite. Ideally, this bootstrap test will execute code which loads JPA persistence units and any associated
081 * ClassFileTransformers for load-time weaving. This is necessary because it is common for an integration test to have
082 * references in the test class itself to JPA entities which need to be weaved. When this occurs, if the persistence
083 * units and ClassFileTransformers are not properly loaded before the entity classes are loaded by the classloader, then
084 * instrumentation will (silently!) fail to occur.</p>
085 *
086 * <p>Much of the code in this class was copied from the JUnit ParentRunner, BlockJUnit4ClassRunner, and
087 * TomcatInstrumentableClassLoader.</p>
088 *
089 * @author Kuali Rice Team (rice.collab@kuali.org)
090 */
091public class LoadTimeWeavableTestRunner extends Runner implements Filterable, Sortable {
092
093    private static final String[] JUNIT_CLASSLOADER_EXCLUDES = { "org.junit.", "junit.framework." };
094
095    private final TestClass originalTestClass;
096    private TestClass fTestClass;
097    private Method currentMethod;
098
099    // static because we only need one custom loader per JVM in which the tests are running, otherwise the memory
100    // usage gets crazy!
101    private static ClassLoader customLoader;
102
103    private Sorter fSorter = Sorter.NULL;
104
105    private List<FrameworkMethod> originalFilteredChildren = null;
106    private List<FrameworkMethod> filteredChildren = null;
107
108    private static final ThreadLocal<Boolean> runningBootstrapTest = new ThreadLocal<Boolean>() {
109        @Override
110        protected Boolean initialValue() {
111            return Boolean.FALSE;
112        }
113    };
114
115    private RunnerScheduler fScheduler = new RunnerScheduler() {
116        public void schedule(Runnable childStatement) {
117            childStatement.run();
118        }
119        public void finished() {
120            // do nothing
121        }
122    };
123
124    /**
125     * Constructs a new {@code ParentRunner} that will run {@code @TestClass}
126     */
127    public LoadTimeWeavableTestRunner(Class<?> testClass) throws InitializationError {
128        this.originalTestClass = new TestClass(testClass);
129        if (LoadTimeWeavableTestRunner.customLoader == null) {
130            LoadTimeWeavableTestRunner.customLoader =
131                    new ShadowingInstrumentableClassLoader(testClass.getClassLoader(), JUNIT_CLASSLOADER_EXCLUDES);
132        }
133        validate();
134    }
135
136    private TestClass getCustomTestClass(Class<?> originalTestClass, ClassLoader customLoader) {
137        try {
138            Class<?> newTestClass = customLoader.loadClass(originalTestClass.getName());
139            if (newTestClass == originalTestClass) {
140                throw new IllegalStateException(newTestClass.getName() + " loaded from custom class loader should have been a different instance but was the same!");
141            }
142            return new TestClass(newTestClass);
143        } catch (ClassNotFoundException e) {
144            throw new IllegalStateException("Failed to load test class from custom classloader: " + originalTestClass.getName());
145        }
146    }
147
148    protected ClassLoader getCustomClassLoader() {
149        return customLoader;
150    }
151
152    /**
153     * Adds to {@code errors} if any method in this class is annotated with
154     * {@code annotation}, but:
155     * <ul>
156     * <li>is not public, or
157     * <li>takes parameters, or
158     * <li>returns something other than void, or
159     * <li>is static (given {@code isStatic is false}), or
160     * <li>is not static (given {@code isStatic is true}).
161     */
162    protected void validatePublicVoidNoArgMethods(Class<? extends Annotation> annotation,
163            boolean isStatic, List<Throwable> errors) {
164        List<FrameworkMethod> methods = getOriginalTestClass().getAnnotatedMethods(annotation);
165
166        for (FrameworkMethod eachTestMethod : methods) {
167            eachTestMethod.validatePublicVoidNoArg(isStatic, errors);
168        }
169    }
170
171    private void validateClassRules(List<Throwable> errors) {
172        CLASS_RULE_VALIDATOR.validate(getOriginalTestClass(), errors);
173        CLASS_RULE_METHOD_VALIDATOR.validate(getOriginalTestClass(), errors);
174    }
175
176    /**
177     * Constructs a {@code Statement} to run all of the tests in the test class. Override to add pre-/post-processing.
178     * Here is an outline of the implementation:
179     * <ul>
180     * <li>Call {@link #runChild(org.junit.runners.model.FrameworkMethod, org.junit.runner.notification.RunNotifier)} on each object returned by {@link #getChildren()} (subject to any imposed filter and sort).</li>
181     * <li>ALWAYS run all non-overridden {@code @BeforeClass} methods on this class
182     * and superclasses before the previous step; if any throws an
183     * Exception, stop execution and pass the exception on.
184     * <li>ALWAYS run all non-overridden {@code @AfterClass} methods on this class
185     * and superclasses before any of the previous steps; all AfterClass methods are
186     * always executed: exceptions thrown by previous steps are combined, if
187     * necessary, with exceptions from AfterClass methods into a
188     * {@link org.junit.runners.model.MultipleFailureException}.
189     * </ul>
190     *
191     * @return {@code Statement}
192     */
193    protected Statement classBlock(final RunNotifier notifier) {
194        Statement statement = childrenInvoker(notifier);
195        statement = withBeforeClasses(statement);
196        statement = withAfterClasses(statement);
197        statement = withClassRules(statement);
198        return statement;
199    }
200
201    /**
202     * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @BeforeClass} methods on this class
203     * and superclasses before executing {@code statement}; if any throws an
204     * Exception, stop execution and pass the exception on.
205     */
206    protected Statement withBeforeClasses(Statement statement) {
207        List<FrameworkMethod> befores = getTestClass()
208                .getAnnotatedMethods(BeforeClass.class);
209        return befores.isEmpty() ? statement :
210                new RunBefores(statement, befores, null);
211    }
212
213    /**
214     * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @AfterClass} methods on this class
215     * and superclasses before executing {@code statement}; all AfterClass methods are
216     * always executed: exceptions thrown by previous steps are combined, if
217     * necessary, with exceptions from AfterClass methods into a
218     * {@link org.junit.runners.model.MultipleFailureException}.
219     */
220    protected Statement withAfterClasses(Statement statement) {
221        List<FrameworkMethod> afters = getTestClass()
222                .getAnnotatedMethods(AfterClass.class);
223        return afters.isEmpty() ? statement :
224                new RunAfters(statement, afters, null);
225    }
226
227    /**
228     * Returns a {@link org.junit.runners.model.Statement}: apply all
229     * static fields assignable to {@link org.junit.rules.TestRule}
230     * annotated with {@link org.junit.ClassRule}.
231     *
232     * @param statement the base statement
233     * @return a RunRules statement if any class-level {@link org.junit.Rule}s are
234     *         found, or the base statement
235     */
236    private Statement withClassRules(Statement statement) {
237        List<TestRule> classRules = classRules();
238        return classRules.isEmpty() ? statement :
239                new RunRules(statement, classRules, getDescription());
240    }
241
242    /**
243     * @return the {@code ClassRule}s that can transform the block that runs
244     *         each method in the tested class.
245     */
246    protected List<TestRule> classRules() {
247        List<TestRule> result = getTestClass().getAnnotatedMethodValues(null, ClassRule.class, TestRule.class);
248
249        result.addAll(getTestClass().getAnnotatedFieldValues(null, ClassRule.class, TestRule.class));
250
251        return result;
252    }
253
254    /**
255     * Returns a {@link org.junit.runners.model.Statement}: Call {@link #runChild(org.junit.runners.model.FrameworkMethod, org.junit.runner.notification.RunNotifier)}
256     * on each object returned by {@link #getChildren()} (subject to any imposed
257     * filter and sort)
258     */
259    protected Statement childrenInvoker(final RunNotifier notifier) {
260        return new Statement() {
261            @Override
262            public void evaluate() {
263                runChildren(notifier);
264            }
265        };
266    }
267
268    private void runChildren(final RunNotifier notifier) {
269        for (final FrameworkMethod each : getFilteredChildren()) {
270            fScheduler.schedule(new Runnable() {
271                public void run() {
272                    LoadTimeWeavableTestRunner.this.runChild(each, notifier);
273                }
274            });
275        }
276        fScheduler.finished();
277    }
278
279    /**
280     * Returns a name used to describe this Runner
281     */
282    protected String getName() {
283        return getOriginalTestClass().getName();
284    }
285
286    /**
287     * Returns a {@link org.junit.runners.model.TestClass} object wrapping the class to be executed.
288     */
289    public final TestClass getTestClass() {
290        if (fTestClass == null) {
291            throw new IllegalStateException("Attempted to access test class but it has not yet been initialized!");
292        }
293        return fTestClass;
294    }
295
296    /**
297     * Returns the original test class that was passed to this test runner.
298     */
299    public final TestClass getOriginalTestClass() {
300        return originalTestClass;
301    }
302
303    /**
304     * Runs a {@link org.junit.runners.model.Statement} that represents a leaf (aka atomic) test.
305     */
306    protected final void runLeaf(Statement statement, Description description,
307            RunNotifier notifier) {
308        EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
309        eachNotifier.fireTestStarted();
310        try {
311            statement.evaluate();
312        } catch (AssumptionViolatedException e) {
313            eachNotifier.addFailedAssumption(e);
314        } catch (Throwable e) {
315            eachNotifier.addFailure(e);
316        } finally {
317            eachNotifier.fireTestFinished();
318        }
319    }
320
321    /**
322     * @return the annotations that should be attached to this runner's
323     *         description.
324     */
325    protected Annotation[] getRunnerAnnotations() {
326        return getOriginalTestClass().getAnnotations();
327    }
328
329    //
330    // Implementation of Runner
331    //
332
333    @Override
334    public Description getDescription() {
335        Description description = Description.createSuiteDescription(getName(),
336                getRunnerAnnotations());
337        for (FrameworkMethod child : getOriginalFilteredChildren()) {
338            description.addChild(describeOriginalChild(child));
339        }
340        return description;
341    }
342
343    @Override
344    public void run(final RunNotifier notifier) {
345        ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
346        Thread.currentThread().setContextClassLoader(customLoader);
347        try {
348            if (runBootstrapTest(notifier, getOriginalTestClass())) {
349                this.fTestClass = getCustomTestClass(getOriginalTestClass().getJavaClass(), customLoader);
350                EachTestNotifier testNotifier = new EachTestNotifier(notifier, getDescription());
351                try {
352                    Statement statement = classBlock(notifier);
353                    statement.evaluate();
354                } catch (AssumptionViolatedException e) {
355                    testNotifier.fireTestIgnored();
356                } catch (StoppedByUserException e) {
357                    throw e;
358                } catch (Throwable e) {
359                    testNotifier.addFailure(e);
360                }
361            }
362        } finally {
363            Thread.currentThread().setContextClassLoader(currentContextClassLoader);
364        }
365    }
366
367    protected boolean runBootstrapTest(RunNotifier notifier, TestClass testClass) {
368        if (!runningBootstrapTest.get().booleanValue()) {
369            runningBootstrapTest.set(Boolean.TRUE);
370            try {
371                BootstrapTest bootstrapTest = getBootstrapTestAnnotation(testClass.getJavaClass());
372                if (bootstrapTest != null) {
373                    Result result = JUnitCore.runClasses(bootstrapTest.value());
374                    List<Failure> failures = result.getFailures();
375                    for (Failure failure : failures) {
376                        notifier.fireTestFailure(failure);
377                    }
378                    return result.getFailureCount() == 0;
379                } else {
380                    throw new IllegalStateException("LoadTimeWeavableTestRunner, must be coupled with an @BootstrapTest annotation to define the bootstrap test to execute.");
381                }
382            } finally {
383                runningBootstrapTest.set(Boolean.FALSE);
384            }
385        }
386        return true;
387    }
388
389    private BootstrapTest getBootstrapTestAnnotation(Class<?> testClass) {
390        BootstrapTest bootstrapTest = testClass.getAnnotation(BootstrapTest.class);
391        if (bootstrapTest != null) {
392            return bootstrapTest;
393        } else if (testClass.getSuperclass() != null) {
394            return getBootstrapTestAnnotation(testClass.getSuperclass());
395        } else {
396            return null;
397        }
398    }
399
400    //
401    // Implementation of Filterable and Sortable
402    //
403
404    public void filter(Filter filter) throws NoTestsRemainException {
405        for (Iterator<FrameworkMethod> iter = getOriginalFilteredChildren().iterator(); iter.hasNext(); ) {
406            FrameworkMethod each = iter.next();
407            if (shouldRun(filter, each)) {
408                try {
409                    filter.apply(each);
410                } catch (NoTestsRemainException e) {
411                    iter.remove();
412                }
413            } else {
414                iter.remove();
415            }
416        }
417        if (getOriginalFilteredChildren().isEmpty()) {
418            throw new NoTestsRemainException();
419        }
420    }
421
422    public void sort(Sorter sorter) {
423        fSorter = sorter;
424        for (FrameworkMethod each : getOriginalFilteredChildren()) {
425            sortChild(each);
426        }
427        Collections.sort(getOriginalFilteredChildren(), comparator());
428    }
429
430    //
431    // Private implementation
432    //
433
434    private void validate() throws InitializationError {
435        List<Throwable> errors = new ArrayList<Throwable>();
436        collectInitializationErrors(errors);
437        if (!errors.isEmpty()) {
438            throw new InitializationError(errors);
439        }
440    }
441
442    private List<FrameworkMethod> getOriginalFilteredChildren() {
443        if (originalFilteredChildren == null) {
444            originalFilteredChildren = new ArrayList<FrameworkMethod>(getOriginalChildren());
445        }
446        return originalFilteredChildren;
447    }
448
449    private List<FrameworkMethod> getFilteredChildren() {
450        if (getOriginalFilteredChildren() == null) {
451            throw new IllegalStateException("Attempted to get filtered children before original filtered children were initialized.");
452        }
453        if (filteredChildren == null) {
454            filteredChildren = new ArrayList<FrameworkMethod>();
455            List<FrameworkMethod> testMethods = computeTestMethods();
456            for (FrameworkMethod originalMethod : getOriginalFilteredChildren()) {
457                for (FrameworkMethod testMethod : testMethods) {
458                    if (originalMethod.isShadowedBy(testMethod)) {
459                        filteredChildren.add(testMethod);
460                    }
461                }
462            }
463        }
464        return filteredChildren;
465    }
466
467    private void sortChild(FrameworkMethod child) {
468        fSorter.apply(child);
469    }
470
471    private boolean shouldRun(Filter filter, FrameworkMethod each) {
472        return filter.shouldRun(describeOriginalChild(each));
473    }
474
475    private Comparator<? super FrameworkMethod> comparator() {
476        return new Comparator<FrameworkMethod>() {
477            public int compare(FrameworkMethod o1, FrameworkMethod o2) {
478                return fSorter.compare(describeChild(o1), describeChild(o2));
479            }
480        };
481    }
482
483    //
484    // Implementation of ParentRunner
485    //
486
487    /**
488     * Runs the test corresponding to {@code child}, which can be assumed to be
489     * an element of the list returned by {@link #getChildren()}.
490     * Subclasses are responsible for making sure that relevant test events are
491     * reported through {@code notifier}
492     */
493    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
494        this.currentMethod = method.getMethod();
495        try {
496            Description description = describeChild(method);
497            if (method.getAnnotation(Ignore.class) != null) {
498                notifier.fireTestIgnored(description);
499            } else {
500                runLeaf(methodBlock(method), description, notifier);
501            }
502        } finally {
503            this.currentMethod = null;
504        }
505    }
506
507    /**
508     * Returns a {@link org.junit.runner.Description} for {@code child}, which can be assumed to
509     * be an element of the list returned by {@link #getChildren()}
510     */
511    protected Description describeChild(FrameworkMethod method) {
512        return Description.createTestDescription(getTestClass().getJavaClass(),
513                testName(method), method.getAnnotations());
514    }
515
516    protected Description describeOriginalChild(FrameworkMethod method) {
517        return Description.createTestDescription(getOriginalTestClass().getJavaClass(),
518                testName(method), method.getAnnotations());
519    }
520
521    /**
522     * Returns a list of objects that define the children of this Runner.
523     */
524    protected List<FrameworkMethod> getChildren() {
525        return computeTestMethods();
526    }
527
528    protected List<FrameworkMethod> getOriginalChildren() {
529        return computeOriginalTestMethods();
530    }
531
532    //
533    // Override in subclasses
534    //
535
536    /**
537     * Returns the methods that run tests. Default implementation returns all
538     * methods annotated with {@code @Test} on this class and superclasses that
539     * are not overridden.
540     */
541    protected List<FrameworkMethod> computeTestMethods() {
542        return getTestClass().getAnnotatedMethods(Test.class);
543    }
544
545    protected List<FrameworkMethod> computeOriginalTestMethods() {
546        return getOriginalTestClass().getAnnotatedMethods(Test.class);
547    }
548
549    /**
550     * Adds to {@code errors} a throwable for each problem noted with the test class (available from {@link #getTestClass()}).
551     * Default implementation adds an error for each method annotated with
552     * {@code @BeforeClass} or {@code @AfterClass} that is not
553     * {@code public static void} with no arguments.
554     */
555    protected void collectInitializationErrors(List<Throwable> errors) {
556        validatePublicVoidNoArgMethods(BeforeClass.class, true, errors);
557        validatePublicVoidNoArgMethods(AfterClass.class, true, errors);
558        validateClassRules(errors);
559        validateNoNonStaticInnerClass(errors);
560        validateConstructor(errors);
561        validateInstanceMethods(errors);
562        validateFields(errors);
563        validateMethods(errors);
564    }
565
566    protected void validateNoNonStaticInnerClass(List<Throwable> errors) {
567        if (getOriginalTestClass().isANonStaticInnerClass()) {
568            String gripe = "The inner class " + getOriginalTestClass().getName()
569                    + " is not static.";
570            errors.add(new Exception(gripe));
571        }
572    }
573
574    /**
575     * Adds to {@code errors} if the test class has more than one constructor,
576     * or if the constructor takes parameters. Override if a subclass requires
577     * different validation rules.
578     */
579    protected void validateConstructor(List<Throwable> errors) {
580        validateOnlyOneConstructor(errors);
581        validateZeroArgConstructor(errors);
582    }
583
584    /**
585     * Adds to {@code errors} if the test class has more than one constructor
586     * (do not override)
587     */
588    protected void validateOnlyOneConstructor(List<Throwable> errors) {
589        if (!hasOneConstructor()) {
590            String gripe = "Test class should have exactly one public constructor";
591            errors.add(new Exception(gripe));
592        }
593    }
594
595    /**
596     * Adds to {@code errors} if the test class's single constructor takes
597     * parameters (do not override)
598     */
599    protected void validateZeroArgConstructor(List<Throwable> errors) {
600        if (!getOriginalTestClass().isANonStaticInnerClass()
601                && hasOneConstructor()
602                && (getOriginalTestClass().getOnlyConstructor().getParameterTypes().length != 0)) {
603            String gripe = "Test class should have exactly one public zero-argument constructor";
604            errors.add(new Exception(gripe));
605        }
606    }
607
608    private boolean hasOneConstructor() {
609        return getOriginalTestClass().getJavaClass().getConstructors().length == 1;
610    }
611
612    /**
613     * Adds to {@code errors} for each method annotated with {@code @Test},
614     * {@code @Before}, or {@code @After} that is not a public, void instance
615     * method with no arguments.
616     *
617     * @deprecated unused API, will go away in future version
618     */
619    @Deprecated
620    protected void validateInstanceMethods(List<Throwable> errors) {
621        validatePublicVoidNoArgMethods(After.class, false, errors);
622        validatePublicVoidNoArgMethods(Before.class, false, errors);
623        validateTestMethods(errors);
624
625        if (computeOriginalTestMethods().size() == 0) {
626            errors.add(new Exception("No runnable methods"));
627        }
628    }
629
630    protected void validateFields(List<Throwable> errors) {
631        RULE_VALIDATOR.validate(getOriginalTestClass(), errors);
632    }
633
634    private void validateMethods(List<Throwable> errors) {
635        RULE_METHOD_VALIDATOR.validate(getOriginalTestClass(), errors);
636    }
637
638    /**
639     * Adds to {@code errors} for each method annotated with {@code @Test}that
640     * is not a public, void instance method with no arguments.
641     */
642    protected void validateTestMethods(List<Throwable> errors) {
643        validatePublicVoidNoArgMethods(Test.class, false, errors);
644    }
645
646    /**
647     * Returns a new fixture for running a test. Default implementation executes
648     * the test class's no-argument constructor (validation should have ensured
649     * one exists).
650     */
651    protected Object createTest() throws Exception {
652        Object test = getTestClass().getOnlyConstructor().newInstance();
653        setTestName(test, currentMethod);
654        setTestMethod(test, currentMethod);
655        return test;
656    }
657
658    /**
659     * Sets the {@link java.lang.reflect.Method} on the test case if it is {@link org.kuali.rice.test.MethodAware}
660     * @param method the current method to be run
661     * @param test the test instance
662     */
663    protected void setTestMethod(Object test, Method method) throws Exception {
664        Class<?> methodAwareClass = Class.forName(MethodAware.class.getName(), true, getCustomClassLoader());
665        if (methodAwareClass.isInstance(test)) {
666            Method setTestMethod = methodAwareClass.getMethod("setTestMethod", Method.class);
667            setTestMethod.invoke(test, method);
668        }
669    }
670
671    protected void setTestName(final Object test, final Method testMethod) throws Exception {
672        String name = testMethod == null ? "" : testMethod.getName();
673        final Method setNameMethod = MethodUtils.getAccessibleMethod(test.getClass(), "setName",
674                new Class[]{String.class});
675        if (setNameMethod != null) {
676            setNameMethod.invoke(test, name);
677        }
678    }
679
680    /**
681     * Returns the name that describes {@code method} for {@link org.junit.runner.Description}s.
682     * Default implementation is the method's name
683     */
684    protected String testName(FrameworkMethod method) {
685        return method.getName();
686    }
687
688    /**
689     * Returns a Statement that, when executed, either returns normally if
690     * {@code method} passes, or throws an exception if {@code method} fails.
691     *
692     * Here is an outline of the default implementation:
693     *
694     * <ul>
695     * <li>Invoke {@code method} on the result of {@code createTest()}, and
696     * throw any exceptions thrown by either operation.
697     * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
698     * expecting} attribute, return normally only if the previous step threw an
699     * exception of the correct type, and throw an exception otherwise.
700     * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
701     * timeout} attribute, throw an exception if the previous step takes more
702     * than the specified number of milliseconds.
703     * <li>ALWAYS run all non-overridden {@code @Before} methods on this class
704     * and superclasses before any of the previous steps; if any throws an
705     * Exception, stop execution and pass the exception on.
706     * <li>ALWAYS run all non-overridden {@code @After} methods on this class
707     * and superclasses after any of the previous steps; all After methods are
708     * always executed: exceptions thrown by previous steps are combined, if
709     * necessary, with exceptions from After methods into a
710     * {@link org.junit.runners.model.MultipleFailureException}.
711     * <li>ALWAYS allow {@code @Rule} fields to modify the execution of the
712     * above steps. A {@code Rule} may prevent all execution of the above steps,
713     * or add additional behavior before and after, or modify thrown exceptions.
714     * For more information, see {@link org.junit.rules.TestRule}
715     * </ul>
716     *
717     * This can be overridden in subclasses, either by overriding this method,
718     * or the implementations creating each sub-statement.
719     */
720    protected Statement methodBlock(FrameworkMethod method) {
721        Object test;
722        try {
723            test = new ReflectiveCallable() {
724                @Override
725                protected Object runReflectiveCall() throws Throwable {
726                    return createTest();
727                }
728            }.run();
729        } catch (Throwable e) {
730            return new Fail(e);
731        }
732
733        Statement statement = methodInvoker(method, test);
734        statement = possiblyExpectingExceptions(method, test, statement);
735        statement = withPotentialTimeout(method, test, statement);
736        statement = withBefores(method, test, statement);
737        statement = withAfters(method, test, statement);
738        statement = withRules(method, test, statement);
739        return statement;
740    }
741
742    //
743    // Statement builders
744    //
745
746    /**
747     * Returns a {@link org.junit.runners.model.Statement} that invokes {@code method} on {@code test}
748     */
749    protected Statement methodInvoker(FrameworkMethod method, Object test) {
750        return new InvokeMethod(method, test);
751    }
752
753    /**
754     * Returns a {@link org.junit.runners.model.Statement}: if {@code method}'s {@code @Test} annotation
755     * has the {@code expecting} attribute, return normally only if {@code next}
756     * throws an exception of the correct type, and throw an exception
757     * otherwise.
758     *
759     * @deprecated Will be private soon: use Rules instead
760     */
761    @Deprecated
762    protected Statement possiblyExpectingExceptions(FrameworkMethod method,
763            Object test, Statement next) {
764        Test annotation = method.getAnnotation(Test.class);
765        return expectsException(annotation) ? new ExpectException(next,
766                getExpectedException(annotation)) : next;
767    }
768
769    /**
770     * Returns a {@link org.junit.runners.model.Statement}: if {@code method}'s {@code @Test} annotation
771     * has the {@code timeout} attribute, throw an exception if {@code next}
772     * takes more than the specified number of milliseconds.
773     *
774     * @deprecated Will be private soon: use Rules instead
775     */
776    @Deprecated
777    protected Statement withPotentialTimeout(FrameworkMethod method,
778            Object test, Statement next) {
779        long timeout = getTimeout(method.getAnnotation(Test.class));
780        return timeout > 0 ? new FailOnTimeout(next, timeout) : next;
781    }
782
783    /**
784     * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @Before}
785     * methods on this class and superclasses before running {@code next}; if
786     * any throws an Exception, stop execution and pass the exception on.
787     *
788     * @deprecated Will be private soon: use Rules instead
789     */
790    @Deprecated
791    protected Statement withBefores(FrameworkMethod method, Object target,
792            Statement statement) {
793        List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(Before.class);
794        return befores.isEmpty() ? statement : new RunBefores(statement,
795                befores, target);
796    }
797
798    /**
799     * Returns a {@link org.junit.runners.model.Statement}: run all non-overridden {@code @After}
800     * methods on this class and superclasses before running {@code next}; all
801     * After methods are always executed: exceptions thrown by previous steps
802     * are combined, if necessary, with exceptions from After methods into a
803     * {@link org.junit.runners.model.MultipleFailureException}.
804     *
805     * @deprecated Will be private soon: use Rules instead
806     */
807    @Deprecated
808    protected Statement withAfters(FrameworkMethod method, Object target,
809            Statement statement) {
810        List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(
811                After.class);
812        return afters.isEmpty() ? statement : new RunAfters(statement, afters,
813                target);
814    }
815
816    private Statement withRules(FrameworkMethod method, Object target,
817            Statement statement) {
818        List<TestRule> testRules = getTestRules(target);
819        Statement result = statement;
820        result = withMethodRules(method, testRules, target, result);
821        result = withTestRules(method, testRules, result);
822
823        return result;
824    }
825
826    private Statement withMethodRules(FrameworkMethod method, List<TestRule> testRules,
827            Object target, Statement result) {
828        for (org.junit.rules.MethodRule each : getMethodRules(target)) {
829            if (!testRules.contains(each)) {
830                result = each.apply(result, method, target);
831            }
832        }
833        return result;
834    }
835
836    private List<org.junit.rules.MethodRule> getMethodRules(Object target) {
837        return rules(target);
838    }
839
840    /**
841     * @param target the test case instance
842     * @return a list of MethodRules that should be applied when executing this
843     *         test
844     */
845    protected List<org.junit.rules.MethodRule> rules(Object target) {
846        return getTestClass().getAnnotatedFieldValues(target, Rule.class, org.junit.rules.MethodRule.class);
847    }
848
849    /**
850     * Returns a {@link org.junit.runners.model.Statement}: apply all non-static value fields
851     * annotated with {@link org.junit.Rule}.
852     *
853     * @param statement The base statement
854     * @return a RunRules statement if any class-level {@link org.junit.Rule}s are
855     *         found, or the base statement
856     */
857    private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules,
858            Statement statement) {
859        return testRules.isEmpty() ? statement :
860                new RunRules(statement, testRules, describeChild(method));
861    }
862
863    /**
864     * @param target the test case instance
865     * @return a list of TestRules that should be applied when executing this
866     *         test
867     */
868    protected List<TestRule> getTestRules(Object target) {
869        List<TestRule> result = getTestClass().getAnnotatedMethodValues(target,
870                Rule.class, TestRule.class);
871
872        result.addAll(getTestClass().getAnnotatedFieldValues(target,
873                Rule.class, TestRule.class));
874
875        return result;
876    }
877
878    private Class<? extends Throwable> getExpectedException(Test annotation) {
879        if (annotation == null || annotation.expected() == Test.None.class) {
880            return null;
881        } else {
882            return annotation.expected();
883        }
884    }
885
886    private boolean expectsException(Test annotation) {
887        return getExpectedException(annotation) != null;
888    }
889
890    private long getTimeout(Test annotation) {
891        if (annotation == null) {
892            return 0;
893        }
894        return annotation.timeout();
895    }
896
897}