public async Task ReadAsync_ReadsEffectiveLengthBytes(
            int from,
            int to,
            int innerLength,
            int effectiveLength
            )
        {
            // Arrange
            var mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            var range  = new RangeItemHeaderValue(from, to);
            var data   = new byte[25];
            var offset = 5;

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act
                await rangeStream.ReadAsync(data, offset, data.Length);

                // Assert
                mockInnerStream.Verify(
                    s => s.ReadAsync(data, offset, effectiveLength, CancellationToken.None),
                    Times.Once()
                    );
                Assert.Equal(effectiveLength, rangeStream.Position);
            }
        }
        public async Task CopyToAsync_ReadsSpecifiedRange(long?from, long?to, string expectedText)
        {
            // Arrange
            var originalText = "This is the whole text.";
            var range        = new RangeItemHeaderValue(from, to);

            using (var innerStream = new MemoryStream())
                using (var writer = new StreamWriter(innerStream))
                    using (var targetStream = new MemoryStream())
                        using (var reader = new StreamReader(targetStream))
                        {
                            await writer.WriteAsync(originalText);

                            await writer.FlushAsync();

                            // Act
                            using (var rangeStream = new ByteRangeStream(innerStream, range))
                            {
                                await rangeStream.CopyToAsync(targetStream);
                            }

                            // Assert
                            targetStream.Position = 0L;
                            var text = await reader.ReadToEndAsync();

                            Assert.Equal(expectedText, text);
                        }
        }
        public void ReadByte_ReadsEffectiveLengthTimes(
            int from,
            int to,
            int innerLength,
            int effectiveLength
            )
        {
            // Arrange
            var mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            var range   = new RangeItemHeaderValue(from, to);
            var counter = 0;

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act
                while (rangeStream.ReadByte() != -1)
                {
                    counter++;
                }

                // Assert
                mockInnerStream.Verify(s => s.ReadByte(), Times.Exactly(effectiveLength));
                Assert.Equal(effectiveLength, counter);
                Assert.Equal(effectiveLength, rangeStream.Position);
            }
        }
        public async Task ReadByte_CanReadAfterLength()
        {
            // Arrange
            var originalText = "This is the whole text.";
            var range        = new RangeItemHeaderValue(0L, null);

            using (var innerStream = new MemoryStream())
                using (var writer = new StreamWriter(innerStream))
                {
                    await writer.WriteAsync(originalText);

                    await writer.FlushAsync();

                    using (var rangeStream = new ByteRangeStream(innerStream, range))
                    {
                        rangeStream.Position = 50L;

                        // Act
                        var read = rangeStream.ReadByte();

                        // Assert
                        Assert.Equal(-1, read);
                    }
                }
        }
        public void BeginRead_ReadsEffectiveLengthBytes(
            int from,
            int to,
            int innerLength,
            int effectiveLength
            )
        {
            // Arrange
            var mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            var range     = new RangeItemHeaderValue(from, to);
            var data      = new byte[25];
            var offset    = 5;
            var callback  = new AsyncCallback(_ => { });
            var userState = new object();

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act
                var result = rangeStream.BeginRead(data, offset, data.Length, callback, userState);
                rangeStream.EndRead(result);

                // Assert
                mockInnerStream.Verify(
                    s => s.BeginRead(data, offset, effectiveLength, callback, userState),
                    Times.Once()
                    );
                Assert.Equal(effectiveLength, rangeStream.Position);
            }
        }
        public async Task BeginRead_CanReadAfterLength()
        {
            // Arrange
            var originalText = "This is the whole text.";
            var range        = new RangeItemHeaderValue(0L, null);
            var data         = new byte[25];
            var callback     = new AsyncCallback(_ => { });
            var userState    = new object();

            using (var innerStream = new MemoryStream())
                using (var writer = new StreamWriter(innerStream))
                {
                    await writer.WriteAsync(originalText);

                    await writer.FlushAsync();

                    using (var rangeStream = new ByteRangeStream(innerStream, range))
                    {
                        rangeStream.Position = 50L;

                        // Act
                        var result = rangeStream.BeginRead(data, 0, data.Length, callback, userState);
                        var read   = rangeStream.EndRead(result);

                        // Assert
                        Assert.Equal(0, read);
                    }
                }
        }
        public void Position_ThrowsOnNegativeValue()
        {
            // Arrange
            var mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(10L);
            var range = new RangeItemHeaderValue(0, 25L);

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act & Assert
                Assert.Throws <ArgumentOutOfRangeException>(() => rangeStream.Position = -1L);
            }
        }
        public void Ctor_SetsContentRange()
        {
            // Arrange
            ContentRangeHeaderValue expectedContentRange = new ContentRangeHeaderValue(5, 9, 20);
            Mock<Stream> mockInnerStream = new Mock<Stream>();
            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(20);
            RangeItemHeaderValue range = new RangeItemHeaderValue(5, 9);

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);

            // Assert
            Assert.Equal(expectedContentRange, rangeStream.ContentRange);
        }
