Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<SourceRoot Condition="$(SourceRoot) == ''">$(MSBuildThisFileDirectory)</SourceRoot>
<SourcePrefix>6.0.0</SourcePrefix>
<SourcePrefix>7.0.0</SourcePrefix>
</PropertyGroup>

<PropertyGroup>
Expand Down
26 changes: 20 additions & 6 deletions src/JUnit.Xml.TestLogger/JunitXmlSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,12 +298,26 @@ private XElement CreateTestSuiteElement(List<TestResultInfo> results, TestRunCon
// Adding required properties, system-out, and system-err elements in the correct
// positions as required by the xsd. In system-out collapse consecutive newlines to a
// single newline.
var element = new XElement(
var suiteElement = new XElement(
"testsuite",
new XElement("properties"),
testCaseElements,
new XElement("system-out", new XCData(stdOut.ToString())),
new XElement("system-err", new XCData(stdErr.ToString())));
testCaseElements);

// Add system-out and system-err elements only if they have content
var systemOutContent = this.InputSanitizer.Sanitize(stdOut.ToString());
var systemErrContent = this.InputSanitizer.Sanitize(stdErr.ToString());

if (!string.IsNullOrWhiteSpace(systemOutContent))
{
suiteElement.Add(new XElement("system-out", systemOutContent));
}

if (!string.IsNullOrWhiteSpace(systemErrContent))
{
suiteElement.Add(new XElement("system-err", systemErrContent));
}

var element = suiteElement;

element.SetAttributeValue("name", Path.GetFileName(results.First().AssemblyPath));

Expand Down Expand Up @@ -410,12 +424,12 @@ private XElement CreateTestCaseElement(TestResultInfo result)

if (!string.IsNullOrWhiteSpace(stdOut.ToString()))
{
testcaseElement.Add(new XElement("system-out", new XCData(stdOut.ToString())));
testcaseElement.Add(new XElement("system-out", this.InputSanitizer.Sanitize(stdOut.ToString())));
}

if (!string.IsNullOrWhiteSpace(stdErr.ToString()))
{
testcaseElement.Add(new XElement("system-err", new XCData(stdErr.ToString())));
testcaseElement.Add(new XElement("system-err", this.InputSanitizer.Sanitize(stdErr.ToString())));
}

testcaseElement.Add(CreatePropertiesElement(result));
Expand Down
3 changes: 2 additions & 1 deletion src/NUnit.Xml.TestLogger/NUnitXmlSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ private static TestSuite CreateFixture(IGrouping<string, TestResultInfo> results

private static XElement CreateTestCaseElement(TestResultInfo result)
{
var sanitizer = new InputSanitizerXml();
var element = new XElement(
"test-case",
new XAttribute("name", result.DisplayName),
Expand All @@ -267,7 +268,7 @@ private static XElement CreateTestCaseElement(TestResultInfo result)

if (!string.IsNullOrWhiteSpace(stdOut.ToString()))
{
element.Add(new XElement("output", new XCData(stdOut.ToString())));
element.Add(new XElement("output", sanitizer.Sanitize(stdOut.ToString())));
}

if (result.Outcome == TestOutcome.Failed)
Expand Down
3 changes: 2 additions & 1 deletion src/Xunit.Xml.TestLogger/XunitXmlSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ private static bool IsError(TestResultInfo result)

private static XElement CreateTestElement(TestResultInfo result)
{
var sanitizer = new InputSanitizerXml();
var element = new XElement(
"test",
new XAttribute("name", result.DisplayName),
Expand All @@ -266,7 +267,7 @@ private static XElement CreateTestElement(TestResultInfo result)
else if (m.Category == "skipReason")
{
// Using the self-defined category skipReason for now
element.Add(new XElement("reason", new XCData(m.Text)));
element.Add(new XElement("reason", sanitizer.Sanitize(m.Text)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void StoreConsoleOutput_False_DoesNotContainConsoleOut()
Assert.DoesNotContain("{998AC9EC-7429-42CD-AD55-72037E7AF3D8}", passedTestCaseStdOutNode.Value);

var testSuiteStdOutNode = resultsXml.XPathSelectElement("/testsuites/testsuite/system-out");
Assert.IsTrue(testSuiteStdOutNode.Value.Equals(string.Empty));
Assert.IsNull(testSuiteStdOutNode);

TestCaseShouldHaveAttachmentInStandardOut(resultsXml, "PassTest11");
}
Expand All @@ -149,7 +149,7 @@ public void StoreConsoleOutput_False_DoesNotContainConsoleErr()
Assert.IsNull(failedTestCaseStdErrNode);

var testSuiteStdErrNode = resultsXml.XPathSelectElement("/testsuites/testsuite/system-err");
Assert.IsTrue(testSuiteStdErrNode.Value.Equals(string.Empty));
Assert.IsNull(testSuiteStdErrNode);
}

[TestMethod]
Expand Down Expand Up @@ -214,7 +214,7 @@ public void StoreConsoleOutput_TestCase_ContainsConsoleOutOnlyForTestCase()
Assert.Contains("{998AC9EC-7429-42CD-AD55-72037E7AF3D8}", passedTestCaseStdOutNode.Value);

var testSuiteStdOutNode = resultsXml.XPathSelectElement("/testsuites/testsuite/system-out");
Assert.IsTrue(testSuiteStdOutNode.Value.Equals(string.Empty));
Assert.IsNull(testSuiteStdOutNode);

TestCaseShouldHaveAttachmentInStandardOut(resultsXml, "PassTest11");
}
Expand All @@ -236,7 +236,7 @@ public void StoreConsoleOutput_TestCase_ContainsConsoleErrOnlyForTestCase()
Assert.Contains("{33F5FD22-6F40-499D-98E4-481D87FAEAA1}", failedTestCaseStdErrNode.Value);

var testSuiteStdErrNode = resultsXml.XPathSelectElement("/testsuites/testsuite/system-err");
Assert.IsTrue(testSuiteStdErrNode.Value.Equals(string.Empty));
Assert.IsNull(testSuiteStdErrNode);
}

private static void TestCaseShouldHaveAttachmentInStandardOut(XDocument resultsXml, string testcaseName)
Expand Down
106 changes: 94 additions & 12 deletions test/JUnit.Xml.TestLogger.UnitTests/JUnitXmlTestSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void CreateTestSuiteShouldGroupTestSuitesByName()
}

[TestMethod]
public void TestCaseSystemOutShouldUseCDATA()
public void TestCaseSystemOutShouldBeSanitized()
{
var serializer = new JunitXmlSerializer();
var result = CreateTestResultInfo(
Expand All @@ -79,7 +79,7 @@ public void TestCaseSystemOutShouldUseCDATA()
}

[TestMethod]
public void TestCaseSystemErrShouldUseCDATA()
public void TestCaseSystemErrShouldBeSanitized()
{
var serializer = new JunitXmlSerializer();
var result = CreateTestResultInfo(
Expand All @@ -93,7 +93,7 @@ public void TestCaseSystemErrShouldUseCDATA()
}

[TestMethod]
public void TestSuiteSystemOutShouldUseCDATA()
public void TestSuiteSystemOutShouldBeSanitized()
{
var serializer = new JunitXmlSerializer();
var results = new List<TestResultInfo> { CreateTestResultInfo() };
Expand All @@ -112,13 +112,12 @@ public void TestSuiteSystemOutShouldUseCDATA()
var systemOutElement = doc.XPathSelectElement("//testsuite/system-out");

Assert.IsNotNull(systemOutElement);
Assert.IsTrue(systemOutElement.FirstNode is XCData);
var cdata = (XCData)systemOutElement.FirstNode;
StringAssert.Contains(cdata.Value, "Framework info with <xml> & characters");
Assert.IsTrue(systemOutElement.FirstNode is System.Xml.Linq.XText);
StringAssert.Contains(systemOutElement.Value, "Framework info with <xml> & characters");
}

[TestMethod]
public void TestSuiteSystemErrShouldUseCDATA()
public void TestSuiteSystemErrShouldBeSanitized()
{
var serializer = new JunitXmlSerializer();
var results = new List<TestResultInfo> { CreateTestResultInfo() };
Expand All @@ -137,9 +136,92 @@ public void TestSuiteSystemErrShouldUseCDATA()
var systemErrElement = doc.XPathSelectElement("//testsuite/system-err");

Assert.IsNotNull(systemErrElement);
Assert.IsTrue(systemErrElement.FirstNode is XCData);
var cdata = (XCData)systemErrElement.FirstNode;
StringAssert.Contains(cdata.Value, "Error - Error message with <xml> & characters");
Assert.IsTrue(systemErrElement.FirstNode is System.Xml.Linq.XText);
StringAssert.Contains(systemErrElement.Value, "Error - Error message with <xml> & characters");
}

[TestMethod]
public void TestSuiteShouldNotIncludeEmptySystemOutElement()
{
var serializer = new JunitXmlSerializer();
var results = new List<TestResultInfo> { CreateTestResultInfo() };
var messages = new List<TestMessageInfo>(); // No messages

var xml = serializer.Serialize(
CreateTestLoggerConfiguration(),
CreateTestRunConfiguration(),
results,
messages);

var doc = XDocument.Parse(xml);
var systemOutElement = doc.XPathSelectElement("//testsuite/system-out");

Assert.IsNull(systemOutElement, "Empty system-out element should not be included in test suite");
}

[TestMethod]
public void TestSuiteShouldNotIncludeEmptySystemErrElement()
{
var serializer = new JunitXmlSerializer();
var results = new List<TestResultInfo> { CreateTestResultInfo() };
var messages = new List<TestMessageInfo>(); // No messages

var xml = serializer.Serialize(
CreateTestLoggerConfiguration(),
CreateTestRunConfiguration(),
results,
messages);

var doc = XDocument.Parse(xml);
var systemErrElement = doc.XPathSelectElement("//testsuite/system-err");

Assert.IsNull(systemErrElement, "Empty system-err element should not be included in test suite");
}

[TestMethod]
public void TestSuiteShouldIncludeSystemOutElementWhenContentExists()
{
var serializer = new JunitXmlSerializer();
var results = new List<TestResultInfo> { CreateTestResultInfo() };
var messages = new List<TestMessageInfo>
{
new TestMessageInfo(TestMessageLevel.Informational, "Framework info message")
};

var xml = serializer.Serialize(
CreateTestLoggerConfiguration(),
CreateTestRunConfiguration(),
results,
messages);

var doc = XDocument.Parse(xml);
var systemOutElement = doc.XPathSelectElement("//testsuite/system-out");

Assert.IsNotNull(systemOutElement, "Non-empty system-out element should be included in test suite");
Assert.IsTrue(systemOutElement.Value.Contains("Framework info message"));
}

[TestMethod]
public void TestSuiteShouldIncludeSystemErrElementWhenContentExists()
{
var serializer = new JunitXmlSerializer();
var results = new List<TestResultInfo> { CreateTestResultInfo() };
var messages = new List<TestMessageInfo>
{
new TestMessageInfo(TestMessageLevel.Error, "Error message")
};

var xml = serializer.Serialize(
CreateTestLoggerConfiguration(),
CreateTestRunConfiguration(),
results,
messages);

var doc = XDocument.Parse(xml);
var systemErrElement = doc.XPathSelectElement("//testsuite/system-err");

Assert.IsNotNull(systemErrElement, "Non-empty system-err element should be included in test suite");
Assert.IsTrue(systemErrElement.Value.Contains("Error - Error message"));
}

private static LoggerConfiguration CreateTestLoggerConfiguration()
Expand Down Expand Up @@ -193,9 +275,9 @@ private static string SerializeAndExtractElementContent(JunitXmlSerializer seria
var targetElement = testCaseElement.Element(elementName);

Assert.IsNotNull(targetElement, $"Element '{elementName}' not found in testcase");
Assert.IsTrue(targetElement.FirstNode is XCData, $"Element '{elementName}' does not contain CDATA");
Assert.IsTrue(targetElement.FirstNode is System.Xml.Linq.XText, $"Element '{elementName}' should contain text node");

return ((XCData)targetElement.FirstNode).Value;
return targetElement.Value;
}

private static TestSuite CreateTestSuite(string name)
Expand Down
3 changes: 1 addition & 2 deletions test/TestLogger.Fixtures/DotnetTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ public string Execute(string assemblyName, string loggerArgs, bool collectCovera
}
};
cleanProcess.Start();
var cleanOutput = cleanProcess.StandardOutput.ReadToEnd();
cleanProcess.StandardOutput.ReadToEnd();
cleanProcess.WaitForExit();
Console.WriteLine("\n\n## Clean output:\n" + cleanOutput);
}

if (!isMTP)
Expand Down
1 change: 1 addition & 0 deletions test/TestLogger.UnitTests/InputSanitizerXmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public void ReplaceInvalidXmlCharShouldIgnoreEmptyOrNullInput(string input)
[DataRow("aa\0\vbb", @"aa\u0000\u000bbb")]
[DataRow("aa\uFFFE", @"aa\ufffe")]
[DataRow("aa\u001F", @"aa\u001f")] // 0x1F from original JUnit logger bug report.
[DataRow("Hello\x1B[4mWorld", @"Hello\u001b[4mWorld")] // ANSI escape character \x1B
public void ReplaceInvalidXmlCharShouldReplaceInvalidXmlCharWithUnicode(string input, string output)
{
var sut = new InputSanitizerXml();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@ public void SkippedTestElementShouldContainSkippingReason(string resultFileName)
Assert.Equal(1, reasonNodes.Count);

var reasonNode = reasonNodes[0].FirstChild;
Assert.IsType<XmlCDataSection>(reasonNode);
Assert.IsType<XmlText>(reasonNode);

XmlCDataSection reasonData = (XmlCDataSection)reasonNode;
XmlText reasonData = (XmlText)reasonNode;

string expectedReason = "Skipped";
Assert.Equal(expectedReason, reasonData.Value);
Expand Down
Loading