Skip to content

Commit

Permalink
Fix a bug where the NUnit-Report fails to generate if the test output…
Browse files Browse the repository at this point in the history
… contains Virtual Terminal Sequences (#2511)

* Add fix

* Simplfy test

* Handle ESC and Bell characters

* Improve test

* Support WindowsPowerShell

* Better representation of VT sequences

* Use unicode printable block to represent invalid characters in CData

* Use unicode printable block to represent invalid characters in CData

* Improve perf when writting output

* Optmize for messages that don't have the special chars

* No dt

* Indexing

* Powershell 5 does not have unicode escape

---------

Co-authored-by: Jakub Jareš <[email protected]>
  • Loading branch information
ocalvo and nohwnd authored Jul 1, 2024
1 parent 337c213 commit 718ba6d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 6 deletions.
39 changes: 33 additions & 6 deletions src/functions/TestResults.NUnit3.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# NUnit3 schema docs: https://docs.nunit.org/articles/nunit/technical-notes/usage/Test-Result-XML-Format.html

[char[]] $script:invalidCDataChars = foreach ($ch in (0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)) { [char]$ch }

function Write-NUnit3Report([Pester.Run] $Result, [System.Xml.XmlWriter] $XmlWriter) {
# Write the XML Declaration
$XmlWriter.WriteStartDocument($false)
Expand Down Expand Up @@ -537,14 +539,39 @@ function Write-NUnit3TestCaseAttributes {
}

function Write-NUnit3OutputElement ($Output, [System.Xml.XmlWriter] $XmlWriter) {
$outputString = @(foreach ($o in $Output) {
if ($null -eq $o) {
[string]::Empty
} else {
$o.ToString()
# The characters in the range 0x01 to 0x20 are invalid for CData
# (with the exception of the characters 0x09, 0x0A and 0x0D)
# We convert each of these using the unicode printable version,
# which is obtained by adding 0x2400
[int]$unicodeControlPictures = 0x2400

# Avoid indexing into an enumerable, such as a `string`, when there is only one item in the
# output array.
$out = @($Output)
$linesCount = $out.Length
$o = for ($i = 0; $i -lt $linesCount; $i++) {
# The input is array of objects, convert them to strings.
$line = if ($null -eq $out[$i]) { [String]::Empty } else { $out[$i].ToString() }

if (0 -gt $line.IndexOfAny($script:invalidCDataChars)) {
# No special chars that need replacing.
$line
}
else {
$chars = [char[]]$line;
$charCount = $chars.Length
for ($j = 0; $j -lt $charCount; $j++) {
$char = $chars[$j]
if ($char -in $script:invalidCDataChars) {
$chars[$j] = [char]([int]$char + $unicodeControlPictures)
}
}

$chars -join ''
}
}) -join [System.Environment]::NewLine
}

$outputString = $o -join [Environment]::NewLine
$XmlWriter.WriteStartElement('output')
$XmlWriter.WriteCData($outputString)
$XmlWriter.WriteEndElement()
Expand Down
28 changes: 28 additions & 0 deletions tst/Pester.RSpec.TestResults.NUnit3.ts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,34 @@ i -PassThru:$PassThru {
$xmlResult.Validate({ throw $args[1].Exception })
}

t 'replaces virtual terminal escape sequences with their printable representations' {
$sb = {
Describe 'Describe VT Sequences' {
It "Successful" {
$esc = [char][int]0x1B
$bell = [char][int]0x07

# write escape sequences to output
"$esc[32mHello`tWorld$esc[0m"
"Ring the bell$bell"
}
}
}
$r = Invoke-Pester -Configuration ([PesterConfiguration]@{ Run = @{ ScriptBlock = $sb; PassThru = $true }; Output = @{ Verbosity = 'None' } })

$xmlResult = [xml] ($r | ConvertTo-NUnitReport -Format NUnit3)
$xmlResult.Schemas.XmlResolver = New-Object System.Xml.XmlUrlResolver
$xmlResult.Schemas.Add($null, $schemaPath) > $null
$xmlResult.Validate({ throw $args[1].Exception })
$xmlDescribe = $xmlResult.'test-run'.'test-suite'.'test-suite'
$xmlTest = $xmlDescribe.'test-case'
$message = $xmlTest.output.'#cdata-section' -split "`n"

# message has the escape sequences replaced with their printable representations
$message[0] | Verify-Equal "␛[32mHello`tWorld␛[0m"
$message[1] | Verify-Equal "Ring the bell␇"
}

t 'should use TestResult.TestSuiteName configuration value as name-attribute for run and root Assembly test-suite' {
$sb = {
Describe 'Describe' {
Expand Down

0 comments on commit 718ba6d

Please sign in to comment.