1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.test;
18
19import com.google.android.collect.Lists;
20
21import junit.framework.Test;
22import junit.framework.TestCase;
23import junit.framework.TestSuite;
24import junit.runner.BaseTestRunner;
25
26import java.lang.reflect.InvocationTargetException;
27import java.lang.reflect.Method;
28import java.lang.reflect.Modifier;
29import java.util.Enumeration;
30import java.util.HashSet;
31import java.util.List;
32import java.util.Set;
33
34/**
35 * @hide - This is part of a framework that is under development and should not be used for
36 * active development.
37 */
38public class TestCaseUtil {
39
40    private TestCaseUtil() {
41    }
42
43    @SuppressWarnings("unchecked")
44    public static List<String> getTestCaseNames(Test test, boolean flatten) {
45        List<Test> tests = (List<Test>) getTests(test, flatten);
46        List<String> testCaseNames = Lists.newArrayList();
47        for (Test aTest : tests) {
48            testCaseNames.add(getTestName(aTest));
49        }
50        return testCaseNames;
51    }
52
53    public static List<? extends Test> getTests(Test test, boolean flatten) {
54        return getTests(test, flatten, new HashSet<Class<?>>());
55    }
56
57    private static List<? extends Test> getTests(Test test, boolean flatten,
58            Set<Class<?>> seen) {
59        List<Test> testCases = Lists.newArrayList();
60        if (test != null) {
61
62            Test workingTest = null;
63            /*
64             * If we want to run a single TestCase method only, we must not
65             * invoke the suite() method, because we will run all test methods
66             * of the class then.
67             */
68            if (test instanceof TestCase &&
69                    ((TestCase)test).getName() == null) {
70                workingTest = invokeSuiteMethodIfPossible(test.getClass(),
71                        seen);
72            }
73            if (workingTest == null) {
74                workingTest = test;
75            }
76
77            if (workingTest instanceof TestSuite) {
78                TestSuite testSuite = (TestSuite) workingTest;
79                Enumeration enumeration = testSuite.tests();
80                while (enumeration.hasMoreElements()) {
81                    Test childTest = (Test) enumeration.nextElement();
82                    if (flatten) {
83                        testCases.addAll(getTests(childTest, flatten, seen));
84                    } else {
85                        testCases.add(childTest);
86                    }
87                }
88            } else {
89                testCases.add(workingTest);
90            }
91        }
92        return testCases;
93    }
94
95    private static Test invokeSuiteMethodIfPossible(Class testClass,
96            Set<Class<?>> seen) {
97        try {
98            Method suiteMethod = testClass.getMethod(
99                    BaseTestRunner.SUITE_METHODNAME, new Class[0]);
100            /*
101             * Additional check necessary: If a TestCase contains a suite()
102             * method that returns a TestSuite including the TestCase itself,
103             * we need to stop the recursion. We use a set of classes to
104             * remember which classes' suite() methods were already invoked.
105             */
106            if (Modifier.isStatic(suiteMethod.getModifiers())
107                    && !seen.contains(testClass)) {
108                seen.add(testClass);
109                try {
110                    return (Test) suiteMethod.invoke(null, (Object[]) null);
111                } catch (InvocationTargetException e) {
112                    // do nothing
113                } catch (IllegalAccessException e) {
114                    // do nothing
115                }
116            }
117        } catch (NoSuchMethodException e) {
118            // do nothing
119        }
120        return null;
121    }
122
123    public static String getTestName(Test test) {
124        if (test instanceof TestCase) {
125            TestCase testCase = (TestCase) test;
126            return testCase.getName();
127        } else if (test instanceof TestSuite) {
128            TestSuite testSuite = (TestSuite) test;
129            String name = testSuite.getName();
130            if (name != null) {
131                int index = name.lastIndexOf(".");
132                if (index > -1) {
133                    return name.substring(index + 1);
134                } else {
135                    return name;
136                }
137            }
138        }
139        return "";
140    }
141
142    public static Test getTestAtIndex(TestSuite testSuite, int position) {
143        int index = 0;
144        Enumeration enumeration = testSuite.tests();
145        while (enumeration.hasMoreElements()) {
146            Test test = (Test) enumeration.nextElement();
147            if (index == position) {
148                return test;
149            }
150            index++;
151        }
152        return null;
153    }
154
155    public static TestSuite createTestSuite(Class<? extends Test> testClass)
156            throws InstantiationException, IllegalAccessException {
157
158        Test test = invokeSuiteMethodIfPossible(testClass,
159                new HashSet<Class<?>>());
160        if (test == null) {
161            return new TestSuite(testClass);
162
163        } else if (TestCase.class.isAssignableFrom(test.getClass())) {
164            TestSuite testSuite = new TestSuite(test.getClass().getName());
165            testSuite.addTest(test);
166            return testSuite;
167        }
168
169        return (TestSuite) test;
170    }
171}
172