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 
17 package android.test;
18 
19 import com.google.android.collect.Lists;
20 
21 import junit.framework.Test;
22 import junit.framework.TestCase;
23 import junit.framework.TestSuite;
24 import junit.runner.BaseTestRunner;
25 
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.lang.reflect.Modifier;
29 import java.util.Enumeration;
30 import java.util.HashSet;
31 import java.util.List;
32 import 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  */
38 public class TestCaseUtil {
39 
TestCaseUtil()40     private TestCaseUtil() {
41     }
42 
43     @SuppressWarnings("unchecked")
getTestCaseNames(Test test, boolean flatten)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 
getTests(Test test, boolean flatten)53     public static List<? extends Test> getTests(Test test, boolean flatten) {
54         return getTests(test, flatten, new HashSet<Class<?>>());
55     }
56 
getTests(Test test, boolean flatten, Set<Class<?>> seen)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 
invokeSuiteMethodIfPossible(Class testClass, Set<Class<?>> seen)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 
getTestName(Test test)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 
getTestAtIndex(TestSuite testSuite, int position)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 
createTestSuite(Class<? extends Test> testClass)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