blob: 09e11188914dacd0799f1897ae2858200fa5f9e3 [file] [log] [blame]
The Android Open Source Projectf8057102009-03-15 16:47:16 -07001/*
2 * Copyright (C) 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 */
16import java.io.BufferedWriter;
17import java.io.File;
18import java.io.FileNotFoundException;
19import java.io.FileOutputStream;
20import java.io.FileWriter;
21import java.io.IOException;
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.Iterator;
Stuart Scott01c2b492014-10-08 18:07:28 -070025import java.util.Set;
The Android Open Source Projectf8057102009-03-15 16:47:16 -070026
27import javax.xml.parsers.DocumentBuilderFactory;
28import javax.xml.parsers.ParserConfigurationException;
29import javax.xml.transform.Transformer;
30import javax.xml.transform.TransformerException;
31import javax.xml.transform.TransformerFactory;
32import javax.xml.transform.TransformerFactoryConfigurationError;
33import javax.xml.transform.dom.DOMSource;
34import javax.xml.transform.stream.StreamResult;
35
36import org.w3c.dom.Attr;
37import org.w3c.dom.Document;
38import org.w3c.dom.Node;
39import org.w3c.dom.NodeList;
40
Brian Muramatsu7f64e852011-02-17 16:52:16 -080041import vogar.ExpectationStore;
Stuart Scott01c2b492014-10-08 18:07:28 -070042import vogar.Expectation;
Brian Muramatsu7f64e852011-02-17 16:52:16 -080043
The Android Open Source Projectf8057102009-03-15 16:47:16 -070044import com.sun.javadoc.AnnotationDesc;
45import com.sun.javadoc.AnnotationTypeDoc;
46import com.sun.javadoc.AnnotationValue;
47import com.sun.javadoc.ClassDoc;
48import com.sun.javadoc.Doclet;
49import com.sun.javadoc.MethodDoc;
50import com.sun.javadoc.RootDoc;
51import com.sun.javadoc.AnnotationDesc.ElementValuePair;
52
53/**
54 * This is only a very simple and brief JavaDoc parser for the CTS.
55 *
56 * Input: The source files of the test cases. It will be represented
57 * as a list of ClassDoc
58 * Output: Generate file description.xml, which defines the TestPackage
59 * TestSuite and TestCases.
60 *
61 * Note:
62 * 1. Since this class has dependencies on com.sun.javadoc package which
63 * is not implemented on Android. So this class can't be compiled.
64 * 2. The TestSuite can be embedded, which means:
65 * TestPackage := TestSuite*
66 * TestSuite := TestSuite* | TestCase*
67 */
68public class DescriptionGenerator extends Doclet {
69 static final String HOST_CONTROLLER = "dalvik.annotation.HostController";
70 static final String KNOWN_FAILURE = "dalvik.annotation.KnownFailure";
Brian Muramatsu168beb02010-10-21 12:39:45 -070071 static final String SUPPRESSED_TEST = "android.test.suitebuilder.annotation.Suppress";
Brian Muramatsu7f64e852011-02-17 16:52:16 -080072 static final String CTS_EXPECTATION_DIR = "cts/tests/expectations";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070073
74 static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
75 static final String TAG_PACKAGE = "TestPackage";
76 static final String TAG_SUITE = "TestSuite";
77 static final String TAG_CASE = "TestCase";
78 static final String TAG_TEST = "Test";
79 static final String TAG_DESCRIPTION = "Description";
80
81 static final String ATTRIBUTE_NAME_VERSION = "version";
82 static final String ATTRIBUTE_VALUE_VERSION = "1.0";
83 static final String ATTRIBUTE_NAME_FRAMEWORK = "AndroidFramework";
84 static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";
85
86 static final String ATTRIBUTE_NAME = "name";
Stuart Scott01c2b492014-10-08 18:07:28 -070087 static final String ATTRIBUTE_ABIS = "abis";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070088 static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070089
90 static final String XML_OUTPUT_PATH = "./description.xml";
91
Phil Dubach0d6ef062009-08-12 18:13:16 -070092 static final String OUTPUT_PATH_OPTION = "-o";
Stuart Scott01c2b492014-10-08 18:07:28 -070093 static final String ARCHITECTURE_OPTION = "-a";
Phil Dubach0d6ef062009-08-12 18:13:16 -070094
The Android Open Source Projectf8057102009-03-15 16:47:16 -070095 /**
96 * Start to parse the classes passed in by javadoc, and generate
97 * the xml file needed by CTS packer.
98 *
99 * @param root The root document passed in by javadoc.
100 * @return Whether the document has been processed.
101 */
102 public static boolean start(RootDoc root) {
103 ClassDoc[] classes = root.classes();
104 if (classes == null) {
105 Log.e("No class found!", null);
106 return true;
107 }
108
Phil Dubach0d6ef062009-08-12 18:13:16 -0700109 String outputPath = XML_OUTPUT_PATH;
Stuart Scott01c2b492014-10-08 18:07:28 -0700110 String architecture = null;
Phil Dubach0d6ef062009-08-12 18:13:16 -0700111 String[][] options = root.options();
112 for (String[] option : options) {
Stuart Scott01c2b492014-10-08 18:07:28 -0700113 if (option.length == 2) {
114 if (option[0].equals(OUTPUT_PATH_OPTION)) {
115 outputPath = option[1];
116 } else if (option[0].equals(ARCHITECTURE_OPTION)) {
117 architecture = option[1];
118 }
Phil Dubach0d6ef062009-08-12 18:13:16 -0700119 }
120 }
Stuart Scott01c2b492014-10-08 18:07:28 -0700121 if (architecture == null || architecture.equals("")) {
122 Log.e("Missing architecture!", null);
123 return false;
124 }
Phil Dubach0d6ef062009-08-12 18:13:16 -0700125
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700126 XMLGenerator xmlGenerator = null;
127 try {
Phil Dubach0d6ef062009-08-12 18:13:16 -0700128 xmlGenerator = new XMLGenerator(outputPath);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700129 } catch (ParserConfigurationException e) {
130 Log.e("Cant initialize XML Generator!", e);
131 return true;
132 }
133
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800134 ExpectationStore ctsExpectationStore = null;
135 try {
136 ctsExpectationStore = VogarUtils.provideExpectationStore("./" + CTS_EXPECTATION_DIR);
137 } catch (IOException e) {
138 Log.e("Couldn't load expectation store.", e);
139 return false;
140 }
141
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700142 for (ClassDoc clazz : classes) {
143 if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
Stuart Scott01c2b492014-10-08 18:07:28 -0700144 xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore, architecture));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700145 }
146 }
147
148 try {
149 xmlGenerator.dump();
150 } catch (Exception e) {
151 Log.e("Can't dump to XML file!", e);
152 }
153
154 return true;
155 }
156
157 /**
Phil Dubach0d6ef062009-08-12 18:13:16 -0700158 * Return the length of any doclet options we recognize
159 * @param option The option name
160 * @return The number of words this option takes (including the option) or 0 if the option
161 * is not recognized.
162 */
163 public static int optionLength(String option) {
164 if (option.equals(OUTPUT_PATH_OPTION)) {
165 return 2;
166 }
167 return 0;
168 }
169
170 /**
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700171 * Check if the class is valid test case inherited from JUnit TestCase.
172 *
173 * @param clazz The class to be checked.
174 * @return If the class is valid test case inherited from JUnit TestCase, return true;
175 * else, return false.
176 */
177 static boolean isValidJUnitTestCase(ClassDoc clazz) {
178 while((clazz = clazz.superclass()) != null) {
179 if (JUNIT_TEST_CASE_CLASS_NAME.equals(clazz.qualifiedName().toLowerCase())) {
180 return true;
181 }
182 }
183
184 return false;
185 }
186
187 /**
188 * Log utility.
189 */
190 static class Log {
191 private static boolean TRACE = true;
192 private static BufferedWriter mTraceOutput = null;
193
194 /**
195 * Log the specified message.
196 *
197 * @param msg The message to be logged.
198 */
199 static void e(String msg, Exception e) {
200 System.out.println(msg);
201
202 if (e != null) {
203 e.printStackTrace();
204 }
205 }
206
207 /**
208 * Add the message to the trace stream.
209 *
210 * @param msg The message to be added to the trace stream.
211 */
212 public static void t(String msg) {
213 if (TRACE) {
214 try {
215 if ((mTraceOutput != null) && (msg != null)) {
216 mTraceOutput.write(msg + "\n");
217 mTraceOutput.flush();
218 }
219 } catch (IOException e) {
220 e.printStackTrace();
221 }
222 }
223 }
224
225 /**
226 * Initialize the trace stream.
227 *
228 * @param name The class name.
229 */
230 public static void initTrace(String name) {
231 if (TRACE) {
232 try {
233 if (mTraceOutput == null) {
234 String fileName = "cts_debug_dg_" + name + ".txt";
235 mTraceOutput = new BufferedWriter(new FileWriter(fileName));
236 }
237 } catch (IOException e) {
238 e.printStackTrace();
239 }
240 }
241 }
242
243 /**
244 * Close the trace stream.
245 */
246 public static void closeTrace() {
247 if (mTraceOutput != null) {
248 try {
249 mTraceOutput.close();
250 mTraceOutput = null;
251 } catch (IOException e) {
252 e.printStackTrace();
253 }
254 }
255 }
256 }
257
258 static class XMLGenerator {
259 String mOutputPath;
260
261 /**
262 * This document is used to represent the description XML file.
263 * It is construct by the classes passed in, which contains the
264 * information of all the test package, test suite and test cases.
265 */
266 Document mDoc;
267
268 XMLGenerator(String outputPath) throws ParserConfigurationException {
269 mOutputPath = outputPath;
270
271 mDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
272
273 Node testPackageElem = mDoc.appendChild(mDoc.createElement(TAG_PACKAGE));
274
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700275 setAttribute(testPackageElem, ATTRIBUTE_NAME_VERSION, ATTRIBUTE_VALUE_VERSION);
276 setAttribute(testPackageElem, ATTRIBUTE_NAME_FRAMEWORK, ATTRIBUTE_VALUE_FRAMEWORK);
277 }
278
279 void addTestClass(TestClass tc) {
280 appendSuiteToElement(mDoc.getDocumentElement(), tc);
281 }
282
283 void dump() throws TransformerFactoryConfigurationError,
284 FileNotFoundException, TransformerException {
285 //rebuildDocument();
286
287 Transformer t = TransformerFactory.newInstance().newTransformer();
288
289 // enable indent in result file
290 t.setOutputProperty("indent", "yes");
291 t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");
292
Jorg Pleumann86192702009-04-21 10:08:53 -0700293 File file = new File(mOutputPath);
294 file.getParentFile().mkdirs();
Scott Su259ced72009-04-30 17:05:49 -0700295
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700296 t.transform(new DOMSource(mDoc),
Jorg Pleumann86192702009-04-21 10:08:53 -0700297 new StreamResult(new FileOutputStream(file)));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700298 }
299
300 /**
301 * Rebuild the document, merging empty suite nodes.
302 */
303 void rebuildDocument() {
304 // merge empty suite nodes
305 Collection<Node> suiteElems = getUnmutableChildNodes(mDoc.getDocumentElement());
306 Iterator<Node> suiteIterator = suiteElems.iterator();
307 while (suiteIterator.hasNext()) {
308 Node suiteElem = suiteIterator.next();
309
310 mergeEmptySuites(suiteElem);
311 }
312 }
313
314 /**
315 * Merge the test suite which only has one sub-suite. In this case, unify
316 * the name of the two test suites.
317 *
318 * @param suiteElem The suite element of which to be merged.
319 */
320 void mergeEmptySuites(Node suiteElem) {
321 Collection<Node> suiteChildren = getSuiteChildren(suiteElem);
322 if (suiteChildren.size() > 1) {
323 for (Node suiteChild : suiteChildren) {
324 mergeEmptySuites(suiteChild);
325 }
326 } else if (suiteChildren.size() == 1) {
327 // do merge
328 Node child = suiteChildren.iterator().next();
329
330 // update name
331 String newName = getAttribute(suiteElem, ATTRIBUTE_NAME) + "."
332 + getAttribute(child, ATTRIBUTE_NAME);
333 setAttribute(child, ATTRIBUTE_NAME, newName);
334
335 // update parent node
336 Node parentNode = suiteElem.getParentNode();
337 parentNode.removeChild(suiteElem);
338 parentNode.appendChild(child);
339
340 mergeEmptySuites(child);
341 }
342 }
343
344 /**
345 * Get the unmuatable child nodes for specified node.
346 *
347 * @param node The specified node.
348 * @return A collection of copied child node.
349 */
350 private Collection<Node> getUnmutableChildNodes(Node node) {
351 ArrayList<Node> nodes = new ArrayList<Node>();
352 NodeList nodelist = node.getChildNodes();
353
354 for (int i = 0; i < nodelist.getLength(); i++) {
355 nodes.add(nodelist.item(i));
356 }
357
358 return nodes;
359 }
360
361 /**
362 * Append a named test suite to a specified element. Including match with
363 * the existing suite nodes and do the real creation and append.
364 *
365 * @param elem The specified element.
366 * @param testSuite The test suite to be appended.
367 */
368 void appendSuiteToElement(Node elem, TestClass testSuite) {
369 String suiteName = testSuite.mName;
370 Collection<Node> children = getSuiteChildren(elem);
371 int dotIndex = suiteName.indexOf('.');
372 String name = dotIndex == -1 ? suiteName : suiteName.substring(0, dotIndex);
373
374 boolean foundMatch = false;
375 for (Node child : children) {
376 String childName = child.getAttributes().getNamedItem(ATTRIBUTE_NAME)
377 .getNodeValue();
378
379 if (childName.equals(name)) {
380 foundMatch = true;
381 if (dotIndex == -1) {
382 appendTestCases(child, testSuite.mCases);
383 } else {
384 testSuite.mName = suiteName.substring(dotIndex + 1, suiteName.length());
385 appendSuiteToElement(child, testSuite);
386 }
387 }
388
389 }
390
391 if (!foundMatch) {
392 appendSuiteToElementImpl(elem, testSuite);
393 }
394 }
395
396 /**
397 * Get the test suite child nodes of a specified element.
398 *
399 * @param elem The specified element node.
400 * @return The matched child nodes.
401 */
402 Collection<Node> getSuiteChildren(Node elem) {
403 ArrayList<Node> suites = new ArrayList<Node>();
404
405 NodeList children = elem.getChildNodes();
406 for (int i = 0; i < children.getLength(); i++) {
407 Node child = children.item(i);
408
409 if (child.getNodeName().equals(DescriptionGenerator.TAG_SUITE)) {
410 suites.add(child);
411 }
412 }
413
414 return suites;
415 }
416
417 /**
418 * Create test case node according to the given method names, and append them
419 * to the test suite element.
420 *
421 * @param elem The test suite element.
422 * @param cases A collection of test cases included by the test suite class.
423 */
424 void appendTestCases(Node elem, Collection<TestMethod> cases) {
425 if (cases.isEmpty()) {
426 // if no method, remove from parent
427 elem.getParentNode().removeChild(elem);
428 } else {
429 for (TestMethod caze : cases) {
Brian Muramatsu168beb02010-10-21 12:39:45 -0700430 if (caze.mIsBroken || caze.mIsSuppressed || caze.mKnownFailure != null) {
Scott Su259ced72009-04-30 17:05:49 -0700431 continue;
432 }
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700433 Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));
434
Phil Dubachdc4e1792009-05-05 14:01:34 -0700435 setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
Stuart Scott01c2b492014-10-08 18:07:28 -0700436 String abis = caze.mAbis.toString();
437 setAttribute(caseNode, ATTRIBUTE_ABIS, abis.substring(1, abis.length() - 1));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700438 if ((caze.mController != null) && (caze.mController.length() != 0)) {
439 setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
440 }
441
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700442 if (caze.mDescription != null && !caze.mDescription.equals("")) {
443 caseNode.appendChild(mDoc.createElement(TAG_DESCRIPTION))
444 .setTextContent(caze.mDescription);
445 }
446 }
447 }
448 }
449
450 /**
451 * Set the attribute of element.
452 *
453 * @param elem The element to be set attribute.
454 * @param name The attribute name.
455 * @param value The attribute value.
456 */
457 protected void setAttribute(Node elem, String name, String value) {
458 Attr attr = mDoc.createAttribute(name);
459 attr.setNodeValue(value);
460
461 elem.getAttributes().setNamedItem(attr);
462 }
463
464 /**
465 * Get the value of a specified attribute of an element.
466 *
467 * @param elem The element node.
468 * @param name The attribute name.
469 * @return The value of the specified attribute.
470 */
471 private String getAttribute(Node elem, String name) {
472 return elem.getAttributes().getNamedItem(name).getNodeValue();
473 }
474
475 /**
476 * Do the append, including creating test suite nodes and test case nodes, and
477 * append them to the element.
478 *
479 * @param elem The specified element node.
480 * @param testSuite The test suite to be append.
481 */
482 void appendSuiteToElementImpl(Node elem, TestClass testSuite) {
483 Node parent = elem;
484 String suiteName = testSuite.mName;
485
486 int dotIndex;
487 while ((dotIndex = suiteName.indexOf('.')) != -1) {
488 String name = suiteName.substring(0, dotIndex);
489
490 Node suiteElem = parent.appendChild(mDoc.createElement(TAG_SUITE));
491 setAttribute(suiteElem, ATTRIBUTE_NAME, name);
492
493 parent = suiteElem;
494 suiteName = suiteName.substring(dotIndex + 1, suiteName.length());
495 }
496
497 Node leafSuiteElem = parent.appendChild(mDoc.createElement(TAG_CASE));
498 setAttribute(leafSuiteElem, ATTRIBUTE_NAME, suiteName);
499
500 appendTestCases(leafSuiteElem, testSuite.mCases);
501 }
502 }
503
504 /**
505 * Represent the test class.
506 */
507 static class TestClass {
508 String mName;
509 Collection<TestMethod> mCases;
510
511 /**
512 * Construct an test suite object.
513 *
514 * @param name Full name of the test suite, such as "com.google.android.Foo"
515 * @param cases The test cases included in this test suite.
516 */
517 TestClass(String name, Collection<TestMethod> cases) {
518 mName = name;
519 mCases = cases;
520 }
521
522 /**
523 * Construct a TestClass object using ClassDoc.
524 *
525 * @param clazz The specified ClassDoc.
526 */
Stuart Scott01c2b492014-10-08 18:07:28 -0700527 TestClass(ClassDoc clazz, ExpectationStore expectationStore, String architecture) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700528 mName = clazz.toString();
Stuart Scott01c2b492014-10-08 18:07:28 -0700529 mCases = getTestMethods(expectationStore, architecture, clazz);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700530 }
531
532 /**
533 * Get all the TestMethod from a ClassDoc, including inherited methods.
534 *
535 * @param clazz The specified ClassDoc.
536 * @return A collection of TestMethod.
537 */
Stuart Scott01c2b492014-10-08 18:07:28 -0700538 Collection<TestMethod> getTestMethods(ExpectationStore expectationStore,
539 String architecture, ClassDoc clazz) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700540 Collection<MethodDoc> methods = getAllMethods(clazz);
541
542 ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
543 Iterator<MethodDoc> iterator = methods.iterator();
544
545 while (iterator.hasNext()) {
546 MethodDoc method = iterator.next();
547
548 String name = method.name();
549
550 AnnotationDesc[] annotations = method.annotations();
551 String controller = "";
552 String knownFailure = null;
Scott Su259ced72009-04-30 17:05:49 -0700553 boolean isBroken = false;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700554 boolean isSuppressed = false;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700555 for (AnnotationDesc cAnnot : annotations) {
556
557 AnnotationTypeDoc atype = cAnnot.annotationType();
558 if (atype.toString().equals(HOST_CONTROLLER)) {
559 controller = getAnnotationDescription(cAnnot);
560 } else if (atype.toString().equals(KNOWN_FAILURE)) {
561 knownFailure = getAnnotationDescription(cAnnot);
Brian Muramatsu168beb02010-10-21 12:39:45 -0700562 } else if (atype.toString().equals(SUPPRESSED_TEST)) {
563 isSuppressed = true;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700564 }
565 }
566
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800567 if (VogarUtils.isVogarKnownFailure(expectationStore, clazz.toString(), name)) {
568 isBroken = true;
569 }
570
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700571 if (name.startsWith("test")) {
Stuart Scott01c2b492014-10-08 18:07:28 -0700572 Expectation expectation = expectationStore.get(
573 VogarUtils.buildFullTestName(clazz.toString(), name));
574 Set<String> supportedAbis =
575 VogarUtils.extractSupportedAbis(architecture, expectation);
576 cases.add(new TestMethod(
577 name, method.commentText(), controller, supportedAbis,
578 knownFailure, isBroken, isSuppressed));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700579 }
580 }
581
582 return cases;
583 }
584
585 /**
586 * Get annotation description.
587 *
588 * @param cAnnot The annotation.
589 */
590 String getAnnotationDescription(AnnotationDesc cAnnot) {
591 ElementValuePair[] cpairs = cAnnot.elementValues();
592 ElementValuePair evp = cpairs[0];
593 AnnotationValue av = evp.value();
594 String description = av.toString();
595 // FIXME: need to find out the reason why there are leading and trailing "
596 description = description.substring(1, description.length() -1);
597 return description;
598 }
599
600 /**
601 * Get all MethodDoc of a ClassDoc, including inherited methods.
602 *
603 * @param clazz The specified ClassDoc.
604 * @return A collection of MethodDoc.
605 */
606 Collection<MethodDoc> getAllMethods(ClassDoc clazz) {
607 ArrayList<MethodDoc> methods = new ArrayList<MethodDoc>();
608
609 for (MethodDoc method : clazz.methods()) {
610 methods.add(method);
611 }
612
613 ClassDoc superClass = clazz.superclass();
614 while (superClass != null) {
615 for (MethodDoc method : superClass.methods()) {
616 methods.add(method);
617 }
618
619 superClass = superClass.superclass();
620 }
621
622 return methods;
623 }
624
625 }
626
627 /**
628 * Represent the test method inside the test class.
629 */
630 static class TestMethod {
631 String mName;
632 String mDescription;
633 String mController;
Stuart Scott01c2b492014-10-08 18:07:28 -0700634 Set<String> mAbis;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700635 String mKnownFailure;
Scott Su259ced72009-04-30 17:05:49 -0700636 boolean mIsBroken;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700637 boolean mIsSuppressed;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700638
639 /**
640 * Construct an test case object.
641 *
642 * @param name The name of the test case.
643 * @param description The description of the test case.
644 * @param knownFailure The reason of known failure.
645 */
Stuart Scott01c2b492014-10-08 18:07:28 -0700646 TestMethod(String name, String description, String controller, Set<String> abis,
647 String knownFailure, boolean isBroken, boolean isSuppressed) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700648 mName = name;
649 mDescription = description;
650 mController = controller;
Stuart Scott01c2b492014-10-08 18:07:28 -0700651 mAbis = abis;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700652 mKnownFailure = knownFailure;
Scott Su259ced72009-04-30 17:05:49 -0700653 mIsBroken = isBroken;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700654 mIsSuppressed = isSuppressed;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700655 }
656 }
657}