public async Task PingPong_Async()
        {
            // Create names for two pipes
            string outName = PipeStreamConformanceTests.GetUniquePipeName();
            string inName  = PipeStreamConformanceTests.GetUniquePipeName();

            // Create the two named pipes, one for each direction, then create
            // another process with which to communicate
            using (var outbound = new NamedPipeServerStream(outName, PipeDirection.Out))
                using (var inbound = new NamedPipeClientStream(".", inName, PipeDirection.In))
                    using (RemoteExecutor.Invoke(new Action <string, string>(PingPong_OtherProcess), outName, inName))
                    {
                        // Wait for both pipes to be connected
                        await Task.WhenAll(outbound.WaitForConnectionAsync(), inbound.ConnectAsync());

                        // Repeatedly write then read a byte to and from the other process
                        var data = new byte[1];
                        for (byte i = 0; i < 10; i++)
                        {
                            data[0] = i;
                            await outbound.WriteAsync(data, 0, data.Length);

                            data[0] = 0;
                            int received = await inbound.ReadAsync(data, 0, data.Length);

                            Assert.Equal(1, received);
                            Assert.Equal(i, data[0]);
                        }
                    }
        }
        public void Allow_Connection_UnderDifferentUsers_ForClientReading(bool useTimeSpan)
        {
            string name = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(
                       name, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
            {
                Task serverTask = server.WaitForConnectionAsync(CancellationToken.None);

                _testAccountImpersonator.RunImpersonated(() =>
                {
                    using (var client = new NamedPipeClientStream(".", name, PipeDirection.In))
                    {
                        if (useTimeSpan)
                        {
                            client.Connect(TimeSpan.FromMilliseconds(10_000));
                        }
                        else
                        {
                            client.Connect(10_000);
                        }
                    }
                });

                Assert.True(serverTask.Wait(10_000));
            }
        }
示例#3
0
        [PlatformSpecific(TestPlatforms.Windows)] // Unix implementation uses bidirectional sockets
        public static void Windows_BufferSizeRoundtripping()
        {
            int    desiredBufferSize = 10;
            string pipeName          = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, desiredBufferSize, desiredBufferSize))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.In))
                {
                    Task clientConnect = client.ConnectAsync();
                    server.WaitForConnection();
                    clientConnect.Wait();

                    Assert.Equal(desiredBufferSize, server.OutBufferSize);
                    Assert.Equal(desiredBufferSize, client.InBufferSize);
                }

            using (var server = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, desiredBufferSize, desiredBufferSize))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.Out))
                {
                    Task clientConnect = client.ConnectAsync();
                    server.WaitForConnection();
                    clientConnect.Wait();

                    Assert.Equal(desiredBufferSize, server.InBufferSize);
                    Assert.Equal(0, client.OutBufferSize);
                }
        }
示例#4
0
        [PlatformSpecific(TestPlatforms.Windows)] // Win32 P/Invokes to verify the user name
        public async Task Windows_GetImpersonationUserName_Succeed(TokenImpersonationLevel level, bool expectedResult)
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName))
            {
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None, level))
                {
                    string expectedUserName;
                    Task   serverTask = server.WaitForConnectionAsync();

                    client.Connect();
                    await serverTask;

                    Assert.Equal(expectedResult, InteropTest.TryGetImpersonationUserName(server.SafePipeHandle, out expectedUserName));

                    if (!expectedResult)
                    {
                        Assert.Equal(string.Empty, expectedUserName);
                        Assert.Throws <IOException>(() => server.GetImpersonationUserName());
                    }
                    else
                    {
                        string actualUserName = server.GetImpersonationUserName();
                        Assert.NotNull(actualUserName);
                        Assert.False(string.IsNullOrWhiteSpace(actualUserName));
                        Assert.Equal(expectedUserName, actualUserName);
                    }
                }
            }
        }
