• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 package com.android.tradefed.testtype.suite;
17 
18 import com.android.tradefed.error.HarnessRuntimeException;
19 import com.android.tradefed.result.error.InfraErrorIdentifier;
20 import com.android.tradefed.util.AbiUtils;
21 
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24 
25 /** Represents a filter for including and excluding tests. */
26 public class SuiteTestFilter {
27 
28     private final Integer mShardIndex;
29     private final String mAbi;
30     private final String mName;
31     private final String mTest;
32 
33     private static final Pattern PARAMETERIZED_TEST_REGEX = Pattern.compile("(.*)?\\[(.*)\\]$");
34 
35     /**
36      * Builds a new {@link SuiteTestFilter} from the given string. Filters can be in one of four
37      * forms, the instance will be initialized as; -"name" -> abi = null, name = "name", test = null
38      * -"name" "test..." -> abi = null, name = "name", test = "test..." -"abi" "name" -> abi =
39      * "abi", name = "name", test = null -"abi" "name" "test..." -> abi = "abi", name = "name", test
40      * = "test..."
41      *
42      * <p>Test identifier can contain multiple parts, eg parameterized tests.
43      *
44      * @param filter the filter to parse
45      * @return the {@link SuiteTestFilter}
46      */
createFrom(String filter)47     public static SuiteTestFilter createFrom(String filter) {
48         if (filter.isEmpty()) {
49             throw new HarnessRuntimeException(
50                     "Filter was empty", InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR);
51         }
52         String[] parts = filter.split(" +");
53         Integer shardIndex = null;
54         String abi = null;
55         String name = null;
56         String test = null;
57         // Either:
58         // <name>
59         // <name> <test>
60         // <abi> <name>
61         // <abi> <name> <test>
62         if (parts.length == 1) {
63             name = parts[0];
64         } else {
65             int index = 0;
66             if (parts[index].startsWith("shard_")) {
67                 shardIndex = Integer.parseInt(parts[index].substring("shard_".length()));
68                 index++;
69             } else {
70                 try {
71                     shardIndex = Integer.parseInt(parts[index]);
72                     index++;
73                 } catch (NumberFormatException e) {
74                     // Ignore
75                 }
76             }
77             if (AbiUtils.isAbiSupportedByCompatibility(parts[index])) {
78                 abi = parts[index];
79                 index++;
80             }
81             name = parts[index];
82             index++;
83             parts = filter.split(" +", index + 1);
84             if (parts.length > index) {
85                 test = parts[index];
86             }
87         }
88         return new SuiteTestFilter(shardIndex, abi, name, test);
89     }
90 
91     /**
92      * Creates a new {@link SuiteTestFilter} from the given parts.
93      *
94      * @param abi The ABI must be supported {@link AbiUtils#isAbiSupportedByCompatibility(String)}
95      * @param name The module's name
96      * @param test The test's identifier eg <package>.<class>#<method>
97      */
SuiteTestFilter(String abi, String name, String test)98     public SuiteTestFilter(String abi, String name, String test) {
99         this(null, abi, name, test);
100     }
101 
102     /**
103      * Creates a new {@link SuiteTestFilter} from the given parts.
104      *
105      * @param abi The ABI must be supported {@link AbiUtils#isAbiSupportedByCompatibility(String)}
106      * @param name The module's name
107      * @param test The test's identifier eg <package>.<class>#<method>
108      */
SuiteTestFilter(Integer shardIndex, String abi, String name, String test)109     public SuiteTestFilter(Integer shardIndex, String abi, String name, String test) {
110         mShardIndex = shardIndex;
111         mAbi = abi;
112         mName = name;
113         mTest = test;
114     }
115 
116     /**
117      * Returns a String representation of this filter. This function is the inverse of {@link
118      * SuiteTestFilter#createFrom(String)}.
119      *
120      * <p>For a valid filter f;
121      *
122      * <pre>{@code
123      * new TestFilter(f).toString().equals(f)
124      * }</pre>
125      */
126     @Override
toString()127     public String toString() {
128         StringBuilder sb = new StringBuilder();
129         if (mShardIndex != null) {
130             sb.append(mShardIndex.toString());
131             sb.append(" ");
132         }
133         if (mAbi != null) {
134             sb.append(mAbi.trim());
135             sb.append(" ");
136         }
137         if (mName != null) {
138             sb.append(mName.trim());
139         }
140         if (mTest != null) {
141             sb.append(" ");
142             sb.append(mTest.trim());
143         }
144         return sb.toString();
145     }
146 
147     /** Returns the shard index of the test, or null if not specified. */
getShardIndex()148     public Integer getShardIndex() {
149         return mShardIndex;
150     }
151 
152     /** @return the abi of this filter, or null if not specified. */
getAbi()153     public String getAbi() {
154         return mAbi;
155     }
156 
157     /** @return the module name of this filter, or null if not specified. */
getName()158     public String getName() {
159         return mName;
160     }
161 
getModuleId()162     public String getModuleId() {
163         StringBuilder sb = new StringBuilder();
164         if (mAbi != null) {
165             sb.append(mAbi.trim());
166             sb.append(" ");
167         }
168         if (mName != null) {
169             sb.append(mName.trim());
170         }
171         return sb.toString();
172     }
173 
174     /**
175      * Returns the base name of the module without any parameterization. If not parameterized, it
176      * will return {@link #getName()};
177      */
getBaseName()178     public String getBaseName() {
179         // If the module looks parameterized, return the base non-parameterized name.
180         Matcher m = PARAMETERIZED_TEST_REGEX.matcher(mName);
181         if (m.find()) {
182             return m.group(1);
183         }
184         return mName;
185     }
186 
187     /**
188      * If the module is parameterized, returns the parameter value. Null if not parameterized.
189      */
getParameterName()190     public String getParameterName() {
191         // If the module looks parameterized, return the parameter name.
192         Matcher m = PARAMETERIZED_TEST_REGEX.matcher(mName);
193         if (m.find()) {
194             return m.group(2);
195         }
196         return null;
197     }
198 
199     /** @return the test identifier of this filter, or null if not specified. */
getTest()200     public String getTest() {
201         return mTest;
202     }
203 
204     @Override
hashCode()205     public int hashCode() {
206         final int prime = 31;
207         int result = 1;
208         result = prime * result + ((mAbi == null) ? 0 : mAbi.hashCode());
209         result = prime * result + ((mName == null) ? 0 : mName.hashCode());
210         result = prime * result + ((mShardIndex == null) ? 0 : mShardIndex.hashCode());
211         result = prime * result + ((mTest == null) ? 0 : mTest.hashCode());
212         return result;
213     }
214 
215     @Override
equals(Object obj)216     public boolean equals(Object obj) {
217         if (this == obj) {
218             return true;
219         }
220         if (obj == null) {
221             return false;
222         }
223         if (getClass() != obj.getClass()) {
224             return false;
225         }
226         SuiteTestFilter other = (SuiteTestFilter) obj;
227         if (mAbi == null) {
228             if (other.mAbi != null) {
229                 return false;
230             }
231         } else if (!mAbi.equals(other.mAbi)) {
232             return false;
233         }
234         if (mName == null) {
235             if (other.mName != null) {
236                 return false;
237             }
238         } else if (!mName.equals(other.mName)) {
239             return false;
240         }
241         if (mShardIndex == null) {
242             if (other.mShardIndex != null) {
243                 return false;
244             }
245         } else if (!mShardIndex.equals(other.mShardIndex)) {
246             return false;
247         }
248         if (mTest == null) {
249             if (other.mTest != null) {
250                 return false;
251             }
252         } else if (!mTest.equals(other.mTest)) {
253             return false;
254         }
255         return true;
256     }
257 }
258