Skip to content

Commit

Permalink
Escape invalid XML chars in testCase and testSuite names (#284)
Browse files Browse the repository at this point in the history
With a
[ParameterizedTest](https://junit.org/junit5/docs/5.0.2/api/org/junit/jupiter/params/ParameterizedTest.html)
it is possible to generate test case names with invalid XML characters.
E.g.

```
@ParameterizedTest
@valuesource(strings = {"Weird\bname"})
void testFoo(String input) {
    ...
}
```

The test case name is derived from the input string, which in this case
contains an invalid XML char `\b`. When tools (like IDEs) try to parse
the junit XML, they'll fail due to the invalid char.

Fix it by escaping test case names. It looks like [test suite
names](https://junit.org/junit5/docs/5.0.3/api/org/junit/jupiter/api/DisplayName.html)
could also contain invalid XML chars, so I'm escaping those as well.

Closes #285
  • Loading branch information
sfc-gh-abalik authored Jul 29, 2024
1 parent 2393517 commit a78287a
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void toXml(XMLStreamWriter xml, TestData test) throws XMLStreamException
}

xml.writeStartElement("testcase");
xml.writeAttribute("name", name);
xml.writeAttribute("name", escapeIllegalCharacters(name));
xml.writeAttribute("classname", LegacyReportingUtils.getClassName(testPlan, id));

/* @Nullable */ Duration maybeDuration = test.getDuration();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.bazel_contrib.contrib_rules_jvm.junit5;

import static com.github.bazel_contrib.contrib_rules_jvm.junit5.SafeXml.escapeIllegalCharacters;
import static com.github.bazel_contrib.contrib_rules_jvm.junit5.SafeXml.writeTextElement;

import java.util.Collection;
Expand All @@ -19,7 +20,7 @@ public void toXml(XMLStreamWriter xml, TestData suite, Collection<TestData> test
throws XMLStreamException {
xml.writeStartElement("testsuite");

xml.writeAttribute("name", suite.getId().getLegacyReportingName());
xml.writeAttribute("name", escapeIllegalCharacters(suite.getId().getLegacyReportingName()));
xml.writeAttribute("tests", String.valueOf(tests.size()));

int errors = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,38 @@ public void ensureOutputsAreProperlyEscaped() {
assertEquals("&#27;[31mAlso bad!&#27;[0m", text);
}

@Test
public void ensureTestCaseNamesAreProperlyEscaped() {
var testDescriptor = new StubbedTestDescriptor(createId("Weird\bname"));
var identifier = TestIdentifier.from(testDescriptor);

var testCaseData = new TestData(identifier);
testCaseData.mark(TestExecutionResult.successful());

Document xml = generateTestXml(Mockito.mock(TestPlan.class), testCaseData);

Node item = xml.getElementsByTagName("testcase").item(0);
String testName = item.getAttributes().getNamedItem("name").getNodeValue();

assertEquals("[engine:mocked]/[class:ExampleTest]/[method:Weird&#8;name", testName);
}

@Test
public void ensureTestSuiteNamesAreProperlyEscaped() {
var testDescriptor = new StubbedTestDescriptor(createId("Weird\bname"));
var identifier = TestIdentifier.from(testDescriptor);

var testSuiteData = new TestData(identifier);
testSuiteData.mark(TestExecutionResult.successful());

Document xml = generateTestXml(Mockito.mock(TestPlan.class), testSuiteData, List.of());

Node item = xml.getElementsByTagName("testsuite").item(0);
String testName = item.getAttributes().getNamedItem("name").getNodeValue();

assertEquals("[engine:mocked]/[class:ExampleTest]/[method:Weird&#8;name()]", testName);
}

private Document generateTestXml(TestPlan testPlan, TestData testCase) {
return generateDocument(xml -> new TestCaseXmlRenderer(testPlan).toXml(xml, testCase));
}
Expand Down

0 comments on commit a78287a

Please sign in to comment.