Home | History | Annotate | Download | only in testtype
      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      */
     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
     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 
    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
    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          */
    191         private boolean parseBoolean(final String stringValue) {
    192             return stringValue != null &&
    193                     Boolean.parseBoolean(stringValue);
    194         }
    195     }
    196 
    197     @Override
    198     protected DefaultHandler createXmlHandler() {
    199         return new TestPackageHandler();
    200     }
    201 
    202     /**
    203      * @return the set of {@link TestPackageDef} containing data parsed from xml
    204      */
    205     public Set<TestPackageDef> getTestPackageDefs() {
    206         return new HashSet<>(mPackageDefs.values());
    207     }
    208 }
    209