Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a test to verify that the testing platform correctly uses the actual process exit code instead of relying on IPC messages from the test host. This relates to PR #7430, which addresses scenarios where the test host might report an incorrect exit code via IPC but then actually exit with a different code (e.g., due to a hang dump killing the process).
Changes:
- Added a new test method
TestHostMessesUpExitCodethat verifies the platform detects when a test host exits with an unexpected exit code - Modified the test asset's
Mainmethod to allow simulating incorrect exit codes via environment variable - Added support for a
ZERO_TESTSenvironment variable to test the scenario where the test host runs zero tests
...sting.Platform.Acceptance.IntegrationTests/EnvironmentVariablesConfigurationProviderTests.cs
Outdated
Show resolved
Hide resolved
…tegrationTests/EnvironmentVariablesConfigurationProviderTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
|
||
| [DynamicData(nameof(TargetFrameworks.AllForDynamicData), typeof(TargetFrameworks))] | ||
| [TestMethod] | ||
| public async Task TestHostMessesUpExitCode(string currentTfm) |
There was a problem hiding this comment.
The test method name doesn't follow the naming conventions used elsewhere in this test file and in similar acceptance test files. Other tests in this codebase use underscores to separate words and often include "Should" for clarity (e.g., CrashDump_InvalidFormat_ShouldFail, AbortWithCTRLPlusC_TestHost_Succeeded). Consider renaming to something like TestHost_WithMessedUpExitCode_ShouldReturnTestHostProcessExitedNonGracefully to be consistent with the established pattern.
| public async Task TestHostMessesUpExitCode(string currentTfm) | |
| public async Task TestHost_WithMessedUpExitCode_ShouldReturnTestHostProcessExitedNonGracefully(string currentTfm) |
| [DynamicData(nameof(TargetFrameworks.AllForDynamicData), typeof(TargetFrameworks))] | ||
| [TestMethod] | ||
| public async Task TestHostMessesUpExitCode(string currentTfm) | ||
| { | ||
| var testHost = TestInfrastructure.TestHost.LocateFrom(AssetFixture.TargetAssetPath, AssetName, currentTfm); | ||
|
|
||
| TestHostResult testHostResult = await testHost.ExecuteAsync( | ||
| environmentVariables: new() | ||
| { | ||
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "1", | ||
| }, cancellationToken: TestContext.CancellationToken); | ||
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | ||
|
|
||
| testHostResult = await testHost.ExecuteAsync( | ||
| environmentVariables: new() | ||
| { | ||
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "100", | ||
| }, cancellationToken: TestContext.CancellationToken); | ||
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | ||
|
|
||
| testHostResult = await testHost.ExecuteAsync( | ||
| environmentVariables: new() | ||
| { | ||
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "1", | ||
| ["ZERO_TESTS"] = "1", | ||
| }, cancellationToken: TestContext.CancellationToken); | ||
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | ||
|
|
||
| testHostResult = await testHost.ExecuteAsync( | ||
| environmentVariables: new() | ||
| { | ||
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "100", | ||
| ["ZERO_TESTS"] = "1", | ||
| }, cancellationToken: TestContext.CancellationToken); | ||
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | ||
|
|
||
| testHostResult = await testHost.ExecuteAsync( | ||
| environmentVariables: new() | ||
| { | ||
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "8", | ||
| ["ZERO_TESTS"] = "1", | ||
| }, cancellationToken: TestContext.CancellationToken); | ||
| testHostResult.AssertExitCodeIs(ExitCodes.ZeroTests); |
There was a problem hiding this comment.
The test has 5 scenarios that are very repetitive with only environment variable values changing. Consider refactoring this test to use [DataRow] or [DynamicData] attributes to parameterize the test cases. This would reduce duplication and make it easier to add new test scenarios. For example: [DataRow("1", null, ExitCodes.TestHostProcessExitedNonGracefully)], [DataRow("100", null, ExitCodes.TestHostProcessExitedNonGracefully)], [DataRow("8", "1", ExitCodes.ZeroTests)], etc.
| [DynamicData(nameof(TargetFrameworks.AllForDynamicData), typeof(TargetFrameworks))] | |
| [TestMethod] | |
| public async Task TestHostMessesUpExitCode(string currentTfm) | |
| { | |
| var testHost = TestInfrastructure.TestHost.LocateFrom(AssetFixture.TargetAssetPath, AssetName, currentTfm); | |
| TestHostResult testHostResult = await testHost.ExecuteAsync( | |
| environmentVariables: new() | |
| { | |
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "1", | |
| }, cancellationToken: TestContext.CancellationToken); | |
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | |
| testHostResult = await testHost.ExecuteAsync( | |
| environmentVariables: new() | |
| { | |
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "100", | |
| }, cancellationToken: TestContext.CancellationToken); | |
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | |
| testHostResult = await testHost.ExecuteAsync( | |
| environmentVariables: new() | |
| { | |
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "1", | |
| ["ZERO_TESTS"] = "1", | |
| }, cancellationToken: TestContext.CancellationToken); | |
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | |
| testHostResult = await testHost.ExecuteAsync( | |
| environmentVariables: new() | |
| { | |
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "100", | |
| ["ZERO_TESTS"] = "1", | |
| }, cancellationToken: TestContext.CancellationToken); | |
| testHostResult.AssertExitCodeIs(ExitCodes.TestHostProcessExitedNonGracefully); | |
| testHostResult = await testHost.ExecuteAsync( | |
| environmentVariables: new() | |
| { | |
| ["MESS_UP_TESTHOST_EXIT_CODE"] = "8", | |
| ["ZERO_TESTS"] = "1", | |
| }, cancellationToken: TestContext.CancellationToken); | |
| testHostResult.AssertExitCodeIs(ExitCodes.ZeroTests); | |
| [DynamicData(nameof(TestHostMessesUpExitCodeData), DynamicDataSourceType.Method)] | |
| [TestMethod] | |
| public async Task TestHostMessesUpExitCode(string currentTfm, string? messUpExitCode, string? zeroTests, ExitCodes expectedExitCode) | |
| { | |
| var testHost = TestInfrastructure.TestHost.LocateFrom(AssetFixture.TargetAssetPath, AssetName, currentTfm); | |
| var environmentVariables = new Dictionary<string, string>(); | |
| if (messUpExitCode is not null) | |
| { | |
| environmentVariables["MESS_UP_TESTHOST_EXIT_CODE"] = messUpExitCode; | |
| } | |
| if (zeroTests is not null) | |
| { | |
| environmentVariables["ZERO_TESTS"] = zeroTests; | |
| } | |
| TestHostResult testHostResult = await testHost.ExecuteAsync( | |
| environmentVariables: environmentVariables, | |
| cancellationToken: TestContext.CancellationToken); | |
| testHostResult.AssertExitCodeIs(expectedExitCode); | |
| } | |
| public static IEnumerable<object?[]> TestHostMessesUpExitCodeData() | |
| { | |
| foreach (object?[] row in TargetFrameworks.AllForDynamicData) | |
| { | |
| var currentTfm = (string)row[0]!; | |
| yield return new object?[] | |
| { | |
| currentTfm, | |
| "1", | |
| null, | |
| ExitCodes.TestHostProcessExitedNonGracefully, | |
| }; | |
| yield return new object?[] | |
| { | |
| currentTfm, | |
| "100", | |
| null, | |
| ExitCodes.TestHostProcessExitedNonGracefully, | |
| }; | |
| yield return new object?[] | |
| { | |
| currentTfm, | |
| "1", | |
| "1", | |
| ExitCodes.TestHostProcessExitedNonGracefully, | |
| }; | |
| yield return new object?[] | |
| { | |
| currentTfm, | |
| "100", | |
| "1", | |
| ExitCodes.TestHostProcessExitedNonGracefully, | |
| }; | |
| yield return new object?[] | |
| { | |
| currentTfm, | |
| "8", | |
| "1", | |
| ExitCodes.ZeroTests, | |
| }; | |
| } |
Related to #7430