using AcDream.App.Rendering; namespace AcDream.App.Tests.Rendering; public sealed class ResourceShutdownTransactionTests { [Fact] public void AttemptsIndependentOperationsAndRetriesOnlyPendingOnes() { var calls = new List(); int retryAttempts = 0; var transaction = new ResourceShutdownTransaction( new ResourceShutdownStage("owners", [ new("first", () => calls.Add("first")), new("retry", () => { calls.Add("retry"); if (retryAttempts++ == 0) throw new InvalidOperationException("synthetic transient failure"); }), new("last", () => calls.Add("last")), ]), new ResourceShutdownStage("dependent", [ new("dependent", () => calls.Add("dependent")), ])); transaction.CompleteOrThrow(); Assert.Equal(["first", "retry", "last", "retry", "dependent"], calls); Assert.True(transaction.IsComplete); } [Fact] public void PersistentFailureNeverRunsDependentStage() { int failures = 0; int dependentCalls = 0; var transaction = new ResourceShutdownTransaction( new ResourceShutdownStage("owner", [ new("persistent", () => { failures++; throw new InvalidOperationException("persistent"); }), ]), new ResourceShutdownStage("dependent", [ new("must-not-run", () => dependentCalls++), ])); Assert.Throws(transaction.CompleteOrThrow); Assert.Equal(2, failures); Assert.Equal(0, dependentCalls); Assert.False(transaction.IsComplete); } [Fact] public void ReentrantCompletionDoesNotReplayActiveOperation() { ResourceShutdownTransaction? transaction = null; int calls = 0; transaction = new ResourceShutdownTransaction( new ResourceShutdownStage("stage", [ new("reentrant", () => { calls++; transaction!.CompleteOrThrow(); }), ])); transaction.CompleteOrThrow(); Assert.Equal(1, calls); Assert.True(transaction.IsComplete); } }