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); }
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)); } }
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); } }
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)); }