using Mongo2Go; using MongoDB.Driver; using StellaOps.TaskRunner.Core.Configuration; using StellaOps.Testing; using Xunit; namespace StellaOps.TaskRunner.Tests; internal sealed class MongoTaskRunnerTestContext : IAsyncDisposable, IDisposable { private readonly MongoDbRunner? runner; private readonly string databaseName; private readonly IMongoClient client; private readonly string connectionString; private MongoTaskRunnerTestContext( IMongoClient client, IMongoDatabase database, MongoDbRunner? runner, string databaseName, string connectionString) { this.client = client; Database = database; this.runner = runner; this.databaseName = databaseName; this.connectionString = connectionString; } public IMongoDatabase Database { get; } public static MongoTaskRunnerTestContext Create() { OpenSslLegacyShim.EnsureOpenSsl11(); var uri = Environment.GetEnvironmentVariable("STELLAOPS_TEST_MONGO_URI"); if (!string.IsNullOrWhiteSpace(uri)) { try { var url = MongoUrl.Create(uri); var client = new MongoClient(url); var databaseName = string.IsNullOrWhiteSpace(url.DatabaseName) ? $"taskrunner-tests-{Guid.NewGuid():N}" : url.DatabaseName; var database = client.GetDatabase(databaseName); return new MongoTaskRunnerTestContext(client, database, runner: null, databaseName, uri); } catch (Exception ex) { Assert.Skip($"Failed to connect to MongoDB using STELLAOPS_TEST_MONGO_URI: {ex.Message}"); throw new InvalidOperationException(); // Unreachable } } try { var runner = MongoDbRunner.Start(singleNodeReplSet: false); var client = new MongoClient(runner.ConnectionString); var databaseName = $"taskrunner-tests-{Guid.NewGuid():N}"; var database = client.GetDatabase(databaseName); return new MongoTaskRunnerTestContext(client, database, runner, databaseName, runner.ConnectionString); } catch (Exception ex) { Assert.Skip($"Unable to start embedded MongoDB (Mongo2Go): {ex.Message}"); throw new InvalidOperationException(); // Unreachable } } public async ValueTask DisposeAsync() { await client.DropDatabaseAsync(databaseName); runner?.Dispose(); } public void Dispose() { client.DropDatabase(databaseName); runner?.Dispose(); } public TaskRunnerMongoOptions CreateMongoOptions() => new() { ConnectionString = connectionString, Database = databaseName }; }