2023-04-12 11:15:36 +02:00
#!/usr/bin/env python
#
# Copyright 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2025-02-14 20:03:30 +01:00
""" Unit test for the gtest_xml_output module. """
2023-04-12 11:15:36 +02:00
import datetime
import errno
import os
import re
import sys
2025-02-14 20:03:30 +01:00
from xml . dom import minidom
2023-04-12 11:15:36 +02:00
from googletest . test import gtest_test_utils
from googletest . test import gtest_xml_test_utils
GTEST_FILTER_FLAG = ' --gtest_filter '
GTEST_LIST_TESTS_FLAG = ' --gtest_list_tests '
GTEST_OUTPUT_FLAG = ' --gtest_output '
GTEST_DEFAULT_OUTPUT_FILE = ' test_detail.xml '
GTEST_PROGRAM_NAME = ' gtest_xml_output_unittest_ '
# The flag indicating stacktraces are not supported
NO_STACKTRACE_SUPPORT_FLAG = ' --no_stacktrace_support '
# The environment variables for test sharding.
TOTAL_SHARDS_ENV_VAR = ' GTEST_TOTAL_SHARDS '
SHARD_INDEX_ENV_VAR = ' GTEST_SHARD_INDEX '
SHARD_STATUS_FILE_ENV_VAR = ' GTEST_SHARD_STATUS_FILE '
SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys . argv
if SUPPORTS_STACK_TRACES :
STACK_TRACE_TEMPLATE = ' \n Stack trace: \n * '
2025-02-14 20:03:30 +01:00
STACK_TRACE_ENTITY_TEMPLATE = ' '
2023-04-12 11:15:36 +02:00
else :
2025-02-14 20:03:30 +01:00
STACK_TRACE_TEMPLATE = ' \n '
STACK_TRACE_ENTITY_TEMPLATE = ' 
 '
