• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.tradefed.testtype;
17 
18 import com.android.cts.util.AbiUtils;
19 import com.android.ddmlib.Log;
20 import com.android.ddmlib.testrunner.TestIdentifier;
21 import com.android.tradefed.util.xml.AbstractXmlParser;
22 
23 import org.xml.sax.Attributes;
24 import org.xml.sax.helpers.DefaultHandler;
25 
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.Stack;
32 
33 /**
34  * Parser for CTS test case XML.
35  * <p/>
36  * Dumb parser that just retrieves data from in the test case xml and stuff it into a
37  * {@link TestPackageDef}. Currently performs limited error checking.
38  */
39 public class TestPackageXmlParser extends AbstractXmlParser {
40 
41     private static final String LOG_TAG = "TestPackageXmlParser";
42 
43     private final boolean mIncludeKnownFailures;
44 
45     private Map<String, TestPackageDef> mPackageDefs = new HashMap<String, TestPackageDef>();
46 
47     /**
48      * @param includeKnownFailures Whether to run tests which are known to fail.
49      */
TestPackageXmlParser(boolean includeKnownFailures)50     public TestPackageXmlParser(boolean includeKnownFailures) {
51         mIncludeKnownFailures = includeKnownFailures;
52     }
53 
54     /**
55      * SAX callback object. Handles parsing data from the xml tags.
56      * <p/>
57      * Expected structure:
58      * <TestPackage>
59      *     <TestSuite ...>
60      *        <TestCase>
61      *           <Test>
62      */
63     private class TestPackageHandler extends DefaultHandler {
64 
65         private static final String TEST_PACKAGE_TAG = "TestPackage";
66         private static final String TEST_SUITE_TAG = "TestSuite";
67         private static final String TEST_CASE_TAG = "TestCase";
68         private static final String TEST_TAG = "Test";
69 
70         // holds current class name segments
71         private Stack<String> mClassNameStack = new Stack<String>();
72 
73         @Override
startElement(String uri, String localName, String name, Attributes attributes)74         public void startElement(String uri, String localName, String name, Attributes attributes) {
75             if (TEST_PACKAGE_TAG.equals(localName)) {
76                 final String appPackageName = attributes.getValue("appPackageName");
77                 final String testPackageNameSpace = attributes.getValue("appNameSpace");
78                 final String packageName = attributes.getValue("name");
79                 final String runnerName = attributes.getValue("runner");
80                 final String jarPath = attributes.getValue("jarPath");
81                 final String javaPackageFilter = attributes.getValue("javaPackageFilter");
82                 final String targetBinaryName = attributes.getValue("targetBinaryName");
83                 final String targetNameSpace = attributes.getValue("targetNameSpace");
84                 final String runTimeArgs = attributes.getValue("runtimeArgs");
85                 final String testType = getTestType(attributes);
86 
87                 for (String abiName : AbiUtils.getAbisSupportedByCts()) {
88                     Abi abi = new Abi(abiName, AbiUtils.getBitness(abiName));
89                     TestPackageDef packageDef = new TestPackageDef();
90                     packageDef.setAppPackageName(appPackageName);
91                     packageDef.setAppNameSpace(testPackageNameSpace);
92                     packageDef.setName(packageName);
93                     packageDef.setRunner(runnerName);
94                     packageDef.setTestType(testType);
95                     packageDef.setJarPath(jarPath);
96                     packageDef.setRunTimeArgs(runTimeArgs);
97                     if (!"".equals(javaPackageFilter)) {
98                         packageDef.setTestPackageName(javaPackageFilter);
99                     }
100                     packageDef.setTargetBinaryName(targetBinaryName);
101                     packageDef.setTargetNameSpace(targetNameSpace);
102                     packageDef.setAbi(abi);
103                     mPackageDefs.put(abiName, packageDef);
104                 }
105 
106                 // reset the class name
107                 mClassNameStack = new Stack<String>();
108             } else if (TEST_SUITE_TAG.equals(localName)) {
109                 String packageSegment = attributes.getValue("name");
110                 if (packageSegment != null) {
111                     mClassNameStack.push(packageSegment);
112                 } else {
113                     Log.e(LOG_TAG, String.format("Invalid XML: missing 'name' attribute for '%s'",
114                             TEST_SUITE_TAG));
115                 }
116             } else if (TEST_CASE_TAG.equals(localName)) {
117                 String classSegment = attributes.getValue("name");
118                 if (classSegment != null) {
119                     mClassNameStack.push(classSegment);
120                 } else {
121                     Log.e(LOG_TAG, String.format("Invalid XML: missing 'name' attribute for '%s'",
122                             TEST_CASE_TAG));
123                 }
124             } else if (TEST_TAG.equals(localName)) {
125                 String methodName = attributes.getValue("name");
126                 if (mPackageDefs.isEmpty()) {
127                     Log.e(LOG_TAG, String.format(
128                             "Invalid XML: encountered a '%s' tag not enclosed within a '%s' tag",
129                             TEST_TAG, TEST_PACKAGE_TAG));
130                 } else if (methodName == null) {
131                     Log.e(LOG_TAG, String.format("Invalid XML: missing 'name' attribute for '%s'",
132                             TEST_TAG));
133                 } else {
134                     // build class name from package segments
135                     StringBuilder classNameBuilder = new StringBuilder();
136                     for (Iterator<String> iter = mClassNameStack.iterator(); iter.hasNext(); ) {
137                         classNameBuilder.append(iter.next());
138                         if (iter.hasNext()) {
139                             classNameBuilder.append(".");
140                         }
141                     }
142                     int timeout = -1;
143                     String timeoutStr = attributes.getValue("timeout");
144                     if (timeoutStr != null) {
145                         timeout = Integer.parseInt(timeoutStr);
146                     }
147                     boolean isKnownFailure = "failure".equals(attributes.getValue("expectation"));
148                     if (!isKnownFailure || mIncludeKnownFailures) {
149                         String abiList = attributes.getValue("abis");
150                         Set<String> abis = new HashSet<String>();
151                         if (abiList == null) {
152                             // If no specification, add all supported abis
153                             abis.addAll(AbiUtils.getAbisSupportedByCts());
154                         } else {
155                             for (String abi : abiList.split(",")) {
156                                 // Else only add the abi which are supported
157                                 abis.add(abi.trim());
158                             }
159                         }
160                         for (String abi : abis) {
161                             TestIdentifier testId = new TestIdentifier(
162                                     classNameBuilder.toString(), methodName);
163                             mPackageDefs.get(abi).addTest(testId, timeout);
164                         }
165                     }
166                 }
167             }
168 
169         }
170 
getTestType(Attributes attributes)171         private String getTestType(Attributes attributes) {
172             if (parseBoolean(attributes.getValue("hostSideOnly"))) {
173                 return TestPackageDef.HOST_SIDE_ONLY_TEST;
174             } else if (parseBoolean(attributes.getValue("vmHostTest"))) {
175                 return TestPackageDef.VM_HOST_TEST;
176             } else {
177                 return attributes.getValue("testType");
178             }
179         }
180 
181         @Override
endElement(String uri, String localName, String qName)182         public void endElement (String uri, String localName, String qName) {
183             if (TEST_SUITE_TAG.equals(localName) || TEST_CASE_TAG.equals(localName)) {
184                 mClassNameStack.pop();
185             }
186         }
187 
188         /**
189          * Parse a boolean attribute value
190          */
parseBoolean(final String stringValue)191         private boolean parseBoolean(final String stringValue) {
192             return stringValue != null &&
193                     Boolean.parseBoolean(stringValue);
194         }
195     }
196 
197     @Override
createXmlHandler()198     protected DefaultHandler createXmlHandler() {
199         return new TestPackageHandler();
200     }
201 
202     /**
203      * @return the set of {@link TestPackageDef} containing data parsed from xml
204      */
getTestPackageDefs()205     public Set<TestPackageDef> getTestPackageDefs() {
206         return new HashSet<>(mPackageDefs.values());
207     }
208 }
209