From 4da124f335565d42f342a456e2d2e43002b14292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 11 Jul 2026 14:07:50 +0200 Subject: [PATCH 1/7] Allow IPC named pipe directory to be overridden on Unix On Unix the IPC named pipe is backed by a Unix domain socket file that was always created under /tmp. Sandboxed environments (e.g. Claude Code on macOS) that block /tmp cannot run `dotnet test`. Resolve the directory as: 1. TESTINGPLATFORM_PIPE_DIRECTORY (explicit opt-in override) 2. Path.GetTempPath() (honors TMPDIR on Unix) 3. /tmp (previous default) Add a sun_path length guard (always) and a writability probe (override only), both failing with actionable, localized messages. Keep the logic self-contained in NamedPipeServer.cs so it flows into dotnet/sdk on the next vendor sync, and document the "creator resolves, full path is passed, peers never recompute" invariant so the directory never becomes a shared convention that couples SDK and test-host versions. Fixes #9821 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../Helpers/EnvironmentVariableConstants.cs | 4 + .../IPC/NamedPipeServer.cs | 109 +++++++++++++++++- .../Resources/PlatformResources.cs | 4 + .../Resources/PlatformResources.resx | 8 ++ .../Resources/xlf/PlatformResources.cs.xlf | 10 ++ .../Resources/xlf/PlatformResources.de.xlf | 10 ++ .../Resources/xlf/PlatformResources.es.xlf | 10 ++ .../Resources/xlf/PlatformResources.fr.xlf | 10 ++ .../Resources/xlf/PlatformResources.it.xlf | 10 ++ .../Resources/xlf/PlatformResources.ja.xlf | 10 ++ .../Resources/xlf/PlatformResources.ko.xlf | 10 ++ .../Resources/xlf/PlatformResources.pl.xlf | 10 ++ .../Resources/xlf/PlatformResources.pt-BR.xlf | 10 ++ .../Resources/xlf/PlatformResources.ru.xlf | 10 ++ .../Resources/xlf/PlatformResources.tr.xlf | 10 ++ .../xlf/PlatformResources.zh-Hans.xlf | 10 ++ .../xlf/PlatformResources.zh-Hant.xlf | 10 ++ .../IPC/IPCTests.cs | 49 ++++++++ 18 files changed, 302 insertions(+), 2 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Platform/Helpers/EnvironmentVariableConstants.cs b/src/Platform/Microsoft.Testing.Platform/Helpers/EnvironmentVariableConstants.cs index 6073f436bd..4c85f7355d 100644 --- a/src/Platform/Microsoft.Testing.Platform/Helpers/EnvironmentVariableConstants.cs +++ b/src/Platform/Microsoft.Testing.Platform/Helpers/EnvironmentVariableConstants.cs @@ -14,6 +14,10 @@ internal static class EnvironmentVariableConstants public const string TESTINGPLATFORM_DEFAULT_HANG_TIMEOUT = nameof(TESTINGPLATFORM_DEFAULT_HANG_TIMEOUT); public const string TESTINGPLATFORM_MESSAGEBUS_DRAINDATA_ATTEMPTS = nameof(TESTINGPLATFORM_MESSAGEBUS_DRAINDATA_ATTEMPTS); + // Overrides the directory where the IPC named pipe (Unix domain socket) files are created. + // Only honored on Unix; Windows named pipes live in the kernel namespace, not on disk. + public const string TESTINGPLATFORM_PIPE_DIRECTORY = nameof(TESTINGPLATFORM_PIPE_DIRECTORY); + public const string TESTINGPLATFORM_TESTHOSTCONTROLLER_SKIPEXTENSION = nameof(TESTINGPLATFORM_TESTHOSTCONTROLLER_SKIPEXTENSION); public const string TESTINGPLATFORM_TESTHOSTCONTROLLER_PIPENAME = nameof(TESTINGPLATFORM_TESTHOSTCONTROLLER_PIPENAME); public const string TESTINGPLATFORM_TESTHOSTCONTROLLER_CORRELATIONID = nameof(TESTINGPLATFORM_TESTHOSTCONTROLLER_CORRELATIONID); diff --git a/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs b/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs index 4b9bd682dd..701875aa23 100644 --- a/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs +++ b/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs @@ -25,6 +25,11 @@ internal sealed class NamedPipeServer : NamedPipeConnectionBase, IServer private static bool IsUnix => Path.DirectorySeparatorChar == '/'; + // Maximum length, in bytes, of the path stored in sockaddr_un.sun_path for a Unix domain socket. + // The smallest limit across supported platforms is macOS' 104 bytes (Linux allows 108); we use the + // smaller value minus one for the NUL terminator so the resolved path stays portable. + internal const int MaxUnixDomainSocketPathLengthInBytes = 104 - 1; + private readonly Func> _callback; private readonly IEnvironment _environment; private readonly NamedPipeServerStream _namedPipeServerStream; @@ -158,6 +163,18 @@ private async Task InternalLoopAsync(CancellationToken cancellationToken) } } + /// + /// Computes the OS-level named pipe name for a friendly . + /// + /// + /// Invariant (important for cross-version / cross-repo compatibility): the process that creates the + /// pipe resolves the directory locally and hands the fully-resolved path to the peer (via an + /// environment variable, a command-line argument, or the dotnet-test handshake). Peers use that path verbatim + /// and never recompute it. Do NOT turn the directory into a convention that both sides derive independently + /// from a shared friendly name/env var - doing so would couple the SDK and test-host versions. Because only + /// the creator's resolution is ever used, a difference in TESTINGPLATFORM_PIPE_DIRECTORY / TMPDIR between the + /// two processes is harmless. + /// public static PipeNameDescription GetPipeName(string name) { if (!IsUnix) @@ -165,8 +182,96 @@ public static PipeNameDescription GetPipeName(string name) return new PipeNameDescription($"testingplatform.pipe.{name.Replace('\\', '.')}"); } - // Similar to https://github.com/dotnet/roslyn/blob/99bf83c7bc52fa1ff27cf792db38755d5767c004/src/Compilers/Shared/NamedPipeUtil.cs#L26-L42 - return new PipeNameDescription(Path.Combine("/tmp", name)); + // On Unix the named pipe is backed by a Unix domain socket file on disk. Historically this file + // was always created under '/tmp' (similar to + // https://github.com/dotnet/roslyn/blob/99bf83c7bc52fa1ff27cf792db38755d5767c004/src/Compilers/Shared/NamedPipeUtil.cs#L26-L42). + // That is a problem in sandboxed environments that block '/tmp' (see + // https://github.com/microsoft/testfx/issues/9821), so we allow the directory to be relocated. + // Resolution precedence: + // 1. TESTINGPLATFORM_PIPE_DIRECTORY - explicit opt-in override, a guaranteed escape hatch. + // 2. Path.GetTempPath() - honors TMPDIR on Unix; usually a per-user, allowed dir. + // 3. '/tmp' - preserves the previous default when neither is set. + (string directory, bool isExplicitOverride) = ResolvePipeDirectory(); + + // Only actively validate the explicit override: it is user-supplied and the most likely to be wrong + // (typo, missing directory, wrong permissions), so we create it if needed and fail fast with an + // actionable message. Path.GetTempPath()/'/tmp' are OS-managed and effectively always writable, so we + // skip the probe there to avoid extra I/O and a behavior change on every pipe creation. + if (isExplicitOverride) + { + EnsureDirectoryIsWritable(directory); + } + + string path = Path.Combine(directory, name); + EnsurePathLengthWithinLimit(path); + + return new PipeNameDescription(path); + } + + private static (string Directory, bool IsExplicitOverride) ResolvePipeDirectory() + => ResolvePipeDirectory( + Environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY), + Path.GetTempPath()); + + // Pure resolution logic split out so it can be unit-tested on any OS (the Unix branch of GetPipeName + // never runs on Windows) without mutating process-wide environment variables. + internal static (string Directory, bool IsExplicitOverride) ResolvePipeDirectory(string? overrideDirectory, string? tempPath) + { + if (!string.IsNullOrWhiteSpace(overrideDirectory)) + { + return (overrideDirectory!, true); + } + + // Path.GetTempPath() honors TMPDIR on Unix and already falls back to '/tmp' itself when TMPDIR is unset. + return string.IsNullOrWhiteSpace(tempPath) + ? ("/tmp", false) + : (tempPath!, false); + } + + private static void EnsureDirectoryIsWritable(string directory) + { + try + { + Directory.CreateDirectory(directory); + + // Probe write access with a short-lived file so a misconfigured directory fails fast with an + // actionable message instead of surfacing a cryptic socket bind failure later on. + string probePath = Path.Combine(directory, $"testingplatform.probe.{Guid.NewGuid():N}"); + using (File.Create(probePath)) + { + } + + File.Delete(probePath); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or System.Security.SecurityException or NotSupportedException or ArgumentException) + { + throw new InvalidOperationException( + string.Format( + CultureInfo.InvariantCulture, + PlatformResources.NamedPipeDirectoryNotWritableErrorMessage, + directory, + ex.Message, + EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY), + ex); + } + } + + // Internal for unit testing: enforce the Unix domain socket sun_path budget so a too-long directory + // (e.g. a deep TMPDIR on macOS) fails with an actionable message instead of a cryptic bind error. + internal static void EnsurePathLengthWithinLimit(string path) + { + int byteLength = System.Text.Encoding.UTF8.GetByteCount(path); + if (byteLength > MaxUnixDomainSocketPathLengthInBytes) + { + throw new InvalidOperationException( + string.Format( + CultureInfo.InvariantCulture, + PlatformResources.NamedPipePathTooLongErrorMessage, + path, + byteLength, + MaxUnixDomainSocketPathLengthInBytes, + EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY)); + } } public void Dispose() diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.cs b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.cs index 8eaeac7f2d..ed16fc0c8f 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.cs +++ b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.cs @@ -32,6 +32,10 @@ internal static partial class PlatformResources internal static string @InternalLoopAsyncDidNotExitSuccessfullyErrorMessage => GetResourceString("InternalLoopAsyncDidNotExitSuccessfullyErrorMessage"); + internal static string @NamedPipePathTooLongErrorMessage => GetResourceString("NamedPipePathTooLongErrorMessage"); + + internal static string @NamedPipeDirectoryNotWritableErrorMessage => GetResourceString("NamedPipeDirectoryNotWritableErrorMessage"); + #if IS_MTP_UNIT_TESTS internal static string @ActiveTestsRunning_FullTestsCount => GetResourceString("ActiveTestsRunning_FullTestsCount"); diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx index eba7e4715e..e10a07dc10 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx +++ b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx @@ -582,6 +582,14 @@ Read more about Microsoft Testing Platform telemetry: https://aka.ms/testingplat Method '{0}' did not exit successfully {0} is the method name. + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Do not report non successful exit value for specific exit codes (e.g. '--ignore-exit-code 8;9' ignore exit code 8 and 9 and will return 0 in these case) diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf index a8f18b45e4..8e344887db 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf @@ -419,6 +419,16 @@ {0} spuštěné testy {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Není k dispozici diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf index 3cc0f98381..45d613e8f7 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf @@ -419,6 +419,16 @@ {0} ausgeführten Tests {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Nicht verfügbar diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf index 9029a4b074..c29a920440 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf @@ -419,6 +419,16 @@ {0} pruebas en ejecución {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available No disponible diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf index c8b87178f9..6ac1623c90 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf @@ -419,6 +419,16 @@ {0} tests en cours d’exécution {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Non disponible diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf index 0fc26c2e8e..5c0dfdeb8a 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf @@ -419,6 +419,16 @@ {0} test in esecuzione {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Non disponibile diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf index 7b4ecde384..847c534cfa 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf @@ -419,6 +419,16 @@ {0} テストを実行しています {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available 利用できません diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf index b701d8459d..bea249f3ae 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf @@ -419,6 +419,16 @@ 실행 중인 테스트 {0} {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available 사용할 수 없음 diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf index 46ba603b81..1d0c650f1b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf @@ -419,6 +419,16 @@ testy {0} uruchomione {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Niedostępne diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf index af0ad62dbd..8f01b670bf 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf @@ -419,6 +419,16 @@ {0} testes em execução {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Não disponível diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf index a424a69ea7..5b4e75587b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf @@ -419,6 +419,16 @@ {0} тестов {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Недоступно diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf index 3e1d58a17b..87dd0ac20b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf @@ -419,6 +419,16 @@ {0} test çalıştırılıyor {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available Kullanılamıyor diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf index 85a8ec4d5f..2eec8debf4 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf @@ -419,6 +419,16 @@ 正在运行 {0} 测试 {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available 不可用 diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf index 0aea3dfde1..9a07aa6f26 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf @@ -419,6 +419,16 @@ 正在執行 {0} 測試 {0} is the number of currently running tests. + + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + + + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + Not available 無法使用 diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs index 87fe4abd05..696064228e 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs @@ -20,6 +20,55 @@ public sealed class IPCTests public IPCTests(TestContext testContext) => _testContext = testContext; + [TestMethod] + public void ResolvePipeDirectory_WhenOverrideProvided_UsesOverrideAsExplicit() + { + (string directory, bool isExplicitOverride) = NamedPipeServer.ResolvePipeDirectory("/custom/pipe/dir", "/tmp"); + + Assert.AreEqual("/custom/pipe/dir", directory); + Assert.IsTrue(isExplicitOverride); + } + + [TestMethod] + [DataRow(null)] + [DataRow("")] + [DataRow(" ")] + public void ResolvePipeDirectory_WhenOverrideMissing_FallsBackToTempPath(string? overrideDirectory) + { + (string directory, bool isExplicitOverride) = NamedPipeServer.ResolvePipeDirectory(overrideDirectory, "/var/folders/tmp"); + + Assert.AreEqual("/var/folders/tmp", directory); + Assert.IsFalse(isExplicitOverride); + } + + [TestMethod] + [DataRow(null)] + [DataRow("")] + public void ResolvePipeDirectory_WhenNeitherOverrideNorTempPathAvailable_FallsBackToTmp(string? tempPath) + { + (string directory, bool isExplicitOverride) = NamedPipeServer.ResolvePipeDirectory(overrideDirectory: null, tempPath); + + Assert.AreEqual("/tmp", directory); + Assert.IsFalse(isExplicitOverride); + } + + [TestMethod] + public void EnsurePathLengthWithinLimit_WhenWithinLimit_DoesNotThrow() + { + string path = "/tmp/" + new string('a', NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes - "/tmp/".Length); + + // Should not throw. + NamedPipeServer.EnsurePathLengthWithinLimit(path); + } + + [TestMethod] + public void EnsurePathLengthWithinLimit_WhenExceedsLimit_Throws() + { + string path = "/tmp/" + new string('a', NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes); + + Assert.ThrowsExactly(() => NamedPipeServer.EnsurePathLengthWithinLimit(path)); + } + [TestMethod] public async Task SingleConnectionNamedPipeServer_MultipleConnection_Fails() { From 385631c9a2496cf35174794e27de51dbad1e3033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 11 Jul 2026 14:28:07 +0200 Subject: [PATCH 2/7] Address review: banned APIs, InternalAPI decls, path normalization, tests - Replace banned System.Environment / string.IsNullOrWhiteSpace with SystemEnvironment / RoslynString to fix RS0030. - Declare the four new internal symbols in InternalAPI.Unshipped.txt (RS0016). - Normalize an explicit override with Path.GetFullPath so a relative TESTINGPLATFORM_PIPE_DIRECTORY resolves to a rooted socket path and honors the "full path handed to peers" invariant (also collapses '..'). - Clarify that the '/tmp' fallback is only reachable via the test overload. - Add unit tests for EnsureDirectoryIsWritable (create-missing happy path and non-creatable error path) and a whitespace DataRow for the tempPath fallback. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../IPC/NamedPipeServer.cs | 28 ++++++++----- .../InternalAPI/InternalAPI.Unshipped.txt | 5 +++ .../IPC/IPCTests.cs | 39 +++++++++++++++++++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs b/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs index 701875aa23..bcbb900f51 100644 --- a/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs +++ b/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs @@ -194,11 +194,15 @@ public static PipeNameDescription GetPipeName(string name) (string directory, bool isExplicitOverride) = ResolvePipeDirectory(); // Only actively validate the explicit override: it is user-supplied and the most likely to be wrong - // (typo, missing directory, wrong permissions), so we create it if needed and fail fast with an - // actionable message. Path.GetTempPath()/'/tmp' are OS-managed and effectively always writable, so we - // skip the probe there to avoid extra I/O and a behavior change on every pipe creation. + // (typo, missing directory, wrong permissions), so we normalize, create it if needed, and fail fast + // with an actionable message. Path.GetTempPath()/'/tmp' are OS-managed and effectively always writable, + // so we skip the probe there to avoid extra I/O and a behavior change on every pipe creation. if (isExplicitOverride) { + // Normalize a possibly-relative override to an absolute path: on Unix NamedPipeServerStream only + // treats rooted names as socket paths (it rejects separators in relative names), and the invariant + // requires handing peers a fully-resolved path. This also collapses any '..' segments. + directory = Path.GetFullPath(directory); EnsureDirectoryIsWritable(directory); } @@ -210,25 +214,29 @@ public static PipeNameDescription GetPipeName(string name) private static (string Directory, bool IsExplicitOverride) ResolvePipeDirectory() => ResolvePipeDirectory( - Environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY), + new SystemEnvironment().GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY), Path.GetTempPath()); // Pure resolution logic split out so it can be unit-tested on any OS (the Unix branch of GetPipeName // never runs on Windows) without mutating process-wide environment variables. internal static (string Directory, bool IsExplicitOverride) ResolvePipeDirectory(string? overrideDirectory, string? tempPath) { - if (!string.IsNullOrWhiteSpace(overrideDirectory)) + if (!RoslynString.IsNullOrWhiteSpace(overrideDirectory)) { - return (overrideDirectory!, true); + return (overrideDirectory, true); } - // Path.GetTempPath() honors TMPDIR on Unix and already falls back to '/tmp' itself when TMPDIR is unset. - return string.IsNullOrWhiteSpace(tempPath) + // Path.GetTempPath() honors TMPDIR on Unix and already falls back to '/tmp' itself when TMPDIR is unset, + // and it always returns a non-empty string in practice. The explicit '/tmp' below is therefore a + // defensive net that is only reachable when a caller passes null/empty tempPath (i.e. the test overload). + return RoslynString.IsNullOrWhiteSpace(tempPath) ? ("/tmp", false) - : (tempPath!, false); + : (tempPath, false); } - private static void EnsureDirectoryIsWritable(string directory) + // Internal for unit testing: normalize/create the explicit override directory and verify it is writable, + // failing fast with an actionable, localized message instead of a cryptic socket bind error later. + internal static void EnsureDirectoryIsWritable(string directory) { try { diff --git a/src/Platform/Microsoft.Testing.Platform/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/InternalAPI/InternalAPI.Unshipped.txt index fc58fdc4ad..a7a744838a 100644 --- a/src/Platform/Microsoft.Testing.Platform/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/InternalAPI/InternalAPI.Unshipped.txt @@ -1,4 +1,6 @@ #nullable enable +const Microsoft.Testing.Platform.Helpers.EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY = "TESTINGPLATFORM_PIPE_DIRECTORY" -> string! +const Microsoft.Testing.Platform.IPC.NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes = 103 -> int Microsoft.Testing.Platform.Helpers.RuntimeFeatureHelper static Microsoft.Testing.Platform.Helpers.RuntimeFeatureHelper.IsMultiThreaded.get -> bool const Microsoft.Testing.Platform.ServerMode.JsonRpcStrings.IsStateful = "isStateful" -> string! @@ -28,6 +30,9 @@ static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.ReadFields(Syst static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.TryReadExecutionScopedField(System.IO.Stream! stream, ushort fieldId, int fieldSize, ref string? executionId, ref string? instanceId) -> bool static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.WriteExecutionScopedHeader(System.IO.Stream! stream, string? executionId, string? instanceId, ushort payloadFieldCount) -> void static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.WriteListPayload(System.IO.Stream! stream, ushort fieldId, T[]? list, System.Action! writeItem) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsureDirectoryIsWritable(string! directory) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsurePathLengthWithinLimit(string! path) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.ResolvePipeDirectory(string? overrideDirectory, string? tempPath) -> (string! Directory, bool IsExplicitOverride) static Microsoft.Testing.Platform.Services.ArtifactFileNameSanitizer.ReplaceInvalidFileNameChars(string! fileName) -> string! static Microsoft.Testing.Platform.Services.ClientCapabilitiesService.operator !=(Microsoft.Testing.Platform.Services.ClientCapabilitiesService? left, Microsoft.Testing.Platform.Services.ClientCapabilitiesService? right) -> bool static Microsoft.Testing.Platform.Services.ClientCapabilitiesService.operator ==(Microsoft.Testing.Platform.Services.ClientCapabilitiesService? left, Microsoft.Testing.Platform.Services.ClientCapabilitiesService? right) -> bool diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs index 696064228e..983ebf7fae 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs @@ -44,6 +44,7 @@ public void ResolvePipeDirectory_WhenOverrideMissing_FallsBackToTempPath(string? [TestMethod] [DataRow(null)] [DataRow("")] + [DataRow(" ")] public void ResolvePipeDirectory_WhenNeitherOverrideNorTempPathAvailable_FallsBackToTmp(string? tempPath) { (string directory, bool isExplicitOverride) = NamedPipeServer.ResolvePipeDirectory(overrideDirectory: null, tempPath); @@ -52,6 +53,44 @@ public void ResolvePipeDirectory_WhenNeitherOverrideNorTempPathAvailable_FallsBa Assert.IsFalse(isExplicitOverride); } + [TestMethod] + public void EnsureDirectoryIsWritable_WhenDirectoryMissingButCreatable_CreatesItAndDoesNotThrow() + { + string directory = Path.Combine(Path.GetTempPath(), $"mtp.pipedir.{Guid.NewGuid():N}"); + try + { + NamedPipeServer.EnsureDirectoryIsWritable(directory); + + Assert.IsTrue(Directory.Exists(directory)); + } + finally + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory, recursive: true); + } + } + } + + [TestMethod] + public void EnsureDirectoryIsWritable_WhenDirectoryCannotBeCreated_ThrowsInvalidOperationException() + { + // Create a regular file, then target a directory *beneath* that file. Directory.CreateDirectory cannot + // create a directory under an existing file, so this deterministically fails on Windows and Unix. + string filePath = Path.Combine(Path.GetTempPath(), $"mtp.pipefile.{Guid.NewGuid():N}"); + File.WriteAllText(filePath, string.Empty); + try + { + string invalidDirectory = Path.Combine(filePath, "sub"); + + Assert.ThrowsExactly(() => NamedPipeServer.EnsureDirectoryIsWritable(invalidDirectory)); + } + finally + { + File.Delete(filePath); + } + } + [TestMethod] public void EnsurePathLengthWithinLimit_WhenWithinLimit_DoesNotThrow() { From b1dbb0c347fd30ca6b9e18bae4fd797a850ab329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 11 Jul 2026 15:04:28 +0200 Subject: [PATCH 3/7] Address review: shared-source compat for NamedPipeServer changes NamedPipeServer.cs is glob-compiled (IPC\*.cs) into HangDump, Retry, TrxReport, and both MSBuild projects, so the earlier fixes must build there: - Read TESTINGPLATFORM_PIPE_DIRECTORY via System.Environment with a scoped RS0030 suppression instead of `new SystemEnvironment()`. Only the MSBuild task project links SystemEnvironment.cs; the other shared-source consumers do not, so the wrapper would not compile there. Reading directly also keeps the file self-contained for the dotnet/sdk vendor copy. - Normalize the selected directory with Path.GetFullPath in every precedence branch (not just the explicit override): Path.GetTempPath() can surface a relative TMPDIR, which NamedPipeServerStream rejects and which would violate the fully-resolved-path invariant. The write probe stays override-only. - Declare the new EnvironmentVariableConstants / NamedPipeServer / PlatformResources members in the HangDump, Retry, TrxReport, and Extensions.MSBuild InternalAPI.Unshipped baselines (they compile these shared files and keep their baselines in sync with core), so RS0016 stays green. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../InternalAPI/InternalAPI.Unshipped.txt | 7 ++++++ .../InternalAPI.Unshipped.txt | 7 ++++++ .../InternalAPI/InternalAPI.Unshipped.txt | 7 ++++++ .../InternalAPI/InternalAPI.Unshipped.txt | 7 ++++++ .../IPC/NamedPipeServer.cs | 25 +++++++++++++------ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Unshipped.txt index 5e12bed0ad..e541f7a149 100644 --- a/src/Platform/Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Unshipped.txt @@ -1,4 +1,11 @@ #nullable enable +const Microsoft.Testing.Platform.Helpers.EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY = "TESTINGPLATFORM_PIPE_DIRECTORY" -> string! +const Microsoft.Testing.Platform.IPC.NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes = 103 -> int +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsureDirectoryIsWritable(string! directory) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsurePathLengthWithinLimit(string! path) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.ResolvePipeDirectory(string? overrideDirectory, string? tempPath) -> (string! Directory, bool IsExplicitOverride) +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.ReadFields(System.IO.Stream! stream, System.Func! tryReadField) -> void static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.TryReadExecutionScopedField(System.IO.Stream! stream, ushort fieldId, int fieldSize, ref string? executionId, ref string? instanceId) -> bool diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.MSBuild/InternalAPI.Unshipped.txt index 2dd2ddc368..d5d961ab7a 100644 --- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/InternalAPI.Unshipped.txt @@ -1,4 +1,11 @@ #nullable enable +const Microsoft.Testing.Platform.Helpers.EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY = "TESTINGPLATFORM_PIPE_DIRECTORY" -> string! +const Microsoft.Testing.Platform.IPC.NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes = 103 -> int +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsureDirectoryIsWritable(string! directory) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsurePathLengthWithinLimit(string! path) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.ResolvePipeDirectory(string? overrideDirectory, string? tempPath) -> (string! Directory, bool IsExplicitOverride) +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.ReadFields(System.IO.Stream! stream, System.Func! tryReadField) -> void static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.TryReadExecutionScopedField(System.IO.Stream! stream, ushort fieldId, int fieldSize, ref string? executionId, ref string? instanceId) -> bool static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.WriteExecutionScopedHeader(System.IO.Stream! stream, string? executionId, string? instanceId, ushort payloadFieldCount) -> void diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Unshipped.txt index 2dd2ddc368..d5d961ab7a 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Unshipped.txt @@ -1,4 +1,11 @@ #nullable enable +const Microsoft.Testing.Platform.Helpers.EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY = "TESTINGPLATFORM_PIPE_DIRECTORY" -> string! +const Microsoft.Testing.Platform.IPC.NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes = 103 -> int +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsureDirectoryIsWritable(string! directory) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsurePathLengthWithinLimit(string! path) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.ResolvePipeDirectory(string? overrideDirectory, string? tempPath) -> (string! Directory, bool IsExplicitOverride) +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.ReadFields(System.IO.Stream! stream, System.Func! tryReadField) -> void static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.TryReadExecutionScopedField(System.IO.Stream! stream, ushort fieldId, int fieldSize, ref string? executionId, ref string? instanceId) -> bool static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.WriteExecutionScopedHeader(System.IO.Stream! stream, string? executionId, string? instanceId, ushort payloadFieldCount) -> void diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt index 5e12bed0ad..e541f7a149 100644 --- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt @@ -1,4 +1,11 @@ #nullable enable +const Microsoft.Testing.Platform.Helpers.EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY = "TESTINGPLATFORM_PIPE_DIRECTORY" -> string! +const Microsoft.Testing.Platform.IPC.NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes = 103 -> int +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsureDirectoryIsWritable(string! directory) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.EnsurePathLengthWithinLimit(string! path) -> void +static Microsoft.Testing.Platform.IPC.NamedPipeServer.ResolvePipeDirectory(string? overrideDirectory, string? tempPath) -> (string! Directory, bool IsExplicitOverride) +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.ReadFields(System.IO.Stream! stream, System.Func! tryReadField) -> void static Microsoft.Testing.Platform.IPC.Serializers.BaseSerializer.TryReadExecutionScopedField(System.IO.Stream! stream, ushort fieldId, int fieldSize, ref string? executionId, ref string? instanceId) -> bool diff --git a/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs b/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs index bcbb900f51..aedf1b7bad 100644 --- a/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs +++ b/src/Platform/Microsoft.Testing.Platform/IPC/NamedPipeServer.cs @@ -193,16 +193,19 @@ public static PipeNameDescription GetPipeName(string name) // 3. '/tmp' - preserves the previous default when neither is set. (string directory, bool isExplicitOverride) = ResolvePipeDirectory(); + // Normalize to an absolute path regardless of which precedence branch supplied the directory. An + // explicit override or a relative TMPDIR can be relative, and on Unix NamedPipeServerStream only treats + // rooted names as socket paths (it rejects separators in non-rooted names). The invariant also requires + // handing peers a fully-resolved path. This additionally collapses any '..' segments. '/tmp' and an + // already-absolute temp path are unchanged. + directory = Path.GetFullPath(directory); + // Only actively validate the explicit override: it is user-supplied and the most likely to be wrong - // (typo, missing directory, wrong permissions), so we normalize, create it if needed, and fail fast - // with an actionable message. Path.GetTempPath()/'/tmp' are OS-managed and effectively always writable, - // so we skip the probe there to avoid extra I/O and a behavior change on every pipe creation. + // (typo, missing directory, wrong permissions), so we create it if needed and fail fast with an + // actionable message. Path.GetTempPath()/'/tmp' are OS-managed and effectively always writable, so we + // skip the probe there to avoid extra I/O and a behavior change on every pipe creation. if (isExplicitOverride) { - // Normalize a possibly-relative override to an absolute path: on Unix NamedPipeServerStream only - // treats rooted names as socket paths (it rejects separators in relative names), and the invariant - // requires handing peers a fully-resolved path. This also collapses any '..' segments. - directory = Path.GetFullPath(directory); EnsureDirectoryIsWritable(directory); } @@ -214,7 +217,13 @@ public static PipeNameDescription GetPipeName(string name) private static (string Directory, bool IsExplicitOverride) ResolvePipeDirectory() => ResolvePipeDirectory( - new SystemEnvironment().GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY), + // Read the environment variable directly rather than through IEnvironment: GetPipeName is a static + // method invoked before any NamedPipeServer instance (and its IEnvironment) exists, and this file is + // shared-compiled into extension projects that do not link the SystemEnvironment wrapper. The banned + // API is suppressed locally, mirroring how SystemEnvironment itself wraps Environment. +#pragma warning disable RS0030 // Do not use banned APIs + Environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY), +#pragma warning restore RS0030 // Do not use banned APIs Path.GetTempPath()); // Pure resolution logic split out so it can be unit-tested on any OS (the Unix branch of GetPipeName From eefaa33b8be7299097d87ab6af84e51d5fc2b4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 11 Jul 2026 15:08:05 +0200 Subject: [PATCH 4/7] Address review: complete InternalAPI baselines for all shared-source consumers The earlier baseline update missed some projects that link the shared files: - EnvironmentVariableConstants.cs is also linked into HotReload -> add the new TESTINGPLATFORM_PIPE_DIRECTORY const there. - PlatformResources.cs (the !IS_CORE_MTP accessors) is linked into nine API-tracked extensions -> add the two new NamedPipe* accessor signatures to HtmlReport, CtrfReport, JUnitReport, VideoRecorder, and CrashDump (the other four were done previously). Verified each affected project builds clean with -warnaserror:RS0016,RS0017,RS0025,RS0037. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../InternalAPI/InternalAPI.Unshipped.txt | 2 ++ .../InternalAPI/InternalAPI.Unshipped.txt | 2 ++ .../InternalAPI/InternalAPI.Unshipped.txt | 1 + .../InternalAPI/InternalAPI.Unshipped.txt | 2 ++ .../InternalAPI/InternalAPI.Unshipped.txt | 2 ++ .../InternalAPI/InternalAPI.Unshipped.txt | 2 ++ 6 files changed, 11 insertions(+) diff --git a/src/Platform/Microsoft.Testing.Extensions.CrashDump/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.CrashDump/InternalAPI/InternalAPI.Unshipped.txt index 819cf7f444..648404fc05 100644 --- a/src/Platform/Microsoft.Testing.Extensions.CrashDump/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.CrashDump/InternalAPI/InternalAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! diff --git a/src/Platform/Microsoft.Testing.Extensions.CtrfReport/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.CtrfReport/InternalAPI/InternalAPI.Unshipped.txt index 819cf7f444..648404fc05 100644 --- a/src/Platform/Microsoft.Testing.Extensions.CtrfReport/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.CtrfReport/InternalAPI/InternalAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! diff --git a/src/Platform/Microsoft.Testing.Extensions.HotReload/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.HotReload/InternalAPI/InternalAPI.Unshipped.txt index 7dc5c58110..de51753905 100644 --- a/src/Platform/Microsoft.Testing.Extensions.HotReload/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.HotReload/InternalAPI/InternalAPI.Unshipped.txt @@ -1 +1,2 @@ #nullable enable +const Microsoft.Testing.Platform.Helpers.EnvironmentVariableConstants.TESTINGPLATFORM_PIPE_DIRECTORY = "TESTINGPLATFORM_PIPE_DIRECTORY" -> string! diff --git a/src/Platform/Microsoft.Testing.Extensions.HtmlReport/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.HtmlReport/InternalAPI/InternalAPI.Unshipped.txt index 819cf7f444..648404fc05 100644 --- a/src/Platform/Microsoft.Testing.Extensions.HtmlReport/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.HtmlReport/InternalAPI/InternalAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! diff --git a/src/Platform/Microsoft.Testing.Extensions.JUnitReport/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.JUnitReport/InternalAPI/InternalAPI.Unshipped.txt index 819cf7f444..648404fc05 100644 --- a/src/Platform/Microsoft.Testing.Extensions.JUnitReport/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.JUnitReport/InternalAPI/InternalAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! diff --git a/src/Platform/Microsoft.Testing.Extensions.VideoRecorder/InternalAPI/InternalAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Extensions.VideoRecorder/InternalAPI/InternalAPI.Unshipped.txt index 819cf7f444..648404fc05 100644 --- a/src/Platform/Microsoft.Testing.Extensions.VideoRecorder/InternalAPI/InternalAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Extensions.VideoRecorder/InternalAPI/InternalAPI.Unshipped.txt @@ -1,2 +1,4 @@ #nullable enable +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipeDirectoryNotWritableErrorMessage.get -> string! +static Microsoft.Testing.Platform.Resources.PlatformResources.NamedPipePathTooLongErrorMessage.get -> string! static Microsoft.Testing.Platform.Services.ArtifactNamingHelper.ResolveAndSanitize(string! template, string! processName, string! processId, System.DateTimeOffset timestamp, System.Func! sanitizeLeafFileName) -> string! From 3d1b2a2cfc4531da818b4146a654fe155811a8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 11 Jul 2026 22:51:31 +0200 Subject: [PATCH 5/7] Address review: clarify pipe-directory error messages re override precedence The two diagnostics suggested setting TMPDIR, but TESTINGPLATFORM_PIPE_DIRECTORY always wins, so that advice is misleading when the override is the cause: - Writability error is emitted only for the explicit override, so drop the TMPDIR mention and tell users to fix the override or unset it to fall back to the default temp directory. - Path-too-long can come from any source, so clarify that TMPDIR only helps when the override is not set. Regenerated the XLF files for all 14 languages. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../Resources/PlatformResources.resx | 6 +++--- .../Resources/xlf/PlatformResources.cs.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.de.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.es.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.fr.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.it.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.ja.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.ko.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.pl.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.pt-BR.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.ru.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.tr.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.zh-Hans.xlf | 10 +++++----- .../Resources/xlf/PlatformResources.zh-Hant.xlf | 10 +++++----- 14 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx index 135eda1425..9f5abf1842 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx +++ b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx @@ -583,12 +583,12 @@ Read more about Microsoft Testing Platform telemetry: https://aka.ms/testingplat {0} is the method name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. Do not report non successful exit value for specific exit codes diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf index 0b01f49c6d..87bb62713b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf index 8a1d7ede04..e8a1748149 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf index 9aecacf85d..ffb758bb46 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf index 5c91bd715f..25bd592238 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf index a63903db7c..ddfafc1123 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf index d5a61355fc..9aef8fd00d 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf index b1ef9b85b8..dbd7bbd8b3 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf index fc5a4aa784..9e096ea252 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf index 131b85f508..a0ba23a9a1 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf index 4fea720580..03a68e4ae4 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf index b244c6180d..c8085f2421 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf index 8828859414..3e07c58dff 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf index 31f6493c7f..26a9113c33 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf @@ -420,13 +420,13 @@ {0} is the number of currently running tests. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable (or 'TMPDIR') to a writable directory. - {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + The named pipe directory '{0}' does not exist or is not writable: {1}. Set the '{2}' environment variable to an existing writable directory, or unset it to fall back to the default temporary directory. + {0} is the directory path, {1} is the underlying error message, {2} is the environment variable name. Do not translate the environment variable name. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. - The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Set the '{3}' environment variable (or 'TMPDIR') to a shorter directory. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. + The named pipe path '{0}' is {1} bytes long, which exceeds the maximum of {2} bytes allowed for a Unix domain socket. Use a shorter directory by setting the '{3}' environment variable, or by setting 'TMPDIR' when '{3}' is not set. {0} is the full pipe path, {1} is its length in bytes, {2} is the maximum allowed length in bytes, {3} is the environment variable name. Do not translate 'TMPDIR' or the environment variable name. From d397fca98e75049b884a2e1bb916435118df3af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 11 Jul 2026 22:54:30 +0200 Subject: [PATCH 6/7] Address review: add multibyte path-length test to prove UTF-8 byte counting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing path-length tests used only ASCII, so a buggy character-count implementation would still pass. Add a test with 40 '好' (3-byte) chars plus a prefix: 45 characters (under the 103 limit) but 125 UTF-8 bytes (over it), proving the guard measures sun_path bytes rather than characters. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../IPC/IPCTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs index 983ebf7fae..01d765f10b 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs @@ -108,6 +108,20 @@ public void EnsurePathLengthWithinLimit_WhenExceedsLimit_Throws() Assert.ThrowsExactly(() => NamedPipeServer.EnsurePathLengthWithinLimit(path)); } + [TestMethod] + public void EnsurePathLengthWithinLimit_WhenMultibyteExceedsByteLimitButNotCharLimit_Throws() + { + // '好' (U+597D) is 3 bytes in UTF-8. 40 of them plus the "/tmp/" prefix is only 45 characters - + // comfortably under the 103 limit if it were (incorrectly) measured in characters - but 125 bytes, + // which exceeds it. This proves the guard measures UTF-8 bytes (matching sun_path) and not characters. + string path = "/tmp/" + new string('好', 40); + + Assert.IsTrue(path.Length < NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes, "Test setup: character count must stay under the limit so only a byte-based check can fail."); + Assert.IsTrue(System.Text.Encoding.UTF8.GetByteCount(path) > NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes, "Test setup: UTF-8 byte count must exceed the limit."); + + Assert.ThrowsExactly(() => NamedPipeServer.EnsurePathLengthWithinLimit(path)); + } + [TestMethod] public async Task SingleConnectionNamedPipeServer_MultipleConnection_Fails() { From 445d58fdcaf2ada457a8c2220e0cef8da564d8a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Mon, 13 Jul 2026 16:15:41 +0200 Subject: [PATCH 7/7] Address review: use MSTest relational asserts (MSTEST0037) Replace Assert.IsTrue(a < b)/Assert.IsTrue(a > b) with Assert.IsLessThan / Assert.IsGreaterThan in the multibyte path-length setup assertions. Note the argument order is (bound, value) - the raw analyzer codefix suggestion had the operands reversed, which would have inverted the assertions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: ae434eba-3cad-4c61-a1da-ef252ae87f48 --- .../Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs index 01d765f10b..a58a061a52 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/IPC/IPCTests.cs @@ -116,8 +116,8 @@ public void EnsurePathLengthWithinLimit_WhenMultibyteExceedsByteLimitButNotCharL // which exceeds it. This proves the guard measures UTF-8 bytes (matching sun_path) and not characters. string path = "/tmp/" + new string('好', 40); - Assert.IsTrue(path.Length < NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes, "Test setup: character count must stay under the limit so only a byte-based check can fail."); - Assert.IsTrue(System.Text.Encoding.UTF8.GetByteCount(path) > NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes, "Test setup: UTF-8 byte count must exceed the limit."); + Assert.IsLessThan(NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes, path.Length, "Test setup: character count must stay under the limit so only a byte-based check can fail."); + Assert.IsGreaterThan(NamedPipeServer.MaxUnixDomainSocketPathLengthInBytes, System.Text.Encoding.UTF8.GetByteCount(path), "Test setup: UTF-8 byte count must exceed the limit."); Assert.ThrowsExactly(() => NamedPipeServer.EnsurePathLengthWithinLimit(path)); }