Skip to content

Add WebSocket transport for the dotnettestcli protocol (browser-wasm support) - #10118

Merged
Amaury Levé (Evangelink) merged 22 commits into
mainfrom
dev/amauryleve/mtp-transport-neutral-dotnettestcli
Jul 22, 2026
Merged

Add WebSocket transport for the dotnettestcli protocol (browser-wasm support)#10118
Amaury Levé (Evangelink) merged 22 commits into
mainfrom
dev/amauryleve/mtp-transport-neutral-dotnettestcli

Conversation

@Evangelink

@Evangelink Amaury Levé (Evangelink) commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

Decouples the dotnet test pipe protocol (a.k.a. dotnettestcli) from System.IO.Pipes so it can also bootstrap over a WebSocket transport — needed for runtimes without named-pipe support (browser-wasm) — while keeping the existing --server dotnettestcli --dotnet-test-pipe <name> behavior and framing/serializer contract unchanged.

Protocol and transport are decoupled: DotnetTestConnection now depends on a small IClient abstraction (implemented identically in shape by NamedPipeClient and the new DotnetTestWebSocketClient), and the shared framing in NamedPipeConnectionBase operates on a plain Stream instead of PipeStream specifically.

What's new

  • Core refactor: NamedPipeConnectionBase.WriteMessageAsync/ReadNextMessageAsync widened from PipeStream to Stream (pipe-drain behavior isolated behind an is PipeStream check, so named-pipe behavior is unaffected).
  • New WebSocket transport (ServerMode/DotnetTest/Transport/):
    • DotnetTestWebSocketClientIClient implementation, handles connect/auth/request-reply.
    • ClientWebSocketDuplexStream — adapts System.Net.WebSockets.WebSocket to a Stream on non-browser runtimes.
    • BrowserWebSocketDuplexStream — talks to the host's native WebSocket via [JSImport]/[JSExport] JS interop. Real browsers supply WebSocket directly; Node 20 hosts use its built-in implementation via --experimental-websocket, with no npm dependency.
  • CLI: new hidden options --dotnet-test-transport {pipe|websocket}, --dotnet-test-websocket-endpoint, --dotnet-test-websocket-token, with validation that rejects conflicting/incomplete option combinations, malformed/non-WebSocket endpoints, empty tokens, and the named-pipe transport on browser-wasm/wasi-wasm early with actionable errors.
  • Handshake: additive Transport property (id 16, NamedPipe/WebSocket) for diagnostics; ProtocolConstants.SupportedVersions bumped to 1.5.0. Framing and serializer formats are unchanged; older peers ignore the additive property.
  • Auth: per-run token passed as a query-string parameter (browsers can't set custom headers on the WebSocket upgrade handshake — same approach ASP.NET Core SignalR uses); never logged (enforced by a dedicated command-line redactor).
  • Docs: docs/mstest-runner-protocol/004-protocol-dotnet-test-pipe.md updated — the intro now states protocol vs. transport, and §15 documents the WebSocket transport, its security model, validation, Node/browser bootstrap, target-runtime coverage, and known gaps.

Known gaps (documented in doc §15.6, not silently degraded)

  • The reverse server-control channel (session cancellation) stays named-pipe-only; disabled on browser/wasi (same graceful fallback as an old SDK never advertising it).
  • wasi-wasm has no transport implemented yet (no ClientWebSocket, no JS host to interop with) — command-line validation rejects it outright with an actionable error.
  • stdio transport was considered and deliberately not implemented (risk of corrupting user/extension console output by multiplexing frames onto it).

Review process

This PR went through multiple automated and independent review rounds. Findings fixed include browser connect/read/write cancellation, legal zero-length WebSocket messages, abrupt connection loss, diagnostic token/endpoint redaction, CLI endpoint/token validation, immutable InternalAPI baseline tracking, transport handshake assertions, and browser-wasm target-runtime coverage.

The latest CI follow-up fixed Node 20 hosting: Node 20.20 does not expose WebSocket globally unless launched with --experimental-websocket. The browser-wasm WebSocket acceptance bootstrap now passes that built-in runtime flag rather than adding an external npm polyfill. Real-browser bootstrap is unchanged.

Testing

  • Full solution build and pack (.\build.cmd -pack -bl) green.
  • Microsoft.Testing.Platform.UnitTests: 1485 tests passing.
  • Browser-wasm WebSocket acceptance tests under Node: 3/3 passing, including authenticated protocol traffic, stalled-connect cancellation, pending-read cancellation/message ordering, zero-length messages, and pre-cancelled writes.
  • Microsoft.Testing.Platform.DotnetTestProtocolContract.UnitTests: 24 tests passing (protocol contract unaffected).
  • DotnetTestPipe acceptance tests: 19 passing (named-pipe transport behavior unaffected).
  • HelpInfoTests/HelpInfoAllExtensionsTests: 30 passing (new CLI options reflected correctly).
  • MSTest DotnetTestCliTests: 6 passing.
  • DotnetTestWebSocketClientTests: real loopback WebSocket round-trip, auth URI, large-message, connection-loss, cancellation, and zero-length-message-before-reply coverage.
  • CommandLineArgumentsRedactorTests: token and endpoint sanitization, missing values, repeated options, option-shaped secrets, and inline forms.

Follow-up work (out of scope, not part of this repo)

The SDK-side loopback WebSocket gateway/listener (accepting the outbound connection, validating the token, speaking the existing binary frame format) needs to be implemented in dotnet/sdk. When launching a browser-wasm bundle under Node 20, the SDK must pass --experimental-websocket to Node. Vendoring the updated Constants.cs/ObjectFieldIds.cs there is optional since the new Transport handshake property is additive/ignorable.

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com
Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54

…support)

