blob: 560fdd0d25641b094c2949f3bc382c1052e55367 [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
The Android Open Source Projectf8057102009-03-15 16:47:16 -070017import java.io.BufferedReader;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070018import java.io.File;
19import java.io.FileInputStream;
Urs Grobfc77f6e2009-04-17 02:07:14 -070020import java.io.FileReader;
21import java.io.IOException;
22import java.lang.annotation.Annotation;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070023import java.lang.reflect.InvocationTargetException;
24import java.lang.reflect.Method;
25import java.util.ArrayList;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070026import java.util.HashSet;
27import java.util.Iterator;
Urs Grobfc77f6e2009-04-17 02:07:14 -070028import java.util.LinkedHashMap;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070029import java.util.Map;
30import java.util.Set;
31
32import javax.xml.parsers.DocumentBuilderFactory;
33import javax.xml.parsers.ParserConfigurationException;
34
35import junit.framework.Test;
36import junit.framework.TestCase;
37import junit.framework.TestResult;
Urs Grobfc77f6e2009-04-17 02:07:14 -070038import junit.textui.ResultPrinter;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070039import 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
46public class CollectAllTests extends DescriptionGenerator {
47
48 static final String ATTRIBUTE_RUNNER = "runner";
49 static final String ATTRIBUTE_PACKAGE = "appPackageName";
50 static final String ATTRIBUTE_NS = "appNameSpace";
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070051 static final String ATTRIBUTE_TARGET = "targetNameSpace";
52 static final String ATTRIBUTE_TARGET_BINARY = "targetBinaryName";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070053 static final String ATTRIBUTE_HOST_SIDE_ONLY = "hostSideOnly";
54 static final String ATTRIBUTE_JAR_PATH = "jarPath";
55
56 static final String JAR_PATH = "LOCAL_JAR_PATH :=";
57 static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
58
59 static final int HOST_SIDE_ONLY = 1;
60 static final int DEVICE_SIDE_ONLY = 2;
61
62 private static String runner;
63 private static String packageName;
64 private static String target;
65 private static String xmlName;
66 private static int testType;
67 private static String jarPath;
68
69 private static Map<String,TestClass> testCases;
70 private static Set<String> failed = new HashSet<String>();
71
72 private static class MyXMLGenerator extends XMLGenerator {
73
74 MyXMLGenerator(String outputPath) throws ParserConfigurationException {
75 super(outputPath);
76
77 Node testPackageElem = mDoc.getDocumentElement();
78
79 setAttribute(testPackageElem, ATTRIBUTE_NAME, xmlName);
80 setAttribute(testPackageElem, ATTRIBUTE_RUNNER, runner);
81 setAttribute(testPackageElem, ATTRIBUTE_PACKAGE, packageName);
82 setAttribute(testPackageElem, ATTRIBUTE_NS, packageName);
83
84 if (testType == HOST_SIDE_ONLY) {
85 setAttribute(testPackageElem, ATTRIBUTE_HOST_SIDE_ONLY, "true");
86 setAttribute(testPackageElem, ATTRIBUTE_JAR_PATH, jarPath);
87 }
88
89 if (!packageName.equals(target)) {
90 setAttribute(testPackageElem, ATTRIBUTE_TARGET, target);
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070091 setAttribute(testPackageElem, ATTRIBUTE_TARGET_BINARY, target);
The Android Open Source Projectf8057102009-03-15 16:47:16 -070092 }
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070093 }
The Android Open Source Projectf8057102009-03-15 16:47:16 -070094 }
95
96 private static String OUTPUTFILE = "";
97 private static String MANIFESTFILE = "";
98 private static String TESTSUITECLASS = "";
99 private static String ANDROID_MAKE_FILE = "";
100
101 private static Test TESTSUITE;
102
103 static XMLGenerator xmlGenerator;
104
105 public static void main(String[] args) {
106 if (args.length > 2) {
107 OUTPUTFILE = args[0];
108 MANIFESTFILE = args [1];
109 TESTSUITECLASS = args[2];
110 if (args.length > 3) {
111 ANDROID_MAKE_FILE = args[3];
112 }
113 } else {
114 System.out.println("usage: \n" +
115 "\t... CollectAllTests <output-file> <manifest-file> <testsuite-class-name> <makefile-file>");
Urs Grobfc77f6e2009-04-17 02:07:14 -0700116 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700117 }
118
119 if (ANDROID_MAKE_FILE.length() > 0) {
120 testType = getTestType(ANDROID_MAKE_FILE);
121 }
122
123 Document manifest = null;
124 try {
125 manifest = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(MANIFESTFILE));
126 } catch (Exception e) {
127 System.err.println("cannot open manifest");
128 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700129 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700130 }
131
132 Element documentElement = manifest.getDocumentElement();
133
134 documentElement.getAttribute("package");
135
136 xmlName = new File(OUTPUTFILE).getName();
137 runner = getElementAttribute(documentElement, "instrumentation", "android:name");
138 packageName = documentElement.getAttribute("package");
139 target = getElementAttribute(documentElement, "instrumentation", "android:targetPackage");
140
141 Class<?> testClass = null;
142 try {
143 testClass = Class.forName(TESTSUITECLASS);
144 } catch (ClassNotFoundException e) {
145 System.err.println("test class not found");
146 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700147 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700148 }
149
150 Method method = null;
151 try {
152 method = testClass.getMethod("suite", new Class<?>[0]);
153 } catch (SecurityException e) {
154 System.err.println("failed to get suite method");
155 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700156 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700157 } catch (NoSuchMethodException e) {
158 System.err.println("failed to get suite method");
159 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700160 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700161 }
162
163 try {
164 TESTSUITE = (Test) method.invoke(null, (Object[])null);
165 } catch (IllegalArgumentException e) {
166 System.err.println("failed to get suite method");
167 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700168 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700169 } catch (IllegalAccessException e) {
170 System.err.println("failed to get suite method");
171 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700172 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700173 } catch (InvocationTargetException e) {
174 System.err.println("failed to get suite method");
175 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700176 System.exit(1);;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700177 }
178
179 try {
180 xmlGenerator = new MyXMLGenerator(OUTPUTFILE + ".xml");
181 } catch (ParserConfigurationException e) {
182 System.err.println("Can't initialize XML Generator");
Urs Grobfc77f6e2009-04-17 02:07:14 -0700183 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700184 }
185
186 testCases = new LinkedHashMap<String, TestClass>();
187 CollectAllTests cat = new CollectAllTests();
188 cat.compose();
189
190 if (!failed.isEmpty()) {
191 System.err.println("The following classes have no default constructor");
192 for (Iterator<String> iterator = failed.iterator(); iterator.hasNext();) {
193 String type = iterator.next();
194 System.err.println(type);
195 }
Urs Grobfc77f6e2009-04-17 02:07:14 -0700196 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700197 }
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();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700209 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700210 }
211 }
212
213 private static int getTestType(String makeFileName) {
214
215 int type = DEVICE_SIDE_ONLY;
216 try {
217 BufferedReader reader = new BufferedReader(new FileReader(makeFileName));
218 String line;
219
220 while ((line =reader.readLine())!=null) {
221 if (line.startsWith(TEST_TYPE)) {
222 type = HOST_SIDE_ONLY;
223 } else if (line.startsWith(JAR_PATH)) {
224 jarPath = line.substring(JAR_PATH.length(), line.length()).trim();
225 }
226 }
227 reader.close();
228 } catch (IOException e) {
229 }
230
231 return type;
232 }
233
234 private static Element getElement(Element element, String tagName) {
235 NodeList elements = element.getElementsByTagName(tagName);
236 if (elements.getLength() > 0) {
237 return (Element) elements.item(0);
238 } else {
239 return null;
240 }
241 }
242
243 private static String getElementAttribute(Element element, String elementName, String attributeName) {
244 Element e = getElement(element, elementName);
245 if (e != null) {
246 return e.getAttribute(attributeName);
247 } else {
248 return "";
249 }
250 }
251
252 public void compose() {
Urs Grobfc77f6e2009-04-17 02:07:14 -0700253 TestRunner runner = new TestRunner() {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700254 @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 }
Urs Grobfc77f6e2009-04-17 02:07:14 -0700268
269
270
271 };
272
273 runner.setPrinter(new ResultPrinter(System.out) {
274 @Override
275 protected void printFooter(TestResult result) {
276 }
277
278 @Override
279 protected void printHeader(long runTime) {
280 }
281 });
282 runner.doRun(TESTSUITE);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700283 }
Urs Grobfc77f6e2009-04-17 02:07:14 -0700284
285 private String getKnownFailure(final Class<? extends TestCase> testClass,
286 final String testName) {
287 return getAnnotation(testClass, testName, KNOWN_FAILURE);
288 }
289
290 private boolean isBrokenTest(final Class<? extends TestCase> testClass,
291 final String testName) {
292 return getAnnotation(testClass, testName, BROKEN_TEST) != null;
293 }
294
295 private String getAnnotation(final Class<? extends TestCase> testClass,
296 final String testName, final String annotationName) {
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700297 try {
Urs Grobfc77f6e2009-04-17 02:07:14 -0700298 Method testMethod = testClass.getMethod(testName, (Class[])null);
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700299 Annotation[] annotations = testMethod.getAnnotations();
300 for (Annotation annot : annotations) {
301
Urs Grobfc77f6e2009-04-17 02:07:14 -0700302 if (annot.annotationType().getName().equals(annotationName)) {
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700303 String annotStr = annot.toString();
304 String knownFailure = null;
305 if (annotStr.contains("(value=")) {
306 knownFailure =
Urs Grobfc77f6e2009-04-17 02:07:14 -0700307 annotStr.substring(annotStr.indexOf("=") + 1,
308 annotStr.length() - 1);
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700309
310 }
311
312 if (knownFailure == null) {
313 knownFailure = "true";
314 }
315
316 return knownFailure;
317 }
318
319 }
320
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700321 } catch (java.lang.NoSuchMethodException e) {
322 }
323
324 return null;
325 }
326
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700327 private void addToTests(TestCase test) {
328
329 String testClassName = test.getClass().getName();
330 String testName = test.getName();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700331 String knownFailure = getKnownFailure(test.getClass(), testName);
332
333 if (isBrokenTest(test.getClass(), testName)) {
334 System.out.println("ignoring broken test: " + test);
335 return;
336 }
337
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700338
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700339 if (!testName.startsWith("test")) {
340 try {
341 test.runBare();
342 } catch (Throwable e) {
343 e.printStackTrace();
344 return;
345 }
346 }
347 TestClass testClass = null;
348 if (testCases.containsKey(testClassName)) {
349 testClass = testCases.get(testClassName);
350 } else {
351 testClass = new TestClass(testClassName, new ArrayList<TestMethod>());
352 testCases.put(testClassName, testClass);
353 }
354
Scott Su259ced72009-04-30 17:05:49 -0700355 testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700356
357 try {
358 test.getClass().getConstructor(new Class<?>[0]);
359 } catch (SecurityException e) {
360 failed.add(test.getClass().getName());
361 } catch (NoSuchMethodException e) {
362 failed.add(test.getClass().getName());
363 }
364 }
365}