Beispiel #9
0
        public void Ctor_SetsLength(int from, int to, int innerLength, int expectedLength)
        {
            // Arrange
            Mock <Stream> mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            RangeItemHeaderValue range = new RangeItemHeaderValue(from, to);

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);

            // Assert
            Assert.Equal(expectedLength, rangeStream.Length);
        }
        public void Seek_ThrowsIfBeforeOrigin(int offset, SeekOrigin origin)
        {
            // Arrange
            var mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(10L);
            var range = new RangeItemHeaderValue(0, 25L);

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act & Assert
                Assert.Throws <IOException>(() => rangeStream.Seek(offset, origin));
            }
        }
Beispiel #11
0
        public void Ctor_SetsContentRange()
        {
            // Arrange
            ContentRangeHeaderValue expectedContentRange = new ContentRangeHeaderValue(5, 9, 20);
            Mock <Stream>           mockInnerStream      = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(20);
            RangeItemHeaderValue range = new RangeItemHeaderValue(5, 9);

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);

            // Assert
            Assert.Equal(expectedContentRange, rangeStream.ContentRange);
        }
        public void Position_ReturnsZeroInitially(long?from)
        {
            // Arrange
            var mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(10L);
            var range = new RangeItemHeaderValue(from, 25L);

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act
                var position = rangeStream.Position;

                // Assert
                Assert.Equal(0L, position);
            }
        }
        public void Position_CanBeSetAfterLength()
        {
            // Arrange
            var expectedPosition = 300L;
            var mockInnerStream  = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(10L);
            var range = new RangeItemHeaderValue(0L, 10L);

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act
                rangeStream.Position = expectedPosition;

                // Assert
                Assert.Equal(expectedPosition, rangeStream.Position);
            }
        }