Decouples the 'dotnet test' pipe protocol from System.IO.Pipes so it can bootstrap
on runtimes without named-pipe support (browser-wasm), while keeping the existing
'--server dotnettestcli --dotnet-test-pipe <name>' behavior and wire format
byte-for-byte unchanged.

Core transport refactor:
- Widen NamedPipeConnectionBase.WriteMessageAsync/ReadNextMessageAsync from
  PipeStream to Stream; isolate WaitForPipeDrain behind an 'is PipeStream' check.
- DotnetTestConnection now talks to an IClient (NamedPipeClient or
  DotnetTestWebSocketClient) instead of hard-coding NamedPipeClient, resolved via
  the new DotnetTestTransportKind/TryGetDotnetTestTransport.

New WebSocket transport:
- ClientWebSocketDuplexStream adapts System.Net.WebSockets.WebSocket to a Stream
  for non-browser runtimes.
- BrowserWebSocketDuplexStream talks to the browser's native WebSocket via
  JSImport/JSExport (same pattern as BrowserOutputDevice), with a self-contained
  embedded JS module imported through a data: URL.
- DotnetTestWebSocketClient implements IClient over either adapter, appending the
  per-run auth token as a query-string parameter (browsers can't set custom
  headers on the WebSocket handshake - same approach ASP.NET Core SignalR uses).

CLI/validation:
- New hidden options --dotnet-test-transport, --dotnet-test-websocket-endpoint,
  --dotnet-test-websocket-token.
- PlatformCommandLineProvider rejects conflicting/incomplete transport option
  combinations and the named-pipe transport on browser-wasm/wasi-wasm early,
  with actionable messages.

Protocol:
- Additive handshake property Transport (id 16, NamedPipe/WebSocket) for
  diagnostics; ProtocolConstants.SupportedVersions bumped to 1.5.0.
- docs/mstest-runner-protocol/004-protocol-dotnet-test-pipe.md updated to
  describe the transport-neutral protocol and the new WebSocket transport (§15).

Known gaps documented in §15.6: the reverse server-control channel stays
named-pipe-only (disabled on browser/wasi), wasi-wasm has no transport yet, and
stdio multiplexing was deliberately not attempted.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
- BrowserWebSocketDuplexStream: honor cancellationToken during reads via a new
  WaitForReceiveAsync helper that races the JS receive() promise against the
  token, so a cancelled request/timeout no longer hangs forever on browser-wasm.
- ClientWebSocketDuplexStream: fix a zero-length-message EOF bug (a legitimate
  empty, non-Close WebSocket message was misreported as end-of-stream), and
  convert the retry from recursion to a loop to avoid a potential
  StackOverflowException against a peer sending many consecutive empty messages.
- DotnetTestWebSocketClient.RequestReplyAsync: catch transport exceptions from
  ReadNextMessageAsync (previously only the write path was guarded), since an
  abrupt WebSocket disconnect surfaces as a thrown exception rather than a
  clean 0-byte EOF the way a named pipe does. Factored the shared
  connection-loss handling (exit-process vs. throw) into HandleMissingResponseAsync.
- Added tests: large-message round-trip spanning multiple WebSocket receives,
  server-closes-without-responding (verifies IOException + no process exit when
  exitProcessOnConnectionLoss is false), and cancellation of a pending
  RequestReplyAsync (verifies OperationCanceledException instead of a hang).

