1aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffinpackage org.junit.internal;
2aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
3aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffinimport java.lang.reflect.Method;
4aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffinimport java.util.Arrays;
5aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffinimport java.util.Comparator;
6aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
7aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffinimport org.junit.FixMethodOrder;
8aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
9aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffinpublic class MethodSorter {
10aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    /**
11aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * DEFAULT sort order
12aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     */
13aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    public static final Comparator<Method> DEFAULT = new Comparator<Method>() {
14aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        public int compare(Method m1, Method m2) {
15aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            int i1 = m1.getName().hashCode();
16aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            int i2 = m2.getName().hashCode();
17aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            if (i1 != i2) {
18aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin                return i1 < i2 ? -1 : 1;
19aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            }
20aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            return NAME_ASCENDING.compare(m1, m2);
21aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        }
22aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    };
23aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
24aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    /**
25aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * Method name ascending lexicographic sort order, with {@link Method#toString()} as a tiebreaker
26aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     */
27aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    public static final Comparator<Method> NAME_ASCENDING = new Comparator<Method>() {
28aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        public int compare(Method m1, Method m2) {
29aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            final int comparison = m1.getName().compareTo(m2.getName());
30aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            if (comparison != 0) {
31aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin                return comparison;
32aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            }
33aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            return m1.toString().compareTo(m2.toString());
34aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        }
35aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    };
36aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
37aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    /**
38aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * Gets declared methods of a class in a predictable order, unless @FixMethodOrder(MethodSorters.JVM) is specified.
39aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     *
40aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * Using the JVM order is unwise since the Java platform does not
41aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * specify any particular order, and in fact JDK 7 returns a more or less
42aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * random order; well-written test code would not assume any order, but some
43aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * does, and a predictable failure is better than a random failure on
44aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * certain platforms. By default, uses an unspecified but deterministic order.
45aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     *
46aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * @param clazz a class
47aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * @return same as {@link Class#getDeclaredMethods} but sorted
48aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     * @see <a href="http://bugs.sun.com/view_bug.do?bug_id=7023180">JDK
49aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     *      (non-)bug #7023180</a>
50aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin     */
51aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    public static Method[] getDeclaredMethods(Class<?> clazz) {
52aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        Comparator<Method> comparator = getSorter(clazz.getAnnotation(FixMethodOrder.class));
53aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
54aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        Method[] methods = clazz.getDeclaredMethods();
55aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        if (comparator != null) {
56aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            Arrays.sort(methods, comparator);
57aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        }
58aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
59aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        return methods;
60aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    }
61aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
62aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    private MethodSorter() {
63aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    }
64aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
65aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    private static Comparator<Method> getSorter(FixMethodOrder fixMethodOrder) {
66aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        if (fixMethodOrder == null) {
67aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin            return DEFAULT;
68aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        }
69aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin
70aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin        return fixMethodOrder.value().getComparator();
71aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin    }
72aeb93fc33cae3aadbb9b46083350ad2dc9aea645Paul Duffin}
73