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