201 lines
7.4 KiB
C#
201 lines
7.4 KiB
C#
using LCU.API.Internal.DocumentLib.Containers;
|
|
using MongoDB.Driver;
|
|
using OwnerNumberMigration;
|
|
using OwnerNumberMigrationTest.TestDataFactories;
|
|
using OwnerNumberMigrationTest.TestDoubles;
|
|
|
|
namespace OwnerNumberMigrationTest;
|
|
|
|
public class AttributeMigrationTest : IDisposable
|
|
{
|
|
private readonly IAttributeMigration _migration;
|
|
|
|
private readonly string _attributeName = Guid.NewGuid().ToString();
|
|
private const string DestinationProperty = nameof(DocumentInformation.PersonNumbers);
|
|
private string[] GetDestinationProperty(DocumentInformation document) => (string[])typeof(DocumentInformation).GetProperty(DestinationProperty)!.GetValue(document)!;
|
|
private readonly FakeMongoCollectionFactory _collectionFactory = new();
|
|
private readonly FakeParsingStrategy<string[]> _parsingStrategy = new(Array.Empty<string>);
|
|
private readonly FakeMigrationObserver _observer = new();
|
|
private readonly FakeDocumentFilterFactory _filterFactory = new();
|
|
|
|
public AttributeMigrationTest()
|
|
{
|
|
_migration = new AttributeMigration<string[]>
|
|
(
|
|
_collectionFactory,
|
|
_attributeName,
|
|
_parsingStrategy,
|
|
DestinationProperty,
|
|
_observer,
|
|
_filterFactory
|
|
);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Migrate_AlreadyCancelled_ReturnsImmediately()
|
|
{
|
|
var cancellation = new CancellationTokenSource();
|
|
cancellation.Cancel();
|
|
var document = await MigrateableDocumentFactory();
|
|
|
|
await _migration.Migrate(cancellation.Token);
|
|
|
|
var documentRecord = (await _collectionFactory
|
|
.GetCollection<DocumentInformation>()
|
|
.FindAsync(Builders<DocumentInformation>.Filter.Eq(d => d.DocumentId, document.DocumentId)))
|
|
.Single();
|
|
var unmigratedDestinationProperty = GetDestinationProperty(document);
|
|
var migratedDestinationProperty = GetDestinationProperty(documentRecord);
|
|
CollectionAssert.AreEquivalent(unmigratedDestinationProperty, migratedDestinationProperty);
|
|
}
|
|
|
|
[Test]
|
|
public void Migrate_DocumentInformationMissingDestination_ThrowsException()
|
|
{
|
|
var migration = new AttributeMigration<string[]>
|
|
(
|
|
_collectionFactory,
|
|
_attributeName,
|
|
_parsingStrategy,
|
|
Guid.NewGuid().ToString(),
|
|
_observer,
|
|
_filterFactory
|
|
);
|
|
|
|
Assert.ThrowsAsync<InvalidOperationException>(() => migration.Migrate(new CancellationToken()));
|
|
}
|
|
|
|
[Test]
|
|
public void Migrate_DocumentInformationMissingDestination_NotifiesObserver()
|
|
{
|
|
var migration = new AttributeMigration<string[]>
|
|
(
|
|
_collectionFactory,
|
|
_attributeName,
|
|
_parsingStrategy,
|
|
Guid.NewGuid().ToString(),
|
|
_observer,
|
|
_filterFactory
|
|
);
|
|
|
|
var thrown = Assert.ThrowsAsync<InvalidOperationException>(() => migration.Migrate(new CancellationToken()));
|
|
|
|
Assert.Contains(thrown, _observer.Errors);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Migrate_DocumentInformationMissingDestination_DoesNotMigrate()
|
|
{
|
|
var document = await MigrateableDocumentFactory();
|
|
var migration = new AttributeMigration<string[]>
|
|
(
|
|
_collectionFactory,
|
|
_attributeName,
|
|
_parsingStrategy,
|
|
Guid.NewGuid().ToString(),
|
|
_observer,
|
|
_filterFactory
|
|
);
|
|
|
|
Assert.ThrowsAsync<InvalidOperationException>(() => migration.Migrate(new CancellationToken()));
|
|
|
|
var documentRecord = (await _collectionFactory
|
|
.GetCollection<DocumentInformation>()
|
|
.FindAsync(Builders<DocumentInformation>.Filter.Eq(d => d.DocumentId, document.DocumentId)))
|
|
.Single();
|
|
var unmigratedDestinationProperty = GetDestinationProperty(document);
|
|
var migratedDestinationProperty = GetDestinationProperty(documentRecord);
|
|
CollectionAssert.AreEquivalent(unmigratedDestinationProperty, migratedDestinationProperty);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Migrate_NotCancelled_NotifiesObserverOfDocument()
|
|
{
|
|
var document = await MigrateableDocumentFactory();
|
|
|
|
await _migration.Migrate(new CancellationToken());
|
|
|
|
var documentsStartedMigrating = _observer.Documents.Select(d => d.doc.DocumentId);
|
|
CollectionAssert.Contains(documentsStartedMigrating, document.DocumentId);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Migrate_NotCancelled_MovesValueFromParseStrategyIntoDestinationAndSaves()
|
|
{
|
|
var document = await MigrateableDocumentFactory();
|
|
var parsedOwners = _parsingStrategy.Values[document.Attributes[_attributeName]] =
|
|
new[]
|
|
{
|
|
Guid.NewGuid().ToString(),
|
|
Guid.NewGuid().ToString()
|
|
};
|
|
|
|
await _migration.Migrate(new CancellationToken());
|
|
|
|
var documentRecord = (await _collectionFactory
|
|
.GetCollection<DocumentInformation>()
|
|
.FindAsync(Builders<DocumentInformation>.Filter.Eq(d => d.DocumentId, document.DocumentId)))
|
|
.Single();
|
|
var migratedDestinationProperty = GetDestinationProperty(documentRecord);
|
|
CollectionAssert.AreEquivalent(parsedOwners, migratedDestinationProperty);
|
|
}
|
|
|
|
[Test]
|
|
public async Task Migrate_AfterDocumentMigrates_NotifiesObserver()
|
|
{
|
|
var document = await MigrateableDocumentFactory();
|
|
|
|
await _migration.Migrate(new CancellationToken());
|
|
|
|
var ended = DateTime.Now;
|
|
var migrationStart = _observer.Documents
|
|
.Where(d => d.doc.DocumentId == document.DocumentId)
|
|
.Select(d => d.started)
|
|
.Single();
|
|
Assert.AreEqual(1, _observer.Completions.Count);
|
|
var migrationCompleted = _observer.Completions.Single();
|
|
Assert.That(migrationCompleted, Is.InRange(migrationStart, ended));
|
|
}
|
|
|
|
[Test]
|
|
public async Task Migrate_TooManyRequests_SleepsForIndicatedTimeThenResumes()
|
|
{
|
|
var document = await MigrateableDocumentFactory();
|
|
var parsedOwners = _parsingStrategy.Values[document.Attributes[_attributeName]] =
|
|
new[]
|
|
{
|
|
Guid.NewGuid().ToString(),
|
|
Guid.NewGuid().ToString()
|
|
};
|
|
_collectionFactory.TooManyRequestsOnWriteFor = TimeSpan.FromMilliseconds(25);
|
|
|
|
await _migration.Migrate(new CancellationToken());
|
|
|
|
_collectionFactory.TooManyRequestsOnWriteFor = null;
|
|
var documentRecord = (await _collectionFactory
|
|
.GetCollection<DocumentInformation>()
|
|
.FindAsync(Builders<DocumentInformation>.Filter.Eq(d => d.DocumentId, document.DocumentId)))
|
|
.Single();
|
|
var migratedDestinationProperty = GetDestinationProperty(documentRecord);
|
|
CollectionAssert.AreEquivalent(parsedOwners, migratedDestinationProperty);
|
|
}
|
|
|
|
private async Task<DocumentInformation> MigrateableDocumentFactory()
|
|
{
|
|
var document = DocumentInformationFactory.CreateDocumentInformation();
|
|
document.Attributes[_attributeName] = Guid.NewGuid().ToString();
|
|
|
|
_filterFactory.ApplicableDocuments[(_attributeName, DestinationProperty)] = new[] { document };
|
|
|
|
await _collectionFactory
|
|
.GetCollection<DocumentInformation>()
|
|
.InsertOneAsync(document);
|
|
|
|
return document;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_collectionFactory.Dispose();
|
|
}
|
|
} |