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