forked from ddrilling/AsbCloudServer
153 lines
5.4 KiB
C#
153 lines
5.4 KiB
C#
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using AsbCloudInfrastructure.Background;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace AsbCloudInfrastructure.Tests.Background;
|
|
|
|
public class WorkTest
|
|
{
|
|
private readonly IServiceProvider serviceProviderMock = Substitute.For<IServiceProvider, ISupportRequiredService>();
|
|
private readonly IServiceScope serviceScopeMock = Substitute.For<IServiceScope>();
|
|
private readonly IServiceScopeFactory serviceScopeFactoryMock = Substitute.For<IServiceScopeFactory>();
|
|
|
|
public WorkTest()
|
|
{
|
|
serviceScopeFactoryMock.CreateScope().Returns(serviceScopeMock);
|
|
((ISupportRequiredService)serviceProviderMock).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactoryMock);
|
|
}
|
|
|
|
[Fact, MethodImpl(MethodImplOptions.NoOptimization)]
|
|
public async Task Start_ShouldReturn_Success()
|
|
{
|
|
//arrange
|
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
|
=> Task.CompletedTask;
|
|
|
|
var work = Work.CreateByDelegate("", workAction);
|
|
|
|
//act
|
|
var begin = DateTime.Now;
|
|
await work.Start(serviceProviderMock, CancellationToken.None);
|
|
var done = DateTime.Now;
|
|
var executionTime = done - begin;
|
|
|
|
//assert
|
|
Assert.Equal(1, work.CountComplete);
|
|
Assert.Equal(1, work.CountStart);
|
|
Assert.Equal(0, work.CountErrors);
|
|
Assert.Null(work.CurrentState);
|
|
Assert.Null(work.LastError);
|
|
|
|
var lastState = work.LastComplete;
|
|
Assert.NotNull(lastState);
|
|
Assert.InRange(lastState.Start, begin, done - 0.5 * executionTime);
|
|
Assert.InRange(lastState.End, done - 0.5 * executionTime, done);
|
|
Assert.InRange(lastState.ExecutionTime, TimeSpan.Zero, executionTime);
|
|
}
|
|
|
|
[Fact, MethodImpl(MethodImplOptions.NoOptimization)]
|
|
public async Task ExecutionWork_Invokes_Callback()
|
|
{
|
|
//arrange
|
|
const string expectedState = "42";
|
|
const double expectedProgress = 42d;
|
|
|
|
var timeout = TimeSpan.FromMilliseconds(80);
|
|
|
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
|
{
|
|
callback.Invoke(expectedState, expectedProgress);
|
|
return Task.Delay(timeout);
|
|
}
|
|
|
|
var work = Work.CreateByDelegate("", workAction);
|
|
|
|
//act
|
|
var begin = DateTime.Now;
|
|
_ = work.Start(serviceProviderMock, CancellationToken.None);
|
|
await Task.Delay(timeout / 3);
|
|
|
|
//assert
|
|
Assert.Equal(0, work.CountComplete);
|
|
Assert.Equal(1, work.CountStart);
|
|
Assert.Equal(0, work.CountErrors);
|
|
Assert.NotNull(work.CurrentState);
|
|
Assert.Null(work.LastComplete);
|
|
Assert.Null(work.LastError);
|
|
|
|
var currentState = work.CurrentState;
|
|
Assert.NotNull(currentState);
|
|
Assert.InRange(currentState.Start, begin, begin + timeout);
|
|
Assert.InRange(currentState.StateUpdate, begin, begin + timeout);
|
|
Assert.Equal(expectedState, currentState.State);
|
|
Assert.Equal(expectedProgress, currentState.Progress);
|
|
}
|
|
|
|
[Fact, MethodImpl(MethodImplOptions.NoOptimization)]
|
|
public async Task ExecutionWork_ShouldReturn_FailsWithInfo()
|
|
{
|
|
//arrange
|
|
const string expectedState = "41";
|
|
const string expectedErrorText = "42";
|
|
var minWorkTime = TimeSpan.FromMilliseconds(10);
|
|
|
|
async Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
|
{
|
|
await Task.Delay(minWorkTime);
|
|
callback(expectedState, 0);
|
|
throw new Exception(expectedErrorText);
|
|
}
|
|
|
|
var work = Work.CreateByDelegate("", workAction);
|
|
|
|
//act
|
|
var begin = DateTime.Now;
|
|
await work.Start(serviceProviderMock, CancellationToken.None);
|
|
|
|
//assert
|
|
Assert.Equal(0, work.CountComplete);
|
|
Assert.Equal(1, work.CountStart);
|
|
Assert.Equal(1, work.CountErrors);
|
|
Assert.Null(work.CurrentState);
|
|
Assert.Null(work.LastComplete);
|
|
|
|
var error = work.LastError;
|
|
Assert.NotNull(error);
|
|
Assert.InRange(error.Start, begin, DateTime.Now);
|
|
Assert.InRange(error.End, begin, DateTime.Now);
|
|
Assert.InRange(error.ExecutionTime, minWorkTime, DateTime.Now - begin);
|
|
Assert.Contains(expectedErrorText, error.ErrorText, StringComparison.InvariantCultureIgnoreCase);
|
|
Assert.Equal(expectedState, error.State);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Stop_ShouldReturn_Success()
|
|
{
|
|
//arrange
|
|
var workTime = TimeSpan.FromMilliseconds(1_000);
|
|
|
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
|
=> Task.Delay(workTime, token);
|
|
|
|
var work = Work.CreateByDelegate("", workAction);
|
|
|
|
//act
|
|
var begin = DateTime.Now;
|
|
_ = work.Start(serviceProviderMock, CancellationToken.None);
|
|
await Task.Delay(10);
|
|
work.Stop();
|
|
await Task.Delay(10);
|
|
|
|
//assert
|
|
Assert.Equal(0, work.CountComplete);
|
|
Assert.Equal(1, work.CountStart);
|
|
Assert.Equal(1, work.CountErrors);
|
|
Assert.Null(work.LastComplete);
|
|
Assert.NotNull(work.LastError);
|
|
}
|
|
} |