Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions docs/ci/mtp-args-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ MTP diagnostic arguments (hang dump, crash dump, exit code handling, timeouts) a
┌───────────────────────────────────────────────────────────────────────────┐
│ MSBuild (build time) │
│ │
│ eng/Testing.props │
│ eng/Testing.targets │
│ MtpBaseArgs = "<diagnostic flags> --hangdump-timeout <T> --timeout <S>"│
│ _BlameArgs = MtpBaseArgs │
│ TestRunnerAdditionalArguments = ... + _BlameArgs (Arcade/Helix path) │
Expand Down Expand Up @@ -42,10 +42,13 @@ MTP diagnostic arguments (hang dump, crash dump, exit code handling, timeouts) a

## Properties

### `MtpBaseArgs` (defined in `eng/Testing.props`)
### `MtpBaseArgs` (defined in `eng/Testing.targets`)

The single source of truth for all MTP diagnostic and timeout arguments. Contains everything that should be passed to every test execution. Timeouts are baked into this property so they flow as one resolved string.

The property is composed in a targets file, after project evaluation, so timeout
overrides declared in an individual test project are reflected in the final arguments.

**Default value:** `--ignore-exit-code 8 --crashdump --hangdump --hangdump-type none --hangdump-timeout 10m --timeout 20m`

| Arg | Purpose |
Expand Down Expand Up @@ -106,7 +109,7 @@ Set in:

## How to add a new MTP diagnostic arg

