blob: 883d70eff8cb6731be5dea3c616f95ab59829f57 [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
Brian Muramatsu7f64e852011-02-17 16:52:16 -080017import org.w3c.dom.Document;
18import org.w3c.dom.Element;
19import org.w3c.dom.Node;
20import org.w3c.dom.NodeList;
21
22import vogar.Expectation;
23import vogar.ExpectationStore;
24import vogar.ModeId;
25
The Android Open Source Projectf8057102009-03-15 16:47:16 -070026import java.io.BufferedReader;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070027import java.io.File;
28import java.io.FileInputStream;
Urs Grobfc77f6e2009-04-17 02:07:14 -070029import java.io.FileReader;
Brett Chabot5977e942010-12-13 16:42:42 -080030import java.io.FilenameFilter;
Urs Grobfc77f6e2009-04-17 02:07:14 -070031import java.io.IOException;
32import java.lang.annotation.Annotation;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070033import java.lang.reflect.InvocationTargetException;
34import java.lang.reflect.Method;
Brian Carlstrom9f2dab82011-04-01 15:47:17 -070035import java.lang.reflect.Modifier;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070036import java.util.ArrayList;
Brett Chabot5977e942010-12-13 16:42:42 -080037import java.util.Arrays;
Brian Carlstrom9f2dab82011-04-01 15:47:17 -070038import java.util.Enumeration;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070039import java.util.HashSet;
40import java.util.Iterator;
Urs Grobfc77f6e2009-04-17 02:07:14 -070041import java.util.LinkedHashMap;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070042import java.util.Map;
43import java.util.Set;
Brian Carlstrom9f2dab82011-04-01 15:47:17 -070044import java.util.jar.JarEntry;
45import java.util.jar.JarFile;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070046
47import javax.xml.parsers.DocumentBuilderFactory;
48import javax.xml.parsers.ParserConfigurationException;
49
50import junit.framework.Test;
51import junit.framework.TestCase;
52import junit.framework.TestResult;
Urs Grobfc77f6e2009-04-17 02:07:14 -070053import junit.textui.ResultPrinter;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070054import junit.textui.TestRunner;
55
The Android Open Source Projectf8057102009-03-15 16:47:16 -070056public class CollectAllTests extends DescriptionGenerator {
57
58 static final String ATTRIBUTE_RUNNER = "runner";
59 static final String ATTRIBUTE_PACKAGE = "appPackageName";
60 static final String ATTRIBUTE_NS = "appNameSpace";
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -070061 static final String ATTRIBUTE_TARGET = "targetNameSpace";
62 static final String ATTRIBUTE_TARGET_BINARY = "targetBinaryName";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070063 static final String ATTRIBUTE_HOST_SIDE_ONLY = "hostSideOnly";
64 static final String ATTRIBUTE_JAR_PATH = "jarPath";
65
66 static final String JAR_PATH = "LOCAL_JAR_PATH :=";
67 static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
68
69 static final int HOST_SIDE_ONLY = 1;
70 static final int DEVICE_SIDE_ONLY = 2;
71
72 private static String runner;
73 private static String packageName;
74 private static String target;
75 private static String xmlName;
76 private static int testType;
77 private static String jarPath;
78
79 private static Map<String,TestClass> testCases;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070080
81 private static class MyXMLGenerator extends XMLGenerator {
82
83 MyXMLGenerator(String outputPath) throws ParserConfigurationException {
84 super(outputPath);
85
86 Node testPackageElem = mDoc.getDocumentElement();
87
88 setAttribute(testPackageElem, ATTRIBUTE_NAME, xmlName);
89 setAttribute(testPackageElem, ATTRIBUTE_RUNNER, runner);
90 setAttribute(testPackageElem, ATTRIBUTE_PACKAGE, packageName);
91 setAttribute(testPackageElem, ATTRIBUTE_NS, packageName);
92
93 if (testType == HOST_SIDE_ONLY) {
94 setAttribute(testPackageElem, ATTRIBUTE_HOST_SIDE_ONLY, "true");
95 setAttribute(testPackageElem, ATTRIBUTE_JAR_PATH, jarPath);
96 }
97
98 if (!packageName.equals(target)) {
99 setAttribute(testPackageElem, ATTRIBUTE_TARGET, target);
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700100 setAttribute(testPackageElem, ATTRIBUTE_TARGET_BINARY, target);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700101 }
Jorg Pleumann8a6c9f92009-05-07 01:33:15 -0700102 }
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700103 }
104
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700105 private static String OUTPUTFILE;
106 private static String MANIFESTFILE;
107 private static String JARFILE;
108 private static String LIBCORE_EXPECTATION_DIR;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700109 private static String ANDROID_MAKE_FILE = "";
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700110
111 static XMLGenerator xmlGenerator;
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800112 private static ExpectationStore libcoreVogarExpectationStore;
113 private static ExpectationStore ctsVogarExpectationStore;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700114
115 public static void main(String[] args) {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700116 if (args.length >= 3 && args.length <= 5) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700117 OUTPUTFILE = args[0];
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700118 MANIFESTFILE = args[1];
119 JARFILE = args[2];
120 if (args.length >= 4) {
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800121 LIBCORE_EXPECTATION_DIR = args[3];
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700122 if (args.length >= 5) {
123 ANDROID_MAKE_FILE = args[4];
124 }
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700125 }
126 } else {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700127 System.err.println("usage: CollectAllTests <output-file> <manifest-file> <jar-file>"
128 + "[expectation-dir [makefile-file]]");
Urs Grobfc77f6e2009-04-17 02:07:14 -0700129 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700130 }
131
132 if (ANDROID_MAKE_FILE.length() > 0) {
133 testType = getTestType(ANDROID_MAKE_FILE);
134 }
135
136 Document manifest = null;
137 try {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700138 manifest = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
139 new FileInputStream(MANIFESTFILE));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700140 } catch (Exception e) {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700141 System.err.println("cannot open manifest " + MANIFESTFILE);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700142 e.printStackTrace();
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700143 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700144 }
145
146 Element documentElement = manifest.getDocumentElement();
147
148 documentElement.getAttribute("package");
149
150 xmlName = new File(OUTPUTFILE).getName();
151 runner = getElementAttribute(documentElement, "instrumentation", "android:name");
152 packageName = documentElement.getAttribute("package");
153 target = getElementAttribute(documentElement, "instrumentation", "android:targetPackage");
154
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700155 try {
156 xmlGenerator = new MyXMLGenerator(OUTPUTFILE + ".xml");
157 } catch (ParserConfigurationException e) {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700158 System.err.println("Can't initialize XML Generator " + OUTPUTFILE + ".xml");
Urs Grobfc77f6e2009-04-17 02:07:14 -0700159 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700160 }
161
Brett Chabot5977e942010-12-13 16:42:42 -0800162 try {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700163 libcoreVogarExpectationStore
164 = VogarUtils.provideExpectationStore(LIBCORE_EXPECTATION_DIR);
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800165 ctsVogarExpectationStore = VogarUtils.provideExpectationStore(CTS_EXPECTATION_DIR);
Brett Chabot5977e942010-12-13 16:42:42 -0800166 } catch (IOException e) {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700167 System.err.println("Can't initialize vogar expectation store from "
168 + LIBCORE_EXPECTATION_DIR);
Brett Chabot5977e942010-12-13 16:42:42 -0800169 e.printStackTrace(System.err);
170 System.exit(1);
171 }
172
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700173 JarFile jarFile = null;
174 try {
175 jarFile = new JarFile(JARFILE);
176 } catch (Exception e) {
177 System.err.println("cannot open jarfile " + JARFILE);
178 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700179 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700180 }
181
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700182 testCases = new LinkedHashMap<String, TestClass>();
183
184 Enumeration<JarEntry> jarEntries = jarFile.entries();
185 while (jarEntries.hasMoreElements()) {
186 JarEntry jarEntry = jarEntries.nextElement();
187 String name = jarEntry.getName();
188 if (!name.endsWith(".class")) {
189 continue;
190 }
191 String className
192 = name.substring(0, name.length() - ".class".length()).replace('/', '.');
193 try {
194 Class<?> klass = Class.forName(className,
195 false,
196 CollectAllTests.class.getClassLoader());
197 if (!TestCase.class.isAssignableFrom(klass)) {
198 continue;
199 }
200 if (Modifier.isAbstract(klass.getModifiers())) {
201 continue;
202 }
203 if (!Modifier.isPublic(klass.getModifiers())) {
204 continue;
205 }
206 try {
207 klass.getConstructor(new Class<?>[] { String.class } );
208 addToTests(klass.asSubclass(TestCase.class));
209 continue;
210 } catch (NoSuchMethodException e) {
211 }
212 try {
213 klass.getConstructor(new Class<?>[0]);
214 addToTests(klass.asSubclass(TestCase.class));
215 continue;
216 } catch (NoSuchMethodException e) {
217 }
218 } catch (ClassNotFoundException e) {
219 System.out.println("class not found " + className);
220 e.printStackTrace();
221 System.exit(1);
222 }
223 }
224
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700225 for (Iterator<TestClass> iterator = testCases.values().iterator(); iterator.hasNext();) {
226 TestClass type = iterator.next();
227 xmlGenerator.addTestClass(type);
228 }
229
230 try {
231 xmlGenerator.dump();
232 } catch (Exception e) {
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700233 System.err.println("cannot dump xml to " + OUTPUTFILE + ".xml");
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700234 e.printStackTrace();
Urs Grobfc77f6e2009-04-17 02:07:14 -0700235 System.exit(1);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700236 }
237 }
238
239 private static int getTestType(String makeFileName) {
240
241 int type = DEVICE_SIDE_ONLY;
242 try {
243 BufferedReader reader = new BufferedReader(new FileReader(makeFileName));
244 String line;
245
246 while ((line =reader.readLine())!=null) {
247 if (line.startsWith(TEST_TYPE)) {
248 type = HOST_SIDE_ONLY;
249 } else if (line.startsWith(JAR_PATH)) {
250 jarPath = line.substring(JAR_PATH.length(), line.length()).trim();
251 }
252 }
253 reader.close();
254 } catch (IOException e) {
255 }
256
257 return type;
258 }
259
260 private static Element getElement(Element element, String tagName) {
261 NodeList elements = element.getElementsByTagName(tagName);
262 if (elements.getLength() > 0) {
263 return (Element) elements.item(0);
264 } else {
265 return null;
266 }
267 }
268
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700269 private static String getElementAttribute(Element element,
270 String elementName,
271 String attributeName) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700272 Element e = getElement(element, elementName);
273 if (e != null) {
274 return e.getAttribute(attributeName);
275 } else {
276 return "";
277 }
278 }
279
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700280 private static String getKnownFailure(final Class<? extends TestCase> testClass,
Urs Grobfc77f6e2009-04-17 02:07:14 -0700281 final String testName) {
282 return getAnnotation(testClass, testName, KNOWN_FAILURE);
283 }
Brian Muramatsub8ed3162010-07-13 12:43:52 -0700284
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700285 private static boolean isKnownFailure(final Class<? extends TestCase> testClass,
Brian Muramatsub8ed3162010-07-13 12:43:52 -0700286 final String testName) {
287 return getAnnotation(testClass, testName, KNOWN_FAILURE) != null;
288 }
289
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700290 private static boolean isBrokenTest(final Class<? extends TestCase> testClass,
Urs Grobfc77f6e2009-04-17 02:07:14 -0700291 final String testName) {
292 return getAnnotation(testClass, testName, BROKEN_TEST) != null;
293 }
Brian Muramatsub8ed3162010-07-13 12:43:52 -0700294
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700295 private static boolean isSuppressed(final Class<? extends TestCase> testClass,
Brian Muramatsu168beb02010-10-21 12:39:45 -0700296 final String testName) {
297 return getAnnotation(testClass, testName, SUPPRESSED_TEST) != null;
298 }
299
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700300 private static boolean hasSideEffects(final Class<? extends TestCase> testClass,
Brian Muramatsu282c6fe2011-01-18 17:14:15 -0800301 final String testName) {
302 return getAnnotation(testClass, testName, SIDE_EFFECT) != null;
303 }
304
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700305 private static String getAnnotation(final Class<? extends TestCase> testClass,
Urs Grobfc77f6e2009-04-17 02:07:14 -0700306 final String testName, final String annotationName) {
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700307 try {
Urs Grobfc77f6e2009-04-17 02:07:14 -0700308 Method testMethod = testClass.getMethod(testName, (Class[])null);
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700309 Annotation[] annotations = testMethod.getAnnotations();
310 for (Annotation annot : annotations) {
311
Urs Grobfc77f6e2009-04-17 02:07:14 -0700312 if (annot.annotationType().getName().equals(annotationName)) {
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700313 String annotStr = annot.toString();
314 String knownFailure = null;
315 if (annotStr.contains("(value=")) {
316 knownFailure =
Urs Grobfc77f6e2009-04-17 02:07:14 -0700317 annotStr.substring(annotStr.indexOf("=") + 1,
318 annotStr.length() - 1);
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700319
320 }
321
322 if (knownFailure == null) {
323 knownFailure = "true";
324 }
325
326 return knownFailure;
327 }
328
329 }
330
The Android Open Source Project7671bec2009-03-19 23:08:36 -0700331 } catch (java.lang.NoSuchMethodException e) {
332 }
333
334 return null;
335 }
336
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700337 private static void addToTests(Class<? extends TestCase> test) {
338 Class testClass = test;
339 Set<String> testNames = new HashSet<String>();
340 while (TestCase.class.isAssignableFrom(testClass)) {
341 Method[] testMethods = testClass.getDeclaredMethods();
342 for (Method testMethod : testMethods) {
343 String testName = testMethod.getName();
344 if (testNames.contains(testName)) {
345 continue;
346 }
347 if (!testName.startsWith("test")) {
348 continue;
349 }
350 if (testMethod.getParameterTypes().length != 0) {
351 continue;
352 }
353 if (!testMethod.getReturnType().equals(Void.TYPE)) {
354 continue;
355 }
356 if (!Modifier.isPublic(testMethod.getModifiers())) {
357 continue;
358 }
359 testNames.add(testName);
360 addToTests(test, testName);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700361 }
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700362 testClass = testClass.getSuperclass();
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700363 }
Brian Carlstrom9f2dab82011-04-01 15:47:17 -0700364 }
365
366 private static void addToTests(Class<? extends TestCase> test, String testName) {
367
368 String testClassName = test.getName();
369 String knownFailure = getKnownFailure(test, testName);
370
371 if (isKnownFailure(test, testName)) {
372 System.out.println("ignoring known failure: " + test + "#" + testName);
373 return;
374 } else if (isBrokenTest(test, testName)) {
375 System.out.println("ignoring broken test: " + test + "#" + testName);
376 return;
377 } else if (isSuppressed(test, testName)) {
378 System.out.println("ignoring suppressed test: " + test + "#" + testName);
379 return;
380 } else if (hasSideEffects(test, testName)) {
381 System.out.println("ignoring test with side effects: " + test + "#" + testName);
382 return;
383 } else if (VogarUtils.isVogarKnownFailure(libcoreVogarExpectationStore,
384 testClassName,
385 testName)) {
386 System.out.println("ignoring libcore expectation known failure: " + test
387 + "#" + testName);
388 return;
389 } else if (VogarUtils.isVogarKnownFailure(ctsVogarExpectationStore,
390 testClassName,
391 testName)) {
392 System.out.println("ignoring cts expectation known failure: " + test
393 + "#" + testName);
394 return;
395 }
396
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700397 TestClass testClass = null;
398 if (testCases.containsKey(testClassName)) {
399 testClass = testCases.get(testClassName);
400 } else {
401 testClass = new TestClass(testClassName, new ArrayList<TestMethod>());
402 testCases.put(testClassName, testClass);
403 }
404
Brian Muramatsu168beb02010-10-21 12:39:45 -0700405 testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false, false));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700406 }
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700407}