From c52460e0bb416b672cb23d7d34018d6351763b1d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:05:42 +0000 Subject: [PATCH 01/10] Initial plan From 7fc2abda9fb4773a60d07ae94346dd1f721c0207 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:37:02 +0000 Subject: [PATCH 02/10] Obsolete NamedPipeClientStream constructor with isConnected parameter (SYSLIB0063) Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com> --- docs/project/list-of-diagnostics.md | 1 + .../Common/src/System/Obsoletions.cs | 3 ++ .../System.IO.Pipes/ref/System.IO.Pipes.cs | 3 ++ .../src/System.IO.Pipes.csproj | 2 + .../System/IO/Pipes/NamedPipeClientStream.cs | 19 +++++++ .../NamedPipeTest.CreateClient.cs | 52 +++++++++++++++++++ .../NamedPipeTest.CrossProcess.cs | 2 +- .../tests/PipeStreamConformanceTests.cs | 4 +- 8 files changed, 83 insertions(+), 3 deletions(-) diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index bb6a670802c733..e98daf39526500 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -117,6 +117,7 @@ The PR that reveals the implementation of the ` are obsolete. Use the new ones that take an IComparer\. | | __`SYSLIB0062`__ | XSLT Script blocks are not supported. | +| __`SYSLIB0063`__ | This constructor has been deprecated and argument bool isConnected does not have any effect. Use NamedPipeClientStream(PipeDirection direction, bool isAsync, SafePipeHandle safePipeHandle) instead. | ## Analyzer Warnings diff --git a/src/libraries/Common/src/System/Obsoletions.cs b/src/libraries/Common/src/System/Obsoletions.cs index 45a552749a9614..81756105c26fda 100644 --- a/src/libraries/Common/src/System/Obsoletions.cs +++ b/src/libraries/Common/src/System/Obsoletions.cs @@ -198,6 +198,9 @@ internal static class Obsoletions internal const string XsltSettingsEnableScriptMessage = "XSLT Script blocks are not supported."; internal const string XsltSettingsEnableScriptDiagId = "SYSLIB0062"; + internal const string NamedPipeClientStreamIsConnectedMessage = "This constructor has been deprecated and argument bool isConnected does not have any effect. Use NamedPipeClientStream(PipeDirection direction, bool isAsync, SafePipeHandle safePipeHandle) instead."; + internal const string NamedPipeClientStreamIsConnectedDiagId = "SYSLIB0063"; + // When adding a new diagnostic ID, add it to the table in docs\project\list-of-diagnostics.md as well. // Keep new const identifiers above this comment. } diff --git a/src/libraries/System.IO.Pipes/ref/System.IO.Pipes.cs b/src/libraries/System.IO.Pipes/ref/System.IO.Pipes.cs index 85387dbbd4b635..f037bc7b2b4cc1 100644 --- a/src/libraries/System.IO.Pipes/ref/System.IO.Pipes.cs +++ b/src/libraries/System.IO.Pipes/ref/System.IO.Pipes.cs @@ -42,7 +42,10 @@ public void DisposeLocalCopyOfClientHandle() { } } public sealed partial class NamedPipeClientStream : System.IO.Pipes.PipeStream { + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This constructor has been deprecated and argument bool isConnected does not have any effect. Use NamedPipeClientStream(PipeDirection direction, bool isAsync, SafePipeHandle safePipeHandle) instead.", DiagnosticId = "SYSLIB0063", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public NamedPipeClientStream(System.IO.Pipes.PipeDirection direction, bool isAsync, bool isConnected, Microsoft.Win32.SafeHandles.SafePipeHandle safePipeHandle) : base (default(System.IO.Pipes.PipeDirection), default(int)) { } + public NamedPipeClientStream(System.IO.Pipes.PipeDirection direction, bool isAsync, Microsoft.Win32.SafeHandles.SafePipeHandle safePipeHandle) : base (default(System.IO.Pipes.PipeDirection), default(int)) { } public NamedPipeClientStream(string pipeName) : base (default(System.IO.Pipes.PipeDirection), default(int)) { } public NamedPipeClientStream(string serverName, string pipeName) : base (default(System.IO.Pipes.PipeDirection), default(int)) { } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] diff --git a/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj b/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj index af23701a5adb30..c8fed74be3fbc6 100644 --- a/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj +++ b/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj @@ -27,6 +27,8 @@ + diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs index 26db5533031718..7f6ec815031aa9 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.ComponentModel; using System.Diagnostics; using System.Security; using System.Security.Principal; @@ -89,6 +90,8 @@ public NamedPipeClientStream(string serverName, string pipeName, PipeDirection d } // Create a NamedPipeClientStream from an existing server pipe handle. + [Obsolete(Obsoletions.NamedPipeClientStreamIsConnectedMessage, DiagnosticId = Obsoletions.NamedPipeClientStreamIsConnectedDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) : base(direction, 0) { @@ -107,6 +110,22 @@ public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConne } } + // Create a NamedPipeClientStream from an existing server pipe handle. + public NamedPipeClientStream(PipeDirection direction, bool isAsync, SafePipeHandle safePipeHandle) + : base(direction, 0) + { + ArgumentNullException.ThrowIfNull(safePipeHandle); + + if (safePipeHandle.IsInvalid) + { + throw new ArgumentException(SR.Argument_InvalidHandle, nameof(safePipeHandle)); + } + ValidateHandleIsPipe(safePipeHandle); + + InitializeHandle(safePipeHandle, true, isAsync); + State = PipeState.Connected; + } + ~NamedPipeClientStream() { Dispose(false); diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 5b164b849fac3c..84c4c699cc9120 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -99,7 +99,9 @@ public static void InvalidImpersonationLevel_Throws_ArgumentOutOfRangeException( [InlineData(PipeDirection.Out)] public static void NullHandle_Throws_ArgumentNullException(PipeDirection direction) { +#pragma warning disable SYSLIB0063 // Testing the obsolete constructor AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, null)); +#pragma warning restore SYSLIB0063 } [Theory] @@ -109,7 +111,9 @@ public static void NullHandle_Throws_ArgumentNullException(PipeDirection directi public static void InvalidHandle_Throws_ArgumentException(PipeDirection direction) { using SafePipeHandle pipeHandle = new SafePipeHandle(new IntPtr(-1), true); +#pragma warning disable SYSLIB0063 // Testing the obsolete constructor AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, pipeHandle)); +#pragma warning restore SYSLIB0063 } [Theory] @@ -129,7 +133,9 @@ public static void BadHandleKind_Throws_IOException(PipeDirection direction) IntPtr handle = safeHandle.DangerousGetHandle(); SafePipeHandle fakePipeHandle = new SafePipeHandle(handle, ownsHandle: false); +#pragma warning disable SYSLIB0063 // Testing the obsolete constructor Assert.Throws(() => new NamedPipeClientStream(direction, false, true, fakePipeHandle)); +#pragma warning restore SYSLIB0063 } finally { @@ -145,5 +151,51 @@ public static void NamedPipeClientStream_InvalidHandleInerhitability() AssertExtensions.Throws("inheritability", () => new NamedPipeClientStream("a", "b", PipeDirection.Out, 0, TokenImpersonationLevel.Delegation, HandleInheritability.None - 1)); AssertExtensions.Throws("inheritability", () => new NamedPipeClientStream("a", "b", PipeDirection.Out, 0, TokenImpersonationLevel.Delegation, HandleInheritability.Inheritable + 1)); } + + [Theory] + [InlineData(PipeDirection.In)] + [InlineData(PipeDirection.InOut)] + [InlineData(PipeDirection.Out)] + public static void NewConstructor_NullHandle_Throws_ArgumentNullException(PipeDirection direction) + { + AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, null)); + } + + [Theory] + [InlineData(PipeDirection.In)] + [InlineData(PipeDirection.InOut)] + [InlineData(PipeDirection.Out)] + public static void NewConstructor_InvalidHandle_Throws_ArgumentException(PipeDirection direction) + { + using SafePipeHandle pipeHandle = new SafePipeHandle(new IntPtr(-1), true); + AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, pipeHandle)); + } + + [Theory] + [InlineData(PipeDirection.In)] + [InlineData(PipeDirection.InOut)] + [InlineData(PipeDirection.Out)] + public static void NewConstructor_BadHandleKind_Throws_IOException(PipeDirection direction) + { + using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), "_NewConstructor_BadHandleKind_Throws_IOException_" + Path.GetRandomFileName()), FileMode.Create, FileAccess.Write, FileShare.None, 8, FileOptions.DeleteOnClose)) + { + SafeFileHandle safeHandle = fs.SafeFileHandle; + + bool gotRef = false; + try + { + safeHandle.DangerousAddRef(ref gotRef); + IntPtr handle = safeHandle.DangerousGetHandle(); + + SafePipeHandle fakePipeHandle = new SafePipeHandle(handle, ownsHandle: false); + Assert.Throws(() => new NamedPipeClientStream(direction, false, fakePipeHandle)); + } + finally + { + if (gotRef) + safeHandle.DangerousRelease(); + } + } + } } } diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CrossProcess.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CrossProcess.cs index e01f42f9d27e58..de94c98b1b0cc1 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CrossProcess.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CrossProcess.cs @@ -35,7 +35,7 @@ public void InheritHandles_AvailableInChildProcess() void ChildFunc(string handle) { - using (var childClient = new NamedPipeClientStream(PipeDirection.Out, isAsync: false, isConnected: true, new SafePipeHandle((IntPtr)long.Parse(handle, CultureInfo.InvariantCulture), ownsHandle: true))) + using (var childClient = new NamedPipeClientStream(PipeDirection.Out, isAsync: false, new SafePipeHandle((IntPtr)long.Parse(handle, CultureInfo.InvariantCulture), ownsHandle: true))) { for (int i = 0; i < 5; i++) { diff --git a/src/libraries/System.IO.Pipes/tests/PipeStreamConformanceTests.cs b/src/libraries/System.IO.Pipes/tests/PipeStreamConformanceTests.cs index 918303b019a0a0..867e12206528de 100644 --- a/src/libraries/System.IO.Pipes/tests/PipeStreamConformanceTests.cs +++ b/src/libraries/System.IO.Pipes/tests/PipeStreamConformanceTests.cs @@ -171,7 +171,7 @@ public async Task ClonedClient_ActsAsOriginalClient() if (writeable is NamedPipeServerStream server) { - using (NamedPipeClientStream client = new NamedPipeClientStream(PipeDirection.In, false, true, ((NamedPipeClientStream)readable).SafePipeHandle)) + using (NamedPipeClientStream client = new NamedPipeClientStream(PipeDirection.In, false, ((NamedPipeClientStream)readable).SafePipeHandle)) { if (OperatingSystem.IsWindows()) { @@ -186,7 +186,7 @@ public async Task ClonedClient_ActsAsOriginalClient() } else { - using (NamedPipeClientStream client = new NamedPipeClientStream(PipeDirection.Out, false, true, ((NamedPipeClientStream)writeable).SafePipeHandle)) + using (NamedPipeClientStream client = new NamedPipeClientStream(PipeDirection.Out, false, ((NamedPipeClientStream)writeable).SafePipeHandle)) { Task clientTask = client.WriteAsync(msg1, 0, msg1.Length); int receivedLength = readable.Read(received1, 0, msg1.Length); From 4aadf1e317008cc39e1e755043b9e2cc47c49f48 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:57:28 +0000 Subject: [PATCH 03/10] Address code review feedback: simplify obsolete constructor and consolidate tests Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com> --- .../System/IO/Pipes/NamedPipeClientStream.cs | 15 +----- .../NamedPipeTest.CreateClient.cs | 49 ++----------------- 2 files changed, 4 insertions(+), 60 deletions(-) diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs index 7f6ec815031aa9..a04db0f0ac1385 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs @@ -93,21 +93,8 @@ public NamedPipeClientStream(string serverName, string pipeName, PipeDirection d [Obsolete(Obsoletions.NamedPipeClientStreamIsConnectedMessage, DiagnosticId = Obsoletions.NamedPipeClientStreamIsConnectedDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) - : base(direction, 0) + : this(direction, isAsync, safePipeHandle) { - ArgumentNullException.ThrowIfNull(safePipeHandle); - - if (safePipeHandle.IsInvalid) - { - throw new ArgumentException(SR.Argument_InvalidHandle, nameof(safePipeHandle)); - } - ValidateHandleIsPipe(safePipeHandle); - - InitializeHandle(safePipeHandle, true, isAsync); - if (isConnected) - { - State = PipeState.Connected; - } } // Create a NamedPipeClientStream from an existing server pipe handle. diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 84c4c699cc9120..442e8088b4a548 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -102,6 +102,7 @@ public static void NullHandle_Throws_ArgumentNullException(PipeDirection directi #pragma warning disable SYSLIB0063 // Testing the obsolete constructor AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, null)); #pragma warning restore SYSLIB0063 + AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, null)); } [Theory] @@ -114,6 +115,7 @@ public static void InvalidHandle_Throws_ArgumentException(PipeDirection directio #pragma warning disable SYSLIB0063 // Testing the obsolete constructor AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, pipeHandle)); #pragma warning restore SYSLIB0063 + AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, pipeHandle)); } [Theory] @@ -136,6 +138,7 @@ public static void BadHandleKind_Throws_IOException(PipeDirection direction) #pragma warning disable SYSLIB0063 // Testing the obsolete constructor Assert.Throws(() => new NamedPipeClientStream(direction, false, true, fakePipeHandle)); #pragma warning restore SYSLIB0063 + Assert.Throws(() => new NamedPipeClientStream(direction, false, fakePipeHandle)); } finally { @@ -151,51 +154,5 @@ public static void NamedPipeClientStream_InvalidHandleInerhitability() AssertExtensions.Throws("inheritability", () => new NamedPipeClientStream("a", "b", PipeDirection.Out, 0, TokenImpersonationLevel.Delegation, HandleInheritability.None - 1)); AssertExtensions.Throws("inheritability", () => new NamedPipeClientStream("a", "b", PipeDirection.Out, 0, TokenImpersonationLevel.Delegation, HandleInheritability.Inheritable + 1)); } - - [Theory] - [InlineData(PipeDirection.In)] - [InlineData(PipeDirection.InOut)] - [InlineData(PipeDirection.Out)] - public static void NewConstructor_NullHandle_Throws_ArgumentNullException(PipeDirection direction) - { - AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, null)); - } - - [Theory] - [InlineData(PipeDirection.In)] - [InlineData(PipeDirection.InOut)] - [InlineData(PipeDirection.Out)] - public static void NewConstructor_InvalidHandle_Throws_ArgumentException(PipeDirection direction) - { - using SafePipeHandle pipeHandle = new SafePipeHandle(new IntPtr(-1), true); - AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, pipeHandle)); - } - - [Theory] - [InlineData(PipeDirection.In)] - [InlineData(PipeDirection.InOut)] - [InlineData(PipeDirection.Out)] - public static void NewConstructor_BadHandleKind_Throws_IOException(PipeDirection direction) - { - using (FileStream fs = new FileStream(Path.Combine(Path.GetTempPath(), "_NewConstructor_BadHandleKind_Throws_IOException_" + Path.GetRandomFileName()), FileMode.Create, FileAccess.Write, FileShare.None, 8, FileOptions.DeleteOnClose)) - { - SafeFileHandle safeHandle = fs.SafeFileHandle; - - bool gotRef = false; - try - { - safeHandle.DangerousAddRef(ref gotRef); - IntPtr handle = safeHandle.DangerousGetHandle(); - - SafePipeHandle fakePipeHandle = new SafePipeHandle(handle, ownsHandle: false); - Assert.Throws(() => new NamedPipeClientStream(direction, false, fakePipeHandle)); - } - finally - { - if (gotRef) - safeHandle.DangerousRelease(); - } - } - } } } From 51b812d6c857256baf22e197a92b57e0c9ff20cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Thu, 16 Oct 2025 09:10:47 -0700 Subject: [PATCH 04/10] Apply suggestions from code review --- .../src/System/IO/Pipes/NamedPipeClientStream.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs index a04db0f0ac1385..29937a161d4b55 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs @@ -89,7 +89,6 @@ public NamedPipeClientStream(string serverName, string pipeName, PipeDirection d _accessRights = AccessRightsFromDirection(direction); } - // Create a NamedPipeClientStream from an existing server pipe handle. [Obsolete(Obsoletions.NamedPipeClientStreamIsConnectedMessage, DiagnosticId = Obsoletions.NamedPipeClientStreamIsConnectedDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) @@ -97,7 +96,6 @@ public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConne { } - // Create a NamedPipeClientStream from an existing server pipe handle. public NamedPipeClientStream(PipeDirection direction, bool isAsync, SafePipeHandle safePipeHandle) : base(direction, 0) { From 071c67fe2e2491808e1bdc456479eec7d0c04315 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:21:17 +0000 Subject: [PATCH 05/10] Remove duplicate obsolete constructor tests to avoid duplication Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com> --- .../tests/NamedPipeTests/NamedPipeTest.CreateClient.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 442e8088b4a548..bd1619168946cb 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -99,9 +99,6 @@ public static void InvalidImpersonationLevel_Throws_ArgumentOutOfRangeException( [InlineData(PipeDirection.Out)] public static void NullHandle_Throws_ArgumentNullException(PipeDirection direction) { -#pragma warning disable SYSLIB0063 // Testing the obsolete constructor - AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, null)); -#pragma warning restore SYSLIB0063 AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, null)); } @@ -112,9 +109,6 @@ public static void NullHandle_Throws_ArgumentNullException(PipeDirection directi public static void InvalidHandle_Throws_ArgumentException(PipeDirection direction) { using SafePipeHandle pipeHandle = new SafePipeHandle(new IntPtr(-1), true); -#pragma warning disable SYSLIB0063 // Testing the obsolete constructor - AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, pipeHandle)); -#pragma warning restore SYSLIB0063 AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, pipeHandle)); } @@ -135,9 +129,6 @@ public static void BadHandleKind_Throws_IOException(PipeDirection direction) IntPtr handle = safeHandle.DangerousGetHandle(); SafePipeHandle fakePipeHandle = new SafePipeHandle(handle, ownsHandle: false); -#pragma warning disable SYSLIB0063 // Testing the obsolete constructor - Assert.Throws(() => new NamedPipeClientStream(direction, false, true, fakePipeHandle)); -#pragma warning restore SYSLIB0063 Assert.Throws(() => new NamedPipeClientStream(direction, false, fakePipeHandle)); } finally From 49bfe4d6161533c83af9cb3bd4542e813b54a0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Thu, 16 Oct 2025 11:25:20 -0500 Subject: [PATCH 06/10] Revert "Remove duplicate obsolete constructor tests to avoid duplication" This reverts commit 071c67fe2e2491808e1bdc456479eec7d0c04315. --- .../tests/NamedPipeTests/NamedPipeTest.CreateClient.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index bd1619168946cb..442e8088b4a548 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -99,6 +99,9 @@ public static void InvalidImpersonationLevel_Throws_ArgumentOutOfRangeException( [InlineData(PipeDirection.Out)] public static void NullHandle_Throws_ArgumentNullException(PipeDirection direction) { +#pragma warning disable SYSLIB0063 // Testing the obsolete constructor + AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, null)); +#pragma warning restore SYSLIB0063 AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, null)); } @@ -109,6 +112,9 @@ public static void NullHandle_Throws_ArgumentNullException(PipeDirection directi public static void InvalidHandle_Throws_ArgumentException(PipeDirection direction) { using SafePipeHandle pipeHandle = new SafePipeHandle(new IntPtr(-1), true); +#pragma warning disable SYSLIB0063 // Testing the obsolete constructor + AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, true, pipeHandle)); +#pragma warning restore SYSLIB0063 AssertExtensions.Throws("safePipeHandle", () => new NamedPipeClientStream(direction, false, pipeHandle)); } @@ -129,6 +135,9 @@ public static void BadHandleKind_Throws_IOException(PipeDirection direction) IntPtr handle = safeHandle.DangerousGetHandle(); SafePipeHandle fakePipeHandle = new SafePipeHandle(handle, ownsHandle: false); +#pragma warning disable SYSLIB0063 // Testing the obsolete constructor + Assert.Throws(() => new NamedPipeClientStream(direction, false, true, fakePipeHandle)); +#pragma warning restore SYSLIB0063 Assert.Throws(() => new NamedPipeClientStream(direction, false, fakePipeHandle)); } finally From 5f635a2c8f4b91a52a27a59ffedada46a4967c8c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Oct 2025 20:58:16 +0000 Subject: [PATCH 07/10] Remove comment lines and add test for Connect on pipe from existing handle Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com> --- .../System/IO/Pipes/NamedPipeClientStream.cs | 1 - .../NamedPipeTest.CreateClient.cs | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs index 29937a161d4b55..0056a9d19672de 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs @@ -88,7 +88,6 @@ public NamedPipeClientStream(string serverName, string pipeName, PipeDirection d _pipeOptions = options; _accessRights = AccessRightsFromDirection(direction); } - [Obsolete(Obsoletions.NamedPipeClientStreamIsConnectedMessage, DiagnosticId = Obsoletions.NamedPipeClientStreamIsConnectedDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 442e8088b4a548..6f8ffed4cac54f 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -154,5 +154,48 @@ public static void NamedPipeClientStream_InvalidHandleInerhitability() AssertExtensions.Throws("inheritability", () => new NamedPipeClientStream("a", "b", PipeDirection.Out, 0, TokenImpersonationLevel.Delegation, HandleInheritability.None - 1)); AssertExtensions.Throws("inheritability", () => new NamedPipeClientStream("a", "b", PipeDirection.Out, 0, TokenImpersonationLevel.Delegation, HandleInheritability.Inheritable + 1)); } + + [Fact] + public static void ConnectOnPipeFromExistingHandle_Throws_InvalidOperationException() + { + string pipeName = PipeStreamConformanceTests.GetUniquePipeName(); + + // Test new constructor - should throw InvalidOperationException when Connect is called + using (var server1 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) + using (var client1 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) + { + client1.Connect(); + server1.WaitForConnection(); + + // Create new instance from handle - the handle is not owned, so we don't dispose clientFromHandle + var clientFromHandle = new NamedPipeClientStream(PipeDirection.InOut, true, new SafePipeHandle(client1.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + Assert.Throws(() => clientFromHandle.Connect()); + } + + // Test obsolete constructor with isConnected: true - should throw InvalidOperationException when Connect is called +#pragma warning disable SYSLIB0063 + using (var server2 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) + using (var client2 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) + { + client2.Connect(); + server2.WaitForConnection(); + + var clientFromHandleTrue = new NamedPipeClientStream(PipeDirection.InOut, true, true, new SafePipeHandle(client2.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + Assert.Throws(() => clientFromHandleTrue.Connect()); + } + + // Test obsolete constructor with isConnected: false - should also throw InvalidOperationException + // because the constructor now ignores isConnected and always sets state to Connected + using (var server3 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) + using (var client3 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) + { + client3.Connect(); + server3.WaitForConnection(); + + var clientFromHandleFalse = new NamedPipeClientStream(PipeDirection.InOut, true, false, new SafePipeHandle(client3.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + Assert.Throws(() => clientFromHandleFalse.Connect()); + } +#pragma warning restore SYSLIB0063 + } } } From 79cc239285bda269372a39f1e9a922463435aa6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:35:51 +0000 Subject: [PATCH 08/10] Fix spacing and test to use non-async handles and test ConnectAsync Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com> --- .../System/IO/Pipes/NamedPipeClientStream.cs | 1 + .../NamedPipeTest.CreateClient.cs | 25 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs index 0056a9d19672de..29937a161d4b55 100644 --- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs +++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs @@ -88,6 +88,7 @@ public NamedPipeClientStream(string serverName, string pipeName, PipeDirection d _pipeOptions = options; _accessRights = AccessRightsFromDirection(direction); } + [Obsolete(Obsoletions.NamedPipeClientStreamIsConnectedMessage, DiagnosticId = Obsoletions.NamedPipeClientStreamIsConnectedDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 6f8ffed4cac54f..17a9b87f72e6f4 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -160,40 +160,43 @@ public static void ConnectOnPipeFromExistingHandle_Throws_InvalidOperationExcept { string pipeName = PipeStreamConformanceTests.GetUniquePipeName(); - // Test new constructor - should throw InvalidOperationException when Connect is called - using (var server1 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) - using (var client1 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) + // Test new constructor - should throw InvalidOperationException when Connect and ConnectAsync are called + using (var server1 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) + using (var client1 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None)) { client1.Connect(); server1.WaitForConnection(); // Create new instance from handle - the handle is not owned, so we don't dispose clientFromHandle - var clientFromHandle = new NamedPipeClientStream(PipeDirection.InOut, true, new SafePipeHandle(client1.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + var clientFromHandle = new NamedPipeClientStream(PipeDirection.InOut, false, new SafePipeHandle(client1.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); Assert.Throws(() => clientFromHandle.Connect()); + Assert.ThrowsAsync(async () => await clientFromHandle.ConnectAsync()).GetAwaiter().GetResult(); } - // Test obsolete constructor with isConnected: true - should throw InvalidOperationException when Connect is called + // Test obsolete constructor with isConnected: true - should throw InvalidOperationException when Connect and ConnectAsync are called #pragma warning disable SYSLIB0063 - using (var server2 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) - using (var client2 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) + using (var server2 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) + using (var client2 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None)) { client2.Connect(); server2.WaitForConnection(); - var clientFromHandleTrue = new NamedPipeClientStream(PipeDirection.InOut, true, true, new SafePipeHandle(client2.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + var clientFromHandleTrue = new NamedPipeClientStream(PipeDirection.InOut, false, true, new SafePipeHandle(client2.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); Assert.Throws(() => clientFromHandleTrue.Connect()); + Assert.ThrowsAsync(async () => await clientFromHandleTrue.ConnectAsync()).GetAwaiter().GetResult(); } // Test obsolete constructor with isConnected: false - should also throw InvalidOperationException // because the constructor now ignores isConnected and always sets state to Connected - using (var server3 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) - using (var client3 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)) + using (var server3 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) + using (var client3 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None)) { client3.Connect(); server3.WaitForConnection(); - var clientFromHandleFalse = new NamedPipeClientStream(PipeDirection.InOut, true, false, new SafePipeHandle(client3.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + var clientFromHandleFalse = new NamedPipeClientStream(PipeDirection.InOut, false, false, new SafePipeHandle(client3.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); Assert.Throws(() => clientFromHandleFalse.Connect()); + Assert.ThrowsAsync(async () => await clientFromHandleFalse.ConnectAsync()).GetAwaiter().GetResult(); } #pragma warning restore SYSLIB0063 } From 51cada24f23dea0c496c692d7faffb7fc426edd3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:14:41 +0000 Subject: [PATCH 09/10] Apply code review feedback: simplify test and use await pattern Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com> --- .../NamedPipeTest.CreateClient.cs | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 17a9b87f72e6f4..787f22ef6c0d4f 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Security.Principal; +using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; using Xunit; @@ -156,24 +157,21 @@ public static void NamedPipeClientStream_InvalidHandleInerhitability() } [Fact] - public static void ConnectOnPipeFromExistingHandle_Throws_InvalidOperationException() + public static async Task ConnectOnPipeFromExistingHandle_Throws_InvalidOperationException() { string pipeName = PipeStreamConformanceTests.GetUniquePipeName(); - - // Test new constructor - should throw InvalidOperationException when Connect and ConnectAsync are called + using (var server1 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) using (var client1 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None)) { client1.Connect(); server1.WaitForConnection(); - // Create new instance from handle - the handle is not owned, so we don't dispose clientFromHandle - var clientFromHandle = new NamedPipeClientStream(PipeDirection.InOut, false, new SafePipeHandle(client1.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + var clientFromHandle = new NamedPipeClientStream(PipeDirection.InOut, false, client1.SafePipeHandle); Assert.Throws(() => clientFromHandle.Connect()); - Assert.ThrowsAsync(async () => await clientFromHandle.ConnectAsync()).GetAwaiter().GetResult(); + await Assert.ThrowsAsync(async () => await clientFromHandle.ConnectAsync()); } - // Test obsolete constructor with isConnected: true - should throw InvalidOperationException when Connect and ConnectAsync are called #pragma warning disable SYSLIB0063 using (var server2 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) using (var client2 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None)) @@ -181,22 +179,20 @@ public static void ConnectOnPipeFromExistingHandle_Throws_InvalidOperationExcept client2.Connect(); server2.WaitForConnection(); - var clientFromHandleTrue = new NamedPipeClientStream(PipeDirection.InOut, false, true, new SafePipeHandle(client2.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + var clientFromHandleTrue = new NamedPipeClientStream(PipeDirection.InOut, isAsync: false, isConnected: true, client2.SafePipeHandle); Assert.Throws(() => clientFromHandleTrue.Connect()); - Assert.ThrowsAsync(async () => await clientFromHandleTrue.ConnectAsync()).GetAwaiter().GetResult(); + await Assert.ThrowsAsync(async () => await clientFromHandleTrue.ConnectAsync()); } - // Test obsolete constructor with isConnected: false - should also throw InvalidOperationException - // because the constructor now ignores isConnected and always sets state to Connected using (var server3 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) using (var client3 = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None)) { client3.Connect(); server3.WaitForConnection(); - var clientFromHandleFalse = new NamedPipeClientStream(PipeDirection.InOut, false, false, new SafePipeHandle(client3.SafePipeHandle.DangerousGetHandle(), ownsHandle: false)); + var clientFromHandleFalse = new NamedPipeClientStream(PipeDirection.InOut, isAsync: false, isConnected: false, client3.SafePipeHandle); Assert.Throws(() => clientFromHandleFalse.Connect()); - Assert.ThrowsAsync(async () => await clientFromHandleFalse.ConnectAsync()).GetAwaiter().GetResult(); + await Assert.ThrowsAsync(async () => await clientFromHandleFalse.ConnectAsync()); } #pragma warning restore SYSLIB0063 } From fcfdc36bea1480bdeadb7e52e224a45cf5ae9906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Tue, 21 Oct 2025 12:31:57 -0700 Subject: [PATCH 10/10] Apply suggestions from code review Remove lambdas --- .../NamedPipeTests/NamedPipeTest.CreateClient.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs index 787f22ef6c0d4f..419a701392c6be 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.CreateClient.cs @@ -168,8 +168,8 @@ public static async Task ConnectOnPipeFromExistingHandle_Throws_InvalidOperation server1.WaitForConnection(); var clientFromHandle = new NamedPipeClientStream(PipeDirection.InOut, false, client1.SafePipeHandle); - Assert.Throws(() => clientFromHandle.Connect()); - await Assert.ThrowsAsync(async () => await clientFromHandle.ConnectAsync()); + Assert.Throws(clientFromHandle.Connect); + await Assert.ThrowsAsync(clientFromHandle.ConnectAsync); } #pragma warning disable SYSLIB0063 @@ -180,8 +180,8 @@ public static async Task ConnectOnPipeFromExistingHandle_Throws_InvalidOperation server2.WaitForConnection(); var clientFromHandleTrue = new NamedPipeClientStream(PipeDirection.InOut, isAsync: false, isConnected: true, client2.SafePipeHandle); - Assert.Throws(() => clientFromHandleTrue.Connect()); - await Assert.ThrowsAsync(async () => await clientFromHandleTrue.ConnectAsync()); + Assert.Throws(clientFromHandleTrue.Connect); + await Assert.ThrowsAsync(clientFromHandleTrue.ConnectAsync); } using (var server3 = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3, PipeTransmissionMode.Byte, PipeOptions.None)) @@ -191,8 +191,8 @@ public static async Task ConnectOnPipeFromExistingHandle_Throws_InvalidOperation server3.WaitForConnection(); var clientFromHandleFalse = new NamedPipeClientStream(PipeDirection.InOut, isAsync: false, isConnected: false, client3.SafePipeHandle); - Assert.Throws(() => clientFromHandleFalse.Connect()); - await Assert.ThrowsAsync(async () => await clientFromHandleFalse.ConnectAsync()); + Assert.Throws(clientFromHandleFalse.Connect); + await Assert.ThrowsAsync(clientFromHandleFalse.ConnectAsync); } #pragma warning restore SYSLIB0063 }