public async Task StopAsyncPreventsFurtherDataConsumption()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "2"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                // Add some input and consume it to ensure PumpAsync is running
                input.Add("a");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                await body.StopAsync();

                // Add some more data. Checking for cancelation and exiting the loop
                // should take priority over reading this data.
                input.Add("b");

                // There shouldn't be any additional data available
                Assert.Equal(0, await stream.ReadAsync(new byte[1], 0, 1));
            }
        }
        public async Task OnlyEnforcesRequestBodyTimeoutAfterSending100Continue()
        {
            using (var input = new TestInput())
            {
                var produceContinueCalled = false;
                var startTimingReadsCalledAfterProduceContinue = false;

                var mockHttpResponseControl = new Mock <IHttpResponseControl>();
                mockHttpResponseControl
                .Setup(httpResponseControl => httpResponseControl.ProduceContinue())
                .Callback(() => produceContinueCalled     = true);
                input.Http1Connection.HttpResponseControl = mockHttpResponseControl.Object;

                var minReadRate        = input.Http1Connection.MinRequestBodyDataRate;
                var mockTimeoutControl = new Mock <ITimeoutControl>();
                mockTimeoutControl
                .Setup(timeoutControl => timeoutControl.StartTimingReads(minReadRate))
                .Callback(() => startTimingReadsCalledAfterProduceContinue = produceContinueCalled);

                input.Http1ConnectionContext.TimeoutControl = mockTimeoutControl.Object;

                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "5"
                }, input.Http1Connection);

                // Add some input and read it to start PumpAsync
                var readTask = body.ReadAsync(new ArraySegment <byte>(new byte[1]));

                Assert.True(startTimingReadsCalledAfterProduceContinue);

                input.Add("a");
                await readTask;

                await body.StopAsync();
            }
        }
        public async Task CanReadAsyncFromRemainingData(HttpVersion httpVersion)
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(httpVersion, new HttpRequestHeaders {
                    HeaderConnection = "upgrade"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                input.Add("Hello");

                var buffer = new byte[1024];

                var count = await stream.ReadAsync(buffer, 0, buffer.Length);

                Assert.Equal(5, count);
                AssertASCII("Hello", new ArraySegment <byte>(buffer, 0, count));

                input.Fin();

                await body.StopAsync();
            }
        }
Esempio n. 4
0
        public async Task PumpAsyncDoesNotReturnAfterCancelingInput()
        {
            using (var input = new TestInput())
            {
                var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders {
                    HeaderContentLength = "2"
                }, input.Http1Connection);
                var stream = new HttpRequestStream(Mock.Of <IHttpBodyControlFeature>());
                stream.StartAcceptingReads(body);

                // Add some input and consume it to ensure PumpAsync is running
                input.Add("a");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                input.Transport.Input.CancelPendingRead();

                // Add more input and verify is read
                input.Add("b");
                Assert.Equal(1, await stream.ReadAsync(new byte[1], 0, 1));

                input.Http1Connection.RequestBodyPipe.Reader.Complete();
                await body.StopAsync();
            }
        }
Esempio n. 5
0
        public async Task CopyToAsyncDoesNotCopyBlocks()
        {
            var writeCount      = 0;
            var writeTcs        = new TaskCompletionSource <(byte[], int, int)>();
            var mockDestination = new Mock <Stream>()
            {
                CallBase = true
            };

            mockDestination
            .Setup(m => m.WriteAsync(It.IsAny <byte[]>(), It.IsAny <int>(), It.IsAny <int>(), CancellationToken.None))
            .Callback((byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
            {
                writeTcs.SetResult((buffer, offset, count));
                writeCount++;
            })
            .Returns(Task.CompletedTask);

            using (var memoryPool = KestrelMemoryPool.Create())
            {
                var options                = new PipeOptions(pool: memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
                var pair                   = DuplexPipe.CreateConnectionPair(options, options);
                var transport              = pair.Transport;
                var application            = pair.Application;
                var http1ConnectionContext = new Http1ConnectionContext
                {
                    ServiceContext     = new TestServiceContext(),
                    ConnectionFeatures = new FeatureCollection(),
                    Application        = application,
                    Transport          = transport,
                    MemoryPool         = memoryPool,
                    TimeoutControl     = Mock.Of <ITimeoutControl>()
                };
                var http1Connection = new Http1Connection(http1ConnectionContext)
                {
                    HasStartedConsumingRequestBody = true
                };

                var headers = new HttpRequestHeaders {
                    HeaderContentLength = "12"
                };
                var body = Http1MessageBody.For(HttpVersion.Http11, headers, http1Connection);

                var copyToAsyncTask = body.CopyToAsync(mockDestination.Object);

                var bytes  = Encoding.ASCII.GetBytes("Hello ");
                var buffer = http1Connection.RequestBodyPipe.Writer.GetMemory(2048);
                ArraySegment <byte> segment;
                Assert.True(MemoryMarshal.TryGetArray(buffer, out segment));
                Buffer.BlockCopy(bytes, 0, segment.Array, segment.Offset, bytes.Length);
                http1Connection.RequestBodyPipe.Writer.Advance(bytes.Length);
                await http1Connection.RequestBodyPipe.Writer.FlushAsync();

                // Verify the block passed to Stream.WriteAsync() is the same one incoming data was written into.
                Assert.Equal((segment.Array, segment.Offset, bytes.Length), await writeTcs.Task);

                // Verify the again when GetMemory returns the tail space of the same block.
                writeTcs = new TaskCompletionSource <(byte[], int, int)>();
                bytes    = Encoding.ASCII.GetBytes("World!");
                buffer   = http1Connection.RequestBodyPipe.Writer.GetMemory(2048);
                Assert.True(MemoryMarshal.TryGetArray(buffer, out segment));
                Buffer.BlockCopy(bytes, 0, segment.Array, segment.Offset, bytes.Length);
                http1Connection.RequestBodyPipe.Writer.Advance(bytes.Length);
                await http1Connection.RequestBodyPipe.Writer.FlushAsync();

                Assert.Equal((segment.Array, segment.Offset, bytes.Length), await writeTcs.Task);

                http1Connection.RequestBodyPipe.Writer.Complete();

                await copyToAsyncTask;

                Assert.Equal(2, writeCount);

                // Don't call body.StopAsync() because PumpAsync() was never called.
                http1Connection.RequestBodyPipe.Reader.Complete();
            }
        }