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