media/webrtc/trunk/testing/gtest/test/gtest_xml_test_utils.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/webrtc/trunk/testing/gtest/test/gtest_xml_test_utils.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,190 @@
     1.4 +#!/usr/bin/env python
     1.5 +#
     1.6 +# Copyright 2006, Google Inc.
     1.7 +# All rights reserved.
     1.8 +#
     1.9 +# Redistribution and use in source and binary forms, with or without
    1.10 +# modification, are permitted provided that the following conditions are
    1.11 +# met:
    1.12 +#
    1.13 +#     * Redistributions of source code must retain the above copyright
    1.14 +# notice, this list of conditions and the following disclaimer.
    1.15 +#     * Redistributions in binary form must reproduce the above
    1.16 +# copyright notice, this list of conditions and the following disclaimer
    1.17 +# in the documentation and/or other materials provided with the
    1.18 +# distribution.
    1.19 +#     * Neither the name of Google Inc. nor the names of its
    1.20 +# contributors may be used to endorse or promote products derived from
    1.21 +# this software without specific prior written permission.
    1.22 +#
    1.23 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.24 +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.25 +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.26 +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.27 +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.28 +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.29 +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.30 +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.31 +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.32 +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.33 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.34 +
    1.35 +"""Unit test utilities for gtest_xml_output"""
    1.36 +
    1.37 +__author__ = 'eefacm@gmail.com (Sean Mcafee)'
    1.38 +
    1.39 +import re
    1.40 +from xml.dom import minidom, Node
    1.41 +
    1.42 +import gtest_test_utils
    1.43 +
    1.44 +
    1.45 +GTEST_OUTPUT_FLAG         = '--gtest_output'
    1.46 +GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml'
    1.47 +
    1.48 +class GTestXMLTestCase(gtest_test_utils.TestCase):
    1.49 +  """
    1.50 +  Base class for tests of Google Test's XML output functionality.
    1.51 +  """
    1.52 +
    1.53 +
    1.54 +  def AssertEquivalentNodes(self, expected_node, actual_node):
    1.55 +    """
    1.56 +    Asserts that actual_node (a DOM node object) is equivalent to
    1.57 +    expected_node (another DOM node object), in that either both of
    1.58 +    them are CDATA nodes and have the same value, or both are DOM
    1.59 +    elements and actual_node meets all of the following conditions:
    1.60 +
    1.61 +    *  It has the same tag name as expected_node.
    1.62 +    *  It has the same set of attributes as expected_node, each with
    1.63 +       the same value as the corresponding attribute of expected_node.
    1.64 +       Exceptions are any attribute named "time", which needs only be
    1.65 +       convertible to a floating-point number and any attribute named
    1.66 +       "type_param" which only has to be non-empty.
    1.67 +    *  It has an equivalent set of child nodes (including elements and
    1.68 +       CDATA sections) as expected_node.  Note that we ignore the
    1.69 +       order of the children as they are not guaranteed to be in any
    1.70 +       particular order.
    1.71 +    """
    1.72 +
    1.73 +    if expected_node.nodeType == Node.CDATA_SECTION_NODE:
    1.74 +      self.assertEquals(Node.CDATA_SECTION_NODE, actual_node.nodeType)
    1.75 +      self.assertEquals(expected_node.nodeValue, actual_node.nodeValue)
    1.76 +      return
    1.77 +
    1.78 +    self.assertEquals(Node.ELEMENT_NODE, actual_node.nodeType)
    1.79 +    self.assertEquals(Node.ELEMENT_NODE, expected_node.nodeType)
    1.80 +    self.assertEquals(expected_node.tagName, actual_node.tagName)
    1.81 +
    1.82 +    expected_attributes = expected_node.attributes
    1.83 +    actual_attributes   = actual_node  .attributes
    1.84 +    self.assertEquals(
    1.85 +        expected_attributes.length, actual_attributes.length,
    1.86 +        'attribute numbers differ in element ' + actual_node.tagName)
    1.87 +    for i in range(expected_attributes.length):
    1.88 +      expected_attr = expected_attributes.item(i)
    1.89 +      actual_attr   = actual_attributes.get(expected_attr.name)
    1.90 +      self.assert_(
    1.91 +          actual_attr is not None,
    1.92 +          'expected attribute %s not found in element %s' %
    1.93 +          (expected_attr.name, actual_node.tagName))
    1.94 +      self.assertEquals(expected_attr.value, actual_attr.value,
    1.95 +                        ' values of attribute %s in element %s differ' %
    1.96 +                        (expected_attr.name, actual_node.tagName))
    1.97 +
    1.98 +    expected_children = self._GetChildren(expected_node)
    1.99 +    actual_children = self._GetChildren(actual_node)
   1.100 +    self.assertEquals(
   1.101 +        len(expected_children), len(actual_children),
   1.102 +        'number of child elements differ in element ' + actual_node.tagName)
   1.103 +    for child_id, child in expected_children.iteritems():
   1.104 +      self.assert_(child_id in actual_children,
   1.105 +                   '<%s> is not in <%s> (in element %s)' %
   1.106 +                   (child_id, actual_children, actual_node.tagName))
   1.107 +      self.AssertEquivalentNodes(child, actual_children[child_id])
   1.108 +
   1.109 +  identifying_attribute = {
   1.110 +    'testsuites': 'name',
   1.111 +    'testsuite': 'name',
   1.112 +    'testcase':  'name',
   1.113 +    'failure':   'message',
   1.114 +    }
   1.115 +
   1.116 +  def _GetChildren(self, element):
   1.117 +    """
   1.118 +    Fetches all of the child nodes of element, a DOM Element object.
   1.119 +    Returns them as the values of a dictionary keyed by the IDs of the
   1.120 +    children.  For <testsuites>, <testsuite> and <testcase> elements, the ID
   1.121 +    is the value of their "name" attribute; for <failure> elements, it is
   1.122 +    the value of the "message" attribute; CDATA sections and non-whitespace
   1.123 +    text nodes are concatenated into a single CDATA section with ID
   1.124 +    "detail".  An exception is raised if any element other than the above
   1.125 +    four is encountered, if two child elements with the same identifying
   1.126 +    attributes are encountered, or if any other type of node is encountered.
   1.127 +    """
   1.128 +
   1.129 +    children = {}
   1.130 +    for child in element.childNodes:
   1.131 +      if child.nodeType == Node.ELEMENT_NODE:
   1.132 +        self.assert_(child.tagName in self.identifying_attribute,
   1.133 +                     'Encountered unknown element <%s>' % child.tagName)
   1.134 +        childID = child.getAttribute(self.identifying_attribute[child.tagName])
   1.135 +        self.assert_(childID not in children)
   1.136 +        children[childID] = child
   1.137 +      elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
   1.138 +        if 'detail' not in children:
   1.139 +          if (child.nodeType == Node.CDATA_SECTION_NODE or
   1.140 +              not child.nodeValue.isspace()):
   1.141 +            children['detail'] = child.ownerDocument.createCDATASection(
   1.142 +                child.nodeValue)
   1.143 +        else:
   1.144 +          children['detail'].nodeValue += child.nodeValue
   1.145 +      else:
   1.146 +        self.fail('Encountered unexpected node type %d' % child.nodeType)
   1.147 +    return children
   1.148 +
   1.149 +  def NormalizeXml(self, element):
   1.150 +    """
   1.151 +    Normalizes Google Test's XML output to eliminate references to transient
   1.152 +    information that may change from run to run.
   1.153 +
   1.154 +    *  The "time" attribute of <testsuites>, <testsuite> and <testcase>
   1.155 +       elements is replaced with a single asterisk, if it contains
   1.156 +       only digit characters.
   1.157 +    *  The "timestamp" attribute of <testsuites> elements is replaced with a
   1.158 +       single asterisk, if it contains a valid ISO8601 datetime value.
   1.159 +    *  The "type_param" attribute of <testcase> elements is replaced with a
   1.160 +       single asterisk (if it sn non-empty) as it is the type name returned
   1.161 +       by the compiler and is platform dependent.
   1.162 +    *  The line info reported in the first line of the "message"
   1.163 +       attribute and CDATA section of <failure> elements is replaced with the
   1.164 +       file's basename and a single asterisk for the line number.
   1.165 +    *  The directory names in file paths are removed.
   1.166 +    *  The stack traces are removed.
   1.167 +    """
   1.168 +
   1.169 +    if element.tagName == 'testsuites':
   1.170 +      timestamp = element.getAttributeNode('timestamp')
   1.171 +      timestamp.value = re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d$',
   1.172 +                               '*', timestamp.value)
   1.173 +    if element.tagName in ('testsuites', 'testsuite', 'testcase'):
   1.174 +      time = element.getAttributeNode('time')
   1.175 +      time.value = re.sub(r'^\d+(\.\d+)?$', '*', time.value)
   1.176 +      type_param = element.getAttributeNode('type_param')
   1.177 +      if type_param and type_param.value:
   1.178 +        type_param.value = '*'
   1.179 +    elif element.tagName == 'failure':
   1.180 +      source_line_pat = r'^.*[/\\](.*:)\d+\n'
   1.181 +      # Replaces the source line information with a normalized form.
   1.182 +      message = element.getAttributeNode('message')
   1.183 +      message.value = re.sub(source_line_pat, '\\1*\n', message.value)
   1.184 +      for child in element.childNodes:
   1.185 +        if child.nodeType == Node.CDATA_SECTION_NODE:
   1.186 +          # Replaces the source line information with a normalized form.
   1.187 +          cdata = re.sub(source_line_pat, '\\1*\n', child.nodeValue)
   1.188 +          # Removes the actual stack trace.
   1.189 +          child.nodeValue = re.sub(r'\nStack trace:\n(.|\n)*',
   1.190 +                                   '', cdata)
   1.191 +    for child in element.childNodes:
   1.192 +      if child.nodeType == Node.ELEMENT_NODE:
   1.193 +        self.NormalizeXml(child)

mercurial