Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep) - #9153

Merged
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615
Jun 16, 2026
Merged

Add black-box baseline tests for dotnet-test pipe protocol (#51615 prep)#9153
Amaury Levé (Evangelink) merged 2 commits into
mainfrom
dev/amauryleve/mtp-pipe-stdout-#51615

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Prep PR for dotnet/sdk#51615 ("Improve stdout/stderr handling of MTP test apps under dotnet test").

This PR is intentionally product-code-free. It introduces a black-box
acceptance harness and three baseline tests that pin today's wire-format
behavior of Microsoft.Testing.Platform running under
--server dotnettestcli, so that the upcoming behavior changes (live
stdout/stderr forwarding, IOutputDevice routing through the pipe,
protocol bump to 1.0.1) can be reviewed against an explicit before/after.

Why a black-box harness?

The production IPC types under src/Platform/Microsoft.Testing.Platform/IPC/*
(NamedPipeServer, IRequest, IResponse, NamedPipeBase, all base
serializers) carry [Microsoft.CodeAnalysis.Embedded], which means they
are emitted as private copies per assembly and cannot be referenced from
the acceptance test project even with InternalsVisibleTo.

Rather than copy-link ~30 files into the test project (and silently
diverge from product over time), the harness re-implements the wire
format on top of System.IO.Pipes.NamedPipeServerStream. As a side
benefit, it now also doubles as a contract test for the wire format.

What's in the PR

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/
├── DotnetTestPipeProtocol.cs ← framing + handshake/event encode/decode (BCL only)
├── FakeDotnetTestSdk.cs ← `FakeDotnetTestSdk.RunAsync(testHost, ...)` harness
├── FakeDotnetTestSdkResult.cs ← DTO returned by harness
└── DotnetTestPipeBaselineTests.cs ← 3 baseline `[TestMethod]`s with inline asset

Baseline tests

  1. DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today
    pins that the test app advertises 1.0.0 and that a fake SDK
    advertising 1.0.0 negotiates 1.0.0.

  2. DotnetTestPipe_EmitsTestSessionStartAndEnd pins that a single
    no-op session produces exactly one TestSessionEvent with
    SessionType=TestSessionStart and one with TestSessionEnd.

  3. DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline
    pins that today the test app emits nothing to stdout/stderr under
    pipe mode for a passing no-op run (the banner is already silenced
    via the existing _isServerMode check in TerminalOutputDevice).

Test results

total: 3
failed: 0
succeeded: 3
duration: 3s 736ms

No product code changes. No public API changes.

Follow-ups (separate PRs)

Once Phase 1 lands, these baseline tests will need to be adjusted to
match the new contracts; today they intentionally describe the current
behavior so the diff is reviewable.

…otnet/sdk#51615)
This PR introduces a hand-rolled `FakeDotnetTestSdk` harness plus three
baseline acceptance tests that pin today's wire-format behavior of
`Microsoft.Testing.Platform` running under `--server dotnettestcli`.
The harness is intentionally black-box: it uses only
`System.IO.Pipes.NamedPipeServerStream` from the BCL and re-implements
the dotnet-test wire format
(`int32 size | int32 serializerId | body`, with leading `ushort fieldCount`
in handshake/event bodies) directly. This was necessary because the
production IPC types under
`src/Platform/Microsoft.Testing.Platform/IPC/*` are decorated with
`[Microsoft.CodeAnalysis.Embedded]` and so cannot be referenced across
assembly boundaries even with `InternalsVisibleTo`. As a side benefit
the harness now also acts as a contract test for the wire format.
The three tests:
1. `DotnetTestPipe_TestAppAdvertisesAndNegotiatesProtocolV100_Today`
pins protocol negotiation: the test app advertises `1.0.0`, and a
fake SDK that advertises `1.0.0` negotiates `1.0.0`.
2. `DotnetTestPipe_EmitsTestSessionStartAndEnd` pins that a single
no-op session produces exactly one `TestSessionEvent` with
`SessionType=TestSessionStart` and one with `TestSessionEnd`.
3. `DotnetTestPipe_ChildEmitsNoStdoutOrStderrForPassingRun_Baseline`
pins that today the test app emits nothing to stdout/stderr under
pipe mode for a passing no-op run (banner is already silenced via
the existing `_isServerMode` check in `TerminalOutputDevice`).
These baselines lock down the current behavior so subsequent work on
dotnet/sdk#51615 (live stdout/stderr forwarding, `IOutputDevice`
routing through the pipe, protocol bump to 1.0.1) can be reviewed
against an explicit before/after.
No product code changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 15, 2026 13:38

CopilotAI 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

This PR adds a black-box acceptance test harness and baseline tests that exercise the current --server dotnettestcli --dotnet-test-pipe wire protocol behavior of Microsoft.Testing.Platform when run under dotnet test, to enable clear before/after review for the upcoming dotnet/sdk#51615 behavior changes.

Changes:

  • Introduces a minimal pipe protocol reader/writer (DotnetTestPipeProtocol) implemented using only BCL types.
  • Adds a fake “dotnet test SDK” harness (FakeDotnetTestSdk) that hosts the pipe server, performs handshake negotiation, and captures frames.
  • Adds three baseline acceptance tests that pin current protocol negotiation, session start/end events, and “no stdout/stderr” behavior under pipe mode.
Show a summary per file
FileDescription
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdkResult.csDTO capturing handshake/messages/process output observed during a pipe-mode run.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/FakeDotnetTestSdk.csFake SDK pipe server harness + handshake/version negotiation logic.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeProtocol.csBlack-box framing + handshake and session-event decoding/encoding helpers.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeBaselineTests.csBaseline acceptance tests + inline test asset used to drive pipe-mode behavior.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 3

@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9153

3 new integration tests graded across 1 file. All three earn A — clear Arrange/Act/Assert structure, multiple meaningful assertions with rich diagnostic failure messages, and no anti-patterns. The baseline-contract pattern (documenting current behavior so regressions are visible as intentional diffs) is a particularly valuable technique for protocol tests.

ΔTestGradeBandNotes
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
ChildEmitsNoStdoutOrStderrForPassingRun_
Baseline
A90–100Three complementary negative assertions cover stdout banner, full stdout, and stderr; each embeds captured output in its failure message.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
EmitsTestSessionStartAndEnd
A90–100Verifies both event count and ordering; diagnostic message surfaces the actual sequence on failure.
newDotnetTestPipeBaselineTests.
DotnetTestPipe_
TestAppAdvertisesAndNegotiatesProtocolV100_
Today
A90–100Null preconditions + two equality assertions pin the version-negotiation contract; messages explain the expected baseline evolution path.

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 242.7 AIC · ⌖ 12.9 AIC · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 930.5 AIC · ⌖ 12.4 AIC ·

- Trim SDK supported-version tokens and project app versions via Select
- Fix misleading CurrentUserOnly comment (harness targets $(NetCurrent))
- Advance stream past extra SessionType bytes to stay aligned
- Remove unnecessary Task.Run wrapper around already-async ExecuteAsync
- Make SelectHighestMutuallySupportedVersion private static
- Add assertion message for SentHandshakeReply guard
- Use Regex-typed DoesNotMatchRegex overload to keep Compiled flag
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit f5704c4 into mainJun 16, 2026
88 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/mtp-pipe-stdout-#51615 branch June 16, 2026 08:05
Sign up for freeto 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.

Consider: Disable MTP's own TerminalTestReporter when running under server mode (pipe specifically maybe?)

2 participants

@Evangelink