1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.tradefed.testtype;
18 
19 import com.android.ddmlib.testrunner.TestIdentifier;
20 
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.regex.Pattern;
29 
30 /**
31  * Filter for {@link TestIdentifier}s.
32  */
33 public class TestFilter {
34 
35     private final Set<String> mExcludedClasses;
36     private final Set<TestIdentifier> mExcludedTests;
37 
38     private final Set<String> mIncludedClasses;
39     private final Set<TestIdentifier> mIncludedTests;
40 
41     private String mIncludedClass = null;
42     private Pattern mIncludedMethod = null;
43 
44     /**
45      * Creates a {@link TestFilter}
46      */
TestFilter()47     public TestFilter() {
48         mExcludedClasses = new HashSet<String>();
49         mExcludedTests = new HashSet<TestIdentifier>();
50 
51         mIncludedClasses = new HashSet<String>();
52         mIncludedTests = new HashSet<TestIdentifier>();
53     }
54 
55     /**
56      * Adds a test class to the filter.
57      * <p/>
58      * All tests in this class should be filtered.
59      */
addExcludedClass(String className)60     public void addExcludedClass(String className) {
61         mExcludedClasses.add(className);
62     }
63 
64     /**
65      * Adds a test class to the filter. All tests in this class should be excluded.
66      */
addExcludedTest(TestIdentifier test)67     public void addExcludedTest(TestIdentifier test) {
68         mExcludedTests.add(test);
69     }
70 
71     /**
72      * Get the test classes to exclude.
73      * <p/>
74      * Exposed for unit testing
75      */
getExcludedClasses()76     Set<String> getExcludedClasses() {
77         return mExcludedClasses;
78     }
79 
80     /**
81      * Get the tests to exclude.
82      * <p/>
83      * Exposed for unit testing
84      */
getExcludedTests()85     Set<TestIdentifier> getExcludedTests() {
86         return mExcludedTests;
87     }
88 
89     /**
90      * Adds a test class to the filter.
91      * <p/>
92      * All tests in this class should be allowed.
93      */
addIncludedClass(String className)94     public void addIncludedClass(String className) {
95         mIncludedClasses.add(className);
96     }
97 
98     /**
99      * Adds a test class to the filter. All tests in this class should be excluded.
100      */
addIncludedTest(TestIdentifier test)101     public void addIncludedTest(TestIdentifier test) {
102         mIncludedTests.add(test);
103     }
104 
105     /**
106      * @return the mIncludedClasses
107      */
getIncludedClasses()108     public Set<String> getIncludedClasses() {
109         return mIncludedClasses;
110     }
111 
112     /**
113      * @return the mIncludedTests
114      */
getIncludedTests()115     public Set<TestIdentifier> getIncludedTests() {
116         return mIncludedTests;
117     }
118 
119     /**
120      * Sets the class name and optionally method that should pass this filter. If non-null, all
121      * other tests will be excluded.
122      *
123      * @param className the test class name to exclusively include
124      * @param method the test method name to exclusively include
125      */
setTestInclusion(String className, String method)126     public void setTestInclusion(String className, String method) {
127         mIncludedClass = className;
128         if (method != null) {
129             mIncludedMethod = Pattern.compile(method);
130         }
131     }
132 
133     /**
134      * Filter the list of tests based on rules in this filter
135      *
136      * @param tests the list of tests to filter
137      * @return a new sorted list of tests that passed the filter
138      */
filter(Collection<TestIdentifier> tests)139     public Collection<TestIdentifier> filter(Collection<TestIdentifier> tests) {
140         List<TestIdentifier> filteredTests = new ArrayList<TestIdentifier>(tests.size());
141         for (TestIdentifier test : tests) {
142             if (mIncludedClass != null && !test.getClassName().equals(mIncludedClass)) {
143                 // skip
144                 continue;
145             }
146             if (mIncludedMethod != null && !mIncludedMethod.matcher(test.getTestName()).matches()) {
147                 // skip
148                 continue;
149             }
150             if (mExcludedClasses.contains(test.getClassName())) {
151                 // skip
152                 continue;
153             }
154             if (mExcludedTests.contains(test)) {
155                 // skip
156                 continue;
157             }
158             if ((!mIncludedTests.isEmpty() || !mIncludedClasses.isEmpty())
159                     && !(mIncludedClasses.contains(test.getClassName())
160                             || mIncludedTests.contains(test))) {
161                 // skip
162                 continue;
163             }
164             filteredTests.add(test);
165         }
166         Collections.sort(filteredTests, new TestIdComparator());
167         return filteredTests;
168     }
169 
170     /**
171      * Return true if there are exclusions rules defined.
172      */
hasExclusion()173     public boolean hasExclusion() {
174         return !mExcludedClasses.isEmpty() || !mExcludedTests.isEmpty();
175     }
176 
177     /**
178      * @return true if there are inclusion rules defined.
179      */
hasInclusion()180     public boolean hasInclusion() {
181         return !mIncludedClasses.isEmpty() || !mIncludedTests.isEmpty();
182     }
183 
184     /**
185      * A {@link Comparator} for {@link TestIdentifier} that compares using
186      * {@link TestIdentifier#toString()}
187      */
188     private class TestIdComparator implements Comparator<TestIdentifier> {
189 
190         @Override
compare(TestIdentifier o1, TestIdentifier o2)191         public int compare(TestIdentifier o1, TestIdentifier o2) {
192             return o1.toString().compareTo(o2.toString());
193         }
194     }
195 }
196