Forward generic warning/error host messages over the dotnet test pipe (protocol 1.3.0)#9521
Conversation
… (protocol 1.3.0) Under the dotnet test pipe protocol the host installed a no-op (or AzDO-only) output device, so host-side diagnostics produced outside test results (hang/crash dump diagnostics, retry summaries, generic extension/framework warnings and errors) were swallowed in multi-assembly runs. This adds a generic DisplayMessage (serializer id 12, protocol 1.3.0) carrying a severity level + text. The host's forwarding output device now relays WarningMessageOutputDeviceData / ErrorMessageOutputDeviceData to the SDK as a DisplayMessage (gated on the SDK negotiating 1.3.0), alongside the existing AzureDevOpsLogMessage path. Informational output is still discarded (severity floor = Warning/Error). The forwarding device is now installed under the pipe protocol everywhere, not just on Azure DevOps agents. Forwarding is version-gated only; a finer-grained handshake type filter is left as a future, additively-introducible knob. The dotnet/sdk consumer side (its own DisplayMessage copy + routing to WriteWarningMessage/WriteErrorMessage) is a separate follow-up, mirroring the AzureDevOpsLogMessage work. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR extends the dotnet test pipe protocol in Microsoft.Testing.Platform (MTP) to forward generic host warning/error diagnostics (not just test results or Azure DevOps logging commands) across multi-assembly runs, by introducing a new DisplayMessage wire frame and negotiating it via protocol 1.3.0.
Changes:
- Add
DisplayMessagemodel/levels + serializer (serializer id 12) and bumpProtocolConstants.SupportedVersionsto include 1.3.0. - Update the pipe connection + output device plumbing so Warning/Error output device messages are forwarded over the protocol when the negotiated version is >= 1.3.0.
- Add/extend unit + acceptance tests, and extend the black-box acceptance wire decoder to recognize
DisplayMessage.
Show a summary per file
| File | Description |
|---|---|
| test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/DotnetTestPassthroughOutputDeviceTests.cs | Adds unit coverage for warning/error forwarding lookup vs informational suppression behavior. |
| test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/ProtocolTests.cs | Adds DisplayMessage round-trip tests, serializer-id stability check (id 12), and version string update. |
| test/UnitTests/Microsoft.Testing.Platform.DotnetTestProtocolContract.UnitTests/DotnetTestProtocolContractTests.cs | Mirrors serializer-id stability + protocol version bump in the contract test project. |
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.cs | Extends acceptance wire reader with serializer id 12 + DisplayMessage body decoding. |
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeDisplayMessageForwardingTests.cs | New acceptance tests validating forwarding at 1.3.0 and absence at 1.2.0. |
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.cs | Updates baseline advertised-protocol expectations to include 1.3.0. |
| src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/IPC/Serializers/DisplayMessageSerializer.cs | New serializer for DisplayMessage (id 12) using the shared field ids/levels. |
| src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/IPC/ObjectFieldIds.cs | Adds embedded DisplayMessageFieldsId with stable serializer + field ids. |
| src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/IPC/Models/DisplayMessage.cs | New IPC model representing forwarded host diagnostics with severity. |
| src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/IPC/Constants.cs | Adds embedded DisplayMessageLevels + bumps supported protocol versions to 1.3.0. |
| src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/DotnetTestConnection.cs | Adds negotiation flag IsDisplayMessageForwardingSupported and sends DisplayMessage requests. |
| src/Platform/Microsoft.Testing.Platform/OutputDevice/OutputDeviceManager.cs | Installs DotnetTestPassthroughOutputDevice under pipe protocol unconditionally (not just on AzDO). |
| src/Platform/Microsoft.Testing.Platform/OutputDevice/DotnetTestPassthroughOutputDevice.cs | Forwards warning/error messages as DisplayMessage (1.3.0+) while preserving informational suppression. |
| src/Platform/Microsoft.Testing.Platform/IPC/Serializers/RegisterSerializers.cs | Registers DisplayMessageSerializer so frames can be sent/received under the pipe protocol. |
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 2
- Review effort level: Low
This comment has been minimized.
This comment has been minimized.
Address PR review: the host serializer now skips any extra bytes beyond the single Level byte when the declared field size is larger (forward-compat for a widened Level / corrupted frame), and the black-box acceptance decoder respects the field size and handles end-of-stream explicitly instead of casting a -1 ReadByte() result to a byte. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
|
/azp run microsoft.testfx |
|
Azure Pipelines successfully started running 1 pipeline(s). |
🧪 Test quality grade — PR #952112 tests graded across 5 files (7 new, 5 modified). 10 grade A, 2 grade B. Both B-grade tests are
This advisory comment was generated automatically. Grades are heuristic
|
Context
Following up on #9463 (Azure DevOps logging-command forwarding), this continues closing the single-assembly ↔
dotnet testfeature-parity gap.Under the
dotnet testpipe protocol the host installs a no-op output device (the SDK'sTerminalTestReporterowns user-facing output), so the only host output that crossed the wire was test results, artifacts, session events, and — since #9463 — Azure DevOps logging commands. Every other host UI message was swallowed. That meant host-side diagnostics produced outside test results were lost in multi-assembly runs:MessageLoggerAdapter, adapter banners, custom extensions) — the broadest gapWhat this does
Rather than special-casing each producer, this adds a generic pass-through channel and lets the client decide what to do with the messages.
Wire contract (shared with dotnet/sdk via
ObjectFieldIds.cs+Constants.cs):ProtocolConstants.SupportedVersions→1.0.0;1.1.0;1.2.0;1.3.0.DisplayMessageFieldsId(serializer id 12) andDisplayMessageLevels(Information/Warning/Error).Host side (this repo only):
DisplayMessagemodel +DisplayMessageSerializer(mirrorsAzureDevOpsLogMessage).DotnetTestConnection: newIsDisplayMessageForwardingSupported(negotiated ≥ 1.3.0) + aSendMessageAsynccase.DotnetTestPassthroughOutputDevicenow forwardsWarningMessageOutputDeviceData/ErrorMessageOutputDeviceDataasDisplayMessage(gated on 1.3.0), alongside the existing Azure DevOps path. Informational text is still discarded (severity floor = Warning/Error).OutputDeviceManagernow installs the forwarding device under the pipe protocol everywhere, not just on Azure DevOps agents (generic messages aren't AzDO-specific; the AzDO branch stays naturally inert off-agent).The SDK-side sink already exists (
TerminalTestReporter.WriteWarningMessage/WriteErrorMessage); only the transport was missing.Design decisions
WantedMessageSeverityknob can be added later without a protocol break.AzureDevOpsLogMessageas its own path — it has a verbatim##vso[...]pipeline-log requirement and is gated on the agent; folding it intoDisplayMessagewould change its semantics.SDK follow-up (separate, like #9463)
dotnet/sdk needs its own
DisplayMessagemodel/serializer copy and routing to the shared reporter'sWriteWarningMessage/WriteErrorMessage. Not done here by design — the message models/serializers aren't shared source yet (only the zero-dependencyObjectFieldIds.cs+Constants.csare).Tests
ProtocolTests):DisplayMessageround-trip (with and without null optional fields), serializer-id stability (id 12), protocol-version string. Mirrored in the standaloneDotnetTestProtocolContract.UnitTests.DotnetTestPassthroughOutputDeviceTests): warning/error look up the connection; informational text is swallowed without touching the service provider.DotnetTestPipeDisplayMessageForwardingTests): at 1.3.0 a framework's warning + error are forwarded asDisplayMessagewith the correct severity levels and instance-id correlation; at 1.2.0 nothing is forwarded.DotnetTestPipeProtocol) extended withDisplayMessagedecoding; baseline test updated to the new advertised version string.All green locally: platform builds clean, 26 platform unit tests + 6 contract tests + 2 new acceptance tests pass, and the 7 existing AzDO-forwarding + baseline acceptance tests still pass (no regression).