public async Task CopyToAsync_AutoFlushing(bool autoFlush, int expectedFlushes)
        {
            // Arrange
            const int SourceSize = (128 * 1024) - 3;

            var sourceBytes = Enumerable.Range(0, SourceSize).Select(i => (byte)(i % 256)).ToArray();
            var source      = new MemoryStream(sourceBytes);
            var destination = new MemoryStream();
            var flushCountingDestination = new FlushCountingStream(destination);

            var streamCopierMock = new Mock <IStreamCopier>();

            streamCopierMock
            .Setup(s => s.CopyAsync(source, It.IsAny <Stream>(), It.IsAny <CancellationToken>()))
            .Returns(async(Stream source_, Stream destination_, CancellationToken cancellation_) =>
            {
                await source_.CopyToAsync(destination_, cancellation_);
                return(StreamCopyResult.Success, null);
            });

            var sut = new StreamCopyHttpContent(source, streamCopierMock.Object, autoFlushHttpClientOutgoingStream: autoFlush, CancellationToken.None);

            // Act & Assert
            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            await sut.CopyToAsync(flushCountingDestination);

            Assert.True(sut.Started);
            Assert.True(sut.ConsumptionTask.IsCompleted);
            Assert.Equal(sourceBytes, destination.ToArray());
            Assert.Equal(expectedFlushes, flushCountingDestination.NumFlushes);
        }
        public async Task CopyToAsync_AsyncSequencing()
        {
            // Arrange
            var source           = new MemoryStream();
            var destination      = new MemoryStream();
            var streamCopierMock = new Mock <IStreamCopier>();
            var tcs = new TaskCompletionSource <(StreamCopyResult, Exception)>();

            streamCopierMock
            .Setup(s => s.CopyAsync(source, destination, It.IsAny <CancellationToken>()))
            .Returns(() => tcs.Task);

            var sut = new StreamCopyHttpContent(source, streamCopierMock.Object, autoFlushHttpClientOutgoingStream: false, CancellationToken.None);

            // Act & Assert
            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            var task = sut.CopyToAsync(destination);

            Assert.True(sut.Started);                      // This should happen synchronously
            Assert.False(sut.ConsumptionTask.IsCompleted); // This cannot happen until the tcs releases it

            tcs.TrySetResult((StreamCopyResult.Success, null));
            await task;

            Assert.True(sut.ConsumptionTask.IsCompleted);
        }
Пример #3
0
        public async Task CopyToAsync_AutoFlushing(bool autoFlush)
        {
            // Must be same as StreamCopier constant.
            const int DefaultBufferSize = 65536;
            const int SourceSize        = (128 * 1024) - 3;

            var expectedFlushes = 0;

            if (autoFlush)
            {
                // How many buffers is needed to send the source rounded up.
                expectedFlushes = (SourceSize - 1) / DefaultBufferSize + 1;
            }
            // Explicit flush after headers are sent.
            expectedFlushes++;

            var sourceBytes = Enumerable.Range(0, SourceSize).Select(i => (byte)(i % 256)).ToArray();
            var source      = new MemoryStream(sourceBytes);
            var destination = new MemoryStream();
            var flushCountingDestination = new FlushCountingStream(destination);

            var sut = new StreamCopyHttpContent(source, autoFlushHttpClientOutgoingStream: autoFlush, new Clock(), CancellationToken.None);

            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            await sut.CopyToAsync(flushCountingDestination);

            Assert.True(sut.Started);
            Assert.True(sut.ConsumptionTask.IsCompleted);
            Assert.Equal(sourceBytes, destination.ToArray());
            Assert.Equal(expectedFlushes, flushCountingDestination.NumFlushes);
        }
        public async Task CopyToAsync_InvokesStreamCopier()
        {
            // Arrange
            const int SourceSize = (128 * 1024) - 3;

            var sourceBytes = Enumerable.Range(0, SourceSize).Select(i => (byte)(i % 256)).ToArray();
            var source      = new MemoryStream(sourceBytes);
            var destination = new MemoryStream();

            var streamCopierMock = new Mock <IStreamCopier>();

            streamCopierMock
            .Setup(s => s.CopyAsync(source, destination, It.IsAny <CancellationToken>()))
            .Returns(async() =>
            {
                await source.CopyToAsync(destination);
                return(StreamCopyResult.Success, null);
            });

            var sut = new StreamCopyHttpContent(source, streamCopierMock.Object, autoFlushHttpClientOutgoingStream: false, CancellationToken.None);

            // Act & Assert
            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            await sut.CopyToAsync(destination);

            Assert.True(sut.Started);
            Assert.True(sut.ConsumptionTask.IsCompleted);
            Assert.Equal(sourceBytes, destination.ToArray());
        }
