1b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpackage org.junit.runner.manipulation;
2b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
3b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runner.Description;
4b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runner.Request;
5b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
6b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot/**
7b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * The canonical case of filtering is when you want to run a single test method in a class. Rather
8b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * than introduce runner API just for that one case, JUnit provides a general filtering mechanism.
9b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * If you want to filter the tests to be run, extend <code>Filter</code> and apply an instance of
10b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * your filter to the {@link org.junit.runner.Request} before running it (see
11b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * {@link org.junit.runner.JUnitCore#run(Request)}. Alternatively, apply a <code>Filter</code> to
12b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * a {@link org.junit.runner.Runner} before running tests (for example, in conjunction with
13b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * {@link org.junit.runner.RunWith}.
14b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */
15b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpublic abstract class Filter {
16b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
17b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * A null <code>Filter</code> that passes all tests through.
18b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
19b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public static Filter ALL= new Filter() {
20b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		@Override
21b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		public boolean shouldRun(Description description) {
22b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			return true;
23b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		}
24b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
25b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		@Override
26b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		public String describe() {
27b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			return "all tests";
28b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		}
29b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
30b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		@Override
31b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		public void apply(Object child) throws NoTestsRemainException {
32b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			// do nothing
33b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		}
34b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
35b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		@Override
36b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		public Filter intersect(Filter second) {
37b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			return second;
38b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		}
39b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	};
40b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
41b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
42b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Returns a {@code Filter} that only runs the single method described by
43b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * {@code desiredDescription}
44b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
45b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public static Filter matchMethodDescription(final Description desiredDescription) {
46b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return new Filter() {
47b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			@Override
48b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			public boolean shouldRun(Description description) {
49b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				if (description.isTest())
50b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot					return desiredDescription.equals(description);
51b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
52b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				// explicitly check if any children want to run
53b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				for (Description each : description.getChildren())
54b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot					if (shouldRun(each))
55b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						return true;
56b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				return false;
57b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			}
58b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
59b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			@Override
60b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			public String describe() {
61b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				return String.format("Method %s", desiredDescription.getDisplayName());
62b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			}
63b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		};
64b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
65b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
66b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
67b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
68b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @param description the description of the test to be run
69b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @return <code>true</code> if the test should be run
70b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
71b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public abstract boolean shouldRun(Description description);
72b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
73b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
74b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Returns a textual description of this Filter
75b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @return a textual description of this Filter
76b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
77b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public abstract String describe();
78b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
79b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
80b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Invoke with a {@link org.junit.runner.Runner} to cause all tests it intends to run
81b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * to first be checked with the filter. Only those that pass the filter will be run.
82b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @param child the runner to be filtered by the receiver
83b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * @throws NoTestsRemainException if the receiver removes all tests
84b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
85b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public void apply(Object child) throws NoTestsRemainException {
86b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		if (!(child instanceof Filterable))
87b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			return;
88b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		Filterable filterable= (Filterable) child;
89b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		filterable.filter(this);
90b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
91b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
92b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	/**
93b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * Returns a new Filter that accepts the intersection of the tests accepted
94b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 * by this Filter and {@code second}
95b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	 */
96b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	public Filter intersect(final Filter second) {
97b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		if (second == this || second == ALL) {
98b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			return this;
99b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		}
100b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		final Filter first= this;
101b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		return new Filter() {
102b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			@Override
103b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			public boolean shouldRun(Description description) {
104b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				return first.shouldRun(description)
105b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot						&& second.shouldRun(description);
106b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			}
107b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot
108b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			@Override
109b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			public String describe() {
110b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot				return first.describe() + " and " + second.describe();
111b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot			}
112b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot		};
113b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot	}
114b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot}
115