1 /*
2  * Copyright (C) 2008 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.suitebuilder;
18 
19 import junit.framework.TestCase;
20 
21 import java.lang.annotation.Annotation;
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 
26 /**
27  * Represents a test to be run. Can be constructed without instantiating the TestCase or even
28  * loading the class.
29  */
30 public class TestMethod {
31 
32     private final String enclosingClassname;
33     private final String testMethodName;
34     private final Class<? extends TestCase> enclosingClass;
35 
TestMethod(Method method, Class<? extends TestCase> enclosingClass)36     public TestMethod(Method method, Class<? extends TestCase> enclosingClass) {
37         this(method.getName(), enclosingClass);
38     }
39 
TestMethod(String methodName, Class<? extends TestCase> enclosingClass)40     public TestMethod(String methodName, Class<? extends TestCase> enclosingClass) {
41         this.enclosingClass = enclosingClass;
42         this.enclosingClassname = enclosingClass.getName();
43         this.testMethodName = methodName;
44     }
45 
TestMethod(TestCase testCase)46     public TestMethod(TestCase testCase) {
47         this(testCase.getName(), testCase.getClass());
48     }
49 
getName()50     public String getName() {
51         return testMethodName;
52     }
53 
getEnclosingClassname()54     public String getEnclosingClassname() {
55         return enclosingClassname;
56     }
57 
getAnnotation(Class<T> annotationClass)58     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
59         try {
60             return getEnclosingClass().getMethod(getName()).getAnnotation(annotationClass);
61         } catch (NoSuchMethodException e) {
62             return null;
63         }
64     }
65 
66     @SuppressWarnings("unchecked")
getEnclosingClass()67     public Class<? extends TestCase> getEnclosingClass() {
68         return enclosingClass;
69     }
70 
createTest()71     public TestCase createTest()
72             throws InvocationTargetException, IllegalAccessException, InstantiationException {
73         return instantiateTest(enclosingClass, testMethodName);
74     }
75 
76     @SuppressWarnings("unchecked")
instantiateTest(Class testCaseClass, String testName)77     private TestCase instantiateTest(Class testCaseClass, String testName)
78             throws InvocationTargetException, IllegalAccessException, InstantiationException {
79         Constructor[] constructors = testCaseClass.getConstructors();
80 
81         if (constructors.length == 0) {
82             return instantiateTest(testCaseClass.getSuperclass(), testName);
83         } else {
84             for (Constructor constructor : constructors) {
85                 Class[] params = constructor.getParameterTypes();
86                 if (noargsConstructor(params)) {
87                     TestCase test = ((Constructor<? extends TestCase>) constructor).newInstance();
88                     // JUnit will run just the one test if you call
89                     // {@link TestCase#setName(String)}
90                     test.setName(testName);
91                     return test;
92                 } else if (singleStringConstructor(params)) {
93                     return ((Constructor<? extends TestCase>) constructor)
94                             .newInstance(testName);
95                 }
96             }
97         }
98         throw new RuntimeException("Unable to locate a constructor for "
99                 + testCaseClass.getName());
100     }
101 
singleStringConstructor(Class[] params)102     private boolean singleStringConstructor(Class[] params) {
103         return (params.length == 1) && (params[0].equals(String.class));
104     }
105 
noargsConstructor(Class[] params)106     private boolean noargsConstructor(Class[] params) {
107         return params.length == 0;
108     }
109 
110     @Override
equals(Object o)111     public boolean equals(Object o) {
112         if (this == o) {
113             return true;
114         }
115         if (o == null || getClass() != o.getClass()) {
116             return false;
117         }
118 
119         TestMethod that = (TestMethod) o;
120 
121         if (enclosingClassname != null
122                 ? !enclosingClassname.equals(that.enclosingClassname)
123                 : that.enclosingClassname != null) {
124             return false;
125         }
126         if (testMethodName != null
127                 ? !testMethodName.equals(that.testMethodName)
128                 : that.testMethodName != null) {
129             return false;
130         }
131         return true;
132     }
133 
134     @Override
hashCode()135     public int hashCode() {
136         int result;
137         result = (enclosingClassname != null ? enclosingClassname.hashCode() : 0);
138         result = 31 * result + (testMethodName != null ? testMethodName.hashCode() : 0);
139         return result;
140     }
141 
142     @Override
toString()143     public String toString() {
144         return enclosingClassname + "." + testMethodName;
145     }
146 }
147