1 /*
2  * Copyright (C) 2011 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 package com.android.cts.javascannerdoclet;
17 
18 import java.io.BufferedWriter;
19 import java.io.File;
20 import java.io.FileNotFoundException;
21 import java.io.FileOutputStream;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.io.PrintWriter;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Iterator;
29 
30 import javax.xml.parsers.DocumentBuilderFactory;
31 import javax.xml.parsers.ParserConfigurationException;
32 import javax.xml.transform.Transformer;
33 import javax.xml.transform.TransformerException;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.TransformerFactoryConfigurationError;
36 import javax.xml.transform.dom.DOMSource;
37 import javax.xml.transform.stream.StreamResult;
38 
39 import org.w3c.dom.Attr;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Node;
42 import org.w3c.dom.NodeList;
43 
44 import com.sun.javadoc.AnnotationDesc;
45 import com.sun.javadoc.AnnotationTypeDoc;
46 import com.sun.javadoc.AnnotationValue;
47 import com.sun.javadoc.ClassDoc;
48 import com.sun.javadoc.Doclet;
49 import com.sun.javadoc.MethodDoc;
50 import com.sun.javadoc.RootDoc;
51 import com.sun.javadoc.AnnotationDesc.ElementValuePair;
52 import com.sun.javadoc.AnnotationTypeElementDoc;
53 
54 /**
55  * Doclet that outputs in the following format:
56  *
57  * suite:android.holo.cts
58  * case:HoloTest
59  * test:testHolo
60  * test:testHoloDialog[:timeout_value]
61  */
62 public class CtsJavaScannerDoclet extends Doclet {
63 
64     private static final String JUNIT4_TEST_ANNOTATION = "org.junit.Test";
65 
66     static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
67 
start(RootDoc root)68     public static boolean start(RootDoc root) {
69         ClassDoc[] classes = root.classes();
70         if (classes == null) {
71             return false;
72         }
73 
74         PrintWriter writer = new PrintWriter(System.out);
75 
76         for (ClassDoc clazz : classes) {
77             if (clazz.isAbstract()) {
78                 continue;
79             }
80 
81             final boolean isJUnit3 = isJUnit3TestCase(clazz);
82             if (!isJUnit3 && !isJUnit4TestClass(clazz)) {
83                 continue;
84             }
85 
86             writer.append("suite:").println(clazz.containingPackage().name());
87             writer.append("case:").println(clazz.name());
88             for (; clazz != null; clazz = clazz.superclass()) {
89                 for (MethodDoc method : clazz.methods()) {
90                     int timeout = -1;
91                     if (isJUnit3) {
92                         if (!method.name().startsWith("test")) {
93                             continue;
94                         }
95 
96                         AnnotationDesc[] annotations = method.annotations();
97                         for (AnnotationDesc annot : annotations) {
98                             String atype = annot.annotationType().toString();
99                             if (atype.equals("com.android.cts.util.TimeoutReq")) {
100                                 ElementValuePair[] cpairs = annot.elementValues();
101                                 for (ElementValuePair pair : cpairs) {
102                                     AnnotationTypeElementDoc elem = pair.element();
103                                     AnnotationValue value = pair.value();
104                                     if (elem.name().equals("minutes")) {
105                                         timeout = ((Integer) value.value());
106                                     }
107                                 }
108                             }
109                         }
110                     } else {
111                         /* JUnit4 */
112                         boolean isTest = false;
113 
114                         for (AnnotationDesc annot : method.annotations()) {
115                             if (annot.annotationType().toString().equals(JUNIT4_TEST_ANNOTATION)) {
116                                 isTest = true;
117 
118                                 for (ElementValuePair pair : annot.elementValues()) {
119                                     if (pair.element().name().equals("timeout")) {
120                                         /* JUnit4 timeouts are in milliseconds. */
121                                         timeout = (int) (((Long) pair.value().value()) / 60000L);
122                                     }
123                                 }
124                             }
125                         }
126 
127                         if (!isTest) {
128                             continue;
129                         }
130                     }
131 
132                     writer.append("test:");
133                     if (timeout >= 0) {
134                         writer.append(method.name()).println(":" + timeout);
135                     } else {
136                         writer.println(method.name());
137                     }
138                 }
139             }
140         }
141 
142         writer.close();
143         return true;
144     }
145 
isJUnit3TestCase(ClassDoc clazz)146     private static boolean isJUnit3TestCase(ClassDoc clazz) {
147         while((clazz = clazz.superclass()) != null) {
148             if (JUNIT_TEST_CASE_CLASS_NAME.equals(clazz.qualifiedName().toLowerCase())) {
149                 return true;
150             }
151         }
152         return false;
153     }
154 
isJUnit4TestClass(ClassDoc clazz)155     private static boolean isJUnit4TestClass(ClassDoc clazz) {
156         for (MethodDoc method : clazz.methods()) {
157             for (AnnotationDesc annot : method.annotations()) {
158                 if (annot.annotationType().toString().equals(JUNIT4_TEST_ANNOTATION)) {
159                     return true;
160                 }
161             }
162         }
163         return false;
164     }
165 }
166