Example #1
0
        public static async Task DataTestAsync <T>(IPipeServer <T> server, IPipeClient <T> client, List <T> values, Func <T, string>?hashFunc = null, CancellationToken cancellationToken = default)
        {
            Trace.WriteLine("Setting up test...");

            var completionSource = new TaskCompletionSource <bool>(false);

            // ReSharper disable once AccessToModifiedClosure
            using var registration = cancellationToken.Register(() => completionSource.TrySetCanceled(cancellationToken));

            var actualHash         = (string?)null;
            var clientDisconnected = false;

            server.ClientConnected += (sender, args) =>
            {
                Trace.WriteLine("Client connected");
            };
            server.ClientDisconnected += (sender, args) =>
            {
                Trace.WriteLine("Client disconnected");
                clientDisconnected = true;

                // ReSharper disable once AccessToModifiedClosure
                completionSource.TrySetResult(true);
            };
            server.MessageReceived += (sender, args) =>
            {
                Trace.WriteLine($"Server_OnMessageReceived: {args.Message}");
                actualHash = hashFunc?.Invoke(args.Message);
                Trace.WriteLine($"ActualHash: {actualHash}");

                // ReSharper disable once AccessToModifiedClosure
                completionSource.TrySetResult(true);
            };
            server.ExceptionOccurred += (sender, args) =>
            {
                Trace.WriteLine($"Server exception occurred: {args.Exception}");

                // ReSharper disable once AccessToModifiedClosure
                completionSource.TrySetException(args.Exception);
            };
            client.Connected         += (sender, args) => Trace.WriteLine("Client_OnConnected");
            client.Disconnected      += (sender, args) => Trace.WriteLine("Client_OnDisconnected");
            client.MessageReceived   += (sender, args) => Trace.WriteLine($"Client_OnMessageReceived: {args.Message}");
            client.ExceptionOccurred += (sender, args) =>
            {
                Trace.WriteLine($"Client exception occurred: {args.Exception}");

                // ReSharper disable once AccessToModifiedClosure
                completionSource.TrySetException(args.Exception);
            };
            AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
            {
                if (args.ExceptionObject is Exception exception)
                {
                    // ReSharper disable once AccessToModifiedClosure
                    completionSource.TrySetException(exception);
                }
            };

            server.ExceptionOccurred += (sender, args) => Trace.WriteLine(args.Exception.ToString());
            client.ExceptionOccurred += (sender, args) => Trace.WriteLine(args.Exception.ToString());

            await server.StartAsync(cancellationToken).ConfigureAwait(false);

            await client.ConnectAsync(cancellationToken).ConfigureAwait(false);

            Trace.WriteLine("Client and server started");
            Trace.WriteLine("---");

            var watcher = Stopwatch.StartNew();

            foreach (var value in values)
            {
                var expectedHash = hashFunc?.Invoke(value);
                Trace.WriteLine($"ExpectedHash: {expectedHash}");

                await client.WriteAsync(value, cancellationToken).ConfigureAwait(false);

                await completionSource.Task.ConfigureAwait(false);

                if (hashFunc != null)
                {
                    Assert.IsNotNull(actualHash, "Server should have received a zero-byte message from the client");
                }

                Assert.AreEqual(expectedHash, actualHash, "SHA-1 hashes for zero-byte message should match");
                Assert.IsFalse(clientDisconnected, "Server should not disconnect the client for explicitly sending zero-length data");

                Trace.WriteLine("---");

                completionSource = new TaskCompletionSource <bool>(false);
            }

            Trace.WriteLine($"Test took {watcher.Elapsed}");
            Trace.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~");
        }