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. 17import xml.dom.minidom 18import xml.parsers 19import os 20 21 22import coverage_target 23import logger 24import errors 25 26class 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 124def 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