Found via 3 rounds of code review (2 code-review passes + 1 rubber-duck pass);
all reported findings fixed and re-verified. Full solution build and the
Microsoft.Testing.Platform.UnitTests / DotnetTestProtocolContract.UnitTests
suites pass (1459 + 24 tests).

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot AI review requested due to automatic review settings July 21, 2026 15:29
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds WebSocket transport support for the dotnettestcli protocol, primarily enabling browser-wasm while retaining named-pipe compatibility.

Changes:

  • Adds browser and non-browser WebSocket stream adapters.
  • Adds transport selection, validation, authentication, and handshake metadata.
  • Updates protocol documentation, resources, API baselines, and tests.
Show a summary per file
File Description
test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/ProtocolTests.cs Updates protocol-version expectation.
test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/DotnetTestWebSocketClientTests.cs Adds non-browser WebSocket transport tests.
test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/PlatformCommandLineProviderTests.cs Tests transport-option validation.
test/UnitTests/Microsoft.Testing.Platform.DotnetTestProtocolContract.UnitTests/DotnetTestProtocolContractTests.cs Pins transport contract constants.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HelpInfoTests.cs Updates core help expectations.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HelpInfoAllExtensionsTests.cs Updates extended help expectations.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.cs Updates named-pipe protocol baseline.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/DotnetTestWebSocketClient.cs Implements the WebSocket protocol client.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/ClientWebSocketDuplexStream.cs Adapts .NET WebSockets to Stream.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/BrowserWebSocketDuplexStream.cs Adds browser JavaScript WebSocket interop.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/IPC/DotnetTestDataConsumer.cs Enables browser use of the consumer.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/IPC/Constants.cs Adds transport constants and protocol 1.5.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/DotnetTestHelper.cs Resolves the selected transport.
src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/DotnetTestConnection.cs Dispatches protocol traffic by transport.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf Adds localized resource entries.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx Defines transport messages and descriptions.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.cs Exposes validation resources to tests.
src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeConnectionBase.cs Generalizes framing from pipes to streams.
src/Platform/Microsoft.Testing.Platform/InternalAPI/InternalAPI.Unshipped.txt Records new internal APIs.
src/Platform/Microsoft.Testing.Platform/InternalAPI/InternalAPI.Shipped.txt Removes prior framing signatures.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.cs Adds transport CLI options and validation.
src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt Records generalized framing APIs.
src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Shipped.txt Removes prior framing signatures.
src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Unshipped.txt Records generalized framing APIs.
src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Shipped.txt Removes prior framing signatures.
src/Platform/Microsoft.Testing.Extensions.MSBuild/InternalAPI.Unshipped.txt Records generalized framing APIs.
src/Platform/Microsoft.Testing.Extensions.MSBuild/InternalAPI.Shipped.txt Removes prior framing signatures.
src/Platform/Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Unshipped.txt Records generalized framing APIs.
src/Platform/Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Shipped.txt Removes prior framing signatures.
docs/mstest-runner-protocol/004-protocol-dotnet-test-pipe.md Documents transport-neutral framing and WebSockets.

Review details

  • Files reviewed: 42/42 changed files
  • Comments generated: 10
  • Review effort level: Medium

…write cancellation

Addresses 3 findings from an independent review of commit 6472e52:

1. Secret leak (High): TestApplication.LogInformationAsync logged the raw
   --diagnostic command-line arguments verbatim, including the value following
   --dotnet-test-websocket-token, contradicting protocol doc SS15.4. Added
   CommandLineArgumentsRedactor, a reusable formatter that masks the token
   value in both space-separated and --option=value/--option:value inline
   forms (handling a missing value and a repeated option), while preserving
   every other argument exactly. Wired into the one call site that logs
   command-line arguments. New CommandLineArgumentsRedactorTests proves the
   token is absent and the placeholder is present across all these shapes.

2. Empty final message treated as EOF (Medium/High): already fixed by the
   prior "Address code review findings" commit (ClientWebSocketDuplexStream
   now loops on any zero-length non-Close result, not just non-final
   fragments) - re-verified, no further change needed here.

