Skip to content

Fix forward-compat crash loading old 2.x extensions on .NET Framework (#9710)#9739

Merged
Evangelink merged 1 commit into
mainfrom
dev/amauryleve/improve-backcompat-acceptance-test
Jul 8, 2026
Merged

Fix forward-compat crash loading old 2.x extensions on .NET Framework (#9710)#9739
Evangelink merged 1 commit into
mainfrom
dev/amauryleve/improve-backcompat-acceptance-test

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

Fixes #9710. A newer Microsoft.Testing.Platform combined with an older (2.x) extension crashes with MissingMethodException on .NET Framework:

Method not found: 'Void Polyfills.Polyfill.Deconstruct(...)'.
   at Microsoft.Testing.Extensions.Telemetry.AppInsightsProvider.<IngestLoopAsync>d__18.MoveNext()

Root cause

Old 2.x extension assemblies (Telemetry, TrxReport, TrxReport.Abstractions, VSTestBridge) were compiled against the platform's internal Polyfills.Polyfill helper, which they access from the platform assembly via [InternalsVisibleTo] (they don't embed their own copy). Their baked-in member references are resolved by the runtime against the platform assembly. Newer platform code stopped using those helpers, so they were dropped — and loading an old extension's netstandard2.0 / .NET Framework asset now throws. The .NET assets bind these to the BCL and are unaffected, which is why the original report crashed on net472 while net8.0 passed.

Fix

  • src/Polyfills/PolyfillBackwardCompatibility.cs — restore the exact Polyfills.Polyfill members old 2.x extensions reference (Deconstruct, Contains×2, AppendJoin×2, CopyToAsync, SaveAsync), guarded #if !NETCOREAPP so they land only in the netstandard2.0 platform asset (the one loaded on .NET Framework). The type is already internal with IVT to these extensions; [Embedded] only hides it from new compile-time references — the CLR still resolves old baked MemberRefs at runtime. A prominent comment warns against re-deleting them as "unused polyfills."

Test

  • TelemetryForwardCompatibilityTests — reproduces the crash: current platform + oldest supported 2.x telemetry extension (2.0.0) on net462 with telemetry enabled (which is what forces AppInsightsProvider.IngestLoopAsync — the crashing method — to actually run). The existing ForwardCompatibilityTests missed this because it pinned 2.2.1 (no longer references the platform Polyfill) and ran telemetry opted out.

Verification (build.cmd -pack + acceptance run)

Notes for reviewers

  • The exact old-extension Polyfill surface was confirmed by decompiling the shipped 2.0.0 netstandard2.0 nupkgs, so the shim covers every extension that referenced it (not just Telemetry). Happy to trim it to telemetry-only (Deconstruct) if preferred, but restoring the full set makes any old 2.x extension load correctly on .NET Framework.

…#9710)

A newer Microsoft.Testing.Platform combined with an older (2.x) extension whose
netstandard2.0 asset was compiled against the platform's internal Polyfills.Polyfill
helper (shared via InternalsVisibleTo) threw MissingMethodException in
AppInsightsProvider.IngestLoopAsync on .NET Framework, crashing the process.

- Restore the exact Polyfills.Polyfill members old 2.x extensions reference
  (Deconstruct, Contains x2, AppendJoin x2, CopyToAsync, SaveAsync), guarded to the
  non-.NET-Core TFMs so they land only in the netstandard2.0 platform asset that is
  loaded on .NET Framework. The type is already internal with IVT to the extensions;
  [Embedded] only hides it from new compile-time references, so the CLR still resolves
  old baked MemberRefs at runtime.
- Add TelemetryForwardCompatibilityTests reproducing the crash: current platform +
  oldest supported 2.x telemetry extension (2.0.0) on net462 with telemetry enabled.
  Verified red without the shim (exit code -532462766) and green with it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 8, 2026 14:36
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9739

GradeTestNotes
A (90–100) new TelemetryForwardCompatibilityTests.
NewerPlatform_
WithOldestSupportedTelemetryExtension_
TelemetryEnabled_
OnNetFramework_
ShouldNotCrash
Clear AAA structure; three complementary assertions cover exit code, summary, and regression-specific failure mode.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 46.3 AIC · ⌖ 6.97 AIC · ⊞ 9.5K · [◷]( · )

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

Fixes #9710, where a newer Microsoft.Testing.Platform crashes with MissingMethodException on .NET Framework when loading an older (2.x) extension. Old 2.x extension assemblies (Telemetry, TrxReport, VSTestBridge) were compiled against the platform's internal Polyfills.Polyfill helpers and resolve those MemberRefs from the platform assembly at runtime via [InternalsVisibleTo]. Newer platform code stopped using those helpers, so they were dropped — breaking the netstandard2.0 load path. The fix restores the exact member set, guarded to the non-netcore asset, and adds a regression test.

Changes:

  • Restore the Polyfills.Polyfill members old 2.x extensions reference (Deconstruct, Contains×2, AppendJoin×2, CopyToAsync, SaveAsync) in a new #if !NETCOREAPP file, with a prominent comment warning against re-deleting them as "unused."
  • Add TelemetryForwardCompatibilityTests reproducing the crash with the oldest supported 2.x telemetry extension (2.0.0) on net462 with telemetry enabled.
Show a summary per file
File Description
src/Polyfills/PolyfillBackwardCompatibility.cs New netstandard2.0/.NET Framework-only file restoring the internal Polyfill members old 2.x extensions bind to at runtime, preventing MissingMethodException.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TelemetryForwardCompatibilityTests.cs New acceptance test reproducing #9710 (newest platform + oldest 2.x telemetry extension on net462, telemetry enabled) and guarding against regression.

Review details

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

@github-actions github-actions Bot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

✅ 15/15 dimensions clean — no findings.

Dimension Severity Verdict
Algorithmic Correctness MAJOR LGTM
Threading & Concurrency BLOCKING LGTM
Public API & Binary Compatibility BLOCKING LGTM
Cross-TFM Compatibility MAJOR LGTM
Defensive Coding MAJOR LGTM
Flakiness Patterns BLOCKING LGTM
Test Isolation MAJOR LGTM
Assertion Quality MAJOR LGTM
Test Completeness & Coverage MAJOR LGTM
Code Structure & Simplification MODERATE LGTM
Naming & Conventions NIT LGTM
Documentation Accuracy NIT LGTM
Performance & Allocations MAJOR LGTM
Resource & IDisposable Management MAJOR LGTM
Scope & PR Discipline MODERATE LGTM

Summary: Clean, well-scoped fix. The polyfill implementations are correct and binary-compatible with old 2.x extension MemberRef tokens. The #if !NETCOREAPP guard correctly targets the netstandard2.0 build (which is what .NET Framework loads). The acceptance test faithfully reproduces the crash conditions (net462 + telemetry enabled + oldest 2.x extension) and the IMPORTANT comment provides strong protection against future accidental removal.

@Evangelink

Copy link
Copy Markdown
Member Author

/backport to rel/4.3

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Started backporting to rel/4.3: https://github.com/microsoft/testfx/actions/runs/28952108089

Evangelink added a commit that referenced this pull request Jul 8, 2026
New 2.3.1 UNRELEASED servicing section for the .NET Framework MissingMethodException regression (#9710) fixed by #9739, being backported to rel/4.3 via #9740.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@Evangelink Evangelink enabled auto-merge (squash) July 8, 2026 15:27
@Evangelink Evangelink added the state/needs-review Awaiting review from the team. label Jul 8, 2026
@Evangelink Evangelink disabled auto-merge July 8, 2026 16:45
@Evangelink Evangelink merged commit dff367b into main Jul 8, 2026
37 of 41 checks passed
@Evangelink Evangelink deleted the dev/amauryleve/improve-backcompat-acceptance-test branch July 8, 2026 16:45
Evangelink added a commit that referenced this pull request Jul 8, 2026
…#9710) by @Evangelink in #9739 (backport to rel/4.3) (#9740)

Co-authored-by: Amaury Levé <amauryleve@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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.

System.MissingMethodException after upgrade to 2.3.0

3 participants