| File: Processes\OrphanDetectionEnvironmentTests.cs | Web Access |
| Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; using Aspire.Cli.Processes; using Aspire.Hosting; namespace Aspire.Cli.Tests.Processes; public class OrphanDetectionEnvironmentTests { [Fact] public void ApplyCurrentProcess_StampsPidAndStartTime() { var environment = new Dictionary<string, string>(StringComparer.Ordinal); OrphanDetectionEnvironment.ApplyCurrentProcess(environment); Assert.Equal(Environment.ProcessId.ToString(CultureInfo.InvariantCulture), environment[KnownConfigNames.CliProcessId]); Assert.NotNull(ProcessStartTimeHelper.TryParseStartTimeUnixSeconds(environment[KnownConfigNames.CliProcessStarted])); Assert.NotNull(ProcessStartTimeHelper.TryParseStartTimeUnixSeconds(environment[KnownConfigNames.CliProcessStartedStable])); } [Fact] public void ApplyCurrentProcess_UsesSuppliedKeyNames() { var environment = new Dictionary<string, string>(StringComparer.Ordinal); OrphanDetectionEnvironment.ApplyCurrentProcess(environment, KnownConfigNames.CliLauncherProcessId, KnownConfigNames.CliLauncherProcessStarted); Assert.Equal(Environment.ProcessId.ToString(CultureInfo.InvariantCulture), environment[KnownConfigNames.CliLauncherProcessId]); Assert.NotNull(ProcessStartTimeHelper.TryParseStartTimeUnixSeconds(environment[KnownConfigNames.CliLauncherProcessStarted])); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessId)); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStartedStable)); } [Fact] public void ApplyCurrentProcess_WithoutOverwrite_PreservesCallerValues() { var environment = new Dictionary<string, string>(StringComparer.Ordinal) { [KnownConfigNames.CliProcessId] = "999", }; OrphanDetectionEnvironment.ApplyCurrentProcess(environment, overwrite: false); Assert.Equal("999", environment[KnownConfigNames.CliProcessId]); // The caller-supplied PID is authoritative, so no start time is stamped: doing so would pair // PID 999 with the current process's start time. Leaving the keys unset keeps the identity // consistent and lets the watchdog fall back to a PID-only existence check. Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStarted)); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStartedStable)); } [Fact] public void ApplyCurrentProcess_WithoutOverwrite_StampsFullIdentityWhenNoPidPresent() { var environment = new Dictionary<string, string>(StringComparer.Ordinal); OrphanDetectionEnvironment.ApplyCurrentProcess(environment, overwrite: false); // With no caller-supplied PID (the common LayoutProcessRunner path), the current process's // identity is stamped in full and the PID and start-time values describe the same process. Assert.Equal(Environment.ProcessId.ToString(CultureInfo.InvariantCulture), environment[KnownConfigNames.CliProcessId]); Assert.NotNull(ProcessStartTimeHelper.TryParseStartTimeUnixSeconds(environment[KnownConfigNames.CliProcessStarted])); Assert.NotNull(ProcessStartTimeHelper.TryParseStartTimeUnixSeconds(environment[KnownConfigNames.CliProcessStartedStable])); } [Fact] public void ApplyCurrentProcess_WithOverwrite_ReplacesCallerValues() { var environment = new Dictionary<string, string>(StringComparer.Ordinal) { [KnownConfigNames.CliProcessId] = "999", }; OrphanDetectionEnvironment.ApplyCurrentProcess(environment, overwrite: true); Assert.Equal(Environment.ProcessId.ToString(CultureInfo.InvariantCulture), environment[KnownConfigNames.CliProcessId]); } [Fact] public void Apply_WithStartTime_StampsBothKeys() { var environment = new Dictionary<string, string?>(StringComparer.Ordinal); OrphanDetectionEnvironment.Apply(environment, pid: 4321, stableStartTimeUnixMilliseconds: 1000, KnownConfigNames.RemoteAppHostProcessId, KnownConfigNames.RemoteAppHostProcessStarted); Assert.Equal("4321", environment[KnownConfigNames.RemoteAppHostProcessId]); Assert.Equal("1000", environment[KnownConfigNames.RemoteAppHostProcessStarted]); } [Fact] public void Apply_WithNullStartTime_StampsPidOnly() { var environment = new Dictionary<string, string?>(StringComparer.Ordinal); OrphanDetectionEnvironment.Apply(environment, pid: 4321, stableStartTimeUnixMilliseconds: null, KnownConfigNames.CliProcessId, KnownConfigNames.CliProcessStarted); Assert.Equal("4321", environment[KnownConfigNames.CliProcessId]); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStarted)); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStartedStable)); } [Fact] public void Apply_WithOverwriteAndNullStartTime_RemovesCallerStartTimes() { var environment = new Dictionary<string, string?>(StringComparer.Ordinal) { [KnownConfigNames.CliProcessId] = "999", [KnownConfigNames.CliProcessStarted] = "111", [KnownConfigNames.CliProcessStartedStable] = "222", }; OrphanDetectionEnvironment.Apply(environment, pid: 4321, stableStartTimeUnixMilliseconds: null, KnownConfigNames.CliProcessId, KnownConfigNames.CliProcessStarted, overwrite: true); Assert.Equal("4321", environment[KnownConfigNames.CliProcessId]); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStarted)); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStartedStable)); } [Fact] public void Apply_WithOverwriteAndUnavailableRuntimeStartTime_RemovesCallerLegacyStartTime() { var environment = new Dictionary<string, string?>(StringComparer.Ordinal) { [KnownConfigNames.CliProcessId] = "999", [KnownConfigNames.CliProcessStarted] = "111", [KnownConfigNames.CliProcessStartedStable] = "222", }; OrphanDetectionEnvironment.Apply(environment, pid: int.MaxValue, stableStartTimeUnixMilliseconds: 1000, KnownConfigNames.CliProcessId, KnownConfigNames.CliProcessStarted, overwrite: true); Assert.Equal(int.MaxValue.ToString(CultureInfo.InvariantCulture), environment[KnownConfigNames.CliProcessId]); Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStarted)); Assert.Equal("1000", environment[KnownConfigNames.CliProcessStartedStable]); } [Fact] public void Apply_WithoutOverwrite_PreservesCallerValues() { var environment = new Dictionary<string, string?>(StringComparer.Ordinal) { [KnownConfigNames.CliProcessId] = "999", [KnownConfigNames.CliProcessStarted] = "111", }; OrphanDetectionEnvironment.Apply(environment, pid: 4321, stableStartTimeUnixMilliseconds: 1000, KnownConfigNames.CliProcessId, KnownConfigNames.CliProcessStarted, overwrite: false); Assert.Equal("999", environment[KnownConfigNames.CliProcessId]); Assert.Equal("111", environment[KnownConfigNames.CliProcessStarted]); // The existing PID (999) is authoritative, so the stable start time for the passed pid (4321) // is not stamped — doing so would pair PID 999 with a different process's start time. Assert.False(environment.ContainsKey(KnownConfigNames.CliProcessStartedStable)); } }