using AcDream.App.Rendering; namespace AcDream.App.Tests.Rendering; public sealed class HostQuiescenceGateTests { [Fact] public async Task ExternalStopWaitsForAdmittedCallbackToReturn() { var gate = new HostQuiescenceGate(); using var callbackEntered = new ManualResetEventSlim(false); using var releaseCallback = new ManualResetEventSlim(false); int calls = 0; Task callback = Task.Run(() => gate.Invoke(() => { callbackEntered.Set(); Assert.True(releaseCallback.Wait(TimeSpan.FromSeconds(5))); calls++; })); Assert.True(callbackEntered.Wait(TimeSpan.FromSeconds(5))); using var stopStarted = new ManualResetEventSlim(false); Task stop = Task.Run(() => { stopStarted.Set(); gate.StopAccepting(); }); Assert.True(stopStarted.Wait(TimeSpan.FromSeconds(5))); await Task.Delay(50); Assert.False(stop.IsCompleted); releaseCallback.Set(); await callback; await stop; gate.Invoke(() => calls++); Assert.Equal(1, calls); Assert.False(gate.IsAccepting); } [Fact] public void CallbackCanStopGateReentrantlyWithoutDeadlock() { var gate = new HostQuiescenceGate(); int calls = 0; gate.Invoke(() => { calls++; gate.StopAccepting(); }); gate.Invoke(() => calls++); Assert.Equal(1, calls); Assert.False(gate.IsAccepting); } }