From 8058fb1c5b4ff6228e7f72893fa81a3fa7d2f952 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 11:36:42 -0400 Subject: [PATCH] .NET: Fix flaky InputWaiter_WaitForInputAsync_BlocksUntilSignaledAsync (#5835) * test: remove finite timeout in BlocksUntilSignaledAsync to fix race Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/962b7404-4266-4a16-906c-ba3e607c2764 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> * address review: clarify comment, add timeout test, cross-reference test names Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/e406a5f2-ad31-4d37-b090-69e10713f885 Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com> Co-authored-by: Jacob Alber --- .../InputWaiterAndOutputFilterTests.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/InputWaiterAndOutputFilterTests.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/InputWaiterAndOutputFilterTests.cs index dead5454b4..c7c231c63e 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/InputWaiterAndOutputFilterTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/InputWaiterAndOutputFilterTests.cs @@ -34,7 +34,13 @@ public sealed class InputWaiterTests : IDisposable [Fact] public async Task InputWaiter_WaitForInputAsync_BlocksUntilSignaledAsync() { - Task waitTask = this._waiter.WaitForInputAsync(TimeSpan.FromSeconds(5)); + // Use the no-timeout overload so that the wait can only be released by SignalInput. + // A finite timeout would make this test's logic racy: the component correctly + // honors the timeout, but if the test thread is starved of CPU time (CI load, + // GC pause) long enough for the timeout to fire, waitTask completes before + // SignalInput is called and the "should not complete before signaled" assertion + // flakes. Timeout behavior is covered separately below. + Task waitTask = this._waiter.WaitForInputAsync(CancellationToken.None); Task completedBeforeSignal = await Task.WhenAny(waitTask, Task.Delay(100)); completedBeforeSignal.Should().NotBeSameAs( @@ -100,6 +106,21 @@ public sealed class InputWaiterTests : IDisposable this._waiter.SignalInput(); await this._waiter.WaitForInputAsync(TimeSpan.FromSeconds(1)); } + + [Fact] + public async Task InputWaiter_WaitForInputAsync_CompletesWhenTimeoutExpiresAsync() + { + // Verify that a finite timeout releases the block even without a signal. + // We only assert that it *does* complete (within a generous outer bound); + // we intentionally do not assert that it stays blocked until the timeout, + // because that would re-introduce the same wall-clock flakiness + // described in BlocksUntilSignaledAsync (see comment on that test). + Task waitTask = this._waiter.WaitForInputAsync(TimeSpan.FromMilliseconds(300)); + + Task completed = await Task.WhenAny(waitTask, Task.Delay(TimeSpan.FromSeconds(5))); + completed.Should().BeSameAs(waitTask, "the wait task should complete once the timeout expires"); + await waitTask; + } } public class OutputFilterTests