From 2c4455c75015a63e694761c57be98cb51eb51637 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Fri, 20 Mar 2026 09:37:15 -0700 Subject: [PATCH] Revert "Use home-based CLI cache and randomized socket paths (#15346)" This reverts commit 1fab1b1817c2f2b8f0f73c2d7a37cee433b38277. --- src/Aspire.Cli/Aspire.Cli.csproj | 1 - src/Aspire.Cli/DotNet/DotNetCliRunner.cs | 12 +- src/Aspire.Cli/Program.cs | 4 +- .../Projects/AppHostServerProject.cs | 25 +++- .../Projects/GuestAppHostProject.cs | 6 +- src/Aspire.Cli/Projects/ProjectUpdater.cs | 2 +- src/Aspire.Cli/Utils/AppHostHelper.cs | 10 +- src/Aspire.Cli/Utils/CliPathHelper.cs | 39 ----- src/Shared/BackchannelConstants.cs | 133 ++++-------------- .../Packaging/PackagingServiceTests.cs | 3 +- .../Utils/AppHostHelperTests.cs | 34 +---- .../Utils/CliPathHelperTests.cs | 34 ----- 12 files changed, 81 insertions(+), 222 deletions(-) delete mode 100644 src/Aspire.Cli/Utils/CliPathHelper.cs delete mode 100644 tests/Aspire.Cli.Tests/Utils/CliPathHelperTests.cs diff --git a/src/Aspire.Cli/Aspire.Cli.csproj b/src/Aspire.Cli/Aspire.Cli.csproj index 7eca03b7b3a..adb5afa80a1 100644 --- a/src/Aspire.Cli/Aspire.Cli.csproj +++ b/src/Aspire.Cli/Aspire.Cli.csproj @@ -58,7 +58,6 @@ - diff --git a/src/Aspire.Cli/DotNet/DotNetCliRunner.cs b/src/Aspire.Cli/DotNet/DotNetCliRunner.cs index 9ddd56b189c..2f88d686563 100644 --- a/src/Aspire.Cli/DotNet/DotNetCliRunner.cs +++ b/src/Aspire.Cli/DotNet/DotNetCliRunner.cs @@ -83,7 +83,17 @@ private string GetMsBuildServerValue() internal static string GetBackchannelSocketPath() { - return CliPathHelper.CreateSocketPath("cli.sock"); + var homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var aspireCliPath = Path.Combine(homeDirectory, ".aspire", "cli", "backchannels"); + + if (!Directory.Exists(aspireCliPath)) + { + Directory.CreateDirectory(aspireCliPath); + } + + var uniqueSocketPathSegment = Guid.NewGuid().ToString("N"); + var socketPath = Path.Combine(aspireCliPath, $"cli.sock.{uniqueSocketPathSegment}"); + return socketPath; } private async Task ExecuteAsync( diff --git a/src/Aspire.Cli/Program.cs b/src/Aspire.Cli/Program.cs index db3e8652f13..4f5e6c776a4 100644 --- a/src/Aspire.Cli/Program.cs +++ b/src/Aspire.Cli/Program.cs @@ -53,7 +53,9 @@ public class Program { private static string GetUsersAspirePath() { - return CliPathHelper.GetAspireHomeDirectory(); + var homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var aspirePath = Path.Combine(homeDirectory, ".aspire"); + return aspirePath; } /// diff --git a/src/Aspire.Cli/Projects/AppHostServerProject.cs b/src/Aspire.Cli/Projects/AppHostServerProject.cs index d2c37cc2d5a..7e4a40d38bd 100644 --- a/src/Aspire.Cli/Projects/AppHostServerProject.cs +++ b/src/Aspire.Cli/Projects/AppHostServerProject.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Security.Cryptography; +using System.Text; using Aspire.Cli.Bundles; using Aspire.Cli.Configuration; using Aspire.Cli.DotNet; @@ -34,7 +36,28 @@ internal sealed class AppHostServerProjectFactory( { public async Task CreateAsync(string appPath, CancellationToken cancellationToken = default) { - var socketPath = CliPathHelper.CreateSocketPath("apphost.sock"); + // Normalize the path + var normalizedPath = Path.GetFullPath(appPath); + normalizedPath = new Uri(normalizedPath).LocalPath; + normalizedPath = OperatingSystem.IsWindows() ? normalizedPath.ToLowerInvariant() : normalizedPath; + + // Generate socket path based on app path hash (deterministic for same project) + var pathHash = SHA256.HashData(Encoding.UTF8.GetBytes(normalizedPath)); + var socketName = Convert.ToHexString(pathHash)[..12].ToLowerInvariant() + ".sock"; + + string socketPath; + if (OperatingSystem.IsWindows()) + { + // Windows uses named pipes + socketPath = socketName; + } + else + { + // Unix uses domain sockets + var socketDir = Path.Combine(Path.GetTempPath(), ".aspire", "sockets"); + Directory.CreateDirectory(socketDir); + socketPath = Path.Combine(socketDir, socketName); + } // Priority 1: Check for dev mode (ASPIRE_REPO_ROOT or running from Aspire source repo) var repoRoot = AspireRepositoryDetector.DetectRepositoryRoot(appPath); diff --git a/src/Aspire.Cli/Projects/GuestAppHostProject.cs b/src/Aspire.Cli/Projects/GuestAppHostProject.cs index 74c16ceda2a..e856ebce8ff 100644 --- a/src/Aspire.Cli/Projects/GuestAppHostProject.cs +++ b/src/Aspire.Cli/Projects/GuestAppHostProject.cs @@ -925,7 +925,11 @@ await GenerateCodeViaRpcAsync( /// private static string GetBackchannelSocketPath() { - return CliPathHelper.CreateSocketPath("cli.sock"); + var homeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var aspireCliPath = Path.Combine(homeDirectory, ".aspire", "cli", "backchannels"); + Directory.CreateDirectory(aspireCliPath); + var socketName = $"{Guid.NewGuid():N}.sock"; + return Path.Combine(aspireCliPath, socketName); } /// diff --git a/src/Aspire.Cli/Projects/ProjectUpdater.cs b/src/Aspire.Cli/Projects/ProjectUpdater.cs index 647011463bd..735d3ddbaff 100644 --- a/src/Aspire.Cli/Projects/ProjectUpdater.cs +++ b/src/Aspire.Cli/Projects/ProjectUpdater.cs @@ -115,7 +115,7 @@ public async Task UpdateProjectAsync(FileInfo projectFile, cancellationToken: cancellationToken); var nugetConfigDirectory = new DirectoryInfo(selectedPathForNewNuGetConfigFile); - await NuGetConfigMerger.CreateOrUpdateAsync(nugetConfigDirectory, channel, AnalyzeAndConfirmNuGetConfigChanges, cancellationToken: cancellationToken); + await NuGetConfigMerger.CreateOrUpdateAsync(nugetConfigDirectory, channel, AnalyzeAndConfirmNuGetConfigChanges, cancellationToken); } interactionService.DisplayEmptyLine(); diff --git a/src/Aspire.Cli/Utils/AppHostHelper.cs b/src/Aspire.Cli/Utils/AppHostHelper.cs index bcde6f6ae1c..f080a53e909 100644 --- a/src/Aspire.Cli/Utils/AppHostHelper.cs +++ b/src/Aspire.Cli/Utils/AppHostHelper.cs @@ -83,8 +83,7 @@ internal static async Task BuildAppHostAsync(IDotNetCliRunner runner, IInte /// Computes the auxiliary backchannel socket path prefix for a given AppHost project file. /// /// - /// Since socket names now include a randomized instance hash and the AppHost's PID - /// (e.g., auxi.sock.{hash}.{instanceHash}.{pid}), + /// Since socket names now include the AppHost's PID (e.g., auxi.sock.{hash}.{pid}), /// the CLI cannot compute the exact socket path. Use this prefix with a glob pattern /// to find matching sockets, or use instead. /// @@ -107,16 +106,15 @@ internal static string[] FindMatchingSockets(string appHostPath, string homeDire /// Extracts the hash portion from an auxiliary socket path. /// /// - /// Works with old format (auxi.sock.{hash}), previous format (auxi.sock.{hash}.{pid}), - /// and current format (auxi.sock.{hash}.{instanceHash}.{pid}). + /// Works with both old format (auxi.sock.{hash}) and new format (auxi.sock.{hash}.{pid}). /// - /// The full socket path (e.g., "/path/to/auxi.sock.b67075ff12d56865.a1b2c3d4e5f6.12345"). + /// The full socket path (e.g., "/path/to/auxi.sock.b67075ff12d56865.12345"). /// The hash portion (e.g., "b67075ff12d56865"), or null if the format is unrecognized. internal static string? ExtractHashFromSocketPath(string socketPath) => BackchannelConstants.ExtractHash(socketPath); /// - /// Extracts the PID from an auxiliary socket path when one is present. + /// Extracts the PID from an auxiliary socket path (new format only). /// /// The full socket path. /// The PID if present and valid, or null for old format sockets. diff --git a/src/Aspire.Cli/Utils/CliPathHelper.cs b/src/Aspire.Cli/Utils/CliPathHelper.cs deleted file mode 100644 index 46f87a397b2..00000000000 --- a/src/Aspire.Cli/Utils/CliPathHelper.cs +++ /dev/null @@ -1,39 +0,0 @@ -// 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.Backchannel; - -namespace Aspire.Cli.Utils; - -internal static class CliPathHelper -{ - internal static string GetAspireHomeDirectory() - => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".aspire"); - - /// - /// Creates a randomized CLI-managed socket path. - /// - /// The socket file prefix. - internal static string CreateSocketPath(string socketPrefix) - { - var socketName = $"{socketPrefix}.{BackchannelConstants.CreateRandomIdentifier()}"; - - if (OperatingSystem.IsWindows()) - { - return socketName; - } - - var socketDirectory = GetCliSocketDirectory(); - Directory.CreateDirectory(socketDirectory); - return Path.Combine(socketDirectory, socketName); - } - - private static string GetCliHomeDirectory() - => Path.Combine(GetAspireHomeDirectory(), "cli"); - - private static string GetCliRuntimeDirectory() - => Path.Combine(GetCliHomeDirectory(), "runtime"); - - private static string GetCliSocketDirectory() - => Path.Combine(GetCliRuntimeDirectory(), "sockets"); -} diff --git a/src/Shared/BackchannelConstants.cs b/src/Shared/BackchannelConstants.cs index af06aabba44..ea80c64990c 100644 --- a/src/Shared/BackchannelConstants.cs +++ b/src/Shared/BackchannelConstants.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Globalization; -using System.IO.Hashing; using System.Security.Cryptography; using System.Text; @@ -34,19 +33,15 @@ namespace Aspire.Hosting.Backchannel; /// Socket Naming Format /// /// -/// New format: auxi.sock.{appHostHash}.{instanceHash}.{pid} +/// New format: auxi.sock.{hash}.{pid} /// /// /// auxi.sock - Prefix (not "aux" because that's reserved on Windows) -/// {appHostHash} - xxHash(AppHost project path)[0:16] - identifies the AppHost project -/// {instanceHash} - random hex identifier[0:12] - makes each socket name non-deterministic +/// {hash} - SHA256(AppHost project path)[0:16] - identifies the AppHost project /// {pid} - Process ID of the AppHost - identifies the specific instance /// /// -/// Previous format (for backward compatibility): auxi.sock.{appHostHash}.{pid} -/// -/// -/// Old format (for backward compatibility): auxi.sock.{appHostHash} +/// Old format (for backward compatibility): auxi.sock.{hash} /// /// /// Why PID in the Filename? @@ -77,30 +72,16 @@ internal static class BackchannelConstants public const string SocketPrefix = "auxi.sock"; /// - /// Number of hex characters to use from the stable xxHash-based AppHost identifier. + /// Number of hex characters to use from the SHA256 hash. /// /// /// Using 16 chars (64 bits) balances uniqueness against path length constraints. /// Unix socket paths are limited to ~104 characters on most systems. - /// Full path example: ~/.aspire/cli/backchannels/auxi.sock.bc43b855b6848166.a1b2c3d4e5f6.46730 - /// = ~78 characters, well under the limit. + /// Full path example: ~/.aspire/cli/backchannels/auxi.sock.bc43b855b6848166.46730 + /// = ~65 characters, well under the limit. /// public const int HashLength = 16; - /// - /// Number of hex characters to use for compact local identifiers. - /// - /// - /// Using 12 chars (48 bits) keeps socket and package cache paths short while still providing - /// enough variation for local file names that are not part of a security boundary. - /// - public const int CompactIdentifierLength = 12; - - /// - /// Number of hex characters to use from the randomized instance identifier. - /// - public const int InstanceHashLength = CompactIdentifierLength; - /// /// Gets the backchannels directory path for the given home directory. /// @@ -122,15 +103,16 @@ public static string GetBackchannelsDirectory(string homeDirectory) /// A 16-character lowercase hex string. public static string ComputeHash(string appHostPath) { - return ComputeStableIdentifier(appHostPath, HashLength); + var hashBytes = SHA256.HashData(Encoding.UTF8.GetBytes(appHostPath)); + return Convert.ToHexString(hashBytes)[..HashLength].ToLowerInvariant(); } /// /// Computes the full socket path for an AppHost instance. /// /// - /// Called by AppHost when creating the socket. Includes a randomized instance hash and the PID - /// to ensure uniqueness across multiple instances of the same AppHost. + /// Called by AppHost when creating the socket. Includes the PID to ensure + /// uniqueness across multiple instances of the same AppHost. /// /// The full path to the AppHost project file. /// The user's home directory. @@ -140,8 +122,7 @@ public static string ComputeSocketPath(string appHostPath, string homeDirectory, { var dir = GetBackchannelsDirectory(homeDirectory); var hash = ComputeHash(appHostPath); - var instanceHash = CreateRandomIdentifier(InstanceHashLength); - return Path.Combine(dir, $"{SocketPrefix}.{hash}.{instanceHash}.{processId}"); + return Path.Combine(dir, $"{SocketPrefix}.{hash}.{processId}"); } /// @@ -166,8 +147,7 @@ public static string ComputeSocketPrefix(string appHostPath, string homeDirector /// /// /// Returns all socket files for an AppHost, regardless of PID. This includes - /// old format (auxi.sock.{hash}), previous format (auxi.sock.{hash}.{pid}), - /// and current format (auxi.sock.{hash}.{instanceHash}.{pid}). + /// both old format (auxi.sock.{hash}) and new format (auxi.sock.{hash}.{pid}). /// /// The full path to the AppHost project file. /// The user's home directory. @@ -183,15 +163,13 @@ public static string[] FindMatchingSockets(string appHostPath, string homeDirect return []; } - // Match old format (auxi.sock.{hash}), previous format (auxi.sock.{hash}.{pid}), - // and current format (auxi.sock.{hash}.{instanceHash}.{pid}) + // Match both old format (auxi.sock.{hash}) and new format (auxi.sock.{hash}.{pid}) // Use pattern with "*" to match optional PID suffix var allMatches = Directory.GetFiles(dir, prefixFileName + "*"); - // Filter to only include exact match (old format), .{pid} suffix (previous format), - // or .{instanceHash}.{pid} suffix (current format). This avoids matching - // auxi.sock.{hash}abc (different hash that starts with same chars) and files - // like auxi.sock.{hash}.12345.bak. + // Filter to only include exact match (old format) or .{pid} suffix (new format) + // This avoids matching auxi.sock.{hash}abc (different hash that starts with same chars) + // and also avoids matching files like auxi.sock.{hash}.12345.bak return allMatches.Where(f => { var fileName = Path.GetFileName(f); @@ -199,24 +177,12 @@ public static string[] FindMatchingSockets(string appHostPath, string homeDirect { return true; // Old format: exact match } - - if (!fileName.StartsWith(prefixFileName + ".", StringComparison.Ordinal)) + if (fileName.StartsWith(prefixFileName + ".", StringComparison.Ordinal) && + int.TryParse(fileName.AsSpan(prefixFileName.Length + 1), NumberStyles.None, CultureInfo.InvariantCulture, out _)) { - return false; + return true; // New format: prefix followed by dot and integer PID } - - var suffix = fileName[(prefixFileName.Length + 1)..]; - var segments = suffix.Split('.'); - - if (segments.Length == 1 && - int.TryParse(segments[0], NumberStyles.None, CultureInfo.InvariantCulture, out _)) - { - return true; // Previous format: prefix followed by integer PID - } - - return segments.Length == 2 && - IsHex(segments[0]) && - int.TryParse(segments[1], NumberStyles.None, CultureInfo.InvariantCulture, out _); + return false; }).ToArray(); } @@ -224,8 +190,7 @@ public static string[] FindMatchingSockets(string appHostPath, string homeDirect /// Extracts the hash from a socket filename. /// /// - /// Works with old format (auxi.sock.{hash}), previous format (auxi.sock.{hash}.{pid}), - /// and current format (auxi.sock.{hash}.{instanceHash}.{pid}). + /// Works with both old format (auxi.sock.{hash}) and new format (auxi.sock.{hash}.{pid}). /// /// The full socket path or filename. /// The hash portion, or null if the format is unrecognized. @@ -233,13 +198,12 @@ public static string[] FindMatchingSockets(string appHostPath, string homeDirect { var fileName = Path.GetFileName(socketPath); - // Handle current format: auxi.sock.{hash}.{instanceHash}.{pid} - // Handle previous format: auxi.sock.{hash}.{pid} + // Handle new format: auxi.sock.{hash}.{pid} // Handle old format: auxi.sock.{hash} if (fileName.StartsWith($"{SocketPrefix}.", StringComparison.Ordinal)) { var afterPrefix = fileName[($"{SocketPrefix}.".Length)..]; - // If there's another dot, it's a multi-segment format - return just the AppHost hash part + // If there's another dot, it's new format - return just the hash part var dotIndex = afterPrefix.IndexOf('.'); return dotIndex > 0 ? afterPrefix[..dotIndex] : afterPrefix; } @@ -256,7 +220,7 @@ public static string[] FindMatchingSockets(string appHostPath, string homeDirect } /// - /// Extracts the PID from a socket filename when one is present. + /// Extracts the PID from a socket filename (new format only). /// /// The full socket path or filename. /// The PID if present and valid, or null for old format sockets. @@ -309,8 +273,7 @@ public static bool ProcessExists(int pid) /// support PID-based orphan detection. /// /// - /// Limitation: This method only cleans up sockets that include a PID - /// (auxi.sock.{hash}.{pid} or auxi.sock.{hash}.{instanceHash}.{pid}) + /// Limitation: This method only cleans up new format sockets (auxi.sock.{hash}.{pid}) /// because old format sockets (auxi.sock.{hash}) don't have a PID for orphan detection. /// Old format sockets are cleaned up via connection-based detection in the CLI. /// @@ -328,7 +291,7 @@ public static int CleanupOrphanedSockets(string backchannelsDirectory, string ha return deleted; } - // Find all sockets for this hash across all supported formats. + // Find all sockets for this hash (both old and new format) var pattern = $"{SocketPrefix}.{hash}*"; foreach (var socketPath in Directory.GetFiles(backchannelsDirectory, pattern)) { @@ -354,48 +317,4 @@ public static int CleanupOrphanedSockets(string backchannelsDirectory, string ha return deleted; } - - /// - /// Computes a compact stable identifier from a string value. - /// - /// - /// Uses XxHash3 because these identifiers are only used for local naming and lookup. They do not - /// protect secrets or cross a trust boundary, so a fast non-cryptographic hash is preferable to SHA-2. - /// - /// The string value to hash. - /// The number of lowercase hex characters to return. - /// A lowercase hex identifier truncated to characters. - public static string ComputeStableIdentifier(string value, int length = CompactIdentifierLength) - { - ArgumentException.ThrowIfNullOrEmpty(value); - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(length); - var xxHash = new XxHash3(); - xxHash.Append(Encoding.UTF8.GetBytes(value)); - - return ToLowerHexIdentifier(xxHash.GetCurrentHash(), length); - } - - /// - /// Creates a compact randomized identifier. - /// - /// The number of lowercase hex characters to return. - /// A lowercase hex identifier truncated to characters. - public static string CreateRandomIdentifier(int length = CompactIdentifierLength) - { - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(length); - - Span randomBytes = stackalloc byte[(length + 1) / 2]; - RandomNumberGenerator.Fill(randomBytes); - - return ToLowerHexIdentifier(randomBytes, length); - } - - private static bool IsHex(string value) - => !string.IsNullOrEmpty(value) && value.All(static c => char.IsAsciiHexDigit(c)); - - private static string ToLowerHexIdentifier(ReadOnlySpan bytes, int length) - { - var hex = Convert.ToHexString(bytes).ToLowerInvariant(); - return hex[..Math.Min(length, hex.Length)]; - } } diff --git a/tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs b/tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs index 7cf4720ef09..51ce56b6907 100644 --- a/tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs +++ b/tests/Aspire.Cli.Tests/Packaging/PackagingServiceTests.cs @@ -382,8 +382,7 @@ public async Task NuGetConfigMerger_WhenChannelRequiresGlobalPackagesFolder_Adds var globalPackagesFolderAdd = configSection.Elements("add") .FirstOrDefault(add => string.Equals((string?)add.Attribute("key"), "globalPackagesFolder", StringComparison.OrdinalIgnoreCase)); Assert.NotNull(globalPackagesFolderAdd); - var actualGlobalPackagesFolder = (string?)globalPackagesFolderAdd.Attribute("value"); - Assert.Equal(".nugetpackages", actualGlobalPackagesFolder); + Assert.Equal(".nugetpackages", (string?)globalPackagesFolderAdd.Attribute("value")); } [Fact] diff --git a/tests/Aspire.Cli.Tests/Utils/AppHostHelperTests.cs b/tests/Aspire.Cli.Tests/Utils/AppHostHelperTests.cs index 87c2fcc5dca..23f862445ed 100644 --- a/tests/Aspire.Cli.Tests/Utils/AppHostHelperTests.cs +++ b/tests/Aspire.Cli.Tests/Utils/AppHostHelperTests.cs @@ -97,25 +97,14 @@ public void ComputeAuxiliarySocketPrefix_HashIs16Characters() [Fact] public void ExtractHashFromSocketPath_ExtractsHashFromNewFormat() { - // Current format: auxi.sock.{hash}.{instanceHash}.{pid} - var socketPath = "/home/user/.aspire/cli/backchannels/auxi.sock.abc123def4567890.a1b2c3d4e5f6.12345"; + // New format: auxi.sock.{hash}.{pid} + var socketPath = "/home/user/.aspire/cli/backchannels/auxi.sock.abc123def4567890.12345"; var hash = AppHostHelper.ExtractHashFromSocketPath(socketPath); Assert.Equal("abc123def4567890", hash); } - [Fact] - public void ExtractHashFromSocketPath_ExtractsHashFromPreviousFormat() - { - // Previous format: auxi.sock.{hash}.{pid} - var socketPath = "/home/user/.aspire/cli/backchannels/auxi.sock.abc123def4567890.12345"; - - var hash = AppHostHelper.ExtractHashFromSocketPath(socketPath); - - Assert.Equal("abc123def4567890", hash); - } - [Fact] public void ExtractHashFromSocketPath_ExtractsHashFromOldFormat() { @@ -151,25 +140,14 @@ public void ExtractHashFromSocketPath_ReturnsNullForUnrecognizedFormat() [Fact] public void ExtractPidFromSocketPath_ExtractsPidFromNewFormat() { - // Current format: auxi.sock.{hash}.{instanceHash}.{pid} - var socketPath = "/home/user/.aspire/cli/backchannels/auxi.sock.abc123def4567890.a1b2c3d4e5f6.12345"; + // New format: auxi.sock.{hash}.{pid} + var socketPath = "/home/user/.aspire/cli/backchannels/auxi.sock.abc123def4567890.12345"; var pid = AppHostHelper.ExtractPidFromSocketPath(socketPath); Assert.Equal(12345, pid); } - [Fact] - public void ExtractPidFromSocketPath_ExtractsPidFromPreviousFormat() - { - // Previous format: auxi.sock.{hash}.{pid} - var socketPath = "/home/user/.aspire/cli/backchannels/auxi.sock.abc123def4567890.12345"; - - var pid = AppHostHelper.ExtractPidFromSocketPath(socketPath); - - Assert.Equal(12345, pid); - } - [Fact] public void ExtractPidFromSocketPath_ReturnsNullForOldFormat() { @@ -237,8 +215,8 @@ public void FindMatchingSockets_FindsMatchingSocketFiles() var prefix = AppHostHelper.ComputeAuxiliarySocketPrefix(appHostPath, workspace.WorkspaceRoot.FullName); var hash = Path.GetFileName(prefix)["auxi.sock.".Length..]; - // Create matching socket files in both current and previous formats. - var socket1 = Path.Combine(backchannelsDir, $"auxi.sock.{hash}.a1b2c3d4e5f6.12345"); + // Create matching socket files (new format with PID) + var socket1 = Path.Combine(backchannelsDir, $"auxi.sock.{hash}.12345"); var socket2 = Path.Combine(backchannelsDir, $"auxi.sock.{hash}.67890"); File.WriteAllText(socket1, ""); File.WriteAllText(socket2, ""); diff --git a/tests/Aspire.Cli.Tests/Utils/CliPathHelperTests.cs b/tests/Aspire.Cli.Tests/Utils/CliPathHelperTests.cs deleted file mode 100644 index 5f31d7fa973..00000000000 --- a/tests/Aspire.Cli.Tests/Utils/CliPathHelperTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Aspire.Cli.Utils; - -namespace Aspire.Cli.Tests.Utils; - -public class CliPathHelperTests(ITestOutputHelper outputHelper) -{ - [Fact] - public void CreateSocketPath_UsesRandomizedIdentifier() - { - using var workspace = TemporaryWorkspace.Create(outputHelper); - - var socketPath1 = CliPathHelper.CreateSocketPath("apphost.sock"); - var socketPath2 = CliPathHelper.CreateSocketPath("apphost.sock"); - - Assert.NotEqual(socketPath1, socketPath2); - - if (OperatingSystem.IsWindows()) - { - Assert.Matches("^apphost\\.sock\\.[a-f0-9]{12}$", socketPath1); - Assert.Matches("^apphost\\.sock\\.[a-f0-9]{12}$", socketPath2); - } - else - { - var expectedDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".aspire", "cli", "runtime", "sockets"); - Assert.Equal(expectedDirectory, Path.GetDirectoryName(socketPath1)); - Assert.Equal(expectedDirectory, Path.GetDirectoryName(socketPath2)); - Assert.Matches("^apphost\\.sock\\.[a-f0-9]{12}$", Path.GetFileName(socketPath1)); - Assert.Matches("^apphost\\.sock\\.[a-f0-9]{12}$", Path.GetFileName(socketPath2)); - } - } -}