Run integration test SSE server in process (#56)

* Run integration test SSE server in process

* Handle expected OCE disposing fixture
This commit is contained in:
Stephen Halter 2025-03-21 19:18:55 -07:00 • committed by GitHub
commit 08e7da100f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 28 additions and 44 deletions

View file

@ -6,7 +6,9 @@ using Serilog;
using System.Text;
using System.Text.Json;
internal class Program
namespace ModelContextProtocol.TestSseServer;
public class Program
{
private static ILoggerFactory CreateLoggerFactory()
{
@ -25,7 +27,9 @@ internal class Program
});
}
private static async Task Main(string[] args)
public static Task Main(string[] args) => MainAsync(args);
public static async Task MainAsync(string[] args, CancellationToken cancellationToken = default)
{
Console.WriteLine("Starting server...");
@ -386,12 +390,19 @@ internal class Program
Console.WriteLine("Server initialized.");
await server.StartAsync();
await server.StartAsync(cancellationToken);
Console.WriteLine("Server started.");
// Run until process is stopped by the client (parent process)
await Task.Delay(Timeout.Infinite);
try
{
// Run until process is stopped by the client (parent process) or test
await Task.Delay(Timeout.Infinite, cancellationToken);
}
finally
{
await server.DisposeAsync();
}
}
const string MCP_TINY_IMAGE =

View file

@ -38,12 +38,6 @@
<Content Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="..\ModelContextProtocol.TestServer\bin\$(Configuration)\net8.0\TestServer.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="..\ModelContextProtocol.TestSseServer\bin\$(Configuration)\net8.0\TestSseServer.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="..\ModelContextProtocol.TestSseServer\bin\$(Configuration)\net8.0\TestSseServer.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View file

@ -1,15 +1,14 @@
using ModelContextProtocol.Client;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Client;
using ModelContextProtocol.Configuration;
using ModelContextProtocol.Protocol.Transport;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
namespace ModelContextProtocol.Tests;
public class SseServerIntegrationTestFixture : IDisposable
public class SseServerIntegrationTestFixture : IAsyncDisposable
{
private Process _process;
private readonly CancellationTokenSource _stopCts = new();
private readonly Task _serverTask;
public ILoggerFactory LoggerFactory { get; }
public McpClientOptions DefaultOptions { get; }
@ -35,40 +34,20 @@ public class SseServerIntegrationTestFixture : IDisposable
Location = "http://localhost:3001/sse"
};
Start();
_serverTask = TestSseServer.Program.MainAsync([], _stopCts.Token);
}
[MemberNotNull(nameof(_process))]
public void Start()
{
// Start the server (which is at TestSseServer.exe on windows and "dotnet TestSseServer.dll" on linux)
var processStartInfo = new ProcessStartInfo
{
FileName = OperatingSystem.IsWindows() ? "TestSseServer.exe" : "dotnet",
Arguments = "TestSseServer.dll",
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
};
_process = Process.Start(processStartInfo)
?? throw new InvalidOperationException($"Could not start process for {processStartInfo.FileName} with '{processStartInfo.Arguments}'.");
// Wait 1 second
Thread.Sleep(1000);
}
public void Dispose()
public async ValueTask DisposeAsync()
{
LoggerFactory.Dispose();
_stopCts.Cancel();
try
{
LoggerFactory?.Dispose();
await _serverTask.ConfigureAwait(false);
}
finally
catch (OperationCanceledException)
{
// Kill the server process
_process.Kill();
}
_stopCts.Dispose();
}
}