Skip to content

Commit

Permalink
Export testsuite properties as XML elements, not attributes.
Browse files Browse the repository at this point in the history
With this change, arbitrary property names in the testsuite no longer
cause the produced XML output to be ill-formed.

PiperOrigin-RevId: 721549090
Change-Id: Iedffa89bf914478f563c8f3b82cd50557762a665
  • Loading branch information
Abseil Team authored and copybara-github committed Jan 31, 2025
1 parent 2b6b042 commit b4aae50
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 88 deletions.
38 changes: 11 additions & 27 deletions googletest/src/gtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4012,16 +4012,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
static void PrintXmlUnitTest(::std::ostream* stream,
const UnitTest& unit_test);

// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
// When the std::string is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static std::string TestPropertiesAsXmlAttributes(const TestResult& result);

// Streams an XML representation of the test properties of a TestResult
// object.
static void OutputXmlTestProperties(std::ostream* stream,
const TestResult& result);
const TestResult& result,
const std::string& indent);

// The output file.
const std::string output_file_;
Expand Down Expand Up @@ -4355,7 +4350,7 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
if (failures == 0 && skips == 0) {
*stream << ">\n";
}
OutputXmlTestProperties(stream, result);
OutputXmlTestProperties(stream, result, /*indent=*/" ");
*stream << " </testcase>\n";
}
}
Expand Down Expand Up @@ -4384,9 +4379,10 @@ void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
OutputXmlAttribute(
stream, kTestsuite, "timestamp",
FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
*stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
}
*stream << ">\n";
OutputXmlTestProperties(stream, test_suite.ad_hoc_test_result(),
/*indent=*/" ");
for (int i = 0; i < test_suite.total_test_count(); ++i) {
if (test_suite.GetTestInfo(i)->is_reportable())
OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
Expand Down Expand Up @@ -4424,11 +4420,12 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
OutputXmlAttribute(stream, kTestsuites, "random_seed",
StreamableToString(unit_test.random_seed()));
}
*stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());

OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
*stream << ">\n";

OutputXmlTestProperties(stream, unit_test.ad_hoc_test_result(),
/*indent=*/" ");
for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
Expand Down Expand Up @@ -4465,37 +4462,24 @@ void XmlUnitTestResultPrinter::PrintXmlTestsList(
*stream << "</" << kTestsuites << ">\n";
}

// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
const TestResult& result) {
Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i);
attributes << " " << property.key() << "=" << "\""
<< EscapeXmlAttribute(property.value()) << "\"";
}
return attributes.GetString();
}

void XmlUnitTestResultPrinter::OutputXmlTestProperties(
std::ostream* stream, const TestResult& result) {
std::ostream* stream, const TestResult& result, const std::string& indent) {
const std::string kProperties = "properties";
const std::string kProperty = "property";

if (result.test_property_count() <= 0) {
return;
}

*stream << " <" << kProperties << ">\n";
*stream << indent << "<" << kProperties << ">\n";
for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i);
*stream << " <" << kProperty;
*stream << indent << " <" << kProperty;
*stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
*stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
*stream << "/>\n";
}
*stream << " </" << kProperties << ">\n";
*stream << indent << "</" << kProperties << ">\n";
}

// End XmlUnitTestResultPrinter
Expand Down
36 changes: 19 additions & 17 deletions googletest/test/googletest-json-output-unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,14 @@
'time': '*',
'timestamp': '*',
'SetUpTestSuite': 'yes',
'SetUpTestSuite (with whitespace)': 'yes and yes',
'TearDownTestSuite': 'aye',
'TearDownTestSuite (with whitespace)': 'aye and aye',
'testsuite': [
{
'name': 'OneProperty',
'file': 'gtest_xml_output_unittest_.cc',
'line': 121,
'line': 125,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -339,7 +341,7 @@
{
'name': 'IntValuedProperty',
'file': 'gtest_xml_output_unittest_.cc',
'line': 125,
'line': 129,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -350,7 +352,7 @@
{
'name': 'ThreeProperties',
'file': 'gtest_xml_output_unittest_.cc',
'line': 129,
'line': 133,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -363,7 +365,7 @@
{
'name': 'TwoValuesForOneKeyUsesLastValue',
'file': 'gtest_xml_output_unittest_.cc',
'line': 135,
'line': 139,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -385,7 +387,7 @@
{
'name': 'RecordProperty',
'file': 'gtest_xml_output_unittest_.cc',
'line': 140,
'line': 144,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -396,7 +398,7 @@
{
'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
'file': 'gtest_xml_output_unittest_.cc',
'line': 153,
'line': 157,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -409,7 +411,7 @@
'ExternalUtilityThatCallsRecordStringValuedProperty'
),
'file': 'gtest_xml_output_unittest_.cc',
'line': 157,
'line': 161,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -431,7 +433,7 @@
{
'name': 'NoopPassingTest',
'file': 'gtest_xml_output_unittest_.cc',
'line': 168,
'line': 172,
'status': 'RUN',
'result': 'SKIPPED',
'timestamp': '*',
Expand Down Expand Up @@ -471,7 +473,7 @@
{
'name': 'NoopPassingTest',
'file': 'gtest_xml_output_unittest_.cc',
'line': 175,
'line': 179,
'status': 'RUN',
'result': 'COMPLETED',
'timestamp': '*',
Expand Down Expand Up @@ -508,7 +510,7 @@
'name': 'HasTypeParamAttribute',
'type_param': 'int',
'file': 'gtest_xml_output_unittest_.cc',
'line': 189,
'line': 193,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -528,7 +530,7 @@
'name': 'HasTypeParamAttribute',
'type_param': 'long',
'file': 'gtest_xml_output_unittest_.cc',
'line': 189,
'line': 193,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -548,7 +550,7 @@
'name': 'HasTypeParamAttribute',
'type_param': 'int',
'file': 'gtest_xml_output_unittest_.cc',
'line': 196,
'line': 200,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -568,7 +570,7 @@
'name': 'HasTypeParamAttribute',
'type_param': 'long',
'file': 'gtest_xml_output_unittest_.cc',
'line': 196,
'line': 200,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -589,7 +591,7 @@
'name': 'HasValueParamAttribute/0',
'value_param': '33',
'file': 'gtest_xml_output_unittest_.cc',
'line': 180,
'line': 184,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -600,7 +602,7 @@
'name': 'HasValueParamAttribute/1',
'value_param': '42',
'file': 'gtest_xml_output_unittest_.cc',
'line': 180,
'line': 184,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -611,7 +613,7 @@
'name': 'AnotherTestThatHasValueParamAttribute/0',
'value_param': '33',
'file': 'gtest_xml_output_unittest_.cc',
'line': 181,
'line': 185,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand All @@ -622,7 +624,7 @@
'name': 'AnotherTestThatHasValueParamAttribute/1',
'value_param': '42',
'file': 'gtest_xml_output_unittest_.cc',
'line': 181,
'line': 185,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
Expand Down
Loading

0 comments on commit b4aae50

Please sign in to comment.