Fix flaky OutgoingFilter_MultipleFilters_ExecuteInOrder test (#1488)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Eric StJohn 2026-04-02 09:27:37 -07:00 • committed by GitHub
commit d4c588b2f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5,6 +5,7 @@ using ModelContextProtocol.AspNetCore.Tests.Utils;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using ModelContextProtocol.Tests.Utils;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
@ -394,6 +395,7 @@ public abstract class MapMcpTests(ITestOutputHelper testOutputHelper) : KestrelI
public async Task OutgoingFilter_MultipleFilters_ExecuteInOrder()
{
var executionOrder = new List<string>();
var allFiltersComplete = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
Builder.Services.AddMcpServer()
.WithHttpTransport(ConfigureStateless)
@ -411,6 +413,7 @@ public abstract class MapMcpTests(ITestOutputHelper testOutputHelper) : KestrelI
if (context.JsonRpcMessage is JsonRpcResponse r2 && r2.Result is JsonObject obj2 && obj2.ContainsKey("tools"))
{
executionOrder.Add("filter1-after");
allFiltersComplete.TrySetResult();
}
});
@ -439,6 +442,14 @@ public abstract class MapMcpTests(ITestOutputHelper testOutputHelper) : KestrelI
await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
// The outermost filter's "after" callback runs after the response has been
// sent to the client, so ListToolsAsync may return before it executes.
// Wait for it to complete before asserting, but use a timeout to avoid hanging
// the test indefinitely if the filter pipeline regresses.
using var allFiltersCts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken);
allFiltersCts.CancelAfter(TestConstants.DefaultTimeout);
await allFiltersComplete.Task.WaitAsync(allFiltersCts.Token);
Assert.Equal(["filter1-before", "filter2-before", "filter2-after", "filter1-after"], executionOrder);
}