using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Mongo2Go; using MongoDB.Bson; using MongoDB.Driver; using StellaOps.Concelier.Storage.Mongo.Migrations; namespace StellaOps.Concelier.Storage.Mongo.Tests; public sealed class EnsureLinkNotMergeCollectionsMigrationTests : IAsyncLifetime { private MongoDbRunner _runner = null!; private IMongoDatabase _database = null!; public Task InitializeAsync() { _runner = MongoDbRunner.Start(singleNodeReplSet: true); var client = new MongoClient(_runner.ConnectionString); _database = client.GetDatabase("lnm-migration-tests"); return Task.CompletedTask; } public Task DisposeAsync() { _runner.Dispose(); return Task.CompletedTask; } [Fact] public async Task CreatesCollectionsAndIndexesIdempotently() { var migration = new EnsureLinkNotMergeCollectionsMigration(); await migration.ApplyAsync(_database, CancellationToken.None); await migration.ApplyAsync(_database, CancellationToken.None); // idempotent second run var collections = await _database.ListCollectionNames().ToListAsync(); collections.Should().Contain(new[] { MongoStorageDefaults.Collections.AdvisoryObservations, MongoStorageDefaults.Collections.AdvisoryLinksets }); var linksetIndexes = await _database .GetCollection(MongoStorageDefaults.Collections.AdvisoryLinksets) .Indexes.List() .ToListAsync(); linksetIndexes.Should().ContainSingle(i => i["name"] == "linkset_tenant_advisory_source" && i["unique"].AsBoolean); var obsIndexes = await _database .GetCollection(MongoStorageDefaults.Collections.AdvisoryObservations) .Indexes.List() .ToListAsync(); obsIndexes.Should().Contain(i => i["name"] == "obs_prov_sourceArtifactSha_unique" && i["unique"].AsBoolean); var linksetValidator = await GetValidatorAsync(MongoStorageDefaults.Collections.AdvisoryLinksets); linksetValidator.Should().NotBeNull(); } private async Task GetValidatorAsync(string collection) { var filter = new BsonDocument("name", collection); var cursor = await _database.ListCollectionsAsync(new ListCollectionsOptions { Filter = filter }); var doc = await cursor.FirstOrDefaultAsync(); return doc?"options"?"validator"?.AsBsonDocument; } }