1 package org.apache.maven.surefire.testset;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.shared.utils.StringUtils;
23 import org.apache.maven.shared.utils.io.MatchPatterns;
24 import org.apache.maven.shared.utils.io.SelectorUtils;
25
26 import java.io.File;
27
28
29
30
31 public final class ResolvedTest
32 {
33
34
35
36 public static enum Type
37 {
38 CLASS, METHOD
39 }
40
41 private static final String CLASS_FILE_EXTENSION = ".class";
42
43 private static final String WILDCARD_CLASS_FILE_EXTENSION = ".class";
44
45 private static final String JAVA_FILE_EXTENSION = ".java";
46
47 private static final String WILDCARD_PATH_PREFIX = "**/";
48
49 private static final String WILDCARD_FILENAME_POSTFIX = ".*";
50
51 private final String classPattern;
52
53 private final String methodPattern;
54
55 private final boolean isRegexTestClassPattern;
56
57 private final boolean isRegexTestMethodPattern;
58
59 private final String description;
60
61
62
63
64
65
66
67
68
69
70
71 public ResolvedTest( String classPattern, String methodPattern, boolean isRegex )
72 {
73 classPattern = tryBlank( classPattern );
74 methodPattern = tryBlank( methodPattern );
75 description = description( classPattern, methodPattern, isRegex );
76
77 if ( isRegex && classPattern != null )
78 {
79 classPattern = wrapRegex( classPattern );
80 }
81
82 if ( isRegex && methodPattern != null )
83 {
84 methodPattern = wrapRegex( methodPattern );
85 }
86
87 this.classPattern = reformatClassPattern( classPattern, isRegex );
88 this.methodPattern = methodPattern;
89 isRegexTestClassPattern = isRegex;
90 isRegexTestMethodPattern = isRegex;
91 }
92
93
94
95
96 public ResolvedTest( Type type, String pattern, boolean isRegex )
97 {
98 pattern = tryBlank( pattern );
99 final boolean isClass = type == Type.CLASS;
100 description = description( isClass ? pattern : null, !isClass ? pattern : null, isRegex );
101 if ( isRegex && pattern != null )
102 {
103 pattern = wrapRegex( pattern );
104 }
105 classPattern = isClass ? reformatClassPattern( pattern, isRegex ) : null;
106 methodPattern = !isClass ? pattern : null;
107 isRegexTestClassPattern = isRegex && isClass;
108 isRegexTestMethodPattern = isRegex && !isClass;
109 }
110
111
112
113
114
115
116
117
118
119 public String getTestClassPattern()
120 {
121 return classPattern;
122 }
123
124 public boolean hasTestClassPattern()
125 {
126 return classPattern != null;
127 }
128
129
130
131
132
133
134
135
136 public String getTestMethodPattern()
137 {
138 return methodPattern;
139 }
140
141 public boolean hasTestMethodPattern()
142 {
143 return methodPattern != null;
144 }
145
146 public boolean isRegexTestClassPattern()
147 {
148 return isRegexTestClassPattern;
149 }
150
151 public boolean isRegexTestMethodPattern()
152 {
153 return isRegexTestMethodPattern;
154 }
155
156 public boolean isEmpty()
157 {
158 return classPattern == null && methodPattern == null;
159 }
160
161 public boolean matchAsInclusive( String testClassFile, String methodName )
162 {
163 testClassFile = tryBlank( testClassFile );
164 methodName = tryBlank( methodName );
165
166 return isEmpty() || alwaysInclusiveQuietly( testClassFile ) || match( testClassFile, methodName );
167 }
168
169 public boolean matchAsExclusive( String testClassFile, String methodName )
170 {
171 testClassFile = tryBlank( testClassFile );
172 methodName = tryBlank( methodName );
173
174 return !isEmpty() && canMatchExclusive( testClassFile, methodName ) && match( testClassFile, methodName );
175 }
176
177 @Override
178 public boolean equals( Object o )
179 {
180 if ( this == o )
181 {
182 return true;
183 }
184 if ( o == null || getClass() != o.getClass() )
185 {
186 return false;
187 }
188
189 ResolvedTest that = (ResolvedTest) o;
190
191 return ( classPattern == null ? that.classPattern == null : classPattern.equals( that.classPattern ) )
192 && ( methodPattern == null ? that.methodPattern == null : methodPattern.equals( that.methodPattern ) );
193 }
194
195 @Override
196 public int hashCode()
197 {
198 int result = classPattern != null ? classPattern.hashCode() : 0;
199 result = 31 * result + ( methodPattern != null ? methodPattern.hashCode() : 0 );
200 return result;
201 }
202
203 @Override
204 public String toString()
205 {
206 return isEmpty() ? null : description;
207 }
208
209 private static String description( String clazz, String method, boolean isRegex )
210 {
211 String description;
212 if ( clazz == null && method == null )
213 {
214 description = null;
215 }
216 else if ( clazz == null )
217 {
218 description = "#" + method;
219 }
220 else if ( method == null )
221 {
222 description = clazz;
223 }
224 else
225 {
226 description = clazz + "#" + method;
227 }
228 return isRegex && description != null ? wrapRegex( description ) : description;
229 }
230
231 private boolean canMatchExclusive( String testClassFile, String methodName )
232 {
233 return testClassFile == null && methodName != null && classPattern == null && methodPattern != null
234 || testClassFile != null && methodName == null && classPattern != null && methodPattern == null
235 || testClassFile != null && methodName != null && ( classPattern != null || methodPattern != null );
236 }
237
238
239
240
241 private boolean alwaysInclusiveQuietly( String testClassFile )
242 {
243 return testClassFile == null && classPattern != null;
244 }
245
246 private boolean match( String testClassFile, String methodName )
247 {
248 return ( classPattern == null || matchTestClassFile( testClassFile ) )
249 && ( methodPattern == null || methodName == null || matchMethodName( methodName ) );
250 }
251
252 private boolean matchTestClassFile( String testClassFile )
253 {
254 return isRegexTestClassPattern ? matchClassRegexPatter( testClassFile ) : matchClassPatter( testClassFile );
255 }
256
257 private boolean matchMethodName( String methodName )
258 {
259 return SelectorUtils.matchPath( methodPattern, methodName );
260 }
261
262 private boolean matchClassPatter( String testClassFile )
263 {
264
265 String classPattern = this.classPattern;
266 if ( File.separatorChar != '/' )
267 {
268 testClassFile = testClassFile.replace( '/', File.separatorChar );
269 classPattern = classPattern.replace( '/', File.separatorChar );
270 }
271
272 if ( classPattern.endsWith( WILDCARD_FILENAME_POSTFIX ) || classPattern.endsWith( CLASS_FILE_EXTENSION ) )
273 {
274 return MatchPatterns.from( classPattern ).matches( testClassFile, true );
275 }
276 else
277 {
278 String[] classPatterns = { classPattern + CLASS_FILE_EXTENSION, classPattern };
279 return MatchPatterns.from( classPatterns ).matches( testClassFile, true );
280 }
281 }
282
283 private boolean matchClassRegexPatter( String testClassFile )
284 {
285 if ( File.separatorChar != '/' )
286 {
287 testClassFile = testClassFile.replace( '/', File.separatorChar );
288 }
289 return MatchPatterns.from( classPattern ).matches( testClassFile, true );
290 }
291
292 private static String tryBlank( String s )
293 {
294 if ( s == null )
295 {
296 return null;
297 }
298 else
299 {
300 s = s.trim();
301 return StringUtils.isEmpty( s ) ? null : s;
302 }
303 }
304
305 private static String reformatClassPattern( String s, boolean isRegex )
306 {
307 if ( s != null && !isRegex )
308 {
309 s = convertToPath( s );
310 s = fromFullyQualifiedClass( s );
311 if ( s != null && !s.startsWith( WILDCARD_PATH_PREFIX ) )
312 {
313 s = WILDCARD_PATH_PREFIX + s;
314 }
315 }
316 return s;
317 }
318
319 private static String convertToPath( String className )
320 {
321 if ( StringUtils.isBlank( className ) )
322 {
323 return null;
324 }
325 else
326 {
327 if ( className.endsWith( JAVA_FILE_EXTENSION ) )
328 {
329 className = className.substring( 0, className.length() - JAVA_FILE_EXTENSION.length() );
330 className += CLASS_FILE_EXTENSION;
331 }
332 return className;
333 }
334 }
335
336 static String wrapRegex( String unwrapped )
337 {
338 return SelectorUtils.REGEX_HANDLER_PREFIX + unwrapped + SelectorUtils.PATTERN_HANDLER_SUFFIX;
339 }
340
341 static String fromFullyQualifiedClass( String cls )
342 {
343 if ( cls.endsWith( CLASS_FILE_EXTENSION ) )
344 {
345 cls = cls.substring( 0, cls.length() - CLASS_FILE_EXTENSION.length() );
346 return cls.replace( '.', '/' ) + CLASS_FILE_EXTENSION;
347 }
348 else if ( !cls.contains( "/" ) )
349 {
350 if ( cls.endsWith( WILDCARD_CLASS_FILE_EXTENSION ) )
351 {
352 String origin = cls;
353 cls = cls.substring( 0, cls.length() - WILDCARD_CLASS_FILE_EXTENSION.length() );
354 return cls.contains( "." ) ? cls.replace( '.', '/' ) + WILDCARD_CLASS_FILE_EXTENSION : origin;
355 }
356 else
357 {
358 return cls.replace( '.', '/' );
359 }
360 }
361 else
362 {
363 return cls;
364 }
365 }
366 }