@ -10,18 +10,36 @@ namespace SixLabors.ImageSharp.Tests.IO
{
public class BufferedReadStreamTests
{
[Fact]
public void BufferedStreamCanReadSingleByteFromOrigin ( )
private readonly Configuration configuration ;
public BufferedReadStreamTests ( )
{
this . configuration = Configuration . CreateDefaultInstance ( ) ;
}
public static readonly TheoryData < int > BufferSizes =
new TheoryData < int > ( )
{
1 , 2 , 4 , 8 ,
1 6 , 9 7 , 5 0 3 ,
7 1 9 , 1 0 2 4 ,
8 0 9 6 , 6 4 7 6 8
} ;
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanReadSingleByteFromOrigin ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
byte [ ] expected = stream . ToArray ( ) ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
Assert . Equal ( expected [ 0 ] , reader . ReadByte ( ) ) ;
// We've read a whole chunk but increment by 1 in our reader.
Assert . Equal ( BufferedReadStream . BufferLength , stream . Position ) ;
Assert . True ( stream . Position > = bufferSize ) ;
Assert . Equal ( 1 , reader . Position ) ;
}
@ -30,21 +48,23 @@ namespace SixLabors.ImageSharp.Tests.IO
}
}
[Fact]
public void BufferedStreamCanReadSingleByteFromOffset ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanReadSingleByteFromOffset ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
byte [ ] expected = stream . ToArray ( ) ;
const int offset = 5 ;
using ( var reader = new BufferedReadStream ( stream ) )
int offset = expected . Length / 2 ;
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
reader . Position = offset ;
Assert . Equal ( expected [ offset ] , reader . ReadByte ( ) ) ;
// We've read a whole chunk but increment by 1 in our reader.
Assert . Equal ( BufferedReadStream . BufferLength + offset , stream . Position ) ;
Assert . Equal ( bufferSize + offset , stream . Position ) ;
Assert . Equal ( offset + 1 , reader . Position ) ;
}
@ -52,33 +72,35 @@ namespace SixLabors.ImageSharp.Tests.IO
}
}
[Fact]
public void BufferedStreamCanReadSubsequentSingleByteCorrectly ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanReadSubsequentSingleByteCorrectly ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
byte [ ] expected = stream . ToArray ( ) ;
int i ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
for ( i = 0 ; i < expected . Length ; i + + )
{
Assert . Equal ( expected [ i ] , reader . ReadByte ( ) ) ;
Assert . Equal ( i + 1 , reader . Position ) ;
if ( i < BufferedReadStream . BufferLength )
if ( i < bufferSize )
{
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength ) ;
Assert . Equal ( stream . Position , bufferSize ) ;
}
else if ( i > = BufferedReadStream . BufferLength & & i < BufferedReadStream . BufferLength * 2 )
else if ( i > = bufferSize & & i < bufferSize * 2 )
{
// We should have advanced to the second chunk now.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength * 2 ) ;
Assert . Equal ( stream . Position , bufferSize * 2 ) ;
}
else
{
// We should have advanced to the third chunk now.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength * 3 ) ;
Assert . Equal ( stream . Position , bufferSize * 3 ) ;
}
}
}
@ -87,109 +109,143 @@ namespace SixLabors.ImageSharp.Tests.IO
}
}
[Fact]
public void BufferedStreamCanReadMultipleBytesFromOrigin ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanReadMultipleBytesFromOrigin ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
var buffer = new byte [ 2 ] ;
byte [ ] expected = stream . ToArray ( ) ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
Assert . Equal ( 2 , reader . Read ( buffer , 0 , 2 ) ) ;
Assert . Equal ( expected [ 0 ] , buffer [ 0 ] ) ;
Assert . Equal ( expected [ 1 ] , buffer [ 1 ] ) ;
// We've read a whole chunk but increment by the buffer length in our reader.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength ) ;
Assert . True ( stream . Position > = bufferSize ) ;
Assert . Equal ( buffer . Length , reader . Position ) ;
}
}
}
[Fact]
public void BufferedStreamCanReadSubsequentMultipleByteCorrectly ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanReadSubsequentMultipleByteCorrectly ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
const int increment = 2 ;
var buffer = new byte [ 2 ] ;
byte [ ] expected = stream . ToArray ( ) ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
for ( int i = 0 , o = 0 ; i < expected . Length / 2 ; i + + , o + = 2 )
for ( int i = 0 , o = 0 ; i < expected . Length / increment ; i + + , o + = increment )
{
Assert . Equal ( 2 , reader . Read ( buffer , 0 , 2 ) ) ;
// Check values are correct.
Assert . Equal ( increment , reader . Read ( buffer , 0 , increment ) ) ;
Assert . Equal ( expected [ o ] , buffer [ 0 ] ) ;
Assert . Equal ( expected [ o + 1 ] , buffer [ 1 ] ) ;
Assert . Equal ( o + 2 , reader . Position ) ;
Assert . Equal ( o + increment , reader . Position ) ;
int offset = i * 2 ;
if ( offset < BufferedReadStream . BufferLength )
{
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength ) ;
}
else if ( offset > = BufferedReadStream . BufferLength & & offset < BufferedReadStream . BufferLength * 2 )
// These tests ensure that we are correctly reading
// our buffer in chunks of the given size.
int offset = i * increment ;
// First chunk.
if ( offset < bufferSize )
{
// We should have advanced to the second chunk now.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength * 2 ) ;
// We've read an entire chunk once and are
// now reading from that chunk.
Assert . True ( stream . Position > = bufferSize ) ;
continue ;
}
else
// Second chunk
if ( offset < bufferSize * 2 )
{
// We should have advanced to the third chunk now.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength * 3 ) ;
Assert . True ( stream . Position > bufferSize ) ;
// Odd buffer size with even increments can
// jump to the third chunk on final read.
Assert . True ( stream . Position < = bufferSize * 3 ) ;
continue ;
}
// Third chunk
Assert . True ( stream . Position > bufferSize * 2 ) ;
}
}
}
}
[Fact]
public void BufferedStreamCanReadSubsequentMultipleByteSpanCorrectly ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanReadSubsequentMultipleByteSpanCorrectly ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
const int increment = 2 ;
Span < byte > buffer = new byte [ 2 ] ;
byte [ ] expected = stream . ToArray ( ) ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
for ( int i = 0 , o = 0 ; i < expected . Length / 2 ; i + + , o + = 2 )
for ( int i = 0 , o = 0 ; i < expected . Length / increment ; i + + , o + = increment )
{
Assert . Equal ( 2 , reader . Read ( buffer , 0 , 2 ) ) ;
// Check values are correct.
Assert . Equal ( increment , reader . Read ( buffer , 0 , increment ) ) ;
Assert . Equal ( expected [ o ] , buffer [ 0 ] ) ;
Assert . Equal ( expected [ o + 1 ] , buffer [ 1 ] ) ;
Assert . Equal ( o + 2 , reader . Position ) ;
Assert . Equal ( o + increment , reader . Position ) ;
int offset = i * 2 ;
if ( offset < BufferedReadStream . BufferLength )
{
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength ) ;
}
else if ( offset > = BufferedReadStream . BufferLength & & offset < BufferedReadStream . BufferLength * 2 )
// These tests ensure that we are correctly reading
// our buffer in chunks of the given size.
int offset = i * increment ;
// First chunk.
if ( offset < bufferSize )
{
// We should have advanced to the second chunk now.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength * 2 ) ;
// We've read an entire chunk once and are
// now reading from that chunk.
Assert . True ( stream . Position > = bufferSize ) ;
continue ;
}
else
// Second chunk
if ( offset < bufferSize * 2 )
{
// We should have advanced to the third chunk now.
Assert . Equal ( stream . Position , BufferedReadStream . BufferLength * 3 ) ;
Assert . True ( stream . Position > bufferSize ) ;
// Odd buffer size with even increments can
// jump to the third chunk on final read.
Assert . True ( stream . Position < = bufferSize * 3 ) ;
continue ;
}
// Third chunk
Assert . True ( stream . Position > bufferSize * 2 ) ;
}
}
}
}
[Fact]
public void BufferedStreamCanSkip ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamCanSkip ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 4 ) )
{
byte [ ] expected = stream . ToArray ( ) ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
int skip = 5 0 ;
int skip = 1 ;
int plusOne = 1 ;
int skip2 = BufferedReadStream . BufferLength ;
int skip2 = bufferSize ;
// Skip
reader . Skip ( skip ) ;
@ -212,22 +268,25 @@ namespace SixLabors.ImageSharp.Tests.IO
}
}
[Fact]
public void BufferedStreamReadsSmallStream ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamReadsSmallStream ( int bufferSize )
{
this . configuration . StreamProcessingBufferSize = bufferSize ;
// Create a stream smaller than the default buffer length
using ( MemoryStream stream = this . CreateTestStream ( BufferedReadStream . BufferLength / 4 ) )
using ( MemoryStream stream = this . CreateTestStream ( Math . Max ( 1 , bufferSize / 4 ) ) )
{
byte [ ] expected = stream . ToArray ( ) ;
const int offset = 5 ;
using ( var reader = new BufferedReadStream ( stream ) )
int offset = expected . Length / 2 ;
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
reader . Position = offset ;
Assert . Equal ( expected [ offset ] , reader . ReadByte ( ) ) ;
// We've read a whole length of the stream but increment by 1 in our reader.
Assert . Equal ( BufferedReadStream . BufferLength / 4 , stream . Position ) ;
Assert . Equal ( Math . Max ( 1 , bufferSize / 4 ) , stream . Position ) ;
Assert . Equal ( offset + 1 , reader . Position ) ;
}
@ -235,13 +294,15 @@ namespace SixLabors.ImageSharp.Tests.IO
}
}
[Fact]
public void BufferedStreamReadsCanReadAllAsSingleByteFromOrigin ( )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamReadsCanReadAllAsSingleByteFromOrigin ( int bufferSize )
{
using ( MemoryStream stream = this . CreateTestStream ( ) )
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize * 3 ) )
{
byte [ ] expected = stream . ToArray ( ) ;
using ( var reader = new BufferedReadStream ( stream ) )
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
for ( int i = 0 ; i < expected . Length ; i + + )
{
@ -251,7 +312,22 @@ namespace SixLabors.ImageSharp.Tests.IO
}
}
private MemoryStream CreateTestStream ( int length = BufferedReadStream . BufferLength * 3 )
[Theory]
[MemberData(nameof(BufferSizes))]
public void BufferedStreamThrowsOnBadPosition ( int bufferSize )
{
this . configuration . StreamProcessingBufferSize = bufferSize ;
using ( MemoryStream stream = this . CreateTestStream ( bufferSize ) )
{
using ( var reader = new BufferedReadStream ( this . configuration , stream ) )
{
Assert . Throws < ArgumentOutOfRangeException > ( ( ) = > reader . Position = - stream . Length ) ;
Assert . Throws < ArgumentOutOfRangeException > ( ( ) = > reader . Position = stream . Length ) ;
}
}
}
private MemoryStream CreateTestStream ( int length )
{
var buffer = new byte [ length ] ;
var random = new Random ( ) ;