Пример #5
0
        public async Task CopyToAsync_AsyncSequencing()
        {
            // Arrange
            var source           = new MemoryStream();
            var destination      = new MemoryStream();
            var streamCopierMock = new Mock <IStreamCopier>();
            var tcs = new TaskCompletionSource <bool>();

            streamCopierMock
            .Setup(s => s.CopyAsync(source, destination, It.IsAny <CancellationToken>()))
            .Returns(async() =>
            {
                await tcs.Task;
            });

            var sut = new StreamCopyHttpContent(source, streamCopierMock.Object, CancellationToken.None);

            // Act & Assert
            sut.ConsumptionTask.IsCompleted.Should().BeFalse();
            sut.Started.Should().BeFalse();
            var task = sut.CopyToAsync(destination);

            sut.Started.Should().BeTrue();                      // This should happen synchronously
            sut.ConsumptionTask.IsCompleted.Should().BeFalse(); // This cannot happen until the tcs releases it

            tcs.TrySetResult(true);
            await task;

            sut.ConsumptionTask.IsCompleted.Should().BeTrue();
        }
Пример #6
0
        public async Task CopyToAsync_InvokesStreamCopier()
        {
            // Arrange
            const int SourceSize = (128 * 1024) - 3;

            var sourceBytes = Enumerable.Range(0, SourceSize).Select(i => (byte)(i % 256)).ToArray();
            var source      = new MemoryStream(sourceBytes);
            var destination = new MemoryStream();

            var streamCopierMock = new Mock <IStreamCopier>();

            streamCopierMock
            .Setup(s => s.CopyAsync(source, destination, It.IsAny <CancellationToken>()))
            .Returns(() => source.CopyToAsync(destination));

            var sut = new StreamCopyHttpContent(source, streamCopierMock.Object, CancellationToken.None);

            // Act & Assert
            sut.ConsumptionTask.IsCompleted.Should().BeFalse();
            sut.Started.Should().BeFalse();
            await sut.CopyToAsync(destination);

            sut.Started.Should().BeTrue();
            sut.ConsumptionTask.IsCompleted.Should().BeTrue();
            destination.ToArray().Should().BeEquivalentTo(sourceBytes);
        }
Пример #7
0
        public Task ReadAsStreamAsync_Throws()
        {
            var source      = new MemoryStream();
            var destination = new MemoryStream();
            var sut         = new StreamCopyHttpContent(source, autoFlushHttpClientOutgoingStream: false, new Clock(), CancellationToken.None);

            Func <Task> func = () => sut.ReadAsStreamAsync();

            return(Assert.ThrowsAsync <NotImplementedException>(func));
        }
        public Task ReadAsStreamAsync_Throws()
        {
            // Arrange
            var source      = new MemoryStream();
            var destination = new MemoryStream();
            var sut         = new StreamCopyHttpContent(source, new Mock <IStreamCopier>().Object, autoFlushHttpClientOutgoingStream: false, CancellationToken.None);

            // Act
            Func <Task> func = () => sut.ReadAsStreamAsync();

            // Assert
            return(Assert.ThrowsAsync <NotImplementedException>(func));
        }
Пример #9
0
        public async Task ReadAsStreamAsync_Throws()
        {
            // Arrange
            var source      = new MemoryStream();
            var destination = new MemoryStream();
            var sut         = new StreamCopyHttpContent(source, new Mock <IStreamCopier>().Object, CancellationToken.None);

            // Act
            Func <Task> func = () => sut.ReadAsStreamAsync();

            // Assert
            await func.Should().ThrowExactlyAsync <NotImplementedException>();
        }