示例#5
0
        public static void Unix_BufferSizeRoundtripping(PipeDirection direction)
        {
            int    desiredBufferSize = 0;
            string pipeName          = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, desiredBufferSize, desiredBufferSize))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut))
                {
                    Task clientConnect = client.ConnectAsync();
                    server.WaitForConnection();
                    clientConnect.Wait();

                    desiredBufferSize = server.OutBufferSize * 2;
                }

            using (var server = new NamedPipeServerStream(pipeName, direction, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, desiredBufferSize, desiredBufferSize))
                using (var client = new NamedPipeClientStream(".", pipeName, direction == PipeDirection.In ? PipeDirection.Out : PipeDirection.In))
                {
                    Task clientConnect = client.ConnectAsync();
                    server.WaitForConnection();
                    clientConnect.Wait();

                    if ((direction & PipeDirection.Out) != 0)
                    {
                        Assert.InRange(server.OutBufferSize, desiredBufferSize, int.MaxValue);
                    }

                    if ((direction & PipeDirection.In) != 0)
                    {
                        Assert.InRange(server.InBufferSize, desiredBufferSize, int.MaxValue);
                    }
                }
        }
        public static void CreateMultipleConcurrentServers_ConnectMultipleClients(PipeOptions extraPipeOptions)
        {
            var pipeServers = new NamedPipeServerStream[5];
            var pipeClients = new NamedPipeClientStream[pipeServers.Length];

            try
            {
                string pipeName = PipeStreamConformanceTests.GetUniquePipeName();
                for (var i = 0; i < pipeServers.Length; i++)
                {
                    pipeServers[i] = new NamedPipeServerStream(
                        pipeName,
                        PipeDirection.InOut,
                        NamedPipeServerStream.MaxAllowedServerInstances,
                        PipeTransmissionMode.Byte,
                        PipeOptions.Asynchronous | PipeOptions.WriteThrough | extraPipeOptions);

                    pipeClients[i] = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous | extraPipeOptions);
                    pipeClients[i].Connect(15_000);
                }
            }
            finally
            {
                for (var i = 0; i < pipeServers.Length; i++)
                {
                    pipeServers[i]?.Dispose();
                    pipeClients[i]?.Dispose();
                }
            }
        }
示例#7
0
 public static void Unix_GetHandleOfNewServerStream_Throws_InvalidOperationException()
 {
     using (var pipe = new NamedPipeServerStream(PipeStreamConformanceTests.GetUniquePipeName(), PipeDirection.Out, 1, PipeTransmissionMode.Byte))
     {
         Assert.Throws <InvalidOperationException>(() => pipe.SafePipeHandle);
     }
 }
        public void InheritHandles_AvailableInChildProcess()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName, PipeDirection.In))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.Out, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.Inheritable))
                {
                    Task.WaitAll(server.WaitForConnectionAsync(), client.ConnectAsync());
                    using (RemoteExecutor.Invoke(new Action <string>(ChildFunc), client.SafePipeHandle.DangerousGetHandle().ToString()))
                    {
                        client.Dispose();
                        for (int i = 0; i < 5; i++)
                        {
                            Assert.Equal(i, server.ReadByte());
                        }
                    }
                }

            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)))
                {
                    for (int i = 0; i < 5; i++)
                    {
                        childClient.WriteByte((byte)i);
                    }
                }
            }
        }
        [PlatformSpecific(TestPlatforms.Windows)]  // Uses P/Invokes
        public async Task RunAsClient_Windows(TokenImpersonationLevel tokenImpersonationLevel)
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None, tokenImpersonationLevel))
                {
                    Task serverTask = server.WaitForConnectionAsync();

                    client.Connect();
                    await serverTask;

                    bool ran = false;
                    if (tokenImpersonationLevel == TokenImpersonationLevel.None)
                    {
                        Assert.Throws <IOException>(() => server.RunAsClient(() => ran = true));
                        Assert.False(ran, "Expected delegate to not have been invoked");
                    }
                    else
                    {
                        server.RunAsClient(() => ran = true);
                        Assert.True(ran, "Expected delegate to have been invoked");
                    }
                }
        }
        public void MaxNumberOfServerInstances_TooManyServers_Throws()
        {
            string name = PipeStreamConformanceTests.GetUniquePipeName();

            using (new NamedPipeServerStream(name, PipeDirection.InOut, 1))
            {
                // NPSS was created with max of 1, so creating another fails.
                Assert.Throws <IOException>(() => new NamedPipeServerStream(name, PipeDirection.InOut, 1));
            }

            using (new NamedPipeServerStream(name, PipeDirection.InOut, 3))
            {
                // NPSS was created with max of 3, but NPSS not only validates against the original max but also
                // against the max of the stream being created, so since there's already 1 and this specifies max == 1, it fails.
                Assert.Throws <UnauthorizedAccessException>(() => new NamedPipeServerStream(name, PipeDirection.InOut, 1));

                using (new NamedPipeServerStream(name, PipeDirection.InOut, 2))     // lower max ignored
                    using (new NamedPipeServerStream(name, PipeDirection.InOut, 4)) // higher max ignored
                    {
                        // NPSS was created with a max of 3, and we're creating a 4th, so it fails.
                        Assert.Throws <IOException>(() => new NamedPipeServerStream(name, PipeDirection.InOut, 3));
                    }

                using (new NamedPipeServerStream(name, PipeDirection.InOut, 3))
                    using (new NamedPipeServerStream(name, PipeDirection.InOut, 3))
                    {
                        // NPSS was created with a max of 3, and we've already created 3, so it fails,
                        // even if the new stream tries to raise it.
                        Assert.Throws <IOException>(() => new NamedPipeServerStream(name, PipeDirection.InOut, 4));
                        Assert.Throws <IOException>(() => new NamedPipeServerStream(name, PipeDirection.InOut, 2));
                    }
            }
        }
        protected override (NamedPipeServerStream Server, NamedPipeClientStream Client) CreateServerAndClientStreams()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();
            var    server   = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            var    client   = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);

            return(server, client);
        }
