Uh oh!
There was an error while loading. Please reload this page.
Make AOT-incompatible code paths a no-op at runtime in MTP/Native AOT mode - #8688
Conversation
… mode This change introduces two targeted improvements that reduce the trim/AOT warning surface for the MSTest adapter when consumers enable `PublishTrimmed=true` or `PublishAot=true` and pull MSTest in via MTP. 1. Centralize `Assembly.Location` handling in a new internal `AssemblyFileLocator` helper. Previously, every call site that needed the path or directory of an on-disk assembly carried its own `#pragma warning disable IL3000` (or relied on an IL3000 attribute suppression) and re-implemented the single-file/Native AOT fallback to `AppContext.BaseDirectory` or the assembly simple name. The helper gives one place to suppress IL3000 with a meaningful justification and one place to maintain the fallback logic. Updated call sites: - `TestSourceHost.SetContext` (WIN_UI branch), - `TestSourceHost.GetAppBaseAsPerPlatform` (NETFRAMEWORK), - `TestSourceHost.GetResolutionPaths` (NET, !WINDOWS_UWP and NETFRAMEWORK), - `DeploymentUtilityBase.Deploy` (filtering the adapter assembly out of the deployment loop). 2. Skip the AssemblyResolver registration and `DataSerializationHelper` work at runtime in Native AOT. `RuntimeFeature.IsDynamicCodeSupported` is the established AOT-detection signal in this codebase (already used by `TestApplication` and `AppInsightsTelemetryProviderExtensions`). When it is `false`: - `TestSourceHost.SetupHost` no longer constructs `AssemblyResolver` (its `AssemblyLoadContext.Resolving` hook can never fire under NAOT). This also lets the trimmer drop `GetResolutionPaths` and the resolver class from the published binary. - `DataSerializationHelper.Serialize` / `Deserialize` throw a descriptive `NotSupportedException` instead of attempting `DataContractJsonSerializer`-based serialization (which requires dynamic code). In MTP mode the in-process `TestMethod.ActualData` is used for parameterized arguments and these methods are not reached at runtime; the throw is a safety net plus a trimmer hint. The trimmer treats `RuntimeFeature.IsDynamicCodeSupported` as a constant `false` substitution during NAOT publish, so the gated branches (and the unreferenced `AssemblyResolver` / DataContract code paths) are statically removed from the published binary. This PR is independent of microsoft#8686 (which is the pragma-to-attribute conversion for the same warnings) but the two changes overlap on `TestSourceHost.cs` and `DataSerializationHelper.cs`; expect a merge conflict between them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Reduces the trim/Native AOT warning surface (and runtime reachability) of AOT-incompatible adapter code paths when MSTest is used via Microsoft.Testing.Platform (MTP), by centralizing Assembly.Location handling and gating unsupported behaviors at runtime.
Changes:
- Added
AssemblyFileLocatorto centralizeAssembly.Locationaccess (single-file/NAOT-safe fallbacks + IL3000 suppression). - Updated
TestSourceHostandDeploymentUtilityBaseto useAssemblyFileLocatorinstead of directAssembly.Locationaccess / IL3000 pragmas. - Gated
AssemblyResolvercreation andDataSerializationHelper.Serialize/DeserializeonRuntimeFeature.IsDynamicCodeSupported, turning AOT-incompatible paths into no-ops/throws in AOT scenarios.
Show a summary per file
| File | Description |
|---|---|
| src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs | Uses AssemblyFileLocator to avoid direct Assembly.Location access in deployment filtering logic. |
| src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs | Skips resolver setup in AOT scenarios; replaces Assembly.Location usage with centralized helper/fallbacks. |
| src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.cs | Throws NotSupportedException when dynamic code isn’t supported (AOT) to prevent DataContract-based serialization usage. |
| src/Adapter/MSTestAdapter.PlatformServices/Helpers/AssemblyFileLocator.cs | New helper encapsulating Assembly.Location access and AOT/single-file fallbacks with IL3000 suppressions. |
Copilot's findings
- Files reviewed: 4/4 changed files
- Comments generated: 3
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…e AOT" RuntimeFeature.IsDynamicCodeSupported is false for any AOT-like runtime without a JIT or interpreter (Native AOT, Mono iOS AOT, Blazor WebAssembly AOT, …), not exclusively Native AOT. Update doc comments, exception messages, and the in-source rationale in TestSourceHost to describe the actual condition being checked. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n netfx/uap `RuntimeFeature.IsDynamicCodeSupported` is .NET Core/5+ only, so the `<see cref=...>` references in the XML docs fail to resolve when the project builds for net462 and uap10.0.16299. Switch to `<c>...</c>` literals to keep the documentation readable on all target frameworks without requiring conditional compilation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Both comments referenced 'source gen mode', but the actual code paths check for Assembly.Location being empty (single-file / Native AOT scenarios). Reworded to describe the real behavior to avoid confusing future maintainers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Amaury Levé (Evangelink)
commented
May 31, 2026
Copilot resolve the merge conflicts in this pull request |
Uh oh!
There was an error while loading. Please reload this page.
What
Two targeted runtime improvements that reduce the trim/AOT warning surface for
MSTest.TestAdapterwhen consumers enable trimming or Native AOT through Microsoft.Testing.Platform (MTP):1.
AssemblyFileLocator— single place to handleAssembly.LocationNew
internal statichelper inMSTestAdapter.PlatformServices/Helpers/AssemblyFileLocator.cswith three members:TryGetLocation(Assembly) -> string?— returnsnullwhenAssembly.Locationis empty (single-file / Native AOT case).GetDirectoryOrAppContextBase(Assembly)— falls back toAppContext.BaseDirectory.GetFileNameOrSimpleName(Assembly)— falls back to<simpleName>.dll.Each member carries a single
[UnconditionalSuppressMessage("SingleFile", "IL3000")]with a meaningful justification. This removes the#pragma warning disable IL3000blocks scattered across call sites:TestSourceHost.SetContext(WIN_UIbranch)TestSourceHost.GetAppBaseAsPerPlatform(NETFRAMEWORK)TestSourceHost.GetResolutionPaths(bothNET && !WINDOWS_UWPandNETFRAMEWORK)DeploymentUtilityBase.Deploy2. Skip
AssemblyResolverandDataSerializationHelperwork in Native AOTGate the relevant code on
RuntimeFeature.IsDynamicCodeSupported— the established AOT-detection signal already used byTestApplicationandAppInsightsTelemetryProviderExtensionsin this codebase:TestSourceHost.SetupHost(NET && !WINDOWS_UWP) no longer constructsAssemblyResolverwhen running under NAOT. ItsAssemblyLoadContext.Resolvinghook can never fire in NAOT anyway. The trimmer can now dropGetResolutionPathsand the whole resolver class.DataSerializationHelper.Serialize/DeserializethrowNotSupportedExceptionunder NAOT with a clear message pointing users to MTP mode (whereTestMethod.ActualDatais used in-process). In practice these methods are not reached in MTP at runtime — discovery setsActualDatadirectly. The throw is a safety net plus a trimmer hint.The trimmer treats
RuntimeFeature.IsDynamicCodeSupportedas a constantfalsesubstitution during NAOT publish, so the gated branches and their transitive dependencies are statically removed from the published binary.Why
PR #8586 enables an integration test that publishes MSTest with
PublishAot=true+TreatWarningsAsErrors=true. The pragma-to-attribute PR (#8686) silences the warnings; this PR goes further by making the code actually safe / no-op at runtime in NAOT, so consumers using MSTest in MTP-only mode get a smaller and more correct published binary.Independence from #8686
This PR branches from
mainand is independent of #8686. The two PRs touchTestSourceHost.csandDataSerializationHelper.csin different ways, so expect merge conflicts; whichever lands first will need the other rebased.Validation
dotnet build src/Adapter/MSTestAdapter.PlatformServices/MSTestAdapter.PlatformServices.csproj -c Release -f net8.0— 0 warnings / 0 errors.dotnet build ... -f net462— 0 warnings / 0 errors (the new NAOT guards are#if NET-fenced so netfx is unaffected).The same acceptance test added in #8686 (
Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources) would benefit from these changes by removing additional warnings from theTestSourceHostandDeploymentUtilityBasesurfaces, and by letting the trimmer drop theAssemblyResolverentirely.