2024-03-14 08:53:08 +00:00
using System ;
2024-01-04 21:16:07 +01:00
using System.Collections.Generic ;
2022-06-19 22:05:52 +02:00
using System.IO ;
2026-01-03 19:09:43 +01:00
using System.Linq ;
2025-10-27 10:52:03 +00:00
using System.Threading ;
using System.Threading.Tasks ;
2026-01-16 15:10:08 +00:00
using AwesomeAssertions ;
2015-12-30 11:19:42 +00:00
using SharpCompress.Common ;
2026-01-16 15:10:08 +00:00
using SharpCompress.Factories ;
2018-04-22 11:19:11 +01:00
using SharpCompress.IO ;
2016-09-26 11:49:49 +01:00
using SharpCompress.Readers ;
2018-07-10 10:15:21 -07:00
using SharpCompress.Test.Mocks ;
2015-12-30 11:19:42 +00:00
using Xunit ;
2022-12-20 15:06:44 +00:00
namespace SharpCompress.Test ;
public abstract class ReaderTests : TestBase
2015-12-30 11:19:42 +00:00
{
2026-02-10 16:15:31 +00:00
protected void Read ( string testArchive , ReaderOptions ? options = null ) = >
2025-10-31 14:33:14 +01:00
ReadCore ( testArchive , options , ReadImpl ) ;
2022-12-20 15:06:44 +00:00
protected void Read (
string testArchive ,
CompressionType expectedCompression ,
ReaderOptions ? options = null
2026-02-10 16:15:31 +00:00
) = > ReadCore ( testArchive , options , ( path , opts ) = > ReadImpl ( path , expectedCompression , opts ) ) ;
2015-12-30 11:19:42 +00:00
2025-10-31 14:33:14 +01:00
private void ReadCore (
string testArchive ,
ReaderOptions ? options ,
Action < string , ReaderOptions > readImpl
)
{
testArchive = Path . Combine ( TEST_ARCHIVES_PATH , testArchive ) ;
options ? ? = new ReaderOptions { BufferSize = 0x20000 } ;
2018-07-11 18:37:49 -07:00
2026-02-06 15:16:45 +00:00
var optionsWithStreamOpen = options with { LeaveStreamOpen = true } ;
readImpl ( testArchive , optionsWithStreamOpen ) ;
2018-07-11 18:37:49 -07:00
2026-02-06 15:16:45 +00:00
var optionsWithStreamClosed = options with { LeaveStreamOpen = false } ;
readImpl ( testArchive , optionsWithStreamClosed ) ;
2025-10-31 14:33:14 +01:00
2022-12-20 15:06:44 +00:00
VerifyFiles ( ) ;
}
2018-07-11 15:34:57 -07:00
2026-02-10 16:15:31 +00:00
private void ReadImpl ( string testArchive , ReaderOptions options ) = >
2025-10-31 14:33:14 +01:00
ReadImplCore ( testArchive , options , UseReader ) ;
2022-12-20 15:06:44 +00:00
private void ReadImpl (
string testArchive ,
CompressionType expectedCompression ,
ReaderOptions options
2026-02-10 16:15:31 +00:00
) = > ReadImplCore ( testArchive , options , r = > UseReader ( r , expectedCompression ) ) ;
2025-10-31 14:33:14 +01:00
private void ReadImplCore ( string testArchive , ReaderOptions options , Action < IReader > useReader )
2022-12-20 15:06:44 +00:00
{
using var file = File . OpenRead ( testArchive ) ;
2026-02-04 14:12:04 +00:00
using var protectedStream = SharpCompressStream . CreateNonDisposing (
2026-01-31 15:29:34 +00:00
new ForwardOnlyStream ( file , options . BufferSize )
2022-12-20 15:14:22 +00:00
) ;
2022-12-20 15:06:44 +00:00
using var testStream = new TestStream ( protectedStream ) ;
2026-01-15 11:41:30 +00:00
using ( var reader = ReaderFactory . OpenReader ( testStream , options ) )
2018-07-11 15:34:57 -07:00
{
2025-10-31 14:33:14 +01:00
useReader ( reader ) ;
2025-08-01 21:47:09 +01:00
Assert . False ( testStream . IsDisposed , $"{nameof(testStream)} prematurely closed" ) ;
2015-12-30 11:19:42 +00:00
}
2022-12-20 15:06:44 +00:00
var message =
$"{nameof(options.LeaveStreamOpen)} is set to '{options.LeaveStreamOpen}', so {nameof(testStream.IsDisposed)} should be set to '{!testStream.IsDisposed}', but is set to {testStream.IsDisposed}" ;
Assert . True ( options . LeaveStreamOpen ! = testStream . IsDisposed , message ) ;
}
2025-10-31 14:33:14 +01:00
protected void UseReader ( IReader reader , CompressionType expectedCompression )
2022-12-20 15:06:44 +00:00
{
while ( reader . MoveToNextEntry ( ) )
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
if ( ! reader . Entry . IsDirectory )
2015-12-30 11:19:42 +00:00
{
2022-12-20 15:06:44 +00:00
Assert . Equal ( expectedCompression , reader . Entry . CompressionType ) ;
2026-02-09 16:52:54 +00:00
reader . WriteEntryToDirectory ( SCRATCH_FILES_PATH ) ;
2015-12-30 11:19:42 +00:00
}
}
}
2024-01-04 21:16:07 +01:00
2025-10-31 14:33:14 +01:00
private void UseReader ( IReader reader )
{
while ( reader . MoveToNextEntry ( ) )
{
if ( ! reader . Entry . IsDirectory )
{
2026-02-09 16:52:54 +00:00
reader . WriteEntryToDirectory ( SCRATCH_FILES_PATH ) ;
2025-10-31 14:33:14 +01:00
}
}
}
2026-02-10 16:15:31 +00:00
protected async Task AssertArchiveAsync (
2026-01-16 15:10:08 +00:00
string testArchive ,
CancellationToken cancellationToken = default
)
{
testArchive = Path . Combine ( TEST_ARCHIVES_PATH , testArchive ) ;
2026-01-17 13:39:57 +00:00
var factory = new TarFactory ( ) ;
2026-02-10 16:15:31 +00:00
(
await factory . IsArchiveAsync (
new FileInfo ( testArchive ) . OpenRead ( ) ,
null ,
cancellationToken
)
)
. Should ( )
. BeTrue ( ) ;
2026-01-17 13:39:57 +00:00
(
await factory . IsArchiveAsync (
new FileInfo ( testArchive ) . OpenRead ( ) ,
cancellationToken : cancellationToken
)
)
. Should ( )
. BeTrue ( ) ;
2026-01-16 15:10:08 +00:00
}
2025-10-27 10:52:03 +00:00
protected async Task ReadAsync (
string testArchive ,
2025-11-25 14:44:03 +00:00
CompressionType ? expectedCompression = null ,
2025-10-27 10:52:03 +00:00
ReaderOptions ? options = null ,
CancellationToken cancellationToken = default
)
{
testArchive = Path . Combine ( TEST_ARCHIVES_PATH , testArchive ) ;
options ? ? = new ReaderOptions ( ) { BufferSize = 0x20000 } ;
2026-02-06 15:16:45 +00:00
var optionsWithStreamOpen = options with { LeaveStreamOpen = true } ;
await ReadImplAsync (
testArchive ,
expectedCompression ,
optionsWithStreamOpen ,
cancellationToken
) ;
2025-10-27 10:52:03 +00:00
2026-02-06 15:16:45 +00:00
var optionsWithStreamClosed = options with { LeaveStreamOpen = false } ;
await ReadImplAsync (
testArchive ,
expectedCompression ,
optionsWithStreamClosed ,
cancellationToken
) ;
2026-01-21 16:57:25 +00:00
2025-10-27 10:52:03 +00:00
VerifyFiles ( ) ;
}
2026-01-08 12:35:12 +00:00
private async ValueTask ReadImplAsync (
2025-10-27 10:52:03 +00:00
string testArchive ,
2025-11-25 14:44:03 +00:00
CompressionType ? expectedCompression ,
2025-10-27 10:52:03 +00:00
ReaderOptions options ,
CancellationToken cancellationToken = default
)
{
using var file = File . OpenRead ( testArchive ) ;
2026-01-20 12:22:38 +00:00
2026-01-22 15:12:18 +00:00
#if ! LEGACY_DOTNET
2026-02-04 14:12:04 +00:00
await using var protectedStream = SharpCompressStream . CreateNonDisposing (
2026-01-29 09:08:40 +00:00
new ForwardOnlyStream ( file , options . BufferSize )
2025-10-27 10:52:03 +00:00
) ;
2026-01-20 12:22:38 +00:00
await using var testStream = new TestStream ( protectedStream ) ;
#else
2026-02-04 14:12:04 +00:00
using var protectedStream = SharpCompressStream . CreateNonDisposing (
2026-01-31 15:29:34 +00:00
new ForwardOnlyStream ( file , options . BufferSize )
2026-01-20 12:22:38 +00:00
) ;
2026-01-20 13:40:51 +00:00
using var testStream = new TestStream ( protectedStream ) ;
#endif
2026-01-08 11:28:15 +00:00
await using (
2026-01-16 09:12:54 +00:00
var reader = await ReaderFactory . OpenAsyncReader (
2026-01-08 11:28:15 +00:00
new AsyncOnlyStream ( testStream ) ,
2026-02-10 16:15:31 +00:00
options ,
cancellationToken
2026-01-08 11:28:15 +00:00
)
)
2025-10-27 10:52:03 +00:00
{
await UseReaderAsync ( reader , expectedCompression , cancellationToken ) ;
Assert . False ( testStream . IsDisposed , $"{nameof(testStream)} prematurely closed" ) ;
}
var message =
$"{nameof(options.LeaveStreamOpen)} is set to '{options.LeaveStreamOpen}', so {nameof(testStream.IsDisposed)} should be set to '{!testStream.IsDisposed}', but is set to {testStream.IsDisposed}" ;
Assert . True ( options . LeaveStreamOpen ! = testStream . IsDisposed , message ) ;
}
2026-01-08 12:35:12 +00:00
public async ValueTask UseReaderAsync (
2026-01-08 12:02:26 +00:00
IAsyncReader reader ,
2025-11-25 14:44:03 +00:00
CompressionType ? expectedCompression ,
2025-10-27 10:52:03 +00:00
CancellationToken cancellationToken = default
)
{
2025-10-27 12:34:24 +00:00
while ( await reader . MoveToNextEntryAsync ( cancellationToken ) )
2025-10-27 10:52:03 +00:00
{
if ( ! reader . Entry . IsDirectory )
{
2025-11-25 14:44:03 +00:00
if ( expectedCompression . HasValue )
{
Assert . Equal ( expectedCompression , reader . Entry . CompressionType ) ;
}
2026-02-09 16:52:54 +00:00
await reader . WriteEntryToDirectoryAsync ( SCRATCH_FILES_PATH , cancellationToken ) ;
2025-10-27 10:52:03 +00:00
}
}
}
2025-11-20 19:43:07 +01:00
protected void ReadForBufferBoundaryCheck ( string fileName , CompressionType compressionType )
{
using var stream = File . OpenRead ( Path . Combine ( TEST_ARCHIVES_PATH , fileName ) ) ;
2026-01-15 12:06:54 +00:00
using var reader = ReaderFactory . OpenReader (
stream ,
new ReaderOptions { LookForHeader = true }
) ;
2025-11-20 19:43:07 +01:00
while ( reader . MoveToNextEntry ( ) )
{
Assert . Equal ( compressionType , reader . Entry . CompressionType ) ;
2026-02-09 16:52:54 +00:00
reader . WriteEntryToDirectory ( SCRATCH_FILES_PATH ) ;
2025-11-20 19:43:07 +01:00
}
CompareFilesByPath (
2025-11-22 12:32:25 +01:00
Path . Combine ( SCRATCH_FILES_PATH , "alice29.txt" ) ,
Path . Combine ( MISC_TEST_FILES_PATH , "alice29.txt" )
2025-11-20 19:43:07 +01:00
) ;
}
2024-01-04 21:16:07 +01:00
protected void Iterate (
string testArchive ,
string fileOrder ,
CompressionType expectedCompression ,
ReaderOptions ? options = null
)
{
2024-04-23 08:52:10 +01:00
if ( ! Environment . OSVersion . IsWindows ( ) )
2024-01-05 00:35:24 +01:00
{
fileOrder = fileOrder . Replace ( '\\' , '/' ) ;
}
2024-01-04 21:16:07 +01:00
var expected = new Stack < string > ( fileOrder . Split ( ' ' ) ) ;
testArchive = Path . Combine ( TEST_ARCHIVES_PATH , testArchive ) ;
using var file = File . OpenRead ( testArchive ) ;
using var forward = new ForwardOnlyStream ( file ) ;
2026-01-15 11:41:30 +00:00
using var reader = ReaderFactory . OpenReader ( forward , options ) ;
2024-03-14 08:37:17 +00:00
while ( reader . MoveToNextEntry ( ) )
2024-01-04 21:16:07 +01:00
{
2024-03-14 08:37:17 +00:00
Assert . Equal ( expectedCompression , reader . Entry . CompressionType ) ;
Assert . Equal ( expected . Pop ( ) , reader . Entry . Key ) ;
2024-01-04 21:16:07 +01:00
}
}
2026-01-03 19:09:43 +01:00
protected void DoMultiReader (
string [ ] archives ,
2026-01-16 10:49:18 +00:00
Func < IEnumerable < Stream > , IReader > readerFactory
2026-01-03 19:09:43 +01:00
)
{
using var reader = readerFactory (
archives . Select ( s = > Path . Combine ( TEST_ARCHIVES_PATH , s ) ) . Select ( File . OpenRead )
) ;
2026-01-16 10:49:18 +00:00
while ( reader . MoveToNextEntry ( ) )
2026-01-03 19:09:43 +01:00
{
2026-02-09 16:52:54 +00:00
reader . WriteEntryToDirectory ( SCRATCH_FILES_PATH ) ;
2026-01-03 19:09:43 +01:00
}
VerifyFiles ( ) ;
}
2015-12-30 11:19:42 +00:00
}