3. Browser cancellation (High): BrowserWebSocketDuplexStream.ReadAsync already
   honored CancellationToken (added in the prior commit); WriteAsync did not.
   Since WebSocket.send() in the JS module is synchronous (queues the frame
   and returns immediately), there is no in-flight operation to race - added
   an upfront ThrowIfCancellationRequested() so an already-cancelled token is
   still observed before doing the uncancellable-once-issued send. Also closed
   a message-loss gap in the existing read-cancellation path: on cancellation,
   the abandoned JS receive() promise is now explicitly cleared via a new
   cancelReceive JS function, so a message the peer sends afterward is queued
   for the next receive() call instead of silently resolving (and being
   discarded by) the stale, abandoned one.

   Verified via `dotnet build` (net8.0/net9.0) and `dotnet publish -r
   browser-wasm` (via samples/BrowserPlayground) that the JS interop
   signatures remain valid for the wasm JS-interop source generator; true
   behavioral testing of the JS cancellation path requires the SDK-side
   WebSocket gateway (not part of this repo) to drive it end-to-end under a
   real browser/node runtime, so this residual gap is now documented precisely
   in doc SS15.6 rather than silently left unstated.

Also updated docs/mstest-runner-protocol/004-protocol-dotnet-test-pipe.md:
- SS15.3: added a CSP caveat - the data: URL dynamic import requires the page's
  Content-Security-Policy to permit it; the prior "no additional assets"
  claim was correct but incomplete under a strict script-src.
- SS15.4: documented that the diagnostic log redaction now also covers the raw
  --dotnet-test-websocket-token command-line argument, not just the
  connection URI.
- SS15.6: documented the exact residual testing gap for the browser JS
  cancellation path.

Full solution build (.\build.cmd -c Debug) green. Microsoft.Testing.Platform.UnitTests:
1469 tests passing (was 1459; +10 new CommandLineArgumentsRedactorTests).
dotnet publish -r browser-wasm (samples/BrowserPlayground) succeeds, confirming
the browser JS-interop signatures compile/link correctly for browser-wasm.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 21, 2026 15:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Comments suppressed due to low confidence (2)

src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/BrowserWebSocketDuplexStream.cs:172

  • The browser connection attempt does not observe cancellationToken: after the module import completes, OpenAsync has no token and can remain pending until the browser's network timeout. This can hang startup/shutdown indefinitely for an unreachable endpoint, unlike the non-browser ClientWebSocket.ConnectAsync path. Please make the JS open operation abortable (closing the connecting socket on cancellation) and propagate OperationCanceledException.
    src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/BrowserWebSocketDuplexStream.cs:37
  • This new NET-only internal type and its accessible members are missing from InternalAPI/net/InternalAPI.Unshipped.txt. The project includes that baseline for non-netstandard targets (Microsoft.Testing.Platform.csproj:90-91), and existing browser-only internals are tracked there (for example BrowserOutputDevice in InternalAPI/net/InternalAPI.Shipped.txt:16-17), so RS0016 will fail those builds.
  • Files reviewed: 45/45 changed files
  • Comments generated: 2
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Adds ReadAsync_WhenServerSendsEmptyBinaryMessageBeforeReply_IgnoresItInsteadOfTreatingAsEof to DotnetTestWebSocketClientTests, which drives a loopback server that injects a genuine zero-length, non-Close binary WebSocket frame immediately before the real protocol reply frame. Asserts the client still receives the correct reply instead of treating the empty message as EOF/disconnect, locking in the ClientWebSocketDuplexStream.ReadAsync fix from f49d7e6 and 554fb6b as a regression test requested by the final independent-review verifier.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 21, 2026 16:02
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Comments suppressed due to low confidence (4)

src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/BrowserWebSocketDuplexStream.cs:37

  • This framework-specific internal type is compiled for the net targets, but none of its type or override signatures are listed in InternalAPI/net/InternalAPI.Unshipped.txt. This project explicitly includes that API baseline for non-netstandard targets (Microsoft.Testing.Platform.csproj:90-91), and the analogous BrowserOutputDevice is tracked in InternalAPI/net/InternalAPI.Shipped.txt:16-17; therefore RS0016 will fail under warnings-as-errors. Add all tracked BrowserWebSocketDuplexStream members to the net-specific unshipped file.
    src/Platform/Microsoft.Testing.Platform/ServerMode/DotnetTest/Transport/BrowserWebSocketDuplexStream.cs:172
  • The cancellation token is no longer observed once OpenAsync starts. If the browser WebSocket handshake stalls, IClient.ConnectAsync and platform startup can remain pending after shutdown cancellation. Make the JS-side open operation cancellable, or race it against the token and ensure any socket that opens after cancellation is closed.
    src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.cs:278
  • The endpoint is only checked for option presence, so values such as not-a-uri, https://..., or an empty string pass validation and later fail in CreateWebSocketClient/ClientWebSocket.ConnectAsync with an unhandled URI or scheme exception. Validate that the argument is an absolute ws:// or wss:// URI here so this CLI surface fails early with an actionable message.
            bool hasTransportOption = commandLineOptions.TryGetOptionArgumentList(DotNetTestTransportOptionKey, out string[]? transportArgs)
                && transportArgs is { Length: 1 };
            bool isWebSocketTransport = hasTransportOption && DotNetTestTransportWebSocketArgument.Equals(transportArgs![0], StringComparison.OrdinalIgnoreCase);
            bool hasEndpoint = commandLineOptions.IsOptionSet(DotNetTestWebSocketEndpointOptionKey);
            bool hasToken = commandLineOptions.IsOptionSet(DotNetTestWebSocketTokenOptionKey);

