1 package org.apache.maven.plugin.surefire.runorder;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.FileNotFoundException;
26 import java.io.FileOutputStream;
27 import java.io.FileReader;
28 import java.io.IOException;
29 import java.io.PrintWriter;
30 import java.io.Reader;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.Comparator;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
40 import org.apache.maven.surefire.report.ReportEntry;
41
42
43
44
45 public class RunEntryStatisticsMap
46 {
47 private final Map runEntryStatistics;
48
49 public RunEntryStatisticsMap( Map runEntryStatistics )
50 {
51 this.runEntryStatistics = Collections.synchronizedMap( runEntryStatistics );
52 }
53
54 public RunEntryStatisticsMap()
55 {
56 this( new HashMap() );
57 }
58
59 public static RunEntryStatisticsMap fromFile( File file )
60 {
61 if ( file.exists() )
62 {
63 try
64 {
65 FileReader fileReader = new FileReader( file );
66 return fromReader( fileReader );
67 }
68 catch ( FileNotFoundException e )
69 {
70 throw new RuntimeException( e );
71 }
72 catch ( IOException e1 )
73 {
74 throw new RuntimeException( e1 );
75 }
76
77 }
78 return new RunEntryStatisticsMap();
79 }
80
81 static RunEntryStatisticsMap fromReader( Reader fileReader )
82 throws IOException
83 {
84 Map result = new HashMap();
85 BufferedReader bufferedReader = new BufferedReader( fileReader );
86 String line = bufferedReader.readLine();
87 while ( line != null )
88 {
89 if ( !line.startsWith( "#" ) )
90 {
91 final RunEntryStatistics stats = RunEntryStatistics.fromString( line );
92 result.put( stats.getTestName(), stats );
93 }
94 line = bufferedReader.readLine();
95 }
96 return new RunEntryStatisticsMap( result );
97 }
98
99 public void serialize( File file )
100 throws FileNotFoundException
101 {
102 FileOutputStream fos = new FileOutputStream( file );
103 PrintWriter printWriter = new PrintWriter( fos );
104 List items = new ArrayList( runEntryStatistics.values() );
105 Collections.sort( items, new RunCountComparator() );
106 RunEntryStatistics item;
107 for ( Iterator iter = items.iterator(); iter.hasNext(); )
108 {
109 item = (RunEntryStatistics) iter.next();
110 printWriter.println( item.getAsString() );
111 }
112 printWriter.close();
113 }
114
115
116 public RunEntryStatistics findOrCreate( ReportEntry reportEntry )
117 {
118 final RunEntryStatistics item = (RunEntryStatistics) runEntryStatistics.get( reportEntry.getName() );
119 return item != null ? item : RunEntryStatistics.fromReportEntry( reportEntry );
120 }
121
122 public RunEntryStatistics createNextGeneration( ReportEntry reportEntry )
123 {
124 final RunEntryStatistics newItem = findOrCreate( reportEntry );
125 final Integer elapsed = reportEntry.getElapsed();
126 return newItem.nextGeneration( elapsed != null ? elapsed.intValue() : 0 );
127 }
128
129 public RunEntryStatistics createNextGenerationFailure( ReportEntry reportEntry )
130 {
131 final RunEntryStatistics newItem = findOrCreate( reportEntry );
132 final Integer elapsed = reportEntry.getElapsed();
133 return newItem.nextGenerationFailure( elapsed != null ? elapsed.intValue() : 0 );
134 }
135
136 public void add( RunEntryStatistics item )
137 {
138 runEntryStatistics.put( item.getTestName(), item );
139 }
140
141 class RunCountComparator
142 implements Comparator
143 {
144 public int compare( Object o, Object o1 )
145 {
146 RunEntryStatistics re = (RunEntryStatistics) o;
147 RunEntryStatistics re1 = (RunEntryStatistics) o1;
148 int runtime = re.getSuccessfulBuilds() - re1.getSuccessfulBuilds();
149 if ( runtime == 0 )
150 {
151 return re.getRunTime() - re1.getRunTime();
152 }
153 return runtime;
154 }
155 }
156
157 public List getPrioritizedTestsClassRunTime( List testsToRun, int threadCount )
158 {
159 final List prioritizedTests = getPrioritizedTests( testsToRun, new TestRuntimeComparator() );
160 ThreadedExecutionScheduler threadedExecutionScheduler = new ThreadedExecutionScheduler( threadCount );
161 for ( Iterator prioritizedTest = prioritizedTests.iterator(); prioritizedTest.hasNext(); )
162 {
163 threadedExecutionScheduler.addTest( (PrioritizedTest) prioritizedTest.next() );
164 }
165
166 return threadedExecutionScheduler.getResult();
167
168 }
169
170 public List getPrioritizedTestsByFailureFirst( List testsToRun )
171 {
172 final List prioritizedTests = getPrioritizedTests( testsToRun, new LeastFailureComparator() );
173 return transformToClasses( prioritizedTests );
174 }
175
176
177 private List getPrioritizedTests( List testsToRun, Comparator priorityComparator )
178 {
179 Map classPriorities = getPriorities( priorityComparator );
180
181 List tests = new ArrayList();
182 for ( Iterator iter = testsToRun.iterator(); iter.hasNext(); )
183 {
184 Class clazz = (Class) iter.next();
185 Priority pri = (Priority) classPriorities.get( clazz.getName() );
186 if ( pri == null )
187 {
188 pri = Priority.newTestClassPriority( clazz.getName() );
189 }
190 PrioritizedTest prioritizedTest = new PrioritizedTest( clazz, pri );
191 tests.add( prioritizedTest );
192 }
193 Collections.sort( tests, new PrioritizedTestComparator() );
194 return tests;
195
196 }
197
198 private List transformToClasses( List tests )
199 {
200 List result = new ArrayList();
201 for ( int i = 0; i < tests.size(); i++ )
202 {
203 result.add( ( (PrioritizedTest) tests.get( i ) ).getClazz() );
204 }
205 return result;
206 }
207
208 public Map getPriorities( Comparator priorityComparator )
209 {
210 Map priorities = new HashMap();
211 for ( Iterator iter = runEntryStatistics.keySet().iterator(); iter.hasNext(); )
212 {
213 String testNames = (String) iter.next();
214 String clazzName = extractClassName( testNames );
215 Priority priority = (Priority) priorities.get( clazzName );
216 if ( priority == null )
217 {
218 priority = new Priority( clazzName );
219 priorities.put( clazzName, priority );
220 }
221
222 RunEntryStatistics itemStat = (RunEntryStatistics) runEntryStatistics.get( testNames );
223 priority.addItem( itemStat );
224 }
225
226 List items = new ArrayList( priorities.values() );
227 Collections.sort( items, priorityComparator );
228 Map result = new HashMap();
229 int i = 0;
230 for ( Iterator iter = items.iterator(); iter.hasNext(); )
231 {
232 Priority pri = (Priority) iter.next();
233 pri.setPriority( i++ );
234 result.put( pri.getClassName(), pri );
235 }
236 return result;
237 }
238
239 class PrioritizedTestComparator
240 implements Comparator
241 {
242 public int compare( Object o, Object o1 )
243 {
244 PrioritizedTest re = (PrioritizedTest) o;
245 PrioritizedTest re1 = (PrioritizedTest) o1;
246 return re.getPriority() - re1.getPriority();
247 }
248 }
249
250 class TestRuntimeComparator
251 implements Comparator
252 {
253 public int compare( Object o, Object o1 )
254 {
255 Priority re = (Priority) o;
256 Priority re1 = (Priority) o1;
257 return re1.getTotalRuntime() - re.getTotalRuntime();
258 }
259 }
260
261 class LeastFailureComparator
262 implements Comparator
263 {
264 public int compare( Object o, Object o1 )
265 {
266 Priority re = (Priority) o;
267 Priority re1 = (Priority) o1;
268 return re.getMinSuccessRate() - re1.getMinSuccessRate();
269 }
270 }
271
272
273 private static final Pattern PARENS = Pattern.compile( "^" + "[^\\(\\)]+"
274 + "\\(("
275 + "[^\\\\(\\\\)]+"
276 + ")\\)" + "$" );
277
278 String extractClassName( String displayName )
279 {
280 Matcher m = PARENS.matcher( displayName );
281 if ( !m.find() )
282 {
283 return displayName;
284 }
285 return m.group( 1 );
286 }
287
288
289 }