1 package org.apache.maven.surefire.api.util;
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.surefire.api.runorder.RunEntryStatisticsMap;
23 import org.apache.maven.surefire.api.testset.RunOrderParameters;
24
25 import java.util.ArrayList;
26 import java.util.Calendar;
27 import java.util.Collections;
28 import java.util.Comparator;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Random;
32
33
34
35
36
37
38 public class DefaultRunOrderCalculator
39 implements RunOrderCalculator
40 {
41 private final Comparator<Class<?>> sortOrder;
42
43 private final RunOrder[] runOrder;
44
45 private final RunOrderParameters runOrderParameters;
46
47 private final int threadCount;
48
49 private final Random random;
50
51 public DefaultRunOrderCalculator( RunOrderParameters runOrderParameters, int threadCount )
52 {
53 this.runOrderParameters = runOrderParameters;
54 this.threadCount = threadCount;
55 this.runOrder = runOrderParameters.getRunOrder();
56 this.sortOrder = this.runOrder.length > 0 ? getSortOrderComparator( this.runOrder[0] ) : null;
57 Long runOrderRandomSeed = runOrderParameters.getRunOrderRandomSeed();
58 random = new Random( runOrderRandomSeed == null ? System.nanoTime() : runOrderRandomSeed );
59 }
60
61 @Override
62 @SuppressWarnings( "checkstyle:magicnumber" )
63 public TestsToRun orderTestClasses( TestsToRun scannedClasses )
64 {
65 List<Class<?>> result = new ArrayList<>( 512 );
66
67 for ( Class<?> scannedClass : scannedClasses )
68 {
69 result.add( scannedClass );
70 }
71
72 orderTestClasses( result, runOrder.length != 0 ? runOrder[0] : null );
73 return new TestsToRun( new LinkedHashSet<>( result ) );
74 }
75
76 private void orderTestClasses( List<Class<?>> testClasses, RunOrder runOrder )
77 {
78 if ( RunOrder.RANDOM.equals( runOrder ) )
79 {
80 Collections.shuffle( testClasses, random );
81 }
82 else if ( RunOrder.FAILEDFIRST.equals( runOrder ) )
83 {
84 RunEntryStatisticsMap stat = RunEntryStatisticsMap.fromFile( runOrderParameters.getRunStatisticsFile() );
85 List<Class<?>> prioritized = stat.getPrioritizedTestsByFailureFirst( testClasses );
86 testClasses.clear();
87 testClasses.addAll( prioritized );
88
89 }
90 else if ( RunOrder.BALANCED.equals( runOrder ) )
91 {
92 RunEntryStatisticsMap stat = RunEntryStatisticsMap.fromFile( runOrderParameters.getRunStatisticsFile() );
93 List<Class<?>> prioritized = stat.getPrioritizedTestsClassRunTime( testClasses, threadCount );
94 testClasses.clear();
95 testClasses.addAll( prioritized );
96
97 }
98 else if ( sortOrder != null )
99 {
100 testClasses.sort( sortOrder );
101 }
102 }
103
104 private static Comparator<Class<?>> getSortOrderComparator( RunOrder runOrder )
105 {
106 if ( RunOrder.ALPHABETICAL.equals( runOrder ) )
107 {
108 return getAlphabeticalComparator();
109 }
110 else if ( RunOrder.REVERSE_ALPHABETICAL.equals( runOrder ) )
111 {
112 return getReverseAlphabeticalComparator();
113 }
114 else if ( RunOrder.HOURLY.equals( runOrder ) )
115 {
116 final int hour = Calendar.getInstance().get( Calendar.HOUR_OF_DAY );
117 return ( ( hour % 2 ) == 0 ) ? getAlphabeticalComparator() : getReverseAlphabeticalComparator();
118 }
119 else
120 {
121 return null;
122 }
123 }
124
125 private static Comparator<Class<?>> getReverseAlphabeticalComparator()
126 {
127 return ( o1, o2 ) -> o2.getName().compareTo( o1.getName() );
128 }
129
130 private static Comparator<Class<?>> getAlphabeticalComparator()
131 {
132 return Comparator.comparing( Class::getName );
133 }
134 }