1aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter#!/usr/bin/env python 2aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# 3aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# Copyright 2006, Google Inc. 4aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# All rights reserved. 5aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# 6aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# Redistribution and use in source and binary forms, with or without 7aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# modification, are permitted provided that the following conditions are 8aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# met: 9aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# 10aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# * Redistributions of source code must retain the above copyright 11aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# notice, this list of conditions and the following disclaimer. 12aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# * Redistributions in binary form must reproduce the above 13aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# copyright notice, this list of conditions and the following disclaimer 14aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# in the documentation and/or other materials provided with the 15aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# distribution. 16aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# * Neither the name of Google Inc. nor the names of its 17aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# contributors may be used to endorse or promote products derived from 18aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# this software without specific prior written permission. 19aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# 20aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 32aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter"""Unit test utilities for gtest_xml_output""" 33aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 34aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter__author__ = 'eefacm@gmail.com (Sean Mcafee)' 35aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 36aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchterimport re 37aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchterfrom xml.dom import minidom, Node 38aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 39aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchterimport gtest_test_utils 40aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 41aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 42aa46da279e2426caf1e103eb079dfec8124c5feeCourtney GoeltzenleuchterGTEST_OUTPUT_FLAG = '--gtest_output' 43aa46da279e2426caf1e103eb079dfec8124c5feeCourtney GoeltzenleuchterGTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml' 44aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 45aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchterclass GTestXMLTestCase(gtest_test_utils.TestCase): 46aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 47aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter Base class for tests of Google Test's XML output functionality. 48aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 49aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 50aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 51aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter def AssertEquivalentNodes(self, expected_node, actual_node): 52aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 53aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter Asserts that actual_node (a DOM node object) is equivalent to 54aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_node (another DOM node object), in that either both of 55aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter them are CDATA nodes and have the same value, or both are DOM 56aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter elements and actual_node meets all of the following conditions: 57aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 58aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * It has the same tag name as expected_node. 59aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * It has the same set of attributes as expected_node, each with 60aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter the same value as the corresponding attribute of expected_node. 61aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter Exceptions are any attribute named "time", which needs only be 62aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter convertible to a floating-point number and any attribute named 63aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter "type_param" which only has to be non-empty. 64aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * It has an equivalent set of child nodes (including elements and 65aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter CDATA sections) as expected_node. Note that we ignore the 66aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter order of the children as they are not guaranteed to be in any 67aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter particular order. 68aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 69aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 70aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if expected_node.nodeType == Node.CDATA_SECTION_NODE: 71aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals(Node.CDATA_SECTION_NODE, actual_node.nodeType) 72aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals(expected_node.nodeValue, actual_node.nodeValue) 73aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter return 74aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 75aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals(Node.ELEMENT_NODE, actual_node.nodeType) 76aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals(Node.ELEMENT_NODE, expected_node.nodeType) 77aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals(expected_node.tagName, actual_node.tagName) 78aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 79aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_attributes = expected_node.attributes 80aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter actual_attributes = actual_node .attributes 81aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals( 82aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_attributes.length, actual_attributes.length, 83aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'attribute numbers differ in element %s:\nExpected: %r\nActual: %r' % ( 84aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter actual_node.tagName, expected_attributes.keys(), 85aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter actual_attributes.keys())) 86aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter for i in range(expected_attributes.length): 87aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_attr = expected_attributes.item(i) 88aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter actual_attr = actual_attributes.get(expected_attr.name) 89aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assert_( 90aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter actual_attr is not None, 91aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'expected attribute %s not found in element %s' % 92aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter (expected_attr.name, actual_node.tagName)) 93aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals( 94aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_attr.value, actual_attr.value, 95aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter ' values of attribute %s in element %s differ: %s vs %s' % 96aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter (expected_attr.name, actual_node.tagName, 97aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_attr.value, actual_attr.value)) 98aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 99aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter expected_children = self._GetChildren(expected_node) 100aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter actual_children = self._GetChildren(actual_node) 101aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assertEquals( 102aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter len(expected_children), len(actual_children), 103aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'number of child elements differ in element ' + actual_node.tagName) 104aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter for child_id, child in expected_children.iteritems(): 105aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assert_(child_id in actual_children, 106aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter '<%s> is not in <%s> (in element %s)' % 107aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter (child_id, actual_children, actual_node.tagName)) 108aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.AssertEquivalentNodes(child, actual_children[child_id]) 109aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 110aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter identifying_attribute = { 111aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'testsuites': 'name', 112aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'testsuite': 'name', 113aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'testcase': 'name', 114aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'failure': 'message', 115aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter } 116aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 117aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter def _GetChildren(self, element): 118aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 119aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter Fetches all of the child nodes of element, a DOM Element object. 120aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter Returns them as the values of a dictionary keyed by the IDs of the 121aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter children. For <testsuites>, <testsuite> and <testcase> elements, the ID 122aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter is the value of their "name" attribute; for <failure> elements, it is 123aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter the value of the "message" attribute; CDATA sections and non-whitespace 124aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter text nodes are concatenated into a single CDATA section with ID 125aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter "detail". An exception is raised if any element other than the above 126aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter four is encountered, if two child elements with the same identifying 127aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter attributes are encountered, or if any other type of node is encountered. 128aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 129aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 130aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter children = {} 131aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter for child in element.childNodes: 132aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if child.nodeType == Node.ELEMENT_NODE: 133aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assert_(child.tagName in self.identifying_attribute, 134aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 'Encountered unknown element <%s>' % child.tagName) 135aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter childID = child.getAttribute(self.identifying_attribute[child.tagName]) 136aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.assert_(childID not in children) 137aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter children[childID] = child 138aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]: 139aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if 'detail' not in children: 140aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if (child.nodeType == Node.CDATA_SECTION_NODE or 141aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter not child.nodeValue.isspace()): 142aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter children['detail'] = child.ownerDocument.createCDATASection( 143aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter child.nodeValue) 144aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter else: 145aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter children['detail'].nodeValue += child.nodeValue 146aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter else: 147aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.fail('Encountered unexpected node type %d' % child.nodeType) 148aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter return children 149aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 150aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter def NormalizeXml(self, element): 151aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 152aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter Normalizes Google Test's XML output to eliminate references to transient 153aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter information that may change from run to run. 154aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 155aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * The "time" attribute of <testsuites>, <testsuite> and <testcase> 156aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter elements is replaced with a single asterisk, if it contains 157aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter only digit characters. 158aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * The "timestamp" attribute of <testsuites> elements is replaced with a 159aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter single asterisk, if it contains a valid ISO8601 datetime value. 160aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * The "type_param" attribute of <testcase> elements is replaced with a 161aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter single asterisk (if it sn non-empty) as it is the type name returned 162aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter by the compiler and is platform dependent. 163aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * The line info reported in the first line of the "message" 164aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter attribute and CDATA section of <failure> elements is replaced with the 165aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter file's basename and a single asterisk for the line number. 166aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * The directory names in file paths are removed. 167aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter * The stack traces are removed. 168aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter """ 169aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter 170aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if element.tagName == 'testsuites': 171aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter timestamp = element.getAttributeNode('timestamp') 172aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter timestamp.value = re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d$', 173aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter '*', timestamp.value) 174aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if element.tagName in ('testsuites', 'testsuite', 'testcase'): 175aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter time = element.getAttributeNode('time') 176aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter time.value = re.sub(r'^\d+(\.\d+)?$', '*', time.value) 177aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter type_param = element.getAttributeNode('type_param') 178aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if type_param and type_param.value: 179aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter type_param.value = '*' 180aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter elif element.tagName == 'failure': 181aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter source_line_pat = r'^.*[/\\](.*:)\d+\n' 182aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter # Replaces the source line information with a normalized form. 183aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter message = element.getAttributeNode('message') 184aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter message.value = re.sub(source_line_pat, '\\1*\n', message.value) 185aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter for child in element.childNodes: 186aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if child.nodeType == Node.CDATA_SECTION_NODE: 187aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter # Replaces the source line information with a normalized form. 188aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter cdata = re.sub(source_line_pat, '\\1*\n', child.nodeValue) 189aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter # Removes the actual stack trace. 190aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter child.nodeValue = re.sub(r'\nStack trace:\n(.|\n)*', 191aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter '', cdata) 192aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter for child in element.childNodes: 193aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter if child.nodeType == Node.ELEMENT_NODE: 194aa46da279e2426caf1e103eb079dfec8124c5feeCourtney Goeltzenleuchter self.NormalizeXml(child) 195