Fix flaky It_generates_satellite_assemblies by decoding captured test stdout as UTF-8#55428
Open
MichaelSimons wants to merge 2 commits into
Open
Fix flaky It_generates_satellite_assemblies by decoding captured test stdout as UTF-8#55428MichaelSimons wants to merge 2 commits into
MichaelSimons wants to merge 2 commits into
Conversation
…test Fixes #55408 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 390f9fba-29f4-4d5a-9178-138258b2b895
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
MichaelSimons
marked this pull request as ready for review
July 23, 2026 13:16
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
MichaelSimons
marked this pull request as draft
July 23, 2026 13:17
MichaelSimons
marked this pull request as ready for review
July 23, 2026 13:18
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses intermittent test failures in the SDK test infrastructure by making redirected stdout capture decode as UTF-8 by default, avoiding host-console code page–dependent mojibake (notably on Windows) when asserting on localized/non-ASCII output.
Changes:
- Default
TestCommand’s captured stdout decoding to UTF-8 when no explicitStandardOutputEncodingis provided. - Add an explanatory comment documenting the flakiness root cause and why UTF-8 is the appropriate default for redirected output.
…apture The satellite-assembly test captures this app's localized stdout. With stdout redirected, Console defaults its output encoding to the host console code page, which varies across CI agents; on some agents 'a-grave' was emitted as a single OEM byte, producing a U+FFFD after UTF-8 capture. Forcing UTF-8 output makes the emitted bytes deterministic on every agent. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 390f9fba-29f4-4d5a-9178-138258b2b895
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #55408
Symptom
Microsoft.NET.Build.Tests.GivenThatWeWantToBuildAnAppWithLibrary.It_generates_satellite_assembliesintermittently fails when asserting the built app's localized stdout contains the French string"Bienvenue à .Net!". Two corruption shapes have been observed across agents:Exit code is 0 and every ASCII line is fine — only the non-ASCII character is mangled. As @baronfel noted on the issue, this is "some kind of encoding/stream error in the stdout - otherwise the expected content looks fine."
Root cause
This is a console/stdout encoding problem in the test path, and it has two sides that must agree, neither of which was pinned:
Child emit side — The built
TestAppprints its localized strings with plainConsole.WriteLine. When its stdout is redirected (as the test harness does), .NET defaultsConsole.OutputEncodingto the host console's active code page. On Windows CI agents that is the OEM code page (e.g. CP437/CP850), which varies by machine and system locale. So the bytes the child emits foràare themselves non-deterministic: UTF-8C3 A0on one agent, a single OEM byte (e.g.0xE0/0x85) on another.Parent capture side — The shared test helper (
TestCommand→Microsoft.DotNet.Cli.Utils.Command) redirects and captures that stdout. WithStandardOutputEncodingleft null,Processdecodes the stream using the parent test host'sConsole.OutputEncoding— again the ambient OEM code page.Because both sides independently follow a machine-dependent code page, they disagree on some agents and the non-ASCII byte(s) get mis-decoded — producing
├á(UTF-8 bytes read as CP437) or�(a lone OEM byte read as UTF-8). Whichever agent an intermittent run lands on determines pass/fail, which is exactly why it flakes.Why the first attempt was insufficient
An earlier revision fixed only the capture side (default the harness to decode UTF-8). That correctly handles agents where the child emits UTF-8, but on an agent where the child emits a single OEM byte it turned
├áinto�— the test still failed. Fixing capture alone cannot work while the child's emit encoding is unpinned. The complete fix must make both sides deterministically UTF-8.Fix
Two small, surgical changes that pin both sides to UTF-8:
test/TestAssets/TestProjects/KitchenSink/TestApp/Program.cs— setConsole.OutputEncoding = Encoding.UTF8;before writing, so the app emits UTF-8 bytes regardless of the host code page. This is BOM-free (Console strips the preamble) and a no-op on platforms that already default to UTF-8.test/Microsoft.NET.TestFramework/Commands/TestCommand.cs— default captured-stdout decoding to UTF-8 when a test hasn't explicitly chosen an encoding:This decodes captured stdout consistently, independent of the host console's code page, and also aligns with the
dotnetCLI, which already emits UTF-8. Tests that opt in viaWithStandardOutputEncoding(...)still win.Why it's correct cross-platform
EntryPointFilePath_WithUnicodeCharactersusesWithStandardOutputEncoding(Encoding.UTF8)).Local validation
Built the SDK (
build.cmd -c Debug, 0 errors) and ran the actual test against the freshly built SDK:It_generates_satellite_assemblies— Passed (1/1).Encoding.Latin1(simulating a hostile OEM agent) reproduced the exact reported failure —Expected string "...Bienvenue � .Net!..." to contain "Bienvenue à .Net!"— then reverted. This ties the reproduction directly to the repo test and confirms the fix is what makes it pass.Additionally reproduced the mechanism end-to-end with standalone built apps under a parent console pinned to CP437: an app using the ambient encoding + UTF-8 capture →
contains-expected=False; an app forcing UTF-8 + UTF-8 capture →contains-expected=True.