• 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.ddmlib.Log;
19 import com.android.ddmlib.testrunner.TestIdentifier;
20 import com.android.tradefed.util.xml.AbstractXmlParser;
21 
22 import org.xml.sax.Attributes;
23 import org.xml.sax.helpers.DefaultHandler;
24 
25 import java.util.Iterator;
26 import java.util.Stack;
27 
28 /**
29  * Parser for CTS test case XML.
30  * <p/>
31  * Dumb parser that just retrieves data from in the test case xml and stuff it into a
32  * {@link TestPackageDef}. Currently performs limited error checking.
33  */
34 public class TestPackageXmlParser extends AbstractXmlParser {
35 
36     private static final String LOG_TAG = "TestPackageXmlParser";
37 
38     private final boolean mIncludeKnownFailures;
39 
40     private TestPackageDef mPackageDef;
41 
TestPackageXmlParser(boolean includeKnownFailures)42     public TestPackageXmlParser(boolean includeKnownFailures) {
43         mIncludeKnownFailures = includeKnownFailures;
44     }
45 
46     /**
47      * SAX callback object. Handles parsing data from the xml tags.
48      * <p/>
49      * Expected structure:
50      * <TestPackage>
51      *     <TestSuite ...>
52      *        <TestCase>
53      *           <Test>
54      */
55     private class TestPackageHandler extends DefaultHandler {
56 
57         private static final String TEST_PACKAGE_TAG = "TestPackage";
58         private static final String TEST_SUITE_TAG = "TestSuite";
59         private static final String TEST_CASE_TAG = "TestCase";
60         private static final String TEST_TAG = "Test";
61 
62         // holds current class name segments
63         private Stack<String> mClassNameStack = new Stack<String>();
64 
65         @Override
startElement(String uri, String localName, String name, Attributes attributes)66         public void startElement(String uri, String localName, String name, Attributes attributes) {
67             if (TEST_PACKAGE_TAG.equals(localName)) {
68                 // appPackageName is used as the uri
69                 final String entryUriValue = attributes.getValue("appPackageName");
70                 final String testPackageNameSpace = attributes.getValue("appNameSpace");
71                 final String packageName = attributes.getValue("name");
72                 final String runnerName = attributes.getValue("runner");
73                 final String jarPath = attributes.getValue("jarPath");
74                 final String signatureCheck = attributes.getValue("signatureCheck");
75                 final String javaPackageFilter = attributes.getValue("javaPackageFilter");
76                 final String targetBinaryName = attributes.getValue("targetBinaryName");
77                 final String targetNameSpace = attributes.getValue("targetNameSpace");
78 
79                 mPackageDef = new TestPackageDef();
80                 mPackageDef.setUri(entryUriValue);
81                 mPackageDef.setAppNameSpace(testPackageNameSpace);
82                 mPackageDef.setName(packageName);
83                 mPackageDef.setRunner(runnerName);
84                 mPackageDef.setTestType(getTestType(attributes));
85                 mPackageDef.setJarPath(jarPath);
86                 mPackageDef.setIsSignatureCheck(parseBoolean(signatureCheck));
87                 mPackageDef.setTestPackageName(javaPackageFilter);
88                 mPackageDef.setTargetBinaryName(targetBinaryName);
89                 mPackageDef.setTargetNameSpace(targetNameSpace);
90 
91                 // reset the class name
92                 mClassNameStack = new Stack<String>();
93             } else if (TEST_SUITE_TAG.equals(localName)) {
94                 String packageSegment = attributes.getValue("name");
95                 if (packageSegment != null) {
96                     mClassNameStack.push(packageSegment);
97                 } else {
98                     Log.e(LOG_TAG, String.format("Invalid XML: missing 'name' attribute for '%s'",
99                             TEST_SUITE_TAG));
100                 }
101             } else if (TEST_CASE_TAG.equals(localName)) {
102                 String classSegment = attributes.getValue("name");
103                 if (classSegment != null) {
104                     mClassNameStack.push(classSegment);
105                 } else {
106                     Log.e(LOG_TAG, String.format("Invalid XML: missing 'name' attribute for '%s'",
107                             TEST_CASE_TAG));
108                 }
109             } else if (TEST_TAG.equals(localName)) {
110                 String methodName = attributes.getValue("name");
111                 if (mPackageDef == null) {
112                     Log.e(LOG_TAG, String.format(
113                             "Invalid XML: encountered a '%s' tag not enclosed within a '%s' tag",
114                             TEST_TAG, TEST_PACKAGE_TAG));
115                 } else if (methodName == null) {
116                     Log.e(LOG_TAG, String.format("Invalid XML: missing 'name' attribute for '%s'",
117                             TEST_TAG));
118                 } else {
119                     // build class name from package segments
120                     StringBuilder classNameBuilder = new StringBuilder();
121                     for (Iterator<String> iter = mClassNameStack.iterator(); iter.hasNext(); ) {
122                         classNameBuilder.append(iter.next());
123                         if (iter.hasNext()) {
124                             classNameBuilder.append(".");
125                         }
126                     }
127 
128                     TestIdentifier testId = new TestIdentifier(classNameBuilder.toString(),
129                             methodName);
130                     boolean isKnownFailure = "failure".equals(attributes.getValue("expectation"));
131                     if (!isKnownFailure || mIncludeKnownFailures) {
132                         mPackageDef.addTest(testId);
133                     }
134                 }
135             }
136 
137         }
138 
getTestType(Attributes attributes)139         private String getTestType(Attributes attributes) {
140             if (parseBoolean(attributes.getValue("hostSideOnly"))) {
141                 return TestPackageDef.HOST_SIDE_ONLY_TEST;
142             } else if (parseBoolean(attributes.getValue("vmHostTest"))) {
143                 return TestPackageDef.VM_HOST_TEST;
144             } else {
145                 return attributes.getValue("testType");
146             }
147         }
148 
149         @Override
endElement(String uri, String localName, String qName)150         public void endElement (String uri, String localName, String qName) {
151             if (TEST_SUITE_TAG.equals(localName) || TEST_CASE_TAG.equals(localName)) {
152                 mClassNameStack.pop();
153             }
154         }
155 
156         /**
157          * Parse a boolean attribute value
158          */
parseBoolean(final String stringValue)159         private boolean parseBoolean(final String stringValue) {
160             return stringValue != null &&
161                     Boolean.parseBoolean(stringValue);
162         }
163     }
164 
165     /**
166      * {@inheritDoc}
167      */
168     @Override
createXmlHandler()169     protected DefaultHandler createXmlHandler() {
170         return new TestPackageHandler();
171     }
172 
173     /**
174      * @returns the {@link TestPackageDef} containing data parsed from xml or <code>null</code> if
175      *          xml did not contain the correct information.
176      */
getTestPackageDef()177     public TestPackageDef getTestPackageDef() {
178         return mPackageDef;
179     }
180 }
181