Skip to content

Fix #2561: Escape control characters in assertion error messages#2690

Merged
nohwnd merged 1 commit into
pester:mainfrom
nohwnd:fix-2561-escape-chars
Jun 12, 2026
Merged

Fix #2561: Escape control characters in assertion error messages#2690
nohwnd merged 1 commit into
pester:mainfrom
nohwnd:fix-2561-escape-chars

Conversation

@nohwnd

@nohwnd nohwnd commented Apr 3, 2026

Copy link
Copy Markdown
Member

Fix #2561

Format-String2 now escapes control characters as Unicode control pictures so they are visible in error messages. Characters like ESC (used in ANSI sequences) now display as their Unicode symbol instead of being invisible.

Copilot-generated fix.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Comment thread src/Format2.ps1 Outdated
@nohwnd nohwnd force-pushed the fix-2561-escape-chars branch from af6075c to 1d213ef Compare April 3, 2026 10:13
@nohwnd nohwnd force-pushed the fix-2561-escape-chars branch from 1d213ef to 1998896 Compare June 12, 2026 11:51
@nohwnd nohwnd marked this pull request as ready for review June 12, 2026 11:51
@nohwnd nohwnd added the Assertions For issues related with assertions label Jun 12, 2026
@nohwnd nohwnd force-pushed the fix-2561-escape-chars branch 2 times, most recently from 39c88be to eb5917c Compare June 12, 2026 13:16
@nohwnd

nohwnd commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

Rewrote at eb5917c per your comments — single StringBuilder pass, fast path for the common no-special-chars case:

  • Module-load [char[]] $script:Format2ControlChars covering 0x00..0x1F.
  • String.IndexOfAny for the cheap probe; if none, just "'$Value'" — no rebuild.
  • Slow path: one StringBuilder, one foreach over GetEnumerator(), control chars get + 0x2400 (Unicode Control Pictures, same trick as Format-CDataString in NUnit3).

Micro-bench (50k calls, PS 7.6.2):

  • fast path: ~1.4s
  • slow path: ~6.8s

Side benefit: now escapes the entire 0x00..0x1F range instead of just 8 hand-listed chars — vertical tab, FS/GS/RS/US etc. also become visible.

Tests: 69/69 green on both PS 7.6 and PS 5.1.

@nohwnd nohwnd force-pushed the fix-2561-escape-chars branch 2 times, most recently from f923523 to d89c54d Compare June 12, 2026 13:27
@nohwnd

nohwnd commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

Moved the hot loop to Pester.Formatter.EscapeControlChars (src/csharp/Pester/Formatter.cs) at d89c54d. Format-String2 is now a one-liner delegating to the C# static.

Correctness on 200,000-char input with 10k each of NUL/TAB/LF/ESC scattered through it — all 40k control chars converted to U+2400..U+241B, zero raw control chars left.

Bench (1k iterations, PS 7.6.2):

length fast (no specials) slow (1 ESC) slow (all ESC)
100 81 ms 56 ms 98 ms
1,000 80 ms 107 ms 95 ms
10,000 422 ms 386 ms 382 ms
100,000 3,685 ms 3,754 ms 3,784 ms

For a typical short error-message string fast and slow paths are both ~0.08 ms per call. 69/69 tests green on PS 7.6 and PS 5.1.

Format-String2 now escapes control characters as Unicode control pictures
so they are visible in error messages. Characters like ESC (used in ANSI
sequences) now display as their Unicode symbol instead of being invisible.

Copilot-generated fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nohwnd nohwnd force-pushed the fix-2561-escape-chars branch from d89c54d to 6f6e181 Compare June 12, 2026 13:32
@nohwnd

nohwnd commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

Good call — pulled the <empty> check and quote-wrapping back out into Format-String2 at 6f6e181. The C# helper now only does what its name says (escape control chars; returns input unchanged when no escaping is needed). 69/69 still green on PS 7.6 and PS 5.1.

function Format-String2 ($Value) {
    if ($null -eq $Value -or $Value.Length -eq 0) {
        return '<empty>'
    }
    "'" + [Pester.Formatter]::EscapeControlChars($Value) + "'"
}

@nohwnd nohwnd enabled auto-merge (squash) June 12, 2026 13:33
@nohwnd nohwnd merged commit 42e4169 into pester:main Jun 12, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Assertions For issues related with assertions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should-BeString: Doesn't handle escape character correctly in error message

1 participant