src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.cs:300

  • This fallback error still says --dotnet-test-pipe is required, but the command now also supports WebSocket and on browser-wasm the suggested pipe option is explicitly unsupported. Report that either a pipe name or the complete WebSocket option set is required; otherwise the new valid transport is omitted and browser users are directed toward an impossible configuration.
            // 3. Nothing selects a transport at all (covers: no options given, or --dotnet-test-transport pipe
            // given explicitly without the required --dotnet-test-pipe name).
            if (!hasPipe && !isWebSocketTransport)
            {
                return ValidationResult.InvalidTask(string.Format(CultureInfo.InvariantCulture, PlatformResources.PlatformCommandLineDotnetTestCliRequiresPipe, DotnetTestCliProtocolName, DotNetTestPipeOptionKey));
            }
  • Files reviewed: 45/45 changed files
  • Comments generated: 8
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 22, 2026 07:44
@Evangelink Amaury Levé (Evangelink) added the state/needs-review Awaiting review from the team. label Jul 22, 2026
Harden the browser transport cancellation and close paths, validate WebSocket bootstrap inputs, restore immutable internal API baselines, and add browser-wasm protocol/cancellation coverage plus handshake assertions.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 22, 2026 08:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 43/43 changed files
  • Comments generated: 3
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Redact option-shaped token values, release browser JS proxies on disposal, and atomically arbitrate receive cancellation against message delivery.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 22, 2026 08:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 43/43 changed files
  • Comments generated: 3
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Keep expanded response-file arguments as the sensitivity context while preserving the original displayed command line, and handle empty sensitive values without throwing.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 22, 2026 13:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 48/48 changed files
  • Comments generated: 2
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Avoid replacing whitespace-only sensitive values in error text and accurately describe browser WebSocket interop as import-only.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 22, 2026 13:25
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 48/48 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread docs/mstest-runner-protocol/004-protocol-dotnet-test-pipe.md Outdated
Match parser trimming when sanitizing validation diagnostics and correct the protocol documentation to describe import-only browser interop.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 22, 2026 13:40
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Comments suppressed due to low confidence (1)

src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineArgumentsRedactor.cs:61

  • string.Replace treats the raw argument as an unrestricted substring, so short invalid endpoint/token values corrupt unrelated validation text. For example, an endpoint value of a replaces every a in the “requires an absolute…” diagnostic with the redaction marker. Redaction should target only the exact argument occurrence emitted by the parser/validator (ideally before formatting), rather than globally replacing arbitrary substrings in the completed message.
                error = error.Replace(original, RedactedPlaceholder);
  • Files reviewed: 48/48 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

Avoid unrestricted short-value substring replacement while preserving malformed quoted-token sanitization.

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

Copilot-Session: 282499c0-c68f-41eb-890a-ad47bb78ce54
Copilot Bot review requested due to automatic review settings July 22, 2026 13:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 48/48 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #10118

GradeTestNotes
B (80–89) new CommandLineHandlerTests.
ParseAndValidateAsync_
ShortInvalidEndpoint_
DoesNotCorruptValidationError
Good regression guard with three meaningful assertions; the DoesNotContain("***REDACTED***bsolute", ...) assertion is cryptic without a comment — consider adding an inline note explaining that the single-char endpoint "a" was previously redacted, corrupting the word "absolute" in the error message.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Re-run with
/grade-tests.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🤖 Automated content by GitHub Copilot. Generated by the Grade Tests on PR (on open / sync) workflow. · 27.2 AIC · ⌖ 6.06 AIC · ⊞ 8.9K · [◷]( · )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-review Awaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants