Skip to content

Commit

Permalink
add ILogger of Microsoft.Extensions.Logging namespace to all integrat…
Browse files Browse the repository at this point in the history
…ion tests
  • Loading branch information
bezzad committed Nov 16, 2024
1 parent 4d37a1a commit 8855b1b
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 37 deletions.
17 changes: 17 additions & 0 deletions src/Downloader.Test/Helper/TestOutputLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;

namespace Downloader.Test.Helper;

public class TestOutputLogger(ITestOutputHelper outputHelper, string categoryName) : ILogger
{
public IDisposable BeginScope<TState>(TState state) => null;

public bool IsEnabled(LogLevel logLevel) => true;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
outputHelper.WriteLine($"{categoryName} [{logLevel}]: {formatter(state, exception)}");
}
}
11 changes: 11 additions & 0 deletions src/Downloader.Test/Helper/TestOutputLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Microsoft.Extensions.Logging;
using Xunit.Abstractions;

namespace Downloader.Test.Helper;

public class TestOutputLoggerProvider(ITestOutputHelper outputHelper) : ILoggerProvider
{
public ILogger CreateLogger(string categoryName) => new TestOutputLogger(outputHelper, categoryName);

public void Dispose() { }
}
15 changes: 12 additions & 3 deletions src/Downloader.Test/IntegrationTests/DownloadIntegrationTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Downloader.DummyHttpServer;
using Downloader.Test.Helper;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.IO;
Expand All @@ -15,6 +17,7 @@ public abstract class DownloadIntegrationTest : IDisposable
{
protected static byte[] FileData { get; set; }
protected readonly ITestOutputHelper Output;
protected readonly ILoggerFactory LogFactory;
protected string Url { get; set; }
protected int FileSize { get; set; }
protected string Filename { get; set; }
Expand All @@ -25,6 +28,10 @@ public abstract class DownloadIntegrationTest : IDisposable
public DownloadIntegrationTest(ITestOutputHelper output)
{
Output = output;
// Create an ILoggerFactory that logs to the ITestOutputHelper
LogFactory = LoggerFactory.Create(builder => {
builder.AddProvider(new TestOutputLoggerProvider(output));
});
Filename = Path.GetRandomFileName();
FilePath = Path.Combine(Path.GetTempPath(), Filename);
FileSize = DummyFileHelper.FileSize16Kb;
Expand Down Expand Up @@ -240,6 +247,7 @@ public async Task StopResumeDownloadTest()
// resume download from stopped point.
await Downloader.DownloadFileTaskAsync(Downloader.Package);
}

var stream = await File.ReadAllBytesAsync(Downloader.Package.FileName);

// assert
Expand Down Expand Up @@ -300,7 +308,7 @@ public async Task StopResumeDownloadFromLastPositionTest()
var totalReceivedBytes = 0L;
Config.BufferBlockSize = 1024;
Config.EnableLiveStreaming = true;

Downloader.DownloadProgressChanged += (_, e) => {
totalProgressedByteSize += e.ProgressedByteSize;
totalReceivedBytes += e.ReceivedBytes.Length;
Expand Down Expand Up @@ -334,7 +342,7 @@ public async Task StopResumeDownloadOverFirstPackagePositionTest()
var isSavingStateOnCancel = false;
var isSavingStateBeforCancel = false;
Config.EnableLiveStreaming = true;

Downloader.DownloadProgressChanged += async (_, _) => {
isSavingStateBeforCancel |= Downloader.Package.IsSaving;
if (--cancellationCount > 0)
Expand Down Expand Up @@ -452,7 +460,8 @@ public async Task SpeedLimitTest()

// assert
Assert.Equal(FileSize, Downloader.Package.TotalFileSize);
Assert.True(averageSpeed <= Config.MaximumBytesPerSecond * 1.5, $"Average Speed: {averageSpeed} , Speed Limit: {Config.MaximumBytesPerSecond}");
Assert.True(averageSpeed <= Config.MaximumBytesPerSecond * 1.5,
$"Average Speed: {averageSpeed} , Speed Limit: {Config.MaximumBytesPerSecond}");
}

[Fact]
Expand Down
20 changes: 14 additions & 6 deletions src/Downloader.Test/IntegrationTests/DownloadServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@
using System.Net;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Downloader.Test.IntegrationTests;

public class DownloadServiceTest : DownloadService, IAsyncLifetime
public class DownloadServiceTest : DownloadService, IAsyncDisposable
{
protected readonly ITestOutputHelper TestOutputHelper;
private string Filename { get; set; }

public Task InitializeAsync()
public DownloadServiceTest(ITestOutputHelper testOutputHelper)
{
Filename = Path.GetRandomFileName();
return Task.CompletedTask;
TestOutputHelper = testOutputHelper;
// Create an ILoggerFactory that logs to the ITestOutputHelper
ILoggerFactory loggerFactory = LoggerFactory.Create(builder => {
builder.AddProvider(new TestOutputLoggerProvider(testOutputHelper));
});
AddLogger(loggerFactory.CreateLogger(GetType()));
}

public new virtual async Task DisposeAsync()
public override async ValueTask DisposeAsync()
{
await base.DisposeAsync();
Package?.Clear();
if (Package?.Storage != null)
await Package.Storage.DisposeAsync();
Expand Down Expand Up @@ -764,10 +772,10 @@ public void TestAddLogger()
{
// arrange
var logFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());

// act
AddLogger(FileLogger.Factory(logFile));

// assert
Assert.NotNull(Logger);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public ParallelDownloadIntegrationTest(ITestOutputHelper output) : base(output)
MaxTryAgainOnFailover = 100
};

Downloader = new DownloadService(Config);
Downloader = new DownloadService(Config, LogFactory);
Downloader.DownloadFileCompleted += DownloadFileCompleted;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public SerialDownloadIntegrationTest(ITestOutputHelper output) : base(output)
MaxTryAgainOnFailover = 100
};

Downloader = new DownloadService(Config);
Downloader = new DownloadService(Config, LogFactory);
Downloader.DownloadFileCompleted += DownloadFileCompleted;
}
}
2 changes: 1 addition & 1 deletion src/Downloader.Test/UnitTests/DownloadBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public async Task TestPackageWhenResume()
{
// arrange
DownloadPackage package = new DownloadPackage() {
Urls = new[] { _url },
Urls = [_url],
IsSupportDownloadInRange = true
};
IDownload download = DownloadBuilder.New().Build(package);
Expand Down
12 changes: 8 additions & 4 deletions src/Downloader.Test/UnitTests/DownloadPackageTestOnFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public override async Task InitializeAsync()

Package = new DownloadPackage() {
FileName = _path,
Urls = new[] { DummyFileHelper.GetFileWithNameUrl(DummyFileHelper.SampleFile16KbName, DummyFileHelper.FileSize16Kb) },
Urls = [
DummyFileHelper.GetFileWithNameUrl(DummyFileHelper.SampleFile16KbName, DummyFileHelper.FileSize16Kb)
],
TotalFileSize = DummyFileHelper.FileSize16Kb
};

Expand All @@ -29,15 +31,17 @@ public override async Task DisposeAsync()
}

[Theory]
[InlineData(true)] // BuildStorageWithReserveSpaceTest
[InlineData(true)] // BuildStorageWithReserveSpaceTest
[InlineData(false)] // BuildStorageTest
public async Task BuildStorageTest(bool reserveSpace)
{
// arrange
_path = Path.GetTempFileName();
Package = new DownloadPackage() {
FileName = _path,
Urls = new[] { DummyFileHelper.GetFileWithNameUrl(DummyFileHelper.SampleFile16KbName, DummyFileHelper.FileSize16Kb) },
Urls = [
DummyFileHelper.GetFileWithNameUrl(DummyFileHelper.SampleFile16KbName, DummyFileHelper.FileSize16Kb)
],
TotalFileSize = DummyFileHelper.FileSize16Kb
};

Expand All @@ -49,4 +53,4 @@ public async Task BuildStorageTest(bool reserveSpace)
Assert.IsType<FileStream>(stream);
Assert.Equal(reserveSpace ? DummyFileHelper.FileSize16Kb : 0, Package.Storage.Length);
}
}
}
8 changes: 5 additions & 3 deletions src/Downloader.Test/UnitTests/DownloadPackageTestOnMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ public class DownloadPackageTestOnMemory : DownloadPackageTest
{
public override async Task InitializeAsync()
{
Package = new DownloadPackage() {
Urls = new[] { DummyFileHelper.GetFileWithNameUrl(DummyFileHelper.SampleFile16KbName, DummyFileHelper.FileSize16Kb) },
Package = new DownloadPackage {
Urls = [
DummyFileHelper.GetFileWithNameUrl(DummyFileHelper.SampleFile16KbName, DummyFileHelper.FileSize16Kb)
],
TotalFileSize = DummyFileHelper.FileSize16Kb
};

await base.InitializeAsync();
}
}
}
10 changes: 5 additions & 5 deletions src/Downloader/AbstractDownloadService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public Task<Stream> DownloadFileTaskAsync(DownloadPackage package, CancellationT
public Task<Stream> DownloadFileTaskAsync(DownloadPackage package, string address,
CancellationToken cancellationToken = default)
{
return DownloadFileTaskAsync(package, new[] { address }, cancellationToken);
return DownloadFileTaskAsync(package, [address], cancellationToken);
}

/// <summary>
Expand All @@ -198,7 +198,7 @@ public virtual async Task<Stream> DownloadFileTaskAsync(DownloadPackage package,
/// <returns>A task that represents the asynchronous download operation. The task result contains the downloaded stream.</returns>
public Task<Stream> DownloadFileTaskAsync(string address, CancellationToken cancellationToken = default)
{
return DownloadFileTaskAsync(new[] { address }, cancellationToken);
return DownloadFileTaskAsync([address], cancellationToken);
}

/// <summary>
Expand All @@ -223,7 +223,7 @@ public virtual async Task<Stream> DownloadFileTaskAsync(string[] urls,
/// <returns>A task that represents the asynchronous download operation.</returns>
public Task DownloadFileTaskAsync(string address, string fileName, CancellationToken cancellationToken = default)
{
return DownloadFileTaskAsync(new[] { address }, fileName, cancellationToken);
return DownloadFileTaskAsync([address], fileName, cancellationToken);
}

/// <summary>
Expand All @@ -250,7 +250,7 @@ public virtual async Task DownloadFileTaskAsync(string[] urls, string fileName,
public Task DownloadFileTaskAsync(string address, DirectoryInfo folder,
CancellationToken cancellationToken = default)
{
return DownloadFileTaskAsync(new[] { address }, folder, cancellationToken);
return DownloadFileTaskAsync([address], folder, cancellationToken);
}

/// <summary>
Expand Down Expand Up @@ -486,7 +486,7 @@ public void Dispose()
/// <summary>
/// Disposes asynchronously of the download service, including clearing the current download operation.
/// </summary>
public async ValueTask DisposeAsync()
public virtual async ValueTask DisposeAsync()
{
await Clear().ConfigureAwait(false);
}
Expand Down
10 changes: 5 additions & 5 deletions src/Downloader/ConcurrentStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ public string Path
get => _path;
set
{
if (!string.IsNullOrWhiteSpace(value))
{
_path = value;
_stream = new FileStream(_path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
}
if (string.IsNullOrWhiteSpace(value))
return;

_path = value;
_stream = new FileStream(_path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
}
}

Expand Down
18 changes: 13 additions & 5 deletions src/Downloader/DownloadService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Downloader.Extensions.Helpers;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
Expand All @@ -18,12 +19,16 @@ public class DownloadService : AbstractDownloadService
/// Initializes a new instance of the <see cref="DownloadService"/> class with the specified options.
/// </summary>
/// <param name="options">The configuration options for the download service.</param>
public DownloadService(DownloadConfiguration options) : base(options) { }
/// <param name="loggerFactory">Pass standard logger factory</param>
public DownloadService(DownloadConfiguration options, ILoggerFactory loggerFactory = null) : base(options)
{
Logger = loggerFactory?.CreateLogger<DownloadService>();
}

/// <summary>
/// Initializes a new instance of the <see cref="DownloadService"/> class with default options.
/// </summary>
public DownloadService() : base(null) { }
public DownloadService(ILoggerFactory loggerFactory = null) : this(null, loggerFactory) { }

/// <summary>
/// Starts the download operation.
Expand All @@ -35,7 +40,8 @@ protected override async Task<Stream> StartDownload()
{
await SingleInstanceSemaphore.WaitAsync().ConfigureAwait(false);
Package.TotalFileSize = await RequestInstances.First().GetFileSize().ConfigureAwait(false);
Package.IsSupportDownloadInRange = await RequestInstances.First().IsSupportDownloadInRange().ConfigureAwait(false);
Package.IsSupportDownloadInRange =
await RequestInstances.First().IsSupportDownloadInRange().ConfigureAwait(false);
Package.BuildStorage(Options.ReserveStorageSpaceBeforeStartingDownload, Options.MaximumMemoryBufferBytes);
ValidateBeforeChunking();
ChunkHub.SetFileChunks(Package);
Expand Down Expand Up @@ -106,7 +112,8 @@ private void SetRangedSizes()
{
if (!Package.IsSupportDownloadInRange)
{
throw new NotSupportedException("The server of your desired address does not support download in a specific range");
throw new NotSupportedException(
"The server of your desired address does not support download in a specific range");
}

if (Options.RangeHigh < Options.RangeLow)
Expand Down Expand Up @@ -230,7 +237,8 @@ private IEnumerable<Task> GetChunksTasks(PauseToken pauseToken)
/// <param name="pause">The pause token for pausing the download.</param>
/// <param name="cancellationTokenSource">The cancellation token source for cancelling the download.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the downloaded chunk.</returns>
private async Task<Chunk> DownloadChunk(Chunk chunk, Request request, PauseToken pause, CancellationTokenSource cancellationTokenSource)
private async Task<Chunk> DownloadChunk(Chunk chunk, Request request, PauseToken pause,
CancellationTokenSource cancellationTokenSource)
{
ChunkDownloader chunkDownloader = new ChunkDownloader(chunk, Options, Package.Storage, Logger);
chunkDownloader.DownloadProgressChanged += OnChunkDownloadProgressChanged;
Expand Down
4 changes: 2 additions & 2 deletions src/Downloader/RequestConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ public class RequestConfiguration
/// </summary>
public RequestConfiguration()
{
Headers = new WebHeaderCollection();
Headers = [];
AllowAutoRedirect = true;
AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
AutomaticDecompression = DecompressionMethods.None;
ClientCertificates = new X509CertificateCollection();
ClientCertificates = [];
ImpersonationLevel = TokenImpersonationLevel.Delegation;
KeepAlive = false; // Please keep this in false. Because of an error (An existing connection was forcibly closed by the remote host)
MaximumAutomaticRedirections = 50;
Expand Down
2 changes: 1 addition & 1 deletion src/Samples/Downloader.Sample/VideoDownloaderHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task DownloadM3U8File(string m3U8Url, string outputFilePath)
static string[] ParseM3U8(string m3U8Content, string baseUrl)
{
string[] lines = m3U8Content.Split(["\r\n", "\r", "\n"], StringSplitOptions.None);
List<string> segmentUrls = new();
List<string> segmentUrls = [];

foreach (string line in lines)
{
Expand Down

0 comments on commit 8855b1b

Please sign in to comment.