2023-04-12 11:15:36 +02:00
# unittest.main() can't handle unknown flags
sys . argv . remove ( NO_STACKTRACE_SUPPORT_FLAG )
EXPECTED_NON_EMPTY_XML = """ <?xml version= " 1.0 " encoding= " UTF-8 " ?>
2025-02-14 20:03:30 +01:00
< testsuites tests = " 28 " failures = " 5 " disabled = " 2 " errors = " 0 " time = " * " timestamp = " * " name = " AllTests " >
< properties >
< property name = " ad_hoc_property " value = " 42 " / >
< / properties >
2023-04-12 11:15:36 +02:00
< testsuite name = " SuccessfulTest " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " Succeeds " file = " gtest_xml_output_unittest_.cc " line = " 53 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " SuccessfulTest " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " FailedTest " tests = " 1 " failures = " 1 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " Fails " file = " gtest_xml_output_unittest_.cc " line = " 61 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " FailedTest " >
< failure message = " gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
2023-04-12 11:15:36 +02:00
Expected equality of these values :
1
2 % ( stack ) s ] ] > < / failure >
< / testcase >
< / testsuite >
< testsuite name = " MixedResultTest " tests = " 3 " failures = " 1 " disabled = " 1 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " Succeeds " file = " gtest_xml_output_unittest_.cc " line = " 88 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " MixedResultTest " / >
< testcase name = " Fails " file = " gtest_xml_output_unittest_.cc " line = " 93 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " MixedResultTest " >
< failure message = " gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
2023-04-12 11:15:36 +02:00
Expected equality of these values :
1
2 % ( stack ) s ] ] > < / failure >
2025-02-14 20:03:30 +01:00
< failure message = " gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 2
 3 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
2023-04-12 11:15:36 +02:00
Expected equality of these values :
2
3 % ( stack ) s ] ] > < / failure >
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " DISABLED_test " file = " gtest_xml_output_unittest_.cc " line = " 98 " status = " notrun " result = " suppressed " time = " * " timestamp = " * " classname = " MixedResultTest " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " XmlQuotingTest " tests = " 1 " failures = " 1 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " OutputsCData " file = " gtest_xml_output_unittest_.cc " line = " 102 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " XmlQuotingTest " >
< failure message = " gtest_xml_output_unittest_.cc:*
Failed
XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]></top> %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
2023-04-12 11:15:36 +02:00
Failed
XML output : < ? xml encoding = " utf-8 " > < top > < ! [ CDATA [ cdata text ] ] > ] ] & gt ; < ! [ CDATA [ < / top > % ( stack ) s ] ] > < / failure >
< / testcase >
< / testsuite >
< testsuite name = " InvalidCharactersTest " tests = " 1 " failures = " 1 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " InvalidCharactersInMessage " file = " gtest_xml_output_unittest_.cc " line = " 109 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " InvalidCharactersTest " >
< failure message = " gtest_xml_output_unittest_.cc:*
Failed
Invalid characters in brackets [] %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
2023-04-12 11:15:36 +02:00
Failed
Invalid characters in brackets [ ] % ( stack ) s ] ] > < / failure >
< / testcase >
< / testsuite >
< testsuite name = " DisabledTest " tests = " 1 " failures = " 0 " disabled = " 1 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " DISABLED_test_not_run " file = " gtest_xml_output_unittest_.cc " line = " 68 " status = " notrun " result = " suppressed " time = " * " timestamp = " * " classname = " DisabledTest " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " SkippedTest " tests = " 3 " failures = " 1 " disabled = " 0 " skipped = " 2 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " Skipped " status = " run " file = " gtest_xml_output_unittest_.cc " line = " 75 " result = " skipped " time = " * " timestamp = " * " classname = " SkippedTest " >
< skipped message = " gtest_xml_output_unittest_.cc:*

 " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
] ] > < / skipped >
2023-04-12 11:15:36 +02:00
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " SkippedWithMessage " file = " gtest_xml_output_unittest_.cc " line = " 79 " status = " run " result = " skipped " time = " * " timestamp = " * " classname = " SkippedTest " >
< skipped message = " gtest_xml_output_unittest_.cc:*
It is good practice to tell why you skip a test.
 " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
It is good practice to tell why you skip a test .
] ] > < / skipped >
2023-04-12 11:15:36 +02:00
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " SkippedAfterFailure " file = " gtest_xml_output_unittest_.cc " line = " 83 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " SkippedTest " >
< failure message = " gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
2023-04-12 11:15:36 +02:00
Expected equality of these values :
1
2 % ( stack ) s ] ] > < / failure >
2025-02-14 20:03:30 +01:00
< skipped message = " gtest_xml_output_unittest_.cc:*
It is good practice to tell why you skip a test.
 " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
It is good practice to tell why you skip a test .
] ] > < / skipped >
2023-04-12 11:15:36 +02:00
< / testcase >
< / testsuite >
2025-02-14 20:03:30 +01:00
< testsuite name = " PropertyRecordingTest " tests = " 4 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
< properties >
< property name = " SetUpTestSuite " value = " yes " / >
< property name = " SetUpTestSuite (with whitespace) " value = " yes and yes " / >
< property name = " TearDownTestSuite " value = " aye " / >
< property name = " TearDownTestSuite (with whitespace) " value = " aye and aye " / >
< / properties >
< testcase name = " OneProperty " file = " gtest_xml_output_unittest_.cc " line = " 125 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " PropertyRecordingTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_1 " value = " 1 " / >
< / properties >
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " IntValuedProperty " file = " gtest_xml_output_unittest_.cc " line = " 129 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " PropertyRecordingTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_int " value = " 1 " / >
< / properties >
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " ThreeProperties " file = " gtest_xml_output_unittest_.cc " line = " 133 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " PropertyRecordingTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_1 " value = " 1 " / >
< property name = " key_2 " value = " 2 " / >
< property name = " key_3 " value = " 3 " / >
< / properties >
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " TwoValuesForOneKeyUsesLastValue " file = " gtest_xml_output_unittest_.cc " line = " 139 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " PropertyRecordingTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_1 " value = " 2 " / >
< / properties >
< / testcase >
< / testsuite >
< testsuite name = " NoFixtureTest " tests = " 3 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " RecordProperty " file = " gtest_xml_output_unittest_.cc " line = " 144 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " NoFixtureTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key " value = " 1 " / >
< / properties >
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " ExternalUtilityThatCallsRecordIntValuedProperty " file = " gtest_xml_output_unittest_.cc " line = " 157 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " NoFixtureTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_for_utility_int " value = " 1 " / >
< / properties >
< / testcase >
2025-02-14 20:03:30 +01:00
< testcase name = " ExternalUtilityThatCallsRecordStringValuedProperty " file = " gtest_xml_output_unittest_.cc " line = " 161 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " NoFixtureTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_for_utility_string " value = " 1 " / >
< / properties >
< / testcase >
< / testsuite >
2025-02-14 20:03:30 +01:00
< testsuite name = " SetupFailTest " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 1 " errors = " 0 " time = " * " timestamp = " * " >
< testcase name = " NoopPassingTest " file = " gtest_xml_output_unittest_.cc " line = " 172 " status = " run " result = " skipped " time = " * " timestamp = " * " classname = " SetupFailTest " >
< skipped message = " gtest_xml_output_unittest_.cc:*
 " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
] ] > < / skipped >
< / testcase >
< testcase name = " " status = " run " result = " completed " classname = " " time = " * " timestamp = " * " >
< failure message = " gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
Expected equality of these values :
1
2 % ( stack ) s ] ] > < / failure >
< / testcase >
< / testsuite >
< testsuite name = " TearDownFailTest " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
< testcase name = " NoopPassingTest " file = " gtest_xml_output_unittest_.cc " line = " 179 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " TearDownFailTest " / >
< testcase name = " " status = " run " result = " completed " classname = " " time = " * " timestamp = " * " >
< failure message = " gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_xml_output_unittest_ . cc : *
Expected equality of these values :
1
2 % ( stack ) s ] ] > < / failure >
< / testcase >
< / testsuite >
2023-04-12 11:15:36 +02:00
< testsuite name = " Single/ValueParamTest " tests = " 4 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " HasValueParamAttribute/0 " file = " gtest_xml_output_unittest_.cc " line = " 184 " value_param = " 33 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/ValueParamTest " / >
< testcase name = " HasValueParamAttribute/1 " file = " gtest_xml_output_unittest_.cc " line = " 184 " value_param = " 42 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/ValueParamTest " / >
< testcase name = " AnotherTestThatHasValueParamAttribute/0 " file = " gtest_xml_output_unittest_.cc " line = " 185 " value_param = " 33 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/ValueParamTest " / >
< testcase name = " AnotherTestThatHasValueParamAttribute/1 " file = " gtest_xml_output_unittest_.cc " line = " 185 " value_param = " 42 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/ValueParamTest " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " TypedTest/0 " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " HasTypeParamAttribute " file = " gtest_xml_output_unittest_.cc " line = " 193 " type_param = " * " status = " run " result = " completed " time = " * " timestamp = " * " classname = " TypedTest/0 " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " TypedTest/1 " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " HasTypeParamAttribute " file = " gtest_xml_output_unittest_.cc " line = " 193 " type_param = " * " status = " run " result = " completed " time = " * " timestamp = " * " classname = " TypedTest/1 " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " Single/TypeParameterizedTestSuite/0 " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " HasTypeParamAttribute " file = " gtest_xml_output_unittest_.cc " line = " 200 " type_param = " * " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/TypeParameterizedTestSuite/0 " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< testsuite name = " Single/TypeParameterizedTestSuite/1 " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " HasTypeParamAttribute " file = " gtest_xml_output_unittest_.cc " line = " 200 " type_param = " * " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/TypeParameterizedTestSuite/1 " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< / testsuites > """ % {
2025-02-14 20:03:30 +01:00
' stack ' : STACK_TRACE_TEMPLATE ,
' stack_entity ' : STACK_TRACE_ENTITY_TEMPLATE ,
2023-04-12 11:15:36 +02:00
}
EXPECTED_FILTERED_TEST_XML = """ <?xml version= " 1.0 " encoding= " UTF-8 " ?>
2025-02-14 20:03:30 +01:00
< testsuites tests = " 1 " failures = " 0 " disabled = " 0 " errors = " 0 " time = " * " timestamp = " * " name = " AllTests " >
< properties >
< property name = " ad_hoc_property " value = " 42 " / >
< / properties >
2023-04-12 11:15:36 +02:00
< testsuite name = " SuccessfulTest " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 "
errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " Succeeds " file = " gtest_xml_output_unittest_.cc " line = " 53 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " SuccessfulTest " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< / testsuites > """
EXPECTED_SHARDED_TEST_XML = """ <?xml version= " 1.0 " encoding= " UTF-8 " ?>
2025-02-14 20:03:30 +01:00
< testsuites tests = " 3 " failures = " 0 " disabled = " 0 " errors = " 0 " time = " * " timestamp = " * " name = " AllTests " >
< properties >
< property name = " ad_hoc_property " value = " 42 " / >
< / properties >
2023-04-12 11:15:36 +02:00
< testsuite name = " SuccessfulTest " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
2025-02-14 20:03:30 +01:00
< testcase name = " Succeeds " file = " gtest_xml_output_unittest_.cc " line = " 53 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " SuccessfulTest " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
2025-02-14 20:03:30 +01:00
< testsuite name = " PropertyRecordingTest " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
< properties >
< property name = " SetUpTestSuite " value = " yes " / >
< property name = " SetUpTestSuite (with whitespace) " value = " yes and yes " / >
< property name = " TearDownTestSuite " value = " aye " / >
< property name = " TearDownTestSuite (with whitespace) " value = " aye and aye " / >
< / properties >
< testcase name = " IntValuedProperty " file = " gtest_xml_output_unittest_.cc " line = " 129 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " PropertyRecordingTest " >
2023-04-12 11:15:36 +02:00
< properties >
< property name = " key_int " value = " 1 " / >
< / properties >
< / testcase >
< / testsuite >
2025-02-14 20:03:30 +01:00
< testsuite name = " Single/TypeParameterizedTestSuite/0 " tests = " 1 " failures = " 0 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
< testcase name = " HasTypeParamAttribute " type_param = " * " file = " gtest_xml_output_unittest_.cc " line = " 200 " status = " run " result = " completed " time = " * " timestamp = " * " classname = " Single/TypeParameterizedTestSuite/0 " / >
2023-04-12 11:15:36 +02:00
< / testsuite >
< / testsuites > """
EXPECTED_NO_TEST_XML = """ <?xml version= " 1.0 " encoding= " UTF-8 " ?>
< testsuites tests = " 0 " failures = " 0 " disabled = " 0 " errors = " 0 " time = " * "
timestamp = " * " name = " AllTests " >
< testsuite name = " NonTestSuiteFailure " tests = " 1 " failures = " 1 " disabled = " 0 " skipped = " 0 " errors = " 0 " time = " * " timestamp = " * " >
< testcase name = " " status = " run " result = " completed " time = " * " timestamp = " * " classname = " " >
2025-02-14 20:03:30 +01:00
< failure message = " gtest_no_test_unittest.cc:*
Expected equality of these values:
 1
 2 %(stack_entity)s " type = " " > < ! [ CDATA [ gtest_no_test_unittest . cc : *
2023-04-12 11:15:36 +02:00
Expected equality of these values :
1
2 % ( stack ) s ] ] > < / failure >
< / testcase >
< / testsuite >
< / testsuites > """ % {
2025-02-14 20:03:30 +01:00
' stack ' : STACK_TRACE_TEMPLATE ,
' stack_entity ' : STACK_TRACE_ENTITY_TEMPLATE ,
2023-04-12 11:15:36 +02:00
}
GTEST_PROGRAM_PATH = gtest_test_utils . GetTestExecutablePath ( GTEST_PROGRAM_NAME )
2025-02-14 20:03:30 +01:00
SUPPORTS_TYPED_TESTS = (
' TypedTest '
in gtest_test_utils . Subprocess (
[ GTEST_PROGRAM_PATH , GTEST_LIST_TESTS_FLAG ] , capture_stderr = False
) . output
)
2023-04-12 11:15:36 +02:00
class GTestXMLOutputUnitTest ( gtest_xml_test_utils . GTestXMLTestCase ) :
2025-02-14 20:03:30 +01:00
""" Unit test for Google Test ' s XML output functionality. """
2023-04-12 11:15:36 +02:00
# This test currently breaks on platforms that do not support typed and
# type-parameterized tests, so we don't run it under them.
if SUPPORTS_TYPED_TESTS :
2025-02-14 20:03:30 +01:00
2023-04-12 11:15:36 +02:00
def testNonEmptyXmlOutput ( self ) :
2025-02-14 20:03:30 +01:00
""" Generates non-empty XML and verifies it matches the expected output.
2023-04-12 11:15:36 +02:00
Runs a test program that generates a non - empty XML output , and
tests that the XML output is expected .
"""
self . _TestXmlOutput ( GTEST_PROGRAM_NAME , EXPECTED_NON_EMPTY_XML , 1 )
def testNoTestXmlOutput ( self ) :
""" Verifies XML output for a Google Test binary without actual tests.
Runs a test program that generates an XML output for a binary without tests ,
and tests that the XML output is expected .
"""
self . _TestXmlOutput ( ' gtest_no_test_unittest ' , EXPECTED_NO_TEST_XML , 0 )
def testTimestampValue ( self ) :
""" Checks whether the timestamp attribute in the XML output is valid.
Runs a test program that generates an empty XML output , and checks if
the timestamp attribute in the testsuites tag is valid .
"""
actual = self . _GetXmlOutput ( ' gtest_no_test_unittest ' , [ ] , { } , 0 )
date_time_str = actual . documentElement . getAttributeNode ( ' timestamp ' ) . value
# datetime.strptime() is only available in Python 2.5+ so we have to
# parse the expected datetime manually.
match = re . match ( r ' ( \ d+)-( \ d \ d)-( \ d \ d)T( \ d \ d):( \ d \ d):( \ d \ d) ' , date_time_str )
self . assertTrue (
2025-02-14 20:03:30 +01:00
re . match , ' XML datettime string %s has incorrect format ' % date_time_str
)
2023-04-12 11:15:36 +02:00
date_time_from_xml = datetime . datetime (
2025-02-14 20:03:30 +01:00
year = int ( match . group ( 1 ) ) ,
month = int ( match . group ( 2 ) ) ,
day = int ( match . group ( 3 ) ) ,
hour = int ( match . group ( 4 ) ) ,
minute = int ( match . group ( 5 ) ) ,
second = int ( match . group ( 6 ) ) ,
)
2023-04-12 11:15:36 +02:00
time_delta = abs ( datetime . datetime . now ( ) - date_time_from_xml )
# timestamp value should be near the current local time
2025-02-14 20:03:30 +01:00
self . assertLess ( time_delta , datetime . timedelta ( seconds = 600 ) )
2023-04-12 11:15:36 +02:00
actual . unlink ( )
def testDefaultOutputFile ( self ) :
2025-02-14 20:03:30 +01:00
""" Tests XML file with default name is created when name is not specified.
2023-04-12 11:15:36 +02:00
Confirms that Google Test produces an XML output file with the expected
default name if no name is explicitly specified .
"""
2025-02-14 20:03:30 +01:00
output_file = os . path . join (
gtest_test_utils . GetTempDir ( ) , GTEST_DEFAULT_OUTPUT_FILE
)
2023-04-12 11:15:36 +02:00
gtest_prog_path = gtest_test_utils . GetTestExecutablePath (
2025-02-14 20:03:30 +01:00
' gtest_no_test_unittest '
)
2023-04-12 11:15:36 +02:00
try :
os . remove ( output_file )
except OSError :
e = sys . exc_info ( ) [ 1 ]
if e . errno != errno . ENOENT :
raise
p = gtest_test_utils . Subprocess (
[ gtest_prog_path , ' %s =xml ' % GTEST_OUTPUT_FLAG ] ,
2025-02-14 20:03:30 +01:00
working_dir = gtest_test_utils . GetTempDir ( ) ,
)
self . assertTrue ( p . exited )
self . assertEqual ( 0 , p . exit_code )
self . assertTrue ( os . path . isfile ( output_file ) )
2023-04-12 11:15:36 +02:00
def testSuppressedXmlOutput ( self ) :
2025-02-14 20:03:30 +01:00
""" Verifies XML output is suppressed if default listener is shut down.
2023-04-12 11:15:36 +02:00
Tests that no XML file is generated if the default XML listener is
shut down before RUN_ALL_TESTS is invoked .
"""
2025-02-14 20:03:30 +01:00
xml_path = os . path . join (
gtest_test_utils . GetTempDir ( ) , GTEST_PROGRAM_NAME + ' out.xml '
)
2023-04-12 11:15:36 +02:00
if os . path . isfile ( xml_path ) :
os . remove ( xml_path )
2025-02-14 20:03:30 +01:00
command = [
GTEST_PROGRAM_PATH ,
' %s =xml: %s ' % ( GTEST_OUTPUT_FLAG , xml_path ) ,
' --shut_down_xml ' ,
]
2023-04-12 11:15:36 +02:00
p = gtest_test_utils . Subprocess ( command )
if p . terminated_by_signal :
# p.signal is available only if p.terminated_by_signal is True.
self . assertFalse (
p . terminated_by_signal ,
2025-02-14 20:03:30 +01:00
' %s was killed by signal %d ' % ( GTEST_PROGRAM_NAME , p . signal ) ,
)
2023-04-12 11:15:36 +02:00
else :
2025-02-14 20:03:30 +01:00
self . assertTrue ( p . exited )
self . assertEqual (
1 ,
p . exit_code ,
" ' %s ' exited with code %s , which doesn ' t match "
' the expected exit code %s . ' % ( command , p . exit_code , 1 ) ,
)
2023-04-12 11:15:36 +02:00
2025-02-14 20:03:30 +01:00
self . assertFalse ( os . path . isfile ( xml_path ) )
2023-04-12 11:15:36 +02:00
def testFilteredTestXmlOutput ( self ) :
""" Verifies XML output when a filter is applied.
Runs a test program that executes only some tests and verifies that
non - selected tests do not show up in the XML output .
"""
2025-02-14 20:03:30 +01:00
self . _TestXmlOutput (
GTEST_PROGRAM_NAME ,
EXPECTED_FILTERED_TEST_XML ,
0 ,
extra_args = [ ' %s =SuccessfulTest.* ' % GTEST_FILTER_FLAG ] ,
)
2023-04-12 11:15:36 +02:00
def testShardedTestXmlOutput ( self ) :
""" Verifies XML output when run using multiple shards.
Runs a test program that executes only one shard and verifies that tests
from other shards do not show up in the XML output .
"""
self . _TestXmlOutput (
GTEST_PROGRAM_NAME ,
EXPECTED_SHARDED_TEST_XML ,
0 ,
2025-02-14 20:03:30 +01:00
extra_env = { SHARD_INDEX_ENV_VAR : ' 0 ' , TOTAL_SHARDS_ENV_VAR : ' 10 ' } ,
)
def _GetXmlOutput (
self , gtest_prog_name , extra_args , extra_env , expected_exit_code
) :
""" Returns the XML output generated by running the program gtest_prog_name.
2023-04-12 11:15:36 +02:00
Furthermore , the program ' s exit code must be expected_exit_code.
2025-02-14 20:03:30 +01:00
Args :
gtest_prog_name : Program to run .
extra_args : Optional arguments to pass to program .
extra_env : Optional environment variables to set .
expected_exit_code : Expected exit code from running gtest_prog_name .
2023-04-12 11:15:36 +02:00
"""
2025-02-14 20:03:30 +01:00
xml_path = os . path . join (
gtest_test_utils . GetTempDir ( ) , gtest_prog_name + ' out.xml '
)
2023-04-12 11:15:36 +02:00
gtest_prog_path = gtest_test_utils . GetTestExecutablePath ( gtest_prog_name )
2025-02-14 20:03:30 +01:00
command = [
gtest_prog_path ,
' %s =xml: %s ' % ( GTEST_OUTPUT_FLAG , xml_path ) ,
] + extra_args
2023-04-12 11:15:36 +02:00
environ_copy = os . environ . copy ( )
if extra_env :
environ_copy . update ( extra_env )
p = gtest_test_utils . Subprocess ( command , env = environ_copy )
if p . terminated_by_signal :
2025-02-14 20:03:30 +01:00
self . assertTrue (
False , ' %s was killed by signal %d ' % ( gtest_prog_name , p . signal )
)
2023-04-12 11:15:36 +02:00
else :
2025-02-14 20:03:30 +01:00
self . assertTrue ( p . exited )
self . assertEqual (
expected_exit_code ,
p . exit_code ,
" ' %s ' exited with code %s , which doesn ' t match "
' the expected exit code %s . '
% ( command , p . exit_code , expected_exit_code ) ,
)
2023-04-12 11:15:36 +02:00
actual = minidom . parse ( xml_path )
return actual
2025-02-14 20:03:30 +01:00
def _TestXmlOutput (
self ,
gtest_prog_name ,
expected_xml ,
expected_exit_code ,
extra_args = None ,
extra_env = None ,
) :
""" Asserts that the XML document matches.
2023-04-12 11:15:36 +02:00
Asserts that the XML document generated by running the program
gtest_prog_name matches expected_xml , a string containing another
XML document . Furthermore , the program ' s exit code must be
expected_exit_code .
2025-02-14 20:03:30 +01:00
Args :
gtest_prog_name : Program to run .
expected_xml : Path to XML document to match .
expected_exit_code : Expected exit code from running gtest_prog_name .
extra_args : Optional arguments to pass to program .
extra_env : Optional environment variables to set .
2023-04-12 11:15:36 +02:00
"""
2025-02-14 20:03:30 +01:00
actual = self . _GetXmlOutput (
gtest_prog_name , extra_args or [ ] , extra_env or { } , expected_exit_code
)
2023-04-12 11:15:36 +02:00
expected = minidom . parseString ( expected_xml )
self . NormalizeXml ( actual . documentElement )
2025-02-14 20:03:30 +01:00
self . AssertEquivalentNodes ( expected . documentElement , actual . documentElement )
2023-04-12 11:15:36 +02:00
expected . unlink ( )
actual . unlink ( )
if __name__ == ' __main__ ' :
os . environ [ ' GTEST_STACK_TRACE_DEPTH ' ] = ' 1 '
gtest_test_utils . Main ( )