blob: e2b6ad186b3048e7ac6c5d2d1939ae9cf4ea134e [file] [log] [blame]
The Android Open Source Projectf8057102009-03-15 16:47:16 -07001/*
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
17import java.io.FileNotFoundException;
18import java.io.IOException;
19import java.io.BufferedReader;
20import java.io.FileReader;
21
22import java.io.File;
23import java.io.FileInputStream;
24import java.lang.reflect.InvocationTargetException;
25import java.lang.reflect.Method;
26import java.util.ArrayList;
27import java.util.LinkedHashMap;
28import java.util.HashSet;
29import java.util.Iterator;
30import java.util.Map;
31import java.util.Set;
32
33import javax.xml.parsers.DocumentBuilderFactory;
34import javax.xml.parsers.ParserConfigurationException;
35
36import junit.framework.Test;
37import junit.framework.TestCase;
38import junit.framework.TestResult;
39import junit.textui.TestRunner;
40
41import org.w3c.dom.Document;
42import org.w3c.dom.Element;
43import org.w3c.dom.Node;
44import org.w3c.dom.NodeList;
45
The Android Open Source Project7671bec2009-03-19 23:08:36 -070046import java.lang.annotation.Annotation;
47import java.lang.ClassNotFoundException;
48import java.lang.NoSuchMethodException;
49
The Android Open Source Projectf8057102009-03-15 16:47:16 -070050public class CollectAllTests extends DescriptionGenerator {
51
52 static final String ATTRIBUTE_RUNNER = "runner";
53 static final String ATTRIBUTE_PACKAGE = "appPackageName";
54 static final String ATTRIBUTE_NS = "appNameSpace";
55 static final String ATTRIBUTE_TARGET = "target";
56 static final String ATTRIBUTE_HOST_SIDE_ONLY = "hostSideOnly";
57 static final String ATTRIBUTE_JAR_PATH = "jarPath";
58
59 static final String JAR_PATH = "LOCAL_JAR_PATH :=";
60 static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
61
62 static final int HOST_SIDE_ONLY = 1;
63 static final int DEVICE_SIDE_ONLY = 2;
64
65 private static String runner;
66 private static String packageName;
67 private static String target;
68 private static String xmlName;
69 private static int testType;
70 private static String jarPath;
71
72 private static Map<String,TestClass> testCases;
73 private static Set<String> failed = new HashSet<String>();
74
75 private static class MyXMLGenerator extends XMLGenerator {
76
77 MyXMLGenerator(String outputPath) throws ParserConfigurationException {
78 super(outputPath);
79
80 Node testPackageElem = mDoc.getDocumentElement();
81
82 setAttribute(testPackageElem, ATTRIBUTE_NAME, xmlName);
83 setAttribute(testPackageElem, ATTRIBUTE_RUNNER, runner);
84 setAttribute(testPackageElem, ATTRIBUTE_PACKAGE, packageName);
85 setAttribute(testPackageElem, ATTRIBUTE_NS, packageName);
86
87 if (testType == HOST_SIDE_ONLY) {
88 setAttribute(testPackageElem, ATTRIBUTE_HOST_SIDE_ONLY, "true");
89 setAttribute(testPackageElem, ATTRIBUTE_JAR_PATH, jarPath);
90 }
91
92 if (!packageName.equals(target)) {
93 setAttribute(testPackageElem, ATTRIBUTE_TARGET, target);
94 }
95 }
96 }
97
98 private static String OUTPUTFILE = "";
99 private static String MANIFESTFILE = "";
100 private static String TESTSUITECLASS = "";
101 private static String ANDROID_MAKE_FILE = "";
102
103 private static Test TESTSUITE;
104
105 static XMLGenerator xmlGenerator;
106
107 public static void main(String[] args) {
108 if (args.length > 2) {
109 OUTPUTFILE = args[0];
110 MANIFESTFILE = args [1];
111 TESTSUITECLASS = args[2];
112 if (args.length > 3) {
113 ANDROID_MAKE_FILE = args[3];
114 }
115 } else {
116 System.out.println("usage: \n" +
117 "\t... CollectAllTests <output-file> <manifest-file> <testsuite-class-name> <makefile-file>");
118 return;
119 }
120
121 if (ANDROID_MAKE_FILE.length() > 0) {
122 testType = getTestType(ANDROID_MAKE_FILE);
123 }
124
125 Document manifest = null;
126 try {
127 manifest = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(MANIFESTFILE));
128 } catch (Exception e) {
129 System.err.println("cannot open manifest");
130 e.printStackTrace();
131 return;
132 }
133
134 Element documentElement = manifest.getDocumentElement();
135
136 documentElement.getAttribute("package");
137
138 xmlName = new File(OUTPUTFILE).getName();
139 runner = getElementAttribute(documentElement, "instrumentation", "android:name");
140 packageName = documentElement.getAttribute("package");
141 target = getElementAttribute(documentElement, "instrumentation", "android:targetPackage");
142
143 Class<?> testClass = null;
144 try {
145 testClass = Class.forName(TESTSUITECLASS);
146 } catch (ClassNotFoundException e) {
147 System.err.println("test class not found");
148 e.printStackTrace();
149 return;
150 }
151
152 Method method = null;
153 try {
154 method = testClass.getMethod("suite", new Class<?>[0]);
155 } catch (SecurityException e) {
156 System.err.println("failed to get suite method");
157 e.printStackTrace();
158 return;
159 } catch (NoSuchMethodException e) {
160 System.err.println("failed to get suite method");
161 e.printStackTrace();
162 return;
163 }
164
165 try {
166 TESTSUITE = (Test) method.invoke(null, (Object[])null);
167 } catch (IllegalArgumentException e) {
168 System.err.println("failed to get suite method");
169 e.printStackTrace();
170 return;
171 } catch (IllegalAccessException e) {
172 System.err.println("failed to get suite method");
173 e.printStackTrace();
174 return;
175 } catch (InvocationTargetException e) {
176 System.err.println("failed to get suite method");
177 e.printStackTrace();
178 return;
179 }
180
181 try {
182 xmlGenerator = new MyXMLGenerator(OUTPUTFILE + ".xml");
183 } catch (ParserConfigurationException e) {
184 System.err.println("Can't initialize XML Generator");
185 }
186
187 testCases = new LinkedHashMap<String, TestClass>();
188 CollectAllTests cat = new CollectAllTests();
189 cat.compose();
190
191 if (!failed.isEmpty()) {
192 System.err.println("The following classes have no default constructor");
193 for (Iterator<String> iterator = failed.iterator(); iterator.hasNext();) {
194 String type = iterator.next();
195 System.err.println(type);
196 }
197 }
198
199 for (Iterator<TestClass> iterator = testCases.values().iterator(); iterator.hasNext();) {
200 TestClass type = iterator.next();
201 xmlGenerator.addTestClass(type);
202 }
203
204 try {
205 xmlGenerator.dump();
206 } catch (Exception e) {
207 System.err.println("cannot dump xml");
208 e.printStackTrace();
209 }
210 }
211
212 private static int getTestType(String makeFileName) {
213
214 int type = DEVICE_SIDE_ONLY;
215 try {
216 BufferedReader reader = new BufferedReader(new FileReader(makeFileName));
217 String line;
218
219 while ((line =reader.readLine())!=null) {
220 if (line.startsWith(TEST_TYPE)) {
221 type = HOST_SIDE_ONLY;
222 } else if (line.startsWith(JAR_PATH)) {
223 jarPath = line.substring(JAR_PATH.length(), line.length()).trim();
224 }
225 }
226 reader.close();
227 } catch (IOException e) {
228 }
229
230 return type;
231 }
232
233 private static Element getElement(Element element, String tagName) {
234 NodeList elements = element.getElementsByTagName(tagName);
235 if (elements.getLength() > 0) {
236 return (Element) elements.item(0);
237 } else {
238 return null;
239 }
240 }
241
242 private static String getElementAttribute(Element element, String elementName, String attributeName) {
243 Element e = getElement(element, elementName);
244 if (e != null) {
245 return e.getAttribute(attributeName);
246 } else {
247 return "";
248 }
249 }
250
251 public void compose() {
252 System.out.println("Collecting all junit tests...");
253 new TestRunner() {
254 @Override
255 protected TestResult createTestResult() {
256 return new TestResult() {
257 @Override
258 protected void run(TestCase test) {
259 addToTests(test);
260 }
261 };
262 }
263
264 @Override
265 public TestResult doRun(Test test) {
266 return super.doRun(test);
267 }
268 }.doRun(TESTSUITE);
269 }
270
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700271 private String getKnownFailure(final String testClassName, final String testName) {
272 try {
273 Class<?> testClass = Class.forName(testClassName);
274 Method testMethod = testClass.getMethod(testName, null);
275 Annotation[] annotations = testMethod.getAnnotations();
276 for (Annotation annot : annotations) {
277
278 if (annot.annotationType().getName().equals(KNOWN_FAILURE)) {
279 String annotStr = annot.toString();
280 String knownFailure = null;
281 if (annotStr.contains("(value=")) {
282 knownFailure =
283 annotStr.substring(annotStr.indexOf("=") + 1, annotStr.length() - 1);
284
285 }
286
287 if (knownFailure == null) {
288 knownFailure = "true";
289 }
290
291 return knownFailure;
292 }
293
294 }
295
296 } catch (java.lang.ClassNotFoundException e) {
297 } catch (java.lang.NoSuchMethodException e) {
298 }
299
300 return null;
301 }
302
303 private void println(final String message) {
304 System.out.println(message);
305 }
306
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700307 private void addToTests(TestCase test) {
308
309 String testClassName = test.getClass().getName();
310 String testName = test.getName();
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700311 String knownFailure = getKnownFailure(testClassName, testName);
312
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700313 if (!testName.startsWith("test")) {
314 try {
315 test.runBare();
316 } catch (Throwable e) {
317 e.printStackTrace();
318 return;
319 }
320 }
321 TestClass testClass = null;
322 if (testCases.containsKey(testClassName)) {
323 testClass = testCases.get(testClassName);
324 } else {
325 testClass = new TestClass(testClassName, new ArrayList<TestMethod>());
326 testCases.put(testClassName, testClass);
327 }
328
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700329 testClass.mCases.add(new TestMethod(testName, "", "", knownFailure));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700330
331 try {
332 test.getClass().getConstructor(new Class<?>[0]);
333 } catch (SecurityException e) {
334 failed.add(test.getClass().getName());
335 } catch (NoSuchMethodException e) {
336 failed.add(test.getClass().getName());
337 }
338 }
339}