Skip to content

Commit

Permalink
Only un-escape unicode character encoding color codes #1124
Browse files Browse the repository at this point in the history
  • Loading branch information
Socolin committed Jul 27, 2024
1 parent f236efb commit 6adc384
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/NUnitTestAdapter/NUnitEngine/NUnitTestEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ protected NUnitTestEvent(XmlNode node) : base(node)

public string MethodName => Node.GetAttribute("methodname");
public string ClassName => Node.GetAttribute("classname");
public string Output => Node.SelectSingleNode("output")?.InnerText.UnEscapeUnicodeCharacters();
public string Output => Node.SelectSingleNode("output")?.InnerText.UnEscapeUnicodeColorCodesCharacters();


public CheckedTime StartTime()
Expand Down Expand Up @@ -165,7 +165,7 @@ public IEnumerable<NUnitAttachment> NUnitAttachments
foreach (XmlNode attachment in Node.SelectNodes("attachments/attachment"))
{
var path = attachment.SelectSingleNode("filePath")?.InnerText ?? string.Empty;
var description = attachment.SelectSingleNode("description")?.InnerText.UnEscapeUnicodeCharacters();
var description = attachment.SelectSingleNode("description")?.InnerText.UnEscapeUnicodeColorCodesCharacters();
nUnitAttachments.Add(new NUnitAttachment(path, description));
}
return nUnitAttachments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ public NUnitTestEventSuiteFinished(XmlNode node) : base(node)
var failureNode = Node.SelectSingleNode("failure");
if (failureNode != null)
{
FailureMessage = failureNode.SelectSingleNode("message")?.InnerText.UnEscapeUnicodeCharacters();
StackTrace = failureNode.SelectSingleNode("stack-trace")?.InnerText.UnEscapeUnicodeCharacters();
FailureMessage = failureNode.SelectSingleNode("message")?.InnerText.UnEscapeUnicodeColorCodesCharacters();
StackTrace = failureNode.SelectSingleNode("stack-trace")?.InnerText.UnEscapeUnicodeColorCodesCharacters();
}
ReasonMessage = Node.SelectSingleNode("reason/message")?.InnerText.UnEscapeUnicodeCharacters();
ReasonMessage = Node.SelectSingleNode("reason/message")?.InnerText.UnEscapeUnicodeColorCodesCharacters();
}

public string ReasonMessage { get; }
Expand Down
8 changes: 4 additions & 4 deletions src/NUnitTestAdapter/NUnitEngine/NUnitTestEventTestCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ public NUnitTestEventTestCase(XmlNode node)
if (failureNode != null)
{
Failure = new NUnitFailure(
failureNode.SelectSingleNode("message")?.InnerText.UnEscapeUnicodeCharacters(),
failureNode.SelectSingleNode("stack-trace")?.InnerText.UnEscapeUnicodeCharacters());
failureNode.SelectSingleNode("message")?.InnerText.UnEscapeUnicodeColorCodesCharacters(),
failureNode.SelectSingleNode("stack-trace")?.InnerText.UnEscapeUnicodeColorCodesCharacters());
}

ReasonMessage = Node.SelectSingleNode("reason/message")?.InnerText.UnEscapeUnicodeCharacters();
ReasonMessage = Node.SelectSingleNode("reason/message")?.InnerText.UnEscapeUnicodeColorCodesCharacters();
}
public string ReasonMessage { get; }

Expand All @@ -73,7 +73,7 @@ public string StackTrace
int i = 1;
foreach (XmlNode assertionStacktraceNode in Node.SelectNodes("assertions/assertion/stack-trace"))
{
stackTrace += $"{i++}) " + assertionStacktraceNode.InnerText.UnEscapeUnicodeCharacters();
stackTrace += $"{i++}) " + assertionStacktraceNode.InnerText.UnEscapeUnicodeColorCodesCharacters();
stackTrace += "\n";
}

Expand Down
44 changes: 42 additions & 2 deletions src/NUnitTestAdapter/NUnitEngine/UnicodeEscapeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ namespace NUnit.VisualStudio.TestAdapter.NUnitEngine;

internal static class UnicodeEscapeHelper
{
public static string UnEscapeUnicodeCharacters(this string text)
private const int EscapeAsciiValue = 0x1B;

public static string UnEscapeUnicodeColorCodesCharacters(this string text)
{
if (text == null)
return null;
Expand Down Expand Up @@ -43,13 +45,51 @@ private static bool TryUnEscapeOneCharacter(string text, int position, out char
if (position + unicodeEscapeSample.Length >= text.Length)
return false;


extraCharacterRead = unicodeEscapeSample.Length;
if (!int.TryParse(text.Substring(position + 2, unicodeEscapeSample.Length - 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var escapeValue))
return false;

// Here we only want to escape color escape character when used in a context of a ANSI color code
// See https://github.com/nunit/nunit3-vs-adapter/issues/1124 for more information.
if (escapeValue != EscapeAsciiValue)
return false;

if (!IsAnsiColorCodeSequence(text, position + extraCharacterRead + 1))
return false;

escapedChar = (char)escapeValue;

return true;
}

private static bool IsAnsiColorCodeSequence(string text, int position)

Check failure on line 65 in src/NUnitTestAdapter/NUnitEngine/UnicodeEscapeHelper.cs

View workflow job for this annotation

GitHub Actions / build

Check failure on line 65 in src/NUnitTestAdapter/NUnitEngine/UnicodeEscapeHelper.cs

View workflow job for this annotation

GitHub Actions / build

{
var start = false;
while (position < text.Length)
{
var c = text[position++];
// Look for the begining [
if (c == '[' && !start)
{
start = true;
continue;
}

// Found the 'm' at the end
if (c == 'm' && start)
return true;

// [ was not found
if (!start)
return false;

// Ignore all number and ;
var isDigit = c is >= '0' and <= '9';
if (!isDigit && c != ';')
return false;
}

// At the end without the ending 'm'
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ namespace NUnit.VisualStudio.TestAdapter.Tests.NUnitEngineTests;

public class UnicodeEscapeHelperTests
{
[TestCase("\\u001b", "\u001b")]
[TestCase("\\u001b", "\\u001b")]
[TestCase("\\u001", "\\u001")]
[TestCase("\\u01", "\\u01")]
[TestCase("\\u1", "\\u1")]
[TestCase("\\u001b6", "\u001b6")]
[TestCase("\\u001b6", "\\u001b6")]
[TestCase("\\u001b[0m", "\u001b[0m")]
[TestCase("\\u001b[36m", "\u001b[36m")]
[TestCase("\\u001b[48;5;122mTest", "\u001b[48;5;122mTest")]
[TestCase("some-text", "some-text")]
public void UnEscapeUnicodeCharacters_ShouldReplaceBackslashU(string value, string expected)
public void UnEscapeUnicodeColorCodesCharactersShouldReplaceBackslashU(string value, string expected)
{
Assert.That(value.UnEscapeUnicodeCharacters(), Is.EqualTo(expected));
Assert.That(value.UnEscapeUnicodeColorCodesCharacters(), Is.EqualTo(expected));
}
}

0 comments on commit 6adc384

Please sign in to comment.