Beispiel #14
0
        public void Read_ReadsEffectiveLengthBytes(int from, int to, int innerLength, int effectiveLength)
        {
            // Arrange
            Mock <Stream> mockInnerStream = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            RangeItemHeaderValue range = new RangeItemHeaderValue(from, to);

            byte[] data   = new byte[25];
            int    offset = 5;

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);

            rangeStream.Read(data, offset, data.Length);

            // Assert
            mockInnerStream.Verify(s => s.Read(data, offset, effectiveLength), Times.Once());
        }
        public void Seek_CanMoveAfterLength(int offset, SeekOrigin origin)
        {
            // Arrange
            var expectedPosition = 25L;
            var mockInnerStream  = new Mock <Stream>();

            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(10L);
            var range = new RangeItemHeaderValue(0L, 10L);

            using (var rangeStream = new ByteRangeStream(mockInnerStream.Object, range))
            {
                // Act
                var newPosition = rangeStream.Seek(offset, origin);

                // Assert
                Assert.Equal(expectedPosition, newPosition);
                Assert.Equal(expectedPosition, rangeStream.Position);
            }
        }
        public async Task Seek_PositionsNextRead(int offset, SeekOrigin origin)
        {
            // Arrange
            var originalText = "890123456789";
            var range        = new RangeItemHeaderValue(2L, null);

            using (var innerStream = new MemoryStream())
                using (var writer = new StreamWriter(innerStream))
                {
                    await writer.WriteAsync(originalText);

                    await writer.FlushAsync();

                    using (var rangeStream = new ByteRangeStream(innerStream, range))
                    {
                        // Act
                        rangeStream.Seek(offset, origin);

                        // Assert
                        var read = rangeStream.ReadByte();
                        Assert.Equal('5', (char)read);
                    }
                }
        }
        public void Read_ReadsEffectiveLengthBytes(int from, int to, int innerLength, int effectiveLength)
        {
            // Arrange
            Mock<Stream> mockInnerStream = new Mock<Stream>();
            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            RangeItemHeaderValue range = new RangeItemHeaderValue(from, to);
            byte[] data = new byte[25];
            int offset = 5;

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);
            rangeStream.Read(data, offset, data.Length);

            // Assert
            mockInnerStream.Verify(s => s.Read(data, offset, effectiveLength), Times.Once());
        }
        public void Ctor_SetsLength(int from, int to, int innerLength, int expectedLength)
        {
            // Arrange
            Mock<Stream> mockInnerStream = new Mock<Stream>();
            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            RangeItemHeaderValue range = new RangeItemHeaderValue(from, to);

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);

            // Assert
            Assert.Equal(expectedLength, rangeStream.Length);
        }
        /// <summary>
        /// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
        /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
        /// of the selected resource represented by the <paramref name="content"/> parameter then an 
        /// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
        /// </summary>
        /// <param name="content">The stream over which to generate a byte range view.</param>
        /// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
        /// <param name="mediaType">The media type of the content stream.</param>
        /// <param name="bufferSize">The buffer size used when copying the content stream.</param>
        public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType, int bufferSize)
        {
            if (content == null)
            {
                throw Error.ArgumentNull("content");
            }
            if (!content.CanSeek)
            {
                throw Error.Argument("content", Properties.Resources.ByteRangeStreamNotSeekable, typeof(ByteRangeStreamContent).Name);
            }
            if (range == null)
            {
                throw Error.ArgumentNull("range");
            }
            if (mediaType == null)
            {
                throw Error.ArgumentNull("mediaType");
            }
            if (bufferSize < MinBufferSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, MinBufferSize);
            }
            if (!range.Unit.Equals(SupportedRangeUnit, StringComparison.OrdinalIgnoreCase))
            {
                throw Error.Argument("range", Properties.Resources.ByteRangeStreamContentNotBytesRange, range.Unit, SupportedRangeUnit);
            }

            try
            {
                // If we have more than one range then we use a multipart/byteranges content type as wrapper.
                // Otherwise we use a non-multipart response.
                if (range.Ranges.Count > 1)
                {
                    // Create Multipart content and copy headers to this content
                    MultipartContent rangeContent = new MultipartContent(ByteRangesContentSubtype);
                    _byteRangeContent = rangeContent;

                    foreach (RangeItemHeaderValue rangeValue in range.Ranges)
                    {
                        try
                        {
                            ByteRangeStream rangeStream = new ByteRangeStream(content, rangeValue);
                            HttpContent rangeBodyPart = new StreamContent(rangeStream, bufferSize);
                            rangeBodyPart.Headers.ContentType = mediaType;
                            rangeBodyPart.Headers.ContentRange = rangeStream.ContentRange;
                            rangeContent.Add(rangeBodyPart);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            // We ignore range errors until we check that we have at least one valid range
                        }
                    }

                    // If no overlapping ranges were found then stop
                    if (!rangeContent.Any())
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = Error.Format(Properties.Resources.ByteRangeStreamNoneOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else if (range.Ranges.Count == 1)
                {
                    try
                    {
                        ByteRangeStream rangeStream = new ByteRangeStream(content, range.Ranges.First());
                        _byteRangeContent = new StreamContent(rangeStream, bufferSize);
                        _byteRangeContent.Headers.ContentType = mediaType;
                        _byteRangeContent.Headers.ContentRange = rangeStream.ContentRange;
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = Error.Format(Properties.Resources.ByteRangeStreamNoOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else
                {
                    throw Error.Argument("range", Properties.Resources.ByteRangeStreamContentNoRanges);
                }

                // Copy headers from byte range content so that we get the right content type etc.
                _byteRangeContent.Headers.CopyTo(Headers);

                _content = content;
                _start = content.Position;
            }
            catch
            {
                if (_byteRangeContent != null)
                {
                    _byteRangeContent.Dispose();
                }
                throw;
            }
        }
        public void ReadByte_ReadsEffectiveLengthTimes(int from, int to, int innerLength, int effectiveLength)
        {
            // Arrange
            Mock<Stream> mockInnerStream = new Mock<Stream>();
            mockInnerStream.Setup(s => s.CanSeek).Returns(true);
            mockInnerStream.Setup(s => s.Length).Returns(innerLength);
            RangeItemHeaderValue range = new RangeItemHeaderValue(from, to);

            // Act
            ByteRangeStream rangeStream = new ByteRangeStream(mockInnerStream.Object, range);
            int counter = 0;
            while (rangeStream.ReadByte() != -1)
            {
                counter++;
            }

            // Assert
            Assert.Equal(effectiveLength, counter);
            mockInnerStream.Verify(s => s.ReadByte(), Times.Exactly(effectiveLength));
        }