Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jul 25, 2025

This PR fixes the issue where test display names containing escape characters (like \n, \t, etc.) are interpreted as actual control characters in console output instead of being displayed literally, and includes performance optimization with multi-targeting framework support.

Problem

When test display names contain escape characters, they break the console output formatting. As shown in the original issue, a test framework publishing test nodes with display names like "Hello(\nWorld {i})" causes the console output to be malformed:

Problem demonstration

The newlines in test names are interpreted as actual line breaks, making the output difficult to read and potentially interfering with terminal functionality.

Solution

The fix replaces all C0 control characters (U+0000-U+001F) with their Unicode control picture equivalents:

  • \n (newline) → (U+240A)
  • \t (tab) → (U+2409)
  • \r (carriage return) → (U+240D)
  • \x001B (escape) → (U+241B)
  • \0 (null) → (U+2400)
  • All other C0 control characters → corresponding Unicode control pictures

After the fix, test names like "Hello(\nWorld 0)" display cleanly as "Hello(␊World 0)" where the control character is visible but doesn't break the console layout.

Multi-Targeting Framework Optimization

The NormalizeSpecialCharacters method has been optimized with conditional compilation to support the project's multi-targeting requirements (netstandard2.0, net6.0, net7.0, net8.0, net9.0):

For .NET 8.0 and later:

  • Uses SearchValues<char> for O(1) detection of control characters
  • Leverages AsSpan().IndexOfAny() for optimal performance
  • Single allocation StringBuilder approach

For earlier frameworks (netstandard2.0, net6.0, net7.0):

  • Uses traditional char[] arrays with IndexOfAny()
  • Maintains identical functionality with compatibility fallback
  • Same optimization benefits where possible

Both implementations provide:

  • Early returns for strings without control characters (zero allocation)
  • Single pass through string with pre-allocated StringBuilder
  • Bit manipulation (0x2400 + c) for Unicode control picture conversion

Implementation

Enhanced NormalizeSpecialCharacters method:

  • Extended from handling just null and escape characters to all C0 control characters (U+0000-U+001F)
  • Multi-targeting optimization using conditional compilation pragmas
  • Uses Unicode control pictures for visual representation

Applied normalization in key locations:

  • RenderTestCompleted - for test execution results output
  • TestDiscovered - when storing discovered test names
  • TestInProgress - when tracking active tests
  • Standard output/error formatting with selective whitespace normalization

Files Modified

  • src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.cs
  • test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs

Testing

Added comprehensive parameterized unit tests covering all 32 C0 control characters (U+0000-U+001F)
Manual verification confirms the fix resolves console formatting issues
Existing tests preserved - simple test names without special characters remain unchanged
Multi-targeting validation - optimization works across all supported framework versions
Performance optimized - normalization only occurs when special characters are present with minimal overhead

Impact

  • Fixes console output corruption caused by control characters in test names
  • Maintains backward compatibility with existing test names
  • Framework-optimized performance leveraging best available APIs per target framework
  • Cross-platform compatible using widely supported Unicode control pictures

Fixes #5133.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@Copilot Copilot AI changed the title [WIP] passed/failed/skipped {TestDisplayName} interprets escape characters Fix escape character handling in test display names Jul 25, 2025
@Copilot Copilot AI requested a review from Evangelink July 25, 2025 14:48
Copilot finished work on behalf of Evangelink July 25, 2025 14:48
Copy link
Member

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the added tests to be parameterized and test all the special characters we handle

Copy link
Contributor Author

Copilot AI commented Jul 25, 2025

Update the added tests to be parameterized and test all the special characters we handle

Updated the tests to be parameterized with all 32 C0 control characters (U+0000-U+001F) that are handled by the NormalizeSpecialCharacters method. Both test completion and test discovery scenarios now comprehensively test every special character with proper validation logic. Fixed in commit a91dafa.

@Copilot Copilot AI requested a review from Evangelink July 25, 2025 17:23
Copilot finished work on behalf of Evangelink July 25, 2025 17:23
Copilot AI and others added 6 commits July 30, 2025 15:56
- Enhanced NormalizeSpecialCharacters to handle all C0 control characters (U+0000-U+001F)
- Added NormalizeTestDisplayName method to apply normalization to test names
- Updated RenderTestCompleted to normalize display names when showing test results
- Updated TestDiscovered and TestInProgress to normalize display names when storing
- Added comprehensive tests for escape character normalization
- Control characters like \n, \t, \r, ESC are now displayed as Unicode control pictures (␊, ␉, ␍, ␛)

This prevents escape characters in test display names from breaking console output formatting.

Co-authored-by: Evangelink <[email protected]>
@Evangelink Evangelink marked this pull request as ready for review July 30, 2025 14:47
@Evangelink Evangelink enabled auto-merge (squash) July 31, 2025 08:19
Evangelink and others added 2 commits July 31, 2025 10:21
Co-authored-by: Jakub Jareš <[email protected]>
Co-authored-by: Jakub Jareš <[email protected]>
@Copilot Copilot AI requested a review from nohwnd July 31, 2025 15:47
Copilot finished work on behalf of nohwnd July 31, 2025 15:47
Copilot finished work on behalf of nohwnd July 31, 2025 15:57
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.cs
Youssef1313
Youssef1313 previously approved these changes Aug 4, 2025
Copilot finished work on behalf of nohwnd August 4, 2025 10:58
@Evangelink Evangelink requested a review from Youssef1313 August 13, 2025 09:38
@Evangelink Evangelink merged commit 3ba3ee4 into main Aug 18, 2025
8 checks passed
@Evangelink Evangelink deleted the copilot/fix-5133 branch August 18, 2025 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

passed/failed/skipped {TestDisplayName} interprets escape characters
4 participants