diff options
Diffstat (limited to 'tests/Agent.Core.Tests')
| -rw-r--r-- | tests/Agent.Core.Tests/ObservabilityTests.cs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/tests/Agent.Core.Tests/ObservabilityTests.cs b/tests/Agent.Core.Tests/ObservabilityTests.cs index cd86bc2..c259eb0 100644 --- a/tests/Agent.Core.Tests/ObservabilityTests.cs +++ b/tests/Agent.Core.Tests/ObservabilityTests.cs @@ -1,6 +1,8 @@ using Agent.App.Logging; using Agent.Core.Localization; using Agent.Mcp; +using System.Diagnostics; +using System.Text; namespace Agent.Core.Tests; @@ -43,4 +45,54 @@ public sealed class ObservabilityTests Assert.DoesNotContain("Cookie", httpText, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("prompt", httpText, StringComparison.OrdinalIgnoreCase); } + + [Fact] + public void Http_request_callbacks_do_not_wait_for_a_blocked_console_writer() + { + using var directory = new TestDirectory(); + using var console = new BlockingTextWriter(); + LocaleCatalog locale = LocaleCatalog.Load(Path.GetFullPath("config/locales"), "en"); + using var application = new RollingFileLog(directory.Path, 1024 * 1024, 2, consoleWriter: console); + using var observer = new McpHostLogObserver(application, locale, directory.Path, true, 1024 * 1024, 2); + + observer.HttpRequestStarted(new McpHttpRequestStartInfo("connection", "trace-1", "127.0.0.1", 50123, "POST", "/mcp")); + Assert.True(console.WaitUntilBlocked(TimeSpan.FromSeconds(5)), "Background writer did not reach the blocking console."); + + var stopwatch = Stopwatch.StartNew(); + observer.HttpRequest(new McpHttpRequestInfo(DateTimeOffset.UtcNow, "connection", "trace-2", "127.0.0.1", 50124, + "127.0.0.1", 8080, "POST", "/mcp", 200, 12.5, "application/json", 100, "test-client", + "2026-07-28", "tools/list", null)); + stopwatch.Stop(); + + Assert.True(stopwatch.Elapsed < TimeSpan.FromMilliseconds(250), $"HTTP callback blocked for {stopwatch.Elapsed}."); + console.Release(); + } + + private sealed class BlockingTextWriter : TextWriter + { + private readonly ManualResetEventSlim _entered = new(false); + private readonly ManualResetEventSlim _release = new(false); + + public override Encoding Encoding => Encoding.UTF8; + + public override void WriteLine(string? value) + { + _entered.Set(); + _release.Wait(TimeSpan.FromSeconds(30)); + } + + public bool WaitUntilBlocked(TimeSpan timeout) => _entered.Wait(timeout); + public void Release() => _release.Set(); + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _release.Set(); + _entered.Dispose(); + _release.Dispose(); + } + base.Dispose(disposing); + } + } } |
