1 #!/usr/bin/python2.4 2 # 3 # 4 # Copyright 2008, 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 import xml.dom.minidom 18 import xml.parsers 19 import os 20 21 22 import coverage_target 23 import logger 24 import errors 25 26 class CoverageTargets: 27 """Accessor for the code coverage target xml file 28 Expects the following format: 29 <targets> 30 <target 31 name="" 32 type="JAVA_LIBRARIES|APPS" 33 build_path="" 34 35 [<src path=""/>] (0..*) - These are relative to build_path. If missing, 36 assumes 'src' 37 >/target> 38 39 TODO: add more format checking 40 """ 41 42 _TARGET_TAG_NAME = 'coverage_target' 43 _NAME_ATTR = 'name' 44 _TYPE_ATTR = 'type' 45 _BUILD_ATTR = 'build_path' 46 _SRC_TAG = 'src' 47 _PATH_ATTR = 'path' 48 49 def __init__(self, ): 50 self._target_map= {} 51 52 def __iter__(self): 53 return iter(self._target_map.values()) 54 55 def Parse(self, file_path): 56 """Parse the coverage target data from from given file path, and add it to 57 the current object 58 Args: 59 file_path: absolute file path to parse 60 Raises: 61 errors.ParseError if file_path cannot be parsed 62 """ 63 try: 64 doc = xml.dom.minidom.parse(file_path) 65 except IOError: 66 # Error: The results file does not exist 67 logger.Log('Results file %s does not exist' % file_path) 68 raise errors.ParseError 69 except xml.parsers.expat.ExpatError: 70 logger.Log('Error Parsing xml file: %s ' % file_path) 71 raise errors.ParseError 72 73 target_elements = doc.getElementsByTagName(self._TARGET_TAG_NAME) 74 75 for target_element in target_elements: 76 target = coverage_target.CoverageTarget() 77 self._ParseCoverageTarget(target, target_element) 78 self._AddTarget(target) 79 80 def _AddTarget(self, target): 81 self._target_map[target.GetName()] = target 82 83 def GetBuildTargets(self): 84 """ returns list of target names """ 85 build_targets = [] 86 for target in self: 87 build_targets.append(target.GetName()) 88 return build_targets 89 90 def GetTargets(self): 91 """ returns list of CoverageTarget""" 92 return self._target_map.values() 93 94 def GetTarget(self, name): 95 """ returns CoverageTarget for given name. None if not found """ 96 try: 97 return self._target_map[name] 98 except KeyError: 99 return None 100 101 def _ParseCoverageTarget(self, target, target_element): 102 """Parse coverage data from XML. 103 104 Args: 105 target: the Coverage object to populate 106 target_element: the XML element to get data from 107 """ 108 target.SetName(target_element.getAttribute(self._NAME_ATTR)) 109 target.SetType(target_element.getAttribute(self._TYPE_ATTR)) 110 target.SetBuildPath(target_element.getAttribute(self._BUILD_ATTR)) 111 self._paths = [] 112 self._ParsePaths(target, target_element) 113 114 def _ParsePaths(self, target, target_element): 115 src_elements = target_element.getElementsByTagName(self._SRC_TAG) 116 if len(src_elements) <= 0: 117 # no src tags specified. Assume build_path + src 118 target.AddPath(os.path.join(target.GetBuildPath(), "src")) 119 for src_element in src_elements: 120 rel_path = src_element.getAttribute(self._PATH_ATTR) 121 target.AddPath(os.path.join(target.GetBuildPath(), rel_path)) 122 123 124 def Parse(xml_file_path): 125 """parses out a file_path class from given path to xml""" 126 targets = CoverageTargets() 127 targets.Parse(xml_file_path) 128 return targets 129