| File: ParentProcessWatchdogTests.cs | Web Access |
| Project: src\tests\Aspire.Managed.Tests\Aspire.Managed.Tests.csproj (Aspire.Managed.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Hosting; using Aspire.Shared; using Xunit; namespace Aspire.Managed.Tests; public class ParentProcessWatchdogTests { [Fact] public void GetExpectedParentStartTimeUnix_PrefersStableValue() { var environment = new Dictionary<string, string?> { [KnownConfigNames.CliProcessStarted] = "1000", [KnownConfigNames.CliProcessStartedStable] = "1001" }; var startTime = ParentProcessWatchdog.GetExpectedParentStartTimeUnix(environment.GetValueOrDefault, out var useRuntimeStartTime); Assert.Equal(1001, startTime); Assert.False(useRuntimeStartTime); } [Fact] public void GetExpectedParentStartTimeUnix_UsesRuntimeComparisonForLegacyValue() { var environment = new Dictionary<string, string?> { [KnownConfigNames.CliProcessStarted] = "1000" }; var startTime = ParentProcessWatchdog.GetExpectedParentStartTimeUnix(environment.GetValueOrDefault, out var useRuntimeStartTime); Assert.Equal(1000, startTime); Assert.True(useRuntimeStartTime); } [Fact] public async Task ParentExitedCallback_StillForceExitsWhenCancellationCallbackThrows() { using var operationCts = new CancellationTokenSource(); using var registration = operationCts.Token.Register(static () => throw new InvalidOperationException("simulated cancellation callback failure")); int? exitCode = null; await ParentProcessWatchdog.CancelAndForceExitAsync( operationCts, CancellationToken.None, forceExitGracePeriod: TimeSpan.Zero, exit: code => exitCode = code); Assert.True(operationCts.IsCancellationRequested); Assert.Equal(124, exitCode); } [Fact] public async Task CancellationBackstopFiresWhenCancellationCallbackBlocks() { using var operationCts = new CancellationTokenSource(); using var callbackStarted = new ManualResetEventSlim(); using var releaseCallback = new ManualResetEventSlim(); using var registration = operationCts.Token.Register(() => { callbackStarted.Set(); releaseCallback.Wait(); }); var exitCode = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously); var cancellationTask = Task.Run(() => ParentProcessWatchdog.CancelAndForceExitAsync( operationCts, CancellationToken.None, forceExitGracePeriod: TimeSpan.FromMilliseconds(50), exit: code => exitCode.TrySetResult(code))); try { Assert.True(callbackStarted.Wait(TimeSpan.FromSeconds(10))); Assert.Equal(124, await exitCode.Task.WaitAsync(TimeSpan.FromSeconds(10))); } finally { releaseCallback.Set(); } await cancellationTask.WaitAsync(TimeSpan.FromSeconds(10)); } }