using System.Collections.Concurrent; using CursorLang.Core.Services; using CursorLang.Tests.Shared; namespace CursorLang.Core.Tests.Services; /// /// The one thing the agent says to the settings window: quit with me. /// /// /// The event names here are the tests' own. The application's name is fixed, and a test /// listening on it would answer for a settings window someone is using — or, signalling, /// close it. /// public sealed class SettingsCloseSignalTests { [Fact] public void The_request_reaches_the_settings_window() { string suffix = UniqueSuffix(); var signal = new SettingsCloseSignal(suffix); ConcurrentQueue requests = new(); signal.CloseRequested += (_, e) => requests.Enqueue(e); try { signal.Listen(); Assert.True(RequestApart(suffix), "the request found nobody listening"); Pump.WaitFor(() => !requests.IsEmpty, "the settings window got the request to close"); } finally { signal.Dispose(); } } // The usual case: the user quits from the tray with no settings window on the screen [Fact] public void A_request_with_no_settings_window_open_passes_without_consequence() { Assert.False(RequestApart(UniqueSuffix())); } // The window has closed on its own, and the process is on its way out anyway [Fact] public void No_request_arrives_after_the_window_is_gone() { string suffix = UniqueSuffix(); var signal = new SettingsCloseSignal(suffix); ConcurrentQueue requests = new(); signal.CloseRequested += (_, e) => requests.Enqueue(e); signal.Listen(); signal.Dispose(); RequestApart(suffix); Pump.Pause(TimeSpan.FromMilliseconds(80)); Assert.Empty(requests); } [Fact] public void Listening_twice_leaves_one_listener() { string suffix = UniqueSuffix(); var signal = new SettingsCloseSignal(suffix); var requests = 0; signal.CloseRequested += (_, _) => Interlocked.Increment(ref requests); try { signal.Listen(); signal.Listen(); Assert.True(RequestApart(suffix)); Pump.WaitFor(() => Volatile.Read(ref requests) > 0, "the request arrived"); Pump.Pause(TimeSpan.FromMilliseconds(80)); Assert.Equal(1, Volatile.Read(ref requests)); } finally { signal.Dispose(); } } [Fact] public void Closing_without_listening_passes_without_consequence() { var signal = new SettingsCloseSignal(UniqueSuffix()); signal.Dispose(); signal.Dispose(); } // Every test gets a namespace of kernel objects of its own private static string UniqueSuffix() => "." + Guid.NewGuid().ToString("N"); /// /// Asks for the close the way the agent does it — from another process, and here /// from another thread, which is as foreign as a test can get. /// private static bool RequestApart(string suffix) { var heard = false; Pump.RunApart(() => heard = SettingsCloseSignal.RequestClose(suffix)); return heard; } }