Пример #10
0
        public void AllowDuplex_ReturnsTrue()
        {
            var source = new MemoryStream();
            var sut    = new StreamCopyHttpContent(source, autoFlushHttpClientOutgoingStream: false, new Clock(), CancellationToken.None);

            // This is an internal property that HttpClient and friends use internally and which must be true
            // to support duplex channels.This test helps detect regressions or changes in undocumented behavior
            // in .NET Core, and it passes as of .NET Core 3.1.
            var allowDuplexProperty = typeof(HttpContent).GetProperty("AllowDuplex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            Assert.NotNull(allowDuplexProperty);
            var allowDuplex = (bool)allowDuplexProperty.GetValue(sut);

            Assert.True(allowDuplex);
        }
Пример #11
0
        public async Task CopyToAsync_InvokesStreamCopier()
        {
            const int SourceSize = (128 * 1024) - 3;

            var sourceBytes = Enumerable.Range(0, SourceSize).Select(i => (byte)(i % 256)).ToArray();
            var source      = new MemoryStream(sourceBytes);
            var destination = new MemoryStream();

            var sut = new StreamCopyHttpContent(source, autoFlushHttpClientOutgoingStream: false, new Clock(), CancellationToken.None);

            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            await sut.CopyToAsync(destination);

            Assert.True(sut.Started);
            Assert.True(sut.ConsumptionTask.IsCompleted);
            Assert.Equal(sourceBytes, destination.ToArray());
        }
Пример #12
0
        public void AllowDuplex_ReturnsTrue()
        {
            // Arrange
            var source           = new MemoryStream();
            var streamCopierMock = new Mock <IStreamCopier>();
            var sut = new StreamCopyHttpContent(source, streamCopierMock.Object, CancellationToken.None);

            // Assert
            // This is an internal property that HttpClient and friends use internally and which must be true
            // to support duplex channels.This test helps detect regressions or changes in undocumented behavior
            // in .NET Core, and it passes as of .NET Core 3.1.
            var allowDuplexProperty = typeof(HttpContent).GetProperty("AllowDuplex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            allowDuplexProperty.Should().NotBeNull();
            var allowDuplex = (bool)allowDuplexProperty.GetValue(sut);

            allowDuplex.Should().BeTrue();
        }
Пример #13
0
        public async Task CopyToAsync_AutoFlushing(bool autoFlush, int expectedFlushes)
        {
            // Arrange
            const int SourceSize = (128 * 1024) - 3;

            var sourceBytes = Enumerable.Range(0, SourceSize).Select(i => (byte)(i % 256)).ToArray();
            var source      = new MemoryStream(sourceBytes);
            var destination = new MemoryStream();
            var flushCountingDestination = new FlushCountingStream(destination);

            var sut = new StreamCopyHttpContent(source, autoFlushHttpClientOutgoingStream: autoFlush, CancellationToken.None);

            // Act & Assert
            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            await sut.CopyToAsync(flushCountingDestination);

            Assert.True(sut.Started);
            Assert.True(sut.ConsumptionTask.IsCompleted);
            Assert.Equal(sourceBytes, destination.ToArray());
            Assert.Equal(expectedFlushes, flushCountingDestination.NumFlushes);
        }
Пример #14
0
        public async Task CopyToAsync_AsyncSequencing()
        {
            var tcs    = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
            var source = new Mock <Stream>();

            source.Setup(s => s.ReadAsync(It.IsAny <Memory <byte> >(), It.IsAny <CancellationToken>())).Returns(() => new ValueTask <int>(tcs.Task));
            var destination = new MemoryStream();

            var sut = new StreamCopyHttpContent(source.Object, autoFlushHttpClientOutgoingStream: false, new Clock(), CancellationToken.None);

            Assert.False(sut.ConsumptionTask.IsCompleted);
            Assert.False(sut.Started);
            var task = sut.CopyToAsync(destination);

            Assert.True(sut.Started);                      // This should happen synchronously
            Assert.False(sut.ConsumptionTask.IsCompleted); // This cannot happen until the tcs releases it

            tcs.TrySetResult(0);
            await task;

            Assert.True(sut.ConsumptionTask.IsCompleted);
        }