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 }