summaryrefslogtreecommitdiff
path: root/tests/Agent.Core.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Agent.Core.Tests')
-rw-r--r--tests/Agent.Core.Tests/ObservabilityTests.cs52
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);
+ }
+ }
}