1#!/usr/bin/python2.4 2# 3# 4# Copyright 2009, The Android Open Source Project 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18"""Utility to parse suite info from xml.""" 19 20# Python imports 21import xml.dom.minidom 22import xml.parsers 23 24# local imports 25import errors 26import logger 27import host_test 28import instrumentation_test 29import native_test 30 31 32class XmlSuiteParser(object): 33 """Parses XML attributes common to all TestSuite's.""" 34 35 # common attributes 36 _NAME_ATTR = 'name' 37 _BUILD_ATTR = 'build_path' 38 _CONTINUOUS_ATTR = 'continuous' 39 _SUITE_ATTR = 'suite' 40 _DESCRIPTION_ATTR = 'description' 41 _EXTRA_BUILD_ARGS_ATTR = 'extra_build_args' 42 _FULL_MAKE_ATTR = 'full_make' 43 _GRANTED_PERMISSIONS_ATTR = 'granted_permissions' 44 45 def Parse(self, element): 46 """Populates common suite attributes from given suite xml element. 47 48 Args: 49 element: xml node to parse 50 Raises: 51 ParseError if a required attribute is missing. 52 Returns: 53 parsed test suite or None 54 """ 55 parser = None 56 if element.nodeName == InstrumentationParser.TAG_NAME: 57 parser = InstrumentationParser() 58 elif element.nodeName == NativeParser.TAG_NAME: 59 parser = NativeParser() 60 elif element.nodeName == HostParser.TAG_NAME: 61 parser = HostParser() 62 else: 63 logger.Log('Unrecognized tag %s found' % element.nodeName) 64 return None 65 test_suite = parser.Parse(element) 66 return test_suite 67 68 def _ParseCommonAttributes(self, suite_element, test_suite): 69 test_suite.SetName(self._ParseAttribute(suite_element, self._NAME_ATTR, 70 True)) 71 test_suite.SetBuildPath(self._ParseAttribute(suite_element, 72 self._BUILD_ATTR, True)) 73 test_suite.SetContinuous(self._ParseAttribute(suite_element, 74 self._CONTINUOUS_ATTR, 75 False, default_value=False)) 76 test_suite.SetIsGrantedPermissions(self._ParseAttribute(suite_element, 77 self._GRANTED_PERMISSIONS_ATTR, 78 False, default_value=True)) 79 test_suite.SetSuite(self._ParseAttribute(suite_element, self._SUITE_ATTR, False, 80 default_value=None)) 81 test_suite.SetDescription(self._ParseAttribute(suite_element, 82 self._DESCRIPTION_ATTR, 83 False, 84 default_value='')) 85 test_suite.SetExtraBuildArgs(self._ParseAttribute( 86 suite_element, self._EXTRA_BUILD_ARGS_ATTR, False, default_value='')) 87 test_suite.SetIsFullMake(self._ParseAttribute( 88 suite_element, self._FULL_MAKE_ATTR, False, default_value=False)) 89 90 91 def _ParseAttribute(self, suite_element, attribute_name, mandatory, 92 default_value=None): 93 if suite_element.hasAttribute(attribute_name): 94 value = suite_element.getAttribute(attribute_name) 95 if default_value in (True, False): 96 value = value.lower() == "true" 97 elif mandatory: 98 error_msg = ('Could not find attribute %s in %s' % 99 (attribute_name, self.TAG_NAME)) 100 raise errors.ParseError(msg=error_msg) 101 else: 102 value = default_value 103 return value 104 105 106class InstrumentationParser(XmlSuiteParser): 107 """Parses instrumentation suite attributes from xml.""" 108 109 # for legacy reasons, the xml tag name for java (device) tests is 'test' 110 TAG_NAME = 'test' 111 112 _PKG_ATTR = 'package' 113 _RUNNER_ATTR = 'runner' 114 _CLASS_ATTR = 'class' 115 _TARGET_ATTR = 'coverage_target' 116 117 def Parse(self, suite_element): 118 """Creates suite and populate with data from xml element.""" 119 suite = instrumentation_test.InstrumentationTestSuite() 120 XmlSuiteParser._ParseCommonAttributes(self, suite_element, suite) 121 suite.SetPackageName(self._ParseAttribute(suite_element, self._PKG_ATTR, 122 True)) 123 suite.SetRunnerName(self._ParseAttribute( 124 suite_element, self._RUNNER_ATTR, False, 125 instrumentation_test.InstrumentationTestSuite.DEFAULT_RUNNER)) 126 suite.SetClassName(self._ParseAttribute(suite_element, self._CLASS_ATTR, 127 False)) 128 suite.SetTargetName(self._ParseAttribute(suite_element, self._TARGET_ATTR, 129 False)) 130 return suite 131 132 133class NativeParser(XmlSuiteParser): 134 """Parses native suite attributes from xml.""" 135 136 TAG_NAME = 'test-native' 137 138 def Parse(self, suite_element): 139 """Creates suite and populate with data from xml element.""" 140 suite = native_test.NativeTestSuite() 141 XmlSuiteParser._ParseCommonAttributes(self, suite_element, suite) 142 return suite 143 144 145class HostParser(XmlSuiteParser): 146 """Parses host suite attributes from xml.""" 147 148 TAG_NAME = 'test-host' 149 150 _CLASS_ATTR = 'class' 151 # TODO: consider obsoleting in favor of parsing the Android.mk to find the 152 # jar name 153 _JAR_ATTR = 'jar_name' 154 155 def Parse(self, suite_element): 156 """Creates suite and populate with data from xml element.""" 157 suite = host_test.HostTestSuite() 158 XmlSuiteParser._ParseCommonAttributes(self, suite_element, suite) 159 suite.SetClassName(self._ParseAttribute(suite_element, self._CLASS_ATTR, 160 True)) 161 suite.SetJarName(self._ParseAttribute(suite_element, self._JAR_ATTR, True)) 162 return suite 163