View Javadoc
1   package org.apache.maven.surefire.api.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * Applies the final runorder of the tests
35   *
36   * @author Kristian Rosenvold
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 }