public async Task ServerShutsDownGracefullyWhenMaxRequestBufferSizeExceeded()
        {
            // Parameters
            var data = new byte[_dataLength];
            var bytesWrittenTimeout         = TimeSpan.FromMilliseconds(100);
            var bytesWrittenPollingInterval = TimeSpan.FromMilliseconds(bytesWrittenTimeout.TotalMilliseconds / 10);
            var maxSendSize = 4096;

            var startReadingRequestBody          = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var clientFinishedSendingRequestBody = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var lastBytesWritten = DateTime.MaxValue;

            var memoryPoolFactory = new DiagnosticMemoryPoolFactory(allowLateReturn: true);

            using (var host = await StartWebHost(16 * 1024, data, false, startReadingRequestBody, clientFinishedSendingRequestBody, memoryPoolFactory.Create))
            {
                var port = host.GetPort();
                using (var socket = CreateSocket(port))
                    using (var stream = new NetworkStream(socket))
                    {
                        await WritePostRequestHeaders(stream, data.Length);

                        var bytesWritten = 0;

                        Func <Task> sendFunc = async() =>
                        {
                            while (bytesWritten < data.Length)
                            {
                                var size = Math.Min(data.Length - bytesWritten, maxSendSize);
                                await stream.WriteAsync(data, bytesWritten, size).ConfigureAwait(false);

                                bytesWritten    += size;
                                lastBytesWritten = DateTime.Now;
                            }

                            clientFinishedSendingRequestBody.TrySetResult(null);
                        };

                        var ignore = sendFunc();

                        // The minimum is (maxRequestBufferSize - maxSendSize + 1), since if bytesWritten is
                        // (maxRequestBufferSize - maxSendSize) or smaller, the client should be able to
                        // complete another send.
                        var minimumExpectedBytesWritten = (16 * 1024) - maxSendSize + 1;

                        // The maximum is harder to determine, since there can be OS-level buffers in both the client
                        // and server, which allow the client to send more than maxRequestBufferSize before getting
                        // paused.  We assume the combined buffers are smaller than the difference between
                        // data.Length and maxRequestBufferSize.
                        var maximumExpectedBytesWritten = data.Length - 1;

                        // Block until the send task has gone a while without writing bytes AND
                        // the bytes written exceeds the minimum expected.  This indicates the server buffer
                        // is full.
                        //
                        // If the send task is paused before the expected number of bytes have been
                        // written, keep waiting since the pause may have been caused by something else
                        // like a slow machine.
                        while ((DateTime.Now - lastBytesWritten) < bytesWrittenTimeout ||
                               bytesWritten < minimumExpectedBytesWritten)
                        {
                            await Task.Delay(bytesWrittenPollingInterval);
                        }

                        // Verify the number of bytes written before the client was paused.
                        Assert.InRange(bytesWritten, minimumExpectedBytesWritten, maximumExpectedBytesWritten);

                        // Dispose host prior to closing connection to verify the server doesn't throw during shutdown
                        // if a connection no longer has alloc and read callbacks configured.
                        await host.StopAsync();

                        host.Dispose();
                    }
            }
            // Allow appfunc to unblock
            startReadingRequestBody.SetResult(null);
            clientFinishedSendingRequestBody.SetResult(null);
            await memoryPoolFactory.WhenAllBlocksReturned(TestConstants.DefaultTimeout);
        }
        public async Task LargeUpload(long?maxRequestBufferSize, bool connectionAdapter, bool expectPause)
        {
            // Parameters
            var data = new byte[_dataLength];
            var bytesWrittenTimeout         = TimeSpan.FromMilliseconds(100);
            var bytesWrittenPollingInterval = TimeSpan.FromMilliseconds(bytesWrittenTimeout.TotalMilliseconds / 10);
            var maxSendSize = 4096;

            var startReadingRequestBody          = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var clientFinishedSendingRequestBody = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var lastBytesWritten = DateTime.MaxValue;

            var memoryPoolFactory = new DiagnosticMemoryPoolFactory(allowLateReturn: true);

            using (var host = await StartWebHost(maxRequestBufferSize, data, connectionAdapter, startReadingRequestBody, clientFinishedSendingRequestBody, memoryPoolFactory.Create))
            {
                var port = host.GetPort();
                using (var socket = CreateSocket(port))
                    using (var stream = new NetworkStream(socket))
                    {
                        await WritePostRequestHeaders(stream, data.Length);

                        var bytesWritten = 0;

                        Func <Task> sendFunc = async() =>
                        {
                            while (bytesWritten < data.Length)
                            {
                                var size = Math.Min(data.Length - bytesWritten, maxSendSize);
                                await stream.WriteAsync(data, bytesWritten, size).ConfigureAwait(false);

                                bytesWritten    += size;
                                lastBytesWritten = DateTime.Now;
                            }

                            Assert.Equal(data.Length, bytesWritten);
                            clientFinishedSendingRequestBody.TrySetResult(null);
                        };

                        var sendTask = sendFunc();

                        if (expectPause)
                        {
                            // The minimum is (maxRequestBufferSize - maxSendSize + 1), since if bytesWritten is
                            // (maxRequestBufferSize - maxSendSize) or smaller, the client should be able to
                            // complete another send.
                            var minimumExpectedBytesWritten = maxRequestBufferSize.Value - maxSendSize + 1;

                            // The maximum is harder to determine, since there can be OS-level buffers in both the client
                            // and server, which allow the client to send more than maxRequestBufferSize before getting
                            // paused.  We assume the combined buffers are smaller than the difference between
                            // data.Length and maxRequestBufferSize.
                            var maximumExpectedBytesWritten = data.Length - 1;

                            // Block until the send task has gone a while without writing bytes AND
                            // the bytes written exceeds the minimum expected.  This indicates the server buffer
                            // is full.
                            //
                            // If the send task is paused before the expected number of bytes have been
                            // written, keep waiting since the pause may have been caused by something else
                            // like a slow machine.
                            while ((DateTime.Now - lastBytesWritten) < bytesWrittenTimeout ||
                                   bytesWritten < minimumExpectedBytesWritten)
                            {
                                await Task.Delay(bytesWrittenPollingInterval);
                            }

                            // Verify the number of bytes written before the client was paused.
                            Assert.InRange(bytesWritten, minimumExpectedBytesWritten, maximumExpectedBytesWritten);

                            // Tell server to start reading request body
                            startReadingRequestBody.TrySetResult(null);

                            // Wait for sendTask to finish sending the remaining bytes
                            await sendTask;
                        }
                        else
                        {
                            // Ensure all bytes can be sent before the server starts reading
                            await sendTask;

                            // Tell server to start reading request body
                            startReadingRequestBody.TrySetResult(null);
                        }

                        await AssertStreamContains(stream, $"bytesRead: {data.Length}");
                    }
                await host.StopAsync();
            }

            await memoryPoolFactory.WhenAllBlocksReturned(TestConstants.DefaultTimeout);
        }