public async Task MessagesShouldPassThruRedundantChannelWhenNotAllChildConnectionsAreSlowOrDown()
        {
            var toxiproxyServerPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "TransactTcp.Tests", "toxiproxy-server-windows-amd64.exe");

            foreach (var existentToxiserverProcess in Process.GetProcessesByName("toxiproxy-server-windows-amd64").ToList())
            {
                existentToxiserverProcess.Kill();
            }

            Directory.CreateDirectory(Path.GetDirectoryName(toxiproxyServerPath));

            await File.WriteAllBytesAsync(toxiproxyServerPath,
                                          Utils.LoadResourceAsByteArray("toxiproxy-server-windows-amd64.exe"));

            using var toxyproxyServerProcess = Process.Start(toxiproxyServerPath);

            try
            {
                //Setting up Toxiproxy proxies
                var connection = new Connection();
                var client     = connection.Client();

                var interface1Proxy = new Proxy()
                {
                    Name     = "interface1Proxy",
                    Enabled  = true,
                    Listen   = "127.0.0.1:12000",
                    Upstream = "127.0.0.1:12001"
                };

                await client.AddAsync(interface1Proxy);

                var interface2Proxy = new Proxy()
                {
                    Name     = "interface2Proxy",
                    Enabled  = true,
                    Listen   = "127.0.0.1:13000",
                    Upstream = "127.0.0.1:13001"
                };

                await client.AddAsync(interface2Proxy);

                using var serverConnection = TcpConnectionFactory.CreateRedundantServer(new[] { new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12001), new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13001) });
                using var clientConnection = TcpConnectionFactory.CreateRedundantClient(new[] { new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12000), new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13000) });

                using var serverConnectedEvent    = new AutoResetEvent(false);
                using var clientConnectedEvent    = new AutoResetEvent(false);
                using var errorsOnServerSideEvent = new AutoResetEvent(false);
                using var errorsOnClientSideEvent = new AutoResetEvent(false);

                int counterOfMessagesArrivedAtServer = 0;
                serverConnection.Start(
                    receivedAction: (c, data) =>
                {
                    if (BitConverter.ToInt32(data) != counterOfMessagesArrivedAtServer)
                    {
                        errorsOnServerSideEvent.Set();
                    }
                    counterOfMessagesArrivedAtServer++;
                },
                    connectionStateChangedAction: (c, fromState, toState) =>
                {
                    if (toState == ConnectionState.Connected)
                    {
                        serverConnectedEvent.Set();
                    }
                });

                int counterOfMessagesArrivedAtClient = 0;
                clientConnection.Start(
                    receivedAction: (c, data) =>
                {
                    if (BitConverter.ToInt32(data) != counterOfMessagesArrivedAtClient)
                    {
                        errorsOnClientSideEvent.Set();
                    }
                    counterOfMessagesArrivedAtClient++;
                },
                    connectionStateChangedAction: (c, fromState, toState) =>
                {
                    if (toState == ConnectionState.Connected)
                    {
                        clientConnectedEvent.Set();
                    }
                });

                WaitHandle.WaitAll(new[] { serverConnectedEvent, clientConnectedEvent }, 5000).ShouldBeTrue();

                var cancellationTokenSource = new CancellationTokenSource();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                Task.Run(async() =>
                {
                    var counter = 0;
                    while (!cancellationTokenSource.IsCancellationRequested)
                    {
                        await clientConnection.SendDataAsync(BitConverter.GetBytes(counter));
                        await serverConnection.SendDataAsync(BitConverter.GetBytes(counter));
                        await Task.Delay(500, cancellationTokenSource.Token);
                        counter++;
                    }
                }, cancellationTokenSource.Token);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

                await Task.Delay(1000);

                interface1Proxy.Enabled = false;
                await client.UpdateAsync(interface1Proxy);

                WaitHandle.WaitAll(new[] { errorsOnServerSideEvent, errorsOnClientSideEvent }, 2000).ShouldBeFalse();

                interface1Proxy.Enabled = true;
                await client.UpdateAsync(interface1Proxy);

                interface2Proxy.Enabled = false;
                await client.UpdateAsync(interface2Proxy);

                WaitHandle.WaitAll(new[] { errorsOnServerSideEvent, errorsOnClientSideEvent }, 2000).ShouldBeFalse();

                interface2Proxy.Enabled = true;
                await client.UpdateAsync(interface2Proxy);

                var latencyProxy = new LatencyToxic()
                {
                    Name     = "latencyToxicInterface2",
                    Stream   = ToxicDirection.DownStream,
                    Toxicity = 1.0,
                };
                latencyProxy.Attributes.Jitter  = 100;
                latencyProxy.Attributes.Latency = 300;

                await interface1Proxy.AddAsync(latencyProxy);

                WaitHandle.WaitAll(new[] { errorsOnServerSideEvent, errorsOnClientSideEvent }, 2000).ShouldBeFalse();

                var slicerToxic = new SlicerToxic()
                {
                    Name     = "slicerToxicInterface1",
                    Stream   = ToxicDirection.UpStream,
                    Toxicity = 1.0,
                };
                slicerToxic.Attributes.AverageSize   = 10;
                slicerToxic.Attributes.Delay         = 5;
                slicerToxic.Attributes.SizeVariation = 1;

                await interface1Proxy.AddAsync(slicerToxic);

                WaitHandle.WaitAll(new[] { errorsOnServerSideEvent, errorsOnClientSideEvent }, 4000).ShouldBeFalse();

                interface2Proxy.Enabled = false;
                await client.UpdateAsync(interface2Proxy);

                WaitHandle.WaitAll(new[] { errorsOnServerSideEvent, errorsOnClientSideEvent }, 2000).ShouldBeFalse();

                cancellationTokenSource.Cancel();
            }
            finally
            {
                toxyproxyServerProcess.Kill();
            }
        }