示例#12
0
 [PlatformSpecific(TestPlatforms.Windows)] // accessing SafePipeHandle on Unix fails for a non-connected stream
 public static void Windows_CreateFromAlreadyBoundHandle_Throws_ArgumentException(PipeDirection direction)
 {
     // The pipe is already bound
     using (var pipe = new NamedPipeServerStream(PipeStreamConformanceTests.GetUniquePipeName(), direction, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
     {
         AssertExtensions.Throws <ArgumentException>("handle", () => new NamedPipeServerStream(direction, true, true, pipe.SafePipeHandle));
     }
 }
示例#13
0
        [PlatformSpecific(TestPlatforms.Windows)] // NumberOfServerInstances > 1 isn't supported and has undefined behavior on Unix
        public static void Windows_ServerCloneWithDifferentDirection_Throws_UnauthorizedAccessException()
        {
            string uniqueServerName = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeServerStream server = new NamedPipeServerStream(uniqueServerName, PipeDirection.In, 2, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
            {
                Assert.Throws <UnauthorizedAccessException>(() => new NamedPipeServerStream(uniqueServerName, PipeDirection.Out));
            }
        }
示例#14
0
        [PlatformSpecific(TestPlatforms.Windows)] // NumberOfServerInstances > 1 isn't supported and has undefined behavior on Unix
        public static void ServerCountOverMaxServerInstances_Throws_IOException()
        {
            string uniqueServerName = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeServerStream server = new NamedPipeServerStream(uniqueServerName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
            {
                Assert.Throws <IOException>(() => new NamedPipeServerStream(uniqueServerName));
            }
        }
示例#15
0
        [PlatformSpecific(TestPlatforms.Windows)] // accessing SafePipeHandle on Unix fails for a non-connected stream
        public static void Windows_CreateFromDisposedServerHandle_Throws_ObjectDisposedException(PipeDirection direction)
        {
            // The pipe is closed when we try to make a new Stream with it
            var            pipe   = new NamedPipeServerStream(PipeStreamConformanceTests.GetUniquePipeName(), direction, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            SafePipeHandle handle = pipe.SafePipeHandle;

            pipe.Dispose();
            Assert.Throws <ObjectDisposedException>(() => new NamedPipeServerStream(direction, true, true, pipe.SafePipeHandle).Dispose());
        }
        public void ClientConnect_Throws_Timeout_When_Pipe_Not_Found()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeClientStream client = new NamedPipeClientStream(pipeName))
            {
                Assert.Throws <TimeoutException>(() => client.Connect(91));
            }
        }
示例#17
0
 [PlatformSpecific(TestPlatforms.Windows)] // can't access SafePipeHandle on Unix until after connection created
 public static void CreateWithNegativeOneServerInstances_DefaultsToMaxServerInstances()
 {
     // When passed -1 as the maxnumberofserverisntances, the NamedPipeServerStream.Windows class
     // will translate that to the platform specific maximum number (255)
     using (var server = new NamedPipeServerStream(PipeStreamConformanceTests.GetUniquePipeName(), PipeDirection.InOut, -1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
         using (var server2 = new NamedPipeServerStream(PipeDirection.InOut, false, true, server.SafePipeHandle))
             using (var server3 = new NamedPipeServerStream(PipeDirection.InOut, false, true, server.SafePipeHandle))
             {
             }
 }
        public async Task ClientConnectAsync_Throws_Timeout_When_Pipe_Not_Found(CancellationToken cancellationToken)
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeClientStream client = new NamedPipeClientStream(pipeName))
            {
                Task waitingClient = client.ConnectAsync(92, cancellationToken);
                await Assert.ThrowsAsync <TimeoutException>(() => { return(waitingClient); });
            }
        }
        public static void CreateServer_ConnectClient_UsingUnixAbsolutePath()
        {
            string name = Path.Combine("/tmp", PipeStreamConformanceTests.GetUniquePipeName());

            using (var server = new NamedPipeServerStream(name, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly))
            {
                using (var client = new NamedPipeClientStream(".", name, PipeDirection.InOut, PipeOptions.CurrentUserOnly))
                {
                    client.Connect();
                }
            }
        }
        public static void CreateServer_ConnectClient()
        {
            string name = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(name, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly))
            {
                using (var client = new NamedPipeClientStream(".", name, PipeDirection.InOut, PipeOptions.CurrentUserOnly))
                {
                    // Should not fail to connect since both, the server and client have the same owner.
                    client.Connect();
                }
            }
        }
        public async Task PipeTransmissionMode_Returns_Byte()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.Out))
                {
                    await Task.WhenAll(server.WaitForConnectionAsync(), client.ConnectAsync());

                    Assert.Equal(PipeTransmissionMode.Byte, server.TransmissionMode);
                    Assert.Equal(PipeTransmissionMode.Byte, client.TransmissionMode);
                }
        }
        public void InvalidReadMode_Throws_ArgumentOutOfRangeException(PipeDirection serverDirection, PipeDirection clientDirection)
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName, serverDirection, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
                using (var client = new NamedPipeClientStream(".", pipeName, clientDirection))
                {
                    Task clientConnect = client.ConnectAsync();
                    server.WaitForConnection();
                    clientConnect.Wait();

                    Assert.Throws <ArgumentOutOfRangeException>(() => server.ReadMode = (PipeTransmissionMode)999);
                    Assert.Throws <ArgumentOutOfRangeException>(() => client.ReadMode = (PipeTransmissionMode)999);
                }
        }
        public static void Connection_UnderSameUser_SingleSide_CurrentUserOnly_Works(PipeOptions serverPipeOptions, PipeOptions clientPipeOptions)
        {
            string name = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(name, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, serverPipeOptions))
                using (var client = new NamedPipeClientStream(".", name, PipeDirection.InOut, clientPipeOptions))
                {
                    Task[] tasks = new[]
                    {
                        Task.Run(() => server.WaitForConnection()),
                        Task.Run(() => client.Connect())
                    };

                    Assert.True(Task.WaitAll(tasks, 20_000));
                }
        }
        [PlatformSpecific(TestPlatforms.AnyUnix)]  // Uses P/Invoke to verify the user name
        public async Task Unix_GetImpersonationUserName_Succeed()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName))
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation))
                {
                    Task serverTask = server.WaitForConnectionAsync();

                    client.Connect();
                    await serverTask;

                    string name = server.GetImpersonationUserName();
                    Assert.NotNull(name);
                    Assert.False(string.IsNullOrWhiteSpace(name));
                }
        }
        [PlatformSpecific(TestPlatforms.Windows)] // Unix doesn't support MaxNumberOfServerInstances
        public async Task Windows_Get_NumberOfServerInstances_Succeed()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 3))
            {
                using (var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation))
                {
                    Task serverTask = server.WaitForConnectionAsync();

                    client.Connect();
                    await serverTask;

                    Assert.True(InteropTest.TryGetNumberOfServerInstances(client.SafePipeHandle, out uint expectedNumberOfServerInstances), "GetNamedPipeHandleState failed");
                    Assert.Equal(expectedNumberOfServerInstances, (uint)client.NumberOfServerInstances);
                }
            }
        }
        [PlatformSpecific(TestPlatforms.Windows)] // Unix ignores MaxNumberOfServerInstances and second client also connects.
        public void ClientConnect_Throws_Timeout_When_Pipe_Busy()
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeServerStream server = new NamedPipeServerStream(pipeName))
                using (NamedPipeClientStream firstClient = new NamedPipeClientStream(pipeName))
                    using (NamedPipeClientStream secondClient = new NamedPipeClientStream(pipeName))
                    {
                        const int timeout = 10_000;
                        Task[]    clientAndServerTasks = new[]
                        {
                            firstClient.ConnectAsync(timeout),
                            Task.Run(() => server.WaitForConnection())
                        };

                        Assert.True(Task.WaitAll(clientAndServerTasks, timeout));

                        Assert.Throws <TimeoutException>(() => secondClient.Connect(93));
                    }
        }
        public static void CreateMultipleServers_ConnectMultipleClients()
        {
            string name1 = PipeStreamConformanceTests.GetUniquePipeName();
            string name2 = PipeStreamConformanceTests.GetUniquePipeName();
            string name3 = PipeStreamConformanceTests.GetUniquePipeName();

            using (var server1 = new NamedPipeServerStream(name1, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly))
                using (var server2 = new NamedPipeServerStream(name2, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly))
                    using (var server3 = new NamedPipeServerStream(name3, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly))
                    {
                        using (var client1 = new NamedPipeClientStream(".", name1, PipeDirection.InOut, PipeOptions.CurrentUserOnly))
                            using (var client2 = new NamedPipeClientStream(".", name2, PipeDirection.InOut, PipeOptions.CurrentUserOnly))
                                using (var client3 = new NamedPipeClientStream(".", name3, PipeDirection.InOut, PipeOptions.CurrentUserOnly))
                                {
                                    client1.Connect();
                                    client2.Connect();
                                    client3.Connect();
                                }
                    }
        }
        [PlatformSpecific(TestPlatforms.Windows)] // Unix implementation uses bidirectional sockets
        public void ConnectWithConflictingDirections_Throws_UnauthorizedAccessException()
        {
            string serverName1 = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeServerStream server = new NamedPipeServerStream(serverName1, PipeDirection.Out))
                using (NamedPipeClientStream client = new NamedPipeClientStream(".", serverName1, PipeDirection.Out))
                {
                    Assert.Throws <UnauthorizedAccessException>(() => client.Connect());
                    Assert.False(client.IsConnected);
                }

            string serverName2 = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeServerStream server = new NamedPipeServerStream(serverName2, PipeDirection.In))
                using (NamedPipeClientStream client = new NamedPipeClientStream(".", serverName2, PipeDirection.In))
                {
                    Assert.Throws <UnauthorizedAccessException>(() => client.Connect());
                    Assert.False(client.IsConnected);
                }
        }
        [PlatformSpecific(TestPlatforms.Windows)] // Unix ignores MaxNumberOfServerInstances and second client also connects.
        public async Task ClientConnectAsync_With_Cancellation_Throws_Timeout_When_Pipe_Busy(CancellationToken cancellationToken)
        {
            string pipeName = PipeStreamConformanceTests.GetUniquePipeName();

            using (NamedPipeServerStream server = new NamedPipeServerStream(pipeName))
                using (NamedPipeClientStream firstClient = new NamedPipeClientStream(pipeName))
                    using (NamedPipeClientStream secondClient = new NamedPipeClientStream(pipeName))
                    {
                        const int timeout = 10_000;
                        Task[]    clientAndServerTasks = new[]
                        {
                            firstClient.ConnectAsync(timeout),
                            Task.Run(() => server.WaitForConnection())
                        };

                        Assert.True(Task.WaitAll(clientAndServerTasks, timeout));

                        Task waitingClient = secondClient.ConnectAsync(94, cancellationToken);
                        await Assert.ThrowsAsync <TimeoutException>(() => { return(waitingClient); });
                    }
        }
        public async Task MultipleServers_ServeMultipleClientsConcurrently(int numServers)
        {
            string name = PipeStreamConformanceTests.GetUniquePipeName();

            var servers = new NamedPipeServerStream[numServers];
            var clients = new NamedPipeClientStream[servers.Length];

            try
            {
                for (int i = 0; i < servers.Length; i++)
                {
                    servers[i] = new NamedPipeServerStream(name, PipeDirection.InOut, numServers, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
                }

                for (int i = 0; i < clients.Length; i++)
                {
                    clients[i] = new NamedPipeClientStream(".", name, PipeDirection.InOut, PipeOptions.Asynchronous);
                }

                Task[] serverWaits = (from server in servers select server.WaitForConnectionAsync()).ToArray();
                Task[] clientWaits = (from client in clients select client.ConnectAsync()).ToArray();
                await serverWaits.Concat(clientWaits).ToArray().WhenAllOrAnyFailed();

                Task[]       serverSends    = (from server in servers select server.WriteAsync(new byte[1], 0, 1)).ToArray();
                Task <int>[] clientReceives = (from client in clients select client.ReadAsync(new byte[1], 0, 1)).ToArray();
                await serverSends.Concat(clientReceives).ToArray().WhenAllOrAnyFailed();
            }
            finally
            {
                for (int i = 0; i < clients.Length; i++)
                {
                    clients[i]?.Dispose();
                }

                for (int i = 0; i < servers.Length; i++)
                {
                    servers[i]?.Dispose();
                }
            }
        }