Run NativeAOT CLI tests in CI (win-x64, linux-x64, osx-arm64) - #54719
Conversation
Hook up test/dotnet-aot.Tests (added in dotnet#54297) to CI. These tests publish the test assembly as a NativeAOT binary and run it on the build agent (same architecture, native toolchain already present from the build), validating the AOT CLI entry-point code under NativeAOT compilation. - run-aot-tests.ps1/.sh: add optional -Trx/--trx (and results dir) to emit a TRX report via the MTP --report-trx options so CI can publish results. - sdk-build.yml: add runNativeAotCliTests parameter; after the Helix queue step (so it never blocks Helix submission), publish+run the AOT test binary with an explicit RID and publish the TRX results. - sdk-job-matrix.yml: enable runNativeAotCliTests on the Windows (x64), Linux (x64), and macOS (arm64) TestBuild legs. Note: this is distinct from runAoTTests/RunAoTTests, which runs the Blazor WebAssembly AoT tests on Helix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR wires up the existing dotnet-aot.Tests (NativeAOT CLI entry-point tests) to actually run in CI on the build agents that already have the NativeAOT toolchain available (win-x64, linux-x64, osx-arm64). It adds optional TRX emission support to the test runner scripts and integrates execution + result publishing into the SDK build pipeline templates.
Changes:
- Add optional
--trx/-Trx+ results directory support to the AOT test runner scripts so CI can publish TRX results. - Add a new pipeline switch (
runNativeAotCliTests) and, when enabled, publish+run the AOT test binary on the build agent and publish the TRX. - Enable the switch for the CI
TestBuildlegs on Windows x64, Linux x64, and macOS arm64.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| test/dotnet-aot.Tests/run-aot-tests.sh | Adds optional TRX/report output arguments for CI publishing while keeping default local behavior unchanged. |
| test/dotnet-aot.Tests/run-aot-tests.ps1 | Adds optional TRX/report output arguments for CI publishing while keeping default local behavior unchanged. |
| eng/pipelines/templates/jobs/sdk-job-matrix.yml | Enables the new NativeAOT CLI test run on the intended OS/arch TestBuild legs. |
| eng/pipelines/templates/jobs/sdk-build.yml | Adds the runNativeAotCliTests parameter and runs/publishes results after Helix queueing. |
The ARM64 TESTBUILD job in .vsts-ci.yml was the only sdk-job-matrix invocation not passing oneESCompat, so its PublishBuildArtifacts@1/PublishPipelineArtifact@1 tasks emitted without the 1ES. prefix and were rejected by 1ES YAML validation when the job is enabled (enableArm64Job=true). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The separate enableArm64Job ARM64 TESTBUILD job became redundant after dotnet#54604 switched the main macOS PR leg to arm64 (both produce job TestBuild_macOS_arm64). It should not be enabled, so the oneESCompat fix is unnecessary; reverting to keep this PR scoped to the AOT test hookup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two CI failures surfaced when the AOT test step ran: 1. Windows used Windows PowerShell 5.1, which does not support multi-argument Join-Path (PS 6+ only). Replaced the 3+ arg Join-Path calls with [System.IO.Path]::Combine. 2. The macOS leg cross-builds osx-arm64 on an x64 hosted agent, so the native arm64 binary could not execute (Bad CPU type). NativeAOT binaries must run on the host architecture, so the pipeline no longer passes the build's target RID; the scripts auto-detect the host RID via .dotnet/dotnet --info instead. Validated end-to-end under Windows PowerShell 5.1: 40 passed, 6 skipped, 0 failed, TRX emitted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Running the AOT CLI tests in CI surfaced real failures from the new tests added in dotnet#54653: * GetFileBasedAppEntryPointToken pulls in Microsoft.Build, which cannot be linked into a NativeAOT image (ILC reports the method 'will always throw'). Skip the three affected AotParserTests under NativeAOT (guarded by RuntimeFeature.IsDynamicCodeSupported, so the managed test run still exercises them). Tracked by dotnet#54806. * InvokeCliSchema_RendersSchemaJsonFromAot evaluates a shell-completion default that requires SHELL to be set; the bare AzDO script task does not export it on Linux. Set SHELL on the AOT test step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Heads-up @baronfel: hooking these tests up to CI runs
Since I also set |
CI status note: latest red is an unrelated broken
|
# Conflicts: # test/dotnet-aot.Tests/AotParserTests.cs
# Conflicts: # eng/pipelines/templates/jobs/sdk-job-matrix.yml
…tial test classes The "Run NativeAOT CLI Tests" CI step reported "Zero tests ran" (MTP exit code 8): the AOT test binary published successfully but discovered no tests. This was a pre-existing failure on main (introduced with the step in #54719) that our rebase inherited. Root cause is a version skew in the MSTest AOT source-generation pipeline. The repo flows the MSTest framework/adapter/platform at the 26360.5 build, but MSTest.Sdk (global.json) defaults MSTestSourceGenerationVersion to the stale 26325.12 build. The 26325 generator is incompatible with the 26360 framework and emits no source-generated reflection metadata, so reflection-free (NativeAOT) discovery finds zero test classes. Fixes (test/dotnet-aot.Tests): - Pin MSTestSourceGenerationVersion to 2.0.0-alpha.26360.5 so the generator matches the flowed framework/adapter/platform version. - Set MSTestSourceGenMode=ReflectionFree and register it as a CompilerVisibleProperty so the generator emits reflection metadata even when the adapter default does not apply in the inner AOT build. - Mark the five [TestClass] types partial, which MSTest source generation requires to augment test classes. Verified locally that a clean AOT-config compile now emits MSTestReflectionMetadata registrations for all five test classes. The native run itself is validated in CI (local ILC is unavailable for the preview.7 nativeaot runtime pack). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b7c0dc09-64f3-40b8-9c5f-45b0fce2e461
…iscovery The test/dotnet-aot.Tests project publishes as NativeAOT and relies on the MSTest source generator for test discovery (reflection isn't AOT-safe). That requires MSTest.Sdk (the MSBuild SDK pinned in global.json) and the MSTest framework packages (MSTestPackageVersion, flowed by darc from microsoft/testfx) to be coherent. A dotnet/dotnet flow bumped MSTestPackageVersion to 4.4.0-preview.26360.5 while MSTest.Sdk stayed at 4.3.0-preview.26325.12, and PR #54719 then enabled the NativeAOT CLI test leg. The SDK/framework skew makes the source generator register zero tests, so the leg fails with MTP exit code 8 (Test run summary: Zero tests ran) on every main build. Normal reflection-based MSTest runs tolerate the skew, so only the AOT leg breaks. Fix: bump MSTest.Sdk to 4.4.0-preview.26360.5 (same testfx build as the MSTest framework), and track MSTest.Sdk as a darc dependency in eng/Version.Details.xml. Like Microsoft.DotNet.Arcade.Sdk and .Helix.Sdk, darc then updates its global.json msbuild-sdks version in lockstep with the MSTest framework packages, preventing the versions from drifting apart again. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59570d89-a7e3-4993-baa9-3fb1f442a617
…iscovery The test/dotnet-aot.Tests project publishes as NativeAOT and relies on the MSTest source generator for test discovery (reflection isn't AOT-safe). That requires MSTest.Sdk (the MSBuild SDK pinned in global.json) and the MSTest framework packages (MSTestPackageVersion, flowed by darc from microsoft/testfx) to be coherent. A dotnet/dotnet flow bumped MSTestPackageVersion to 4.4.0-preview.26360.5 while MSTest.Sdk stayed at 4.3.0-preview.26325.12, and PR #54719 then enabled the NativeAOT CLI test leg. The SDK/framework skew makes the source generator register zero tests, so the leg fails with MTP exit code 8 (Test run summary: Zero tests ran) on every main build. Normal reflection-based MSTest runs tolerate the skew, so only the AOT leg breaks. Fix: bump MSTest.Sdk to 4.4.0-preview.26360.5 (same testfx build as the MSTest framework), and track MSTest.Sdk as a darc dependency in eng/Version.Details.xml. Like Microsoft.DotNet.Arcade.Sdk and .Helix.Sdk, darc then updates its global.json msbuild-sdks version in lockstep with the MSTest framework packages, preventing the versions from drifting apart again. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 59570d89-a7e3-4993-baa9-3fb1f442a617
Summary
PR #54297 added the
dotnet-aot.Testsproject (NativeAOT CLI entry-point tests) but did not hook them up to any pipeline, so they never run in CI. This change wires them up so they run for each platform that currently runs tests in CI.These tests are run on the build agent (not Helix): the test assembly is published as a NativeAOT binary and executed on the agent. NativeAOT binaries must run on the architecture they were built for, so the runner scripts auto-detect the agent's host RID (via
.dotnet/dotnet --info). On a cross-architecture leg (e.g. the macOS leg cross-buildsosx-arm64on an x64 hosted agent), the tests run for the host architecture (osx-x64).Changes
test/dotnet-aot.Tests/run-aot-tests.ps1/.sh— add an optional-Trx/--trxflag (plus results directory) that runs the AOT test binary with the MTP--report-trxoptions, emitting a TRX report underartifacts/TestResults/<config>/so CI can publish results. Default-off, so local behavior is unchanged. The PowerShell script uses[System.IO.Path]::Combinefor path joins so it runs under Windows PowerShell 5.1 (the CIpowershell:task host), which does not support multi-argumentJoin-Path.eng/pipelines/templates/jobs/sdk-build.yml— add arunNativeAotCliTestsparameter (defaultfalse). When enabled, after the Helix queue step (so it never blocks the broader Helix test submission), publish + run the AOT test binary, then publish the TRX viaPublishTestResults@2. The scripts auto-detect the host RID rather than being passed the build's target RID.eng/pipelines/templates/jobs/sdk-job-matrix.yml— enablerunNativeAotCliTests: trueon the Windows (x64), Linux (x64), and macOSTestBuildlegs — the platforms that run tests in CI.eng/pipelines/templates/jobs/sdk-build.yml(Linux step) — setSHELLfor the AOT test step.--cli-schemaevaluates a shell-completion default that throws whenSHELLis unset in the bare AzDOscript:task.test/dotnet-aot.Tests/AotParserTests.cs— running the tests under NativeAOT for the first time surfaced a real AOT issue from Unify the managed and NativeAOT CLI parsers into one shared implementation #54653:GetFileBasedAppEntryPointTokenpulls inMicrosoft.Build, which cannot be linked into a NativeAOT image (ILC reports the method "will always throw"). The three affected tests are skipped under AOT only (guarded byRuntimeFeature.IsDynamicCodeSupported, so the managed test run still exercises them), tracked by #54806.Notes
runAoTTests/RunAoTTests, which runs the Blazor WebAssembly AoT tests on Helix.dnbinary in the SDK layout plus the 3 file-based-app tests quarantined by #54806.