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