1 /*******************************************************************************
2  * Copyright (c) 2009 SpringSource and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Andrew Eisenberg - initial API and implementation
13  *     Andrew Eisenberg <andrew@eisenberg.as> - [JUnit] Rerun failed first does not work with JUnit4 - https://bugs.eclipse.org/bugs/show_bug.cgi?id=140392
14  *******************************************************************************/
15 
16 package org.eclipse.jdt.internal.junit4.runner;
17 
18 import java.util.Arrays;
19 import java.util.Comparator;
20 import java.util.HashSet;
21 import java.util.Set;
22 
23 import org.junit.runner.Description;
24 
25 /**
26  * Comparator for descriptions to sort according to inclusion in a failure list.
27  * A description is considered to have failures if its name or one of its transitive
28  * children's names are in the failures list.
29  * If neither or both have failures, returns 0.
30  *
31  * @since 3.6
32  */
33 public class FailuresFirstSorter implements Comparator<Description> {
34 
35 	private final Set<String> failuresList;
36 
37 	/**
38 	 * Creates a sorter.
39 	 *
40 	 * @param failuresList list of failed tests based on the description's display string
41 	 */
FailuresFirstSorter(String[] failuresList)42 	public FailuresFirstSorter(String[] failuresList) {
43 		this.failuresList = new HashSet<String>(Arrays.asList(failuresList));
44 	}
45 
46 	/**
47 	 * Compares two descriptions based on the failure list.
48 	 * @param d1 the first Description to compare with
49 	 * @param d2 the second Description to compare with
50 	 * @return -1 if only d1 has failures, 1 if only d2 has failures, 0 otherwise
51 	 */
compare(Description d1, Description d2)52 	public int compare(Description d1, Description d2) {
53 		boolean d1HasFailures = hasFailures(d1);
54 		boolean d2HasFailures = hasFailures(d2);
55 
56 		if (d1HasFailures) {
57 			return -1;
58 		} else if (d2HasFailures) {
59 			return 1;
60 		} else { // ((d1HasFailures && d2HasFailures) || (!d1HasFailures && !d2HasFailures))
61 			return 0;
62 		}
63 	}
64 
hasFailures(Description d)65 	private boolean hasFailures(Description d) {
66 		if (failuresList.contains(d.getDisplayName())) {
67 			return true;
68 		} else {
69 			for (Description child : d.getChildren()) {
70 				if (hasFailures(child)) {
71 					return true;
72 				}
73 			}
74 		}
75 		return false;
76 	}
77 
78 }
79