This commit is contained in:
Zeeshaun
2026-03-13 09:11:35 -05:00
parent f004c8205a
commit c2d6bda458
197 changed files with 14970 additions and 0 deletions
@@ -0,0 +1,25 @@
using LCU.API.Internal.DocumentLib.Containers;
using Microsoft.Extensions.Hosting;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigration.ValueParsing;
using OwnerNumberMigration;
namespace OwnerNumberMigrationTest.Migrations;
public class AccountNumberMigrationTest : AttributeMigrationTaskTest<string>
{
protected override string SourceAttribute => "AccountNumber";
protected override string DestinationAttribute => nameof(DocumentInformation.AccountNumber);
protected override IHostedService MigrationTaskFactory
(
AttributeMigrationFactory<string> factory,
IParsingStrategyFactory strategyFactory,
IMigrationManager manager
) => new AccountNumberMigration(factory, strategyFactory, manager);
public AccountNumberMigrationTest() : base(() => string.Empty)
{
}
}
@@ -0,0 +1,170 @@
using Microsoft.Extensions.Hosting;
using Moq;
using OwnerNumberMigration;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigration.ValueParsing;
using OwnerNumberMigrationTest.TestDoubles;
namespace OwnerNumberMigrationTest.Migrations;
public abstract class AttributeMigrationTaskTest<T>
{
protected abstract IHostedService MigrationTaskFactory
(
AttributeMigrationFactory<T> factory,
IParsingStrategyFactory strategyFactory,
IMigrationManager manager
);
private IHostedService MigrationServiceFactory() => MigrationTaskFactory
(
(_, _, _) => _migration.Object,
StrategyFactory.Object,
_manager.Object
);
protected abstract string SourceAttribute { get; }
protected abstract string DestinationAttribute { get; }
protected readonly Mock<IParsingStrategyFactory> StrategyFactory = new();
private readonly FakeParsingStrategy<T> _parsingStrategy;
private readonly Mock<IAttributeMigration> _migration = new();
private readonly Mock<IMigrationManager> _manager = new();
protected AttributeMigrationTaskTest(Func<T> newT)
{
_parsingStrategy = new FakeParsingStrategy<T>(newT);
}
[SetUp]
public void SetUp()
{
StrategyFactory
.Setup(f => f.CreateParsingStrategy<T>(SourceAttribute))
.Returns((IValueParsingStrategy<T>)_parsingStrategy);
_migration.Reset();
}
[Test]
public void Constructor_AllCases_CreatesMigrationWithJobTypeAttributes()
{
string? sourceAttribute = null;
string? destinationAttribute = null;
IValueParsingStrategy<T>? parsingStrategy = null;
MigrationTaskFactory
(
(source, strategy, destination) =>
{
sourceAttribute = source;
parsingStrategy = strategy;
destinationAttribute = destination;
return _migration.Object;
},
StrategyFactory.Object,
_manager.Object
);
Assert.AreEqual(SourceAttribute, sourceAttribute);
Assert.AreSame(_parsingStrategy, parsingStrategy);
Assert.AreEqual(DestinationAttribute, destinationAttribute);
}
[Test]
public async Task StartAsync_TokenCancelled_DoesNotStartMigration()
{
var cancellation = new CancellationToken(true);
var migration = MigrationServiceFactory();
await migration.StartAsync(cancellation);
_migration.Verify(m => m.Migrate(It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task StartAsync_NotCanceled_StartsMigrationTaskAndReturns()
{
var cancellation = new CancellationToken();
_migration
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
.Returns<CancellationToken>(async token =>
{
await Task.Delay(TimeSpan.MaxValue, token);
}
);
var migration = MigrationServiceFactory();
await migration.StartAsync(cancellation);
_migration.Verify(m => m.Migrate(It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task StartAsync_NotCanceled_RegistersMigrationTaskWithManager()
{
var cancellation = new CancellationToken();
var migrationTask = Task.Run(() => { });
_migration
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
.Returns(migrationTask);
var migration = MigrationServiceFactory();
await migration.StartAsync(cancellation);
_manager.Verify(m => m.Start(migrationTask), Times.Once);
}
[Test]
public async Task StopAsync_NotStarted_ReturnsWithoutError()
{
var cancellation = new CancellationToken();
var migration = MigrationServiceFactory();
Assert.DoesNotThrowAsync(() => migration.StopAsync(cancellation));
}
[Test]
public async Task StopAsync_AlreadyCompleted_CleansUpMigrationTask()
{
var cancellation = new CancellationToken();
Task? migrationTask = null;
_migration
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
.Returns<CancellationToken>(token => migrationTask = Task.Run
(
() => { },
token
));
var migration = MigrationServiceFactory();
await migration.StartAsync(cancellation);
await migrationTask;
await migration.StopAsync(cancellation);
Assert.AreEqual(TaskStatus.RanToCompletion, migrationTask.Status);
}
[Test]
public async Task StopAsync_NotCompleted_CancelsMigrationTaskThenCleansUp()
{
var cancellation = new CancellationToken();
Task? migrationTask = null;
_migration
.Setup(m => m.Migrate(It.IsAny<CancellationToken>()))
.Returns<CancellationToken>(token => migrationTask = Task.Run
(
async () =>
{
await Task.Delay(-1, token);
},
token
));
var migration = MigrationServiceFactory();
await migration.StartAsync(cancellation);
await migration.StopAsync(cancellation);
Assert.AreEqual(TaskStatus.Canceled, migrationTask.Status);
}
}
@@ -0,0 +1,102 @@
using Microsoft.Extensions.Hosting;
using Moq;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigrationTest.TestDataFactories;
namespace OwnerNumberMigrationTest.Migrations;
public class MigrationManagerTest
{
private readonly IMigrationManager _manager;
private readonly Mock<IHostApplicationLifetime> _lifetime = new();
public MigrationManagerTest()
{
_manager = new MigrationManager(_lifetime.Object);
}
[SetUp]
public void SetUp()
{
_lifetime.Reset();
}
[Test]
public async Task Start_OneTaskThatFinishes_EndsApplication()
{
var applicationStopped = new SemaphoreSlim(0);
_lifetime
.Setup(l => l.StopApplication())
.Callback(() => applicationStopped.Release());
var task = Task.CompletedTask;
_manager.Start(task);
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
}
[Test]
public async Task Start_OneTaskThatCancels_EndsApplication()
{
var applicationStopped = new SemaphoreSlim(0);
_lifetime
.Setup(l => l.StopApplication())
.Callback(() => applicationStopped.Release());
var task = Task.FromCanceled(new CancellationToken(true));
_manager.Start(task);
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
}
[Test]
public async Task Start_OneTaskThatErrors_EndsApplication()
{
var applicationStopped = new SemaphoreSlim(0);
_lifetime
.Setup(l => l.StopApplication())
.Callback(() => applicationStopped.Release());
_lifetime
.Setup(l => l.StopApplication())
.Callback(() => applicationStopped.Release());
var task = Task.FromException(new Exception());
_manager.Start(task);
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
}
[Test]
public async Task Start_MultipleTasksThatFinish_EndsApplicationAfterAll()
{
var applicationStopped = new SemaphoreSlim(0);
_lifetime
.Setup(l => l.StopApplication())
.Callback(() => applicationStopped.Release());
var semaphores = EnumerableDataSeriesFactory
.CreateSeries(() => new SemaphoreSlim(0), 5)
.ToArray();
var tasks = semaphores
.Select(s => Task.Run(async () => await s.WaitAsync()))
.ToArray();
foreach(var task in tasks) _manager.Start(task);
_lifetime.Verify(l => l.StopApplication(), Times.Never);
foreach (var semaphore in semaphores[..^1])
{
semaphore.Release();
_lifetime.Verify(l => l.StopApplication(), Times.Never);
}
foreach (var semaphore in semaphores[^1..])
{
semaphore.Release();
}
await applicationStopped.WaitAsync(TimeSpan.FromMilliseconds(50));
_lifetime.Verify(l => l.StopApplication(), Times.AtLeastOnce);
}
}
@@ -0,0 +1,25 @@
using LCU.API.Internal.DocumentLib.Containers;
using Microsoft.Extensions.Hosting;
using OwnerNumberMigration;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigration.ValueParsing;
namespace OwnerNumberMigrationTest.Migrations;
public class OrganizationNumberMigrationTest : AttributeMigrationTaskTest<string[]>
{
protected override string SourceAttribute => "OrganizationNumber";
protected override string DestinationAttribute => nameof(DocumentInformation.OrganizationNumbers);
protected override IHostedService MigrationTaskFactory
(
AttributeMigrationFactory<string[]> factory,
IParsingStrategyFactory strategyFactory,
IMigrationManager manager
) => new OrganizationNumberMigration(factory, strategyFactory, manager);
public OrganizationNumberMigrationTest() : base(Array.Empty<string>)
{
}
}
@@ -0,0 +1,25 @@
using Microsoft.Extensions.Hosting;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigration;
using OwnerNumberMigration.ValueParsing;
using LCU.API.Internal.DocumentLib.Containers;
namespace OwnerNumberMigrationTest.Migrations;
public class OrganizationNumbersMigrationTest : AttributeMigrationTaskTest<string[]>
{
protected override string SourceAttribute => "OrganizationNumbers";
protected override string DestinationAttribute => nameof(DocumentInformation.OrganizationNumbers);
protected override IHostedService MigrationTaskFactory
(
AttributeMigrationFactory<string[]> factory,
IParsingStrategyFactory strategyFactory,
IMigrationManager manager
) => new OrganizationNumbersMigration(factory, strategyFactory, manager);
public OrganizationNumbersMigrationTest() : base(Array.Empty<string>)
{
}
}
@@ -0,0 +1,25 @@
using Microsoft.Extensions.Hosting;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigration;
using OwnerNumberMigration.ValueParsing;
using LCU.API.Internal.DocumentLib.Containers;
namespace OwnerNumberMigrationTest.Migrations;
public class PersonNumberMigrationTest : AttributeMigrationTaskTest<string[]>
{
protected override string SourceAttribute => "PersonNumber";
protected override string DestinationAttribute => nameof(DocumentInformation.PersonNumbers);
protected override IHostedService MigrationTaskFactory
(
AttributeMigrationFactory<string[]> factory,
IParsingStrategyFactory strategyFactory,
IMigrationManager manager
) => new PersonNumberMigration(factory, strategyFactory, manager);
public PersonNumberMigrationTest() : base(Array.Empty<string>)
{
}
}
@@ -0,0 +1,25 @@
using Microsoft.Extensions.Hosting;
using OwnerNumberMigration.Migrations;
using OwnerNumberMigration;
using OwnerNumberMigration.ValueParsing;
using LCU.API.Internal.DocumentLib.Containers;
namespace OwnerNumberMigrationTest.Migrations;
public class PersonNumbersMigrationTest : AttributeMigrationTaskTest<string[]>
{
protected override string SourceAttribute => "PersonNumbers";
protected override string DestinationAttribute => nameof(DocumentInformation.PersonNumbers);
protected override IHostedService MigrationTaskFactory
(
AttributeMigrationFactory<string[]> factory,
IParsingStrategyFactory strategyFactory,
IMigrationManager manager
) => new PersonNumbersMigration(factory, strategyFactory, manager);
public PersonNumbersMigrationTest() : base(Array.Empty<string>)
{
}
}