001 package org.junit.runners;
002
003 import static org.junit.internal.Checks.notNull;
004 import static org.junit.internal.runners.rules.RuleMemberValidator.CLASS_RULE_METHOD_VALIDATOR;
005 import static org.junit.internal.runners.rules.RuleMemberValidator.CLASS_RULE_VALIDATOR;
006
007 import java.lang.annotation.Annotation;
008 import java.lang.reflect.Method;
009 import java.util.ArrayList;
010 import java.util.Collections;
011 import java.util.Comparator;
012 import java.util.Iterator;
013 import java.util.LinkedHashMap;
014 import java.util.List;
015 import java.util.Map;
016 import java.util.concurrent.locks.Lock;
017 import java.util.concurrent.locks.ReentrantLock;
018
019 import org.junit.AfterClass;
020 import org.junit.BeforeClass;
021 import org.junit.ClassRule;
022 import org.junit.FixMethodOrder;
023 import org.junit.Ignore;
024 import org.junit.Rule;
025 import org.junit.internal.AssumptionViolatedException;
026 import org.junit.internal.runners.model.EachTestNotifier;
027 import org.junit.internal.runners.statements.RunAfters;
028 import org.junit.internal.runners.statements.RunBefores;
029 import org.junit.rules.RunRules;
030 import org.junit.rules.TestRule;
031 import org.junit.runner.Description;
032 import org.junit.runner.Runner;
033 import org.junit.runner.manipulation.Filter;
034 import org.junit.runner.manipulation.Filterable;
035 import org.junit.runner.manipulation.Orderer;
036 import org.junit.runner.manipulation.InvalidOrderingException;
037 import org.junit.runner.manipulation.NoTestsRemainException;
038 import org.junit.runner.manipulation.Orderable;
039 import org.junit.runner.manipulation.Sorter;
040 import org.junit.runner.notification.RunNotifier;
041 import org.junit.runner.notification.StoppedByUserException;
042 import org.junit.runners.model.FrameworkMember;
043 import org.junit.runners.model.FrameworkMethod;
044 import org.junit.runners.model.InitializationError;
045 import org.junit.runners.model.InvalidTestClassError;
046 import org.junit.runners.model.MemberValueConsumer;
047 import org.junit.runners.model.RunnerScheduler;
048 import org.junit.runners.model.Statement;
049 import org.junit.runners.model.TestClass;
050 import org.junit.validator.AnnotationsValidator;
051 import org.junit.validator.TestClassValidator;
052
053 /**
054 * Provides most of the functionality specific to a Runner that implements a
055 * "parent node" in the test tree, with children defined by objects of some data
056 * type {@code T}. (For {@link BlockJUnit4ClassRunner}, {@code T} is
057 * {@link Method} . For {@link Suite}, {@code T} is {@link Class}.) Subclasses
058 * must implement finding the children of the node, describing each child, and
059 * running each child. ParentRunner will filter and sort children, handle
060 * {@code @BeforeClass} and {@code @AfterClass} methods,
061 * handle annotated {@link ClassRule}s, create a composite
062 * {@link Description}, and run children sequentially.
063 *
064 * @since 4.5
065 */
066 public abstract class ParentRunner<T> extends Runner implements Filterable,
067 Orderable {
068 private static final List<TestClassValidator> VALIDATORS = Collections.<TestClassValidator>singletonList(
069 new AnnotationsValidator());
070
071 private final Lock childrenLock = new ReentrantLock();
072 private final TestClass testClass;
073
074 // Guarded by childrenLock
075 private volatile List<T> filteredChildren = null;
076
077 private volatile RunnerScheduler scheduler = new RunnerScheduler() {
078 public void schedule(Runnable childStatement) {
079 childStatement.run();
080 }
081
082 public void finished() {
083 // do nothing
084 }
085 };
086
087 /**
088 * Constructs a new {@code ParentRunner} that will run {@code @TestClass}
089 */
090 protected ParentRunner(Class<?> testClass) throws InitializationError {
091 this.testClass = createTestClass(testClass);
092 validate();
093 }
094
095 /**
096 * Constructs a new {@code ParentRunner} that will run the {@code TestClass}.
097 *
098 * @since 4.13
099 */
100 protected ParentRunner(TestClass testClass) throws InitializationError {
101 this.testClass = notNull(testClass);
102 validate();
103 }
104
105 /**
106 * @deprecated Please use {@link #ParentRunner(org.junit.runners.model.TestClass)}.
107 * @since 4.12
108 */
109 @Deprecated
110 protected TestClass createTestClass(Class<?> testClass) {
111 return new TestClass(testClass);
112 }
113
114 //
115 // Must be overridden
116 //
117
118 /**
119 * Returns a list of objects that define the children of this Runner.
120 */
121 protected abstract List<T> getChildren();
122
123 /**
124 * Returns a {@link Description} for {@code child}, which can be assumed to
125 * be an element of the list returned by {@link ParentRunner#getChildren()}
126 */
127 protected abstract Description describeChild(T child);
128
129 /**
130 * Runs the test corresponding to {@code child}, which can be assumed to be
131 * an element of the list returned by {@link ParentRunner#getChildren()}.
132 * Subclasses are responsible for making sure that relevant test events are
133 * reported through {@code notifier}
134 */
135 protected abstract void runChild(T child, RunNotifier notifier);
136
137 //
138 // May be overridden
139 //
140
141 /**
142 * Adds to {@code errors} a throwable for each problem noted with the test class (available from {@link #getTestClass()}).
143 * Default implementation adds an error for each method annotated with
144 * {@code @BeforeClass} or {@code @AfterClass} that is not
145 * {@code public static void} with no arguments.
146 */
147 protected void collectInitializationErrors(List<Throwable> errors) {
148 validatePublicVoidNoArgMethods(BeforeClass.class, true, errors);
149 validatePublicVoidNoArgMethods(AfterClass.class, true, errors);
150 validateClassRules(errors);
151 applyValidators(errors);
152 }
153
154 private void applyValidators(List<Throwable> errors) {
155 if (getTestClass().getJavaClass() != null) {
156 for (TestClassValidator each : VALIDATORS) {
157 errors.addAll(each.validateTestClass(getTestClass()));
158 }
159 }
160 }
161
162 /**
163 * Adds to {@code errors} if any method in this class is annotated with
164 * {@code annotation}, but:
165 * <ul>
166 * <li>is not public, or
167 * <li>takes parameters, or
168 * <li>returns something other than void, or
169 * <li>is static (given {@code isStatic is false}), or
170 * <li>is not static (given {@code isStatic is true}).
171 * </ul>
172 */
173 protected void validatePublicVoidNoArgMethods(Class<? extends Annotation> annotation,
174 boolean isStatic, List<Throwable> errors) {
175 List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(annotation);
176
177 for (FrameworkMethod eachTestMethod : methods) {
178 eachTestMethod.validatePublicVoidNoArg(isStatic, errors);
179 }
180 }
181
182 private void validateClassRules(List<Throwable> errors) {
183 CLASS_RULE_VALIDATOR.validate(getTestClass(), errors);
184 CLASS_RULE_METHOD_VALIDATOR.validate(getTestClass(), errors);
185 }
186
187 /**
188 * Constructs a {@code Statement} to run all of the tests in the test class.
189 * Override to add pre-/post-processing. Here is an outline of the
190 * implementation:
191 * <ol>
192 * <li>Determine the children to be run using {@link #getChildren()}
193 * (subject to any imposed filter and sort).</li>
194 * <li>If there are any children remaining after filtering and ignoring,
195 * construct a statement that will:
196 * <ol>
197 * <li>Apply all {@code ClassRule}s on the test-class and superclasses.</li>
198 * <li>Run all non-overridden {@code @BeforeClass} methods on the test-class
199 * and superclasses; if any throws an Exception, stop execution and pass the
200 * exception on.</li>
201 * <li>Run all remaining tests on the test-class.</li>
202 * <li>Run all non-overridden {@code @AfterClass} methods on the test-class
203 * and superclasses: exceptions thrown by previous steps are combined, if
204 * necessary, with exceptions from AfterClass methods into a
205 * {@link org.junit.runners.model.MultipleFailureException}.</li>
206 * </ol>
207 * </li>
208 * </ol>
209 *
210 * @return {@code Statement}
211 */
212 protected Statement classBlock(final RunNotifier notifier) {
213 Statement statement = childrenInvoker(notifier);
214 if (!areAllChildrenIgnored()) {
215 statement = withBeforeClasses(statement);
216 statement = withAfterClasses(statement);
217 statement = withClassRules(statement);
218 statement = withInterruptIsolation(statement);
219 }
220 return statement;
221 }
222
223 private boolean areAllChildrenIgnored() {
224 for (T child : getFilteredChildren()) {
225 if (!isIgnored(child)) {
226 return false;
227 }
228 }
229 return true;
230 }
231
232 /**
233 * Returns a {@link Statement}: run all non-overridden {@code @BeforeClass} methods on this class
234 * and superclasses before executing {@code statement}; if any throws an
235 * Exception, stop execution and pass the exception on.
236 */
237 protected Statement withBeforeClasses(Statement statement) {
238 List<FrameworkMethod> befores = testClass
239 .getAnnotatedMethods(BeforeClass.class);
240 return befores.isEmpty() ? statement :
241 new RunBefores(statement, befores, null);
242 }
243
244 /**
245 * Returns a {@link Statement}: run all non-overridden {@code @AfterClass} methods on this class
246 * and superclasses after executing {@code statement}; all AfterClass methods are
247 * always executed: exceptions thrown by previous steps are combined, if
248 * necessary, with exceptions from AfterClass methods into a
249 * {@link org.junit.runners.model.MultipleFailureException}.
250 */
251 protected Statement withAfterClasses(Statement statement) {
252 List<FrameworkMethod> afters = testClass
253 .getAnnotatedMethods(AfterClass.class);
254 return afters.isEmpty() ? statement :
255 new RunAfters(statement, afters, null);
256 }
257
258 /**
259 * Returns a {@link Statement}: apply all
260 * static fields assignable to {@link TestRule}
261 * annotated with {@link ClassRule}.
262 *
263 * @param statement the base statement
264 * @return a RunRules statement if any class-level {@link Rule}s are
265 * found, or the base statement
266 */
267 private Statement withClassRules(Statement statement) {
268 List<TestRule> classRules = classRules();
269 return classRules.isEmpty() ? statement :
270 new RunRules(statement, classRules, getDescription());
271 }
272
273 /**
274 * @return the {@code ClassRule}s that can transform the block that runs
275 * each method in the tested class.
276 */
277 protected List<TestRule> classRules() {
278 ClassRuleCollector collector = new ClassRuleCollector();
279 testClass.collectAnnotatedMethodValues(null, ClassRule.class, TestRule.class, collector);
280 testClass.collectAnnotatedFieldValues(null, ClassRule.class, TestRule.class, collector);
281 return collector.getOrderedRules();
282 }
283
284 /**
285 * Returns a {@link Statement}: Call {@link #runChild(Object, RunNotifier)}
286 * on each object returned by {@link #getChildren()} (subject to any imposed
287 * filter and sort)
288 */
289 protected Statement childrenInvoker(final RunNotifier notifier) {
290 return new Statement() {
291 @Override
292 public void evaluate() {
293 runChildren(notifier);
294 }
295 };
296 }
297
298 /**
299 * @return a {@link Statement}: clears interrupt status of current thread after execution of statement
300 */
301 protected final Statement withInterruptIsolation(final Statement statement) {
302 return new Statement() {
303 @Override
304 public void evaluate() throws Throwable {
305 try {
306 statement.evaluate();
307 } finally {
308 Thread.interrupted(); // clearing thread interrupted status for isolation
309 }
310 }
311 };
312 }
313
314 /**
315 * Evaluates whether a child is ignored. The default implementation always
316 * returns <code>false</code>.
317 *
318 * <p>{@link BlockJUnit4ClassRunner}, for example, overrides this method to
319 * filter tests based on the {@link Ignore} annotation.
320 */
321 protected boolean isIgnored(T child) {
322 return false;
323 }
324
325 private void runChildren(final RunNotifier notifier) {
326 final RunnerScheduler currentScheduler = scheduler;
327 try {
328 for (final T each : getFilteredChildren()) {
329 currentScheduler.schedule(new Runnable() {
330 public void run() {
331 ParentRunner.this.runChild(each, notifier);
332 }
333 });
334 }
335 } finally {
336 currentScheduler.finished();
337 }
338 }
339
340 /**
341 * Returns a name used to describe this Runner
342 */
343 protected String getName() {
344 return testClass.getName();
345 }
346
347 //
348 // Available for subclasses
349 //
350
351 /**
352 * Returns a {@link TestClass} object wrapping the class to be executed.
353 */
354 public final TestClass getTestClass() {
355 return testClass;
356 }
357
358 /**
359 * Runs a {@link Statement} that represents a leaf (aka atomic) test.
360 */
361 protected final void runLeaf(Statement statement, Description description,
362 RunNotifier notifier) {
363 EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
364 eachNotifier.fireTestStarted();
365 try {
366 statement.evaluate();
367 } catch (AssumptionViolatedException e) {
368 eachNotifier.addFailedAssumption(e);
369 } catch (Throwable e) {
370 eachNotifier.addFailure(e);
371 } finally {
372 eachNotifier.fireTestFinished();
373 }
374 }
375
376 /**
377 * @return the annotations that should be attached to this runner's
378 * description.
379 */
380 protected Annotation[] getRunnerAnnotations() {
381 return testClass.getAnnotations();
382 }
383
384 //
385 // Implementation of Runner
386 //
387
388 @Override
389 public Description getDescription() {
390 Class<?> clazz = getTestClass().getJavaClass();
391 Description description;
392 // if subclass overrides `getName()` then we should use it
393 // to maintain backwards compatibility with JUnit 4.12
394 if (clazz == null || !clazz.getName().equals(getName())) {
395 description = Description.createSuiteDescription(getName(), getRunnerAnnotations());
396 } else {
397 description = Description.createSuiteDescription(clazz, getRunnerAnnotations());
398 }
399
400 for (T child : getFilteredChildren()) {
401 description.addChild(describeChild(child));
402 }
403 return description;
404 }
405
406 @Override
407 public void run(final RunNotifier notifier) {
408 EachTestNotifier testNotifier = new EachTestNotifier(notifier,
409 getDescription());
410 testNotifier.fireTestSuiteStarted();
411 try {
412 Statement statement = classBlock(notifier);
413 statement.evaluate();
414 } catch (AssumptionViolatedException e) {
415 testNotifier.addFailedAssumption(e);
416 } catch (StoppedByUserException e) {
417 throw e;
418 } catch (Throwable e) {
419 testNotifier.addFailure(e);
420 } finally {
421 testNotifier.fireTestSuiteFinished();
422 }
423 }
424
425 //
426 // Implementation of Filterable and Sortable
427 //
428
429 public void filter(Filter filter) throws NoTestsRemainException {
430 childrenLock.lock();
431 try {
432 List<T> children = new ArrayList<T>(getFilteredChildren());
433 for (Iterator<T> iter = children.iterator(); iter.hasNext(); ) {
434 T each = iter.next();
435 if (shouldRun(filter, each)) {
436 try {
437 filter.apply(each);
438 } catch (NoTestsRemainException e) {
439 iter.remove();
440 }
441 } else {
442 iter.remove();
443 }
444 }
445 filteredChildren = Collections.unmodifiableList(children);
446 if (filteredChildren.isEmpty()) {
447 throw new NoTestsRemainException();
448 }
449 } finally {
450 childrenLock.unlock();
451 }
452 }
453
454 public void sort(Sorter sorter) {
455 if (shouldNotReorder()) {
456 return;
457 }
458
459 childrenLock.lock();
460 try {
461 for (T each : getFilteredChildren()) {
462 sorter.apply(each);
463 }
464 List<T> sortedChildren = new ArrayList<T>(getFilteredChildren());
465 Collections.sort(sortedChildren, comparator(sorter));
466 filteredChildren = Collections.unmodifiableList(sortedChildren);
467 } finally {
468 childrenLock.unlock();
469 }
470 }
471
472 /**
473 * Implementation of {@link Orderable#order(Orderer)}.
474 *
475 * @since 4.13
476 */
477 public void order(Orderer orderer) throws InvalidOrderingException {
478 if (shouldNotReorder()) {
479 return;
480 }
481
482 childrenLock.lock();
483 try {
484 List<T> children = getFilteredChildren();
485 // In theory, we could have duplicate Descriptions. De-dup them before ordering,
486 // and add them back at the end.
487 Map<Description, List<T>> childMap = new LinkedHashMap<Description, List<T>>(
488 children.size());
489 for (T child : children) {
490 Description description = describeChild(child);
491 List<T> childrenWithDescription = childMap.get(description);
492 if (childrenWithDescription == null) {
493 childrenWithDescription = new ArrayList<T>(1);
494 childMap.put(description, childrenWithDescription);
495 }
496 childrenWithDescription.add(child);
497 orderer.apply(child);
498 }
499
500 List<Description> inOrder = orderer.order(childMap.keySet());
501
502 children = new ArrayList<T>(children.size());
503 for (Description description : inOrder) {
504 children.addAll(childMap.get(description));
505 }
506 filteredChildren = Collections.unmodifiableList(children);
507 } finally {
508 childrenLock.unlock();
509 }
510 }
511
512 //
513 // Private implementation
514 //
515
516 private boolean shouldNotReorder() {
517 // If the test specifies a specific order, do not reorder.
518 return getDescription().getAnnotation(FixMethodOrder.class) != null;
519 }
520
521 private void validate() throws InitializationError {
522 List<Throwable> errors = new ArrayList<Throwable>();
523 collectInitializationErrors(errors);
524 if (!errors.isEmpty()) {
525 throw new InvalidTestClassError(testClass.getJavaClass(), errors);
526 }
527 }
528
529 private List<T> getFilteredChildren() {
530 if (filteredChildren == null) {
531 childrenLock.lock();
532 try {
533 if (filteredChildren == null) {
534 filteredChildren = Collections.unmodifiableList(
535 new ArrayList<T>(getChildren()));
536 }
537 } finally {
538 childrenLock.unlock();
539 }
540 }
541 return filteredChildren;
542 }
543
544 private boolean shouldRun(Filter filter, T each) {
545 return filter.shouldRun(describeChild(each));
546 }
547
548 private Comparator<? super T> comparator(final Sorter sorter) {
549 return new Comparator<T>() {
550 public int compare(T o1, T o2) {
551 return sorter.compare(describeChild(o1), describeChild(o2));
552 }
553 };
554 }
555
556 /**
557 * Sets a scheduler that determines the order and parallelization
558 * of children. Highly experimental feature that may change.
559 */
560 public void setScheduler(RunnerScheduler scheduler) {
561 this.scheduler = scheduler;
562 }
563
564 private static class ClassRuleCollector implements MemberValueConsumer<TestRule> {
565 final List<RuleContainer.RuleEntry> entries = new ArrayList<RuleContainer.RuleEntry>();
566
567 public void accept(FrameworkMember<?> member, TestRule value) {
568 ClassRule rule = member.getAnnotation(ClassRule.class);
569 entries.add(new RuleContainer.RuleEntry(value, RuleContainer.RuleEntry.TYPE_TEST_RULE,
570 rule != null ? rule.order() : null));
571 }
572
573 public List<TestRule> getOrderedRules() {
574 Collections.sort(entries, RuleContainer.ENTRY_COMPARATOR);
575 List<TestRule> result = new ArrayList<TestRule>(entries.size());
576 for (RuleContainer.RuleEntry entry : entries) {
577 result.add((TestRule) entry.rule);
578 }
579 return result;
580 }
581 }
582 }