1. Edit `eng/Testing.props` — append the arg to `MtpBaseArgs` (or to `_MtpDiagnosticFlags` if it's timeout-independent)
1. Edit `eng/Testing.targets` — append the arg to `MtpBaseArgs` (or to `_MtpDiagnosticFlags` if it's timeout-independent)
2. That's it. The arg flows automatically through both paths:
- **Arcade/Helix**: via `_BlameArgs` → `TestRunnerAdditionalArguments`
- **GitHub Actions**: via runsheet → `run-tests.yml` `mtpBaseArgs` input
Expand Down
22 changes: 0 additions & 22 deletions eng/Testing.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,4 @@
<_ShortName Condition="'$(_ShortName)' == ''">$([System.IO.Path]::GetFileNameWithoutExtension('$(MSBuildProjectName)').Replace('Aspire.', '').Replace('.Tests', ''))</_ShortName>
</PropertyGroup>

<PropertyGroup>
<!--
MtpBaseArgs: The single source of truth for MTP diagnostic arguments, including
per-project timeouts. Shared by the Arcade/Helix path (TestRunnerAdditionalArguments)
and the GitHub Actions path (run-tests.yml via runsheet pipeline).
See docs/ci/mtp-args-pipeline.md for details.
-->
<_MtpDiagnosticFlags>--ignore-exit-code 8 --crashdump --hangdump --hangdump-type none</_MtpDiagnosticFlags>
<MtpBaseArgs Condition="'$(MtpBaseArgs)' == ''">$(_MtpDiagnosticFlags) --hangdump-timeout $(TestHangTimeout) --timeout $(TestSessionTimeout)</MtpBaseArgs>

<!-- Variant with uncollected-bucket timeouts, used for split-test entries that don't match a named collection -->
<_UncollectedMtpBaseArgs>$(_MtpDiagnosticFlags) --hangdump-timeout $(UncollectedTestsHangTimeout) --timeout $(UncollectedTestsSessionTimeout)</_UncollectedMtpBaseArgs>

<_BlameArgs>$(MtpBaseArgs)</_BlameArgs>

<TestRunnerAdditionalArguments>$(TestRunnerAdditionalArguments) --filter-not-trait &quot;category=failing&quot;</TestRunnerAdditionalArguments>
<!-- ignore exit code 8 (zero tests ran) is already in MtpBaseArgs / _BlameArgs -->

<TestRunnerAdditionalArguments Condition="'$(RunQuarantinedTests)' != 'true' and '$(RunOuterloopTests)' != 'true'">$(TestRunnerAdditionalArguments) $(_NonQuarantinedTestRunAdditionalArgs) $(_NonOuterloopTestRunAdditionalArgs) $(_BlameArgs)</TestRunnerAdditionalArguments>
<TestRunnerAdditionalArguments Condition="'$(RunQuarantinedTests)' == 'true'">$(TestRunnerAdditionalArguments) $(_QuarantinedTestRunAdditionalArgs) $(_BlameArgs)</TestRunnerAdditionalArguments>
<TestRunnerAdditionalArguments Condition="'$(RunOuterloopTests)' == 'true'">$(TestRunnerAdditionalArguments) $(_OuterloopTestRunAdditionalArgs) $(_BlameArgs)</TestRunnerAdditionalArguments>
</PropertyGroup>
</Project>
20 changes: 20 additions & 0 deletions eng/Testing.targets
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
<Project>
<PropertyGroup>
<!--
Compose these arguments after project evaluation so test projects can override
their timeout properties in the project file.
Comment thread
radical marked this conversation as resolved.
Resolved
-->
<_MtpDiagnosticFlags>--ignore-exit-code 8 --crashdump --hangdump --hangdump-type none</_MtpDiagnosticFlags>
<MtpBaseArgs Condition="'$(MtpBaseArgs)' == ''">$(_MtpDiagnosticFlags) --hangdump-timeout $(TestHangTimeout) --timeout $(TestSessionTimeout)</MtpBaseArgs>

<!-- Variant with uncollected-bucket timeouts, used for split-test entries that don't match a named collection -->
<_UncollectedMtpBaseArgs>$(_MtpDiagnosticFlags) --hangdump-timeout $(UncollectedTestsHangTimeout) --timeout $(UncollectedTestsSessionTimeout)</_UncollectedMtpBaseArgs>

<_BlameArgs>$(MtpBaseArgs)</_BlameArgs>

<TestRunnerAdditionalArguments>$(TestRunnerAdditionalArguments) --filter-not-trait &quot;category=failing&quot;</TestRunnerAdditionalArguments>
<!-- ignore exit code 8 (zero tests ran) is already in MtpBaseArgs / _BlameArgs -->

<TestRunnerAdditionalArguments Condition="'$(RunQuarantinedTests)' != 'true' and '$(RunOuterloopTests)' != 'true'">$(TestRunnerAdditionalArguments) $(_NonQuarantinedTestRunAdditionalArgs) $(_NonOuterloopTestRunAdditionalArgs) $(_BlameArgs)</TestRunnerAdditionalArguments>
<TestRunnerAdditionalArguments Condition="'$(RunQuarantinedTests)' == 'true'">$(TestRunnerAdditionalArguments) $(_QuarantinedTestRunAdditionalArgs) $(_BlameArgs)</TestRunnerAdditionalArguments>
<TestRunnerAdditionalArguments Condition="'$(RunOuterloopTests)' == 'true'">$(TestRunnerAdditionalArguments) $(_OuterloopTestRunAdditionalArgs) $(_BlameArgs)</TestRunnerAdditionalArguments>
</PropertyGroup>

<!--
Environment variables:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ extends:
jobs:
- job: TemplateTests
displayName: Template Tests
timeoutInMinutes: 30
timeoutInMinutes: 45
pool:
name: NetCore1ESPool-Internal
image: windows.vs2026preview.scout.amd64
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

<!-- Timeout configuration -->
<TestSessionTimeout>20m</TestSessionTimeout>
<TestSessionTimeout Condition="'$(RunOnlyBasicBuildTemplateTests)' == 'true'">30m</TestSessionTimeout>
<TestHangTimeout>15m</TestHangTimeout>

<!--
Expand Down
2 changes: 2 additions & 0 deletions tests/Aspire.Templates.Tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Each class runs 51 cases across the SDK/target-framework matrix. Keeping them se
lets CI shard all 153 cases without tripling a single job's runtime. The framework
tests check generated package names, versions, and executable output where required
before building, so update these expectations when changing starter test dependencies.
The internal pipeline runs all `basic-build` cases in one process, so that invocation
uses a 30-minute session timeout while the class-sharded runs retain the 20-minute timeout.

- The sdk+workload is never updated automatically. In other words, once installed the workload packs don't get overwritten even when the source binaries changes in `artifacts`. This may change in future.

Expand Down
33 changes: 33 additions & 0 deletions tests/Infrastructure.Tests/MicrosoftTestingPlatformTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.RegularExpressions;
using System.Text.Json;
using System.Xml.Linq;
using Aspire.TestUtilities;
using Xunit;
Expand All @@ -10,6 +11,38 @@ namespace Infrastructure.Tests;

public sealed class MicrosoftTestingPlatformTests(ITestOutputHelper output)
{
[Theory]
[InlineData(false, "20m")]
[InlineData(true, "30m")]
[RequiresTools(["pwsh"])]
public async Task ProjectTimeoutOverridesFlowToMtpArguments(bool basicBuild, string expectedSessionTimeout)
{
using var workspace = TemporaryWorkspace.Create(output);
var script = Path.Combine(workspace.Path, "evaluate.ps1");
await File.WriteAllTextAsync(script, """
& $env:TEST_DOTNET msbuild (Join-Path $env:TEST_REPO 'tests/Aspire.Templates.Tests/Aspire.Templates.Tests.csproj') -nologo `
-getProperty:MtpBaseArgs,TestRunnerAdditionalArguments `
"/p:RunOnlyBasicBuildTemplateTests=$env:TEST_BASIC_BUILD"
exit $LASTEXITCODE
""");
using var command = new PowerShellCommand(script, output)
.WithWorkingDirectory(RepoRoot.Path)
.WithEnvironmentVariable("TEST_DOTNET", Path.Combine(RepoRoot.Path, ".dotnet", OperatingSystem.IsWindows() ? "dotnet.exe" : "dotnet"))
.WithEnvironmentVariable("TEST_REPO", RepoRoot.Path)
.WithEnvironmentVariable("TEST_BASIC_BUILD", basicBuild.ToString());
var result = await command.ExecuteAsync();
result.EnsureSuccessful();

using var document = JsonDocument.Parse(result.Output);
var properties = document.RootElement.GetProperty("Properties");
Assert.Equal(
$"--ignore-exit-code 8 --crashdump --hangdump --hangdump-type none --hangdump-timeout 15m --timeout {expectedSessionTimeout}",
properties.GetProperty("MtpBaseArgs").GetString());
var testRunnerAdditionalArguments = properties.GetProperty("TestRunnerAdditionalArguments").GetString()!;
Assert.Equal(basicBuild, testRunnerAdditionalArguments.Contains("--filter-trait category=basic-build", StringComparison.Ordinal));
Assert.Contains($"--hangdump-timeout 15m --timeout {expectedSessionTimeout}", testRunnerAdditionalArguments, StringComparison.Ordinal);
}

[Fact]
[RequiresTools(["pwsh"])]
public async Task ArcadeRunnerOptionsAreRegisteredByTheCurrentTestHost()
Expand Down
Loading