Skip to content

Commit 08e7da1

Browse files
authored
Run integration test SSE server in process (#56)
* Run integration test SSE server in process * Handle expected OCE disposing fixture
1 parent 54e60fe commit 08e7da1

File tree

3 files changed

+28
-44
lines changed

3 files changed

+28
-44
lines changed

Diff for: tests/ModelContextProtocol.TestSseServer/Program.cs

+16-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
using System.Text;
77
using System.Text.Json;
88

9-
internal class Program
9+
namespace ModelContextProtocol.TestSseServer;
10+
11+
public class Program
1012
{
1113
private static ILoggerFactory CreateLoggerFactory()
1214
{
@@ -25,7 +27,9 @@ private static ILoggerFactory CreateLoggerFactory()
2527
});
2628
}
2729

28-
private static async Task Main(string[] args)
30+
public static Task Main(string[] args) => MainAsync(args);
31+
32+
public static async Task MainAsync(string[] args, CancellationToken cancellationToken = default)
2933
{
3034
Console.WriteLine("Starting server...");
3135

@@ -386,12 +390,19 @@ static CreateMessageRequestParams CreateRequestSamplingParams(string context, st
386390

387391
Console.WriteLine("Server initialized.");
388392

389-
await server.StartAsync();
393+
await server.StartAsync(cancellationToken);
390394

391395
Console.WriteLine("Server started.");
392396

393-
// Run until process is stopped by the client (parent process)
394-
await Task.Delay(Timeout.Infinite);
397+
try
398+
{
399+
// Run until process is stopped by the client (parent process) or test
400+
await Task.Delay(Timeout.Infinite, cancellationToken);
401+
}
402+
finally
403+
{
404+
await server.DisposeAsync();
405+
}
395406
}
396407

397408
const string MCP_TINY_IMAGE =

Diff for: tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj

-6
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,6 @@
3838
<Content Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="..\ModelContextProtocol.TestServer\bin\$(Configuration)\net8.0\TestServer.dll">
3939
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
4040
</Content>
41-
<Content Condition="$([MSBuild]::IsOSPlatform('Windows'))" Include="..\ModelContextProtocol.TestSseServer\bin\$(Configuration)\net8.0\TestSseServer.exe">
42-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
43-
</Content>
44-
<Content Condition="$([MSBuild]::IsOSPlatform('Linux'))" Include="..\ModelContextProtocol.TestSseServer\bin\$(Configuration)\net8.0\TestSseServer.dll">
45-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
46-
</Content>
4741
</ItemGroup>
4842

4943
</Project>
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
using ModelContextProtocol.Client;
1+
using Microsoft.Extensions.Logging;
2+
using ModelContextProtocol.Client;
23
using ModelContextProtocol.Configuration;
34
using ModelContextProtocol.Protocol.Transport;
4-
using Microsoft.Extensions.Logging;
5-
using System.Diagnostics;
6-
using System.Diagnostics.CodeAnalysis;
75

86
namespace ModelContextProtocol.Tests;
97

10-
public class SseServerIntegrationTestFixture : IDisposable
8+
public class SseServerIntegrationTestFixture : IAsyncDisposable
119
{
12-
private Process _process;
10+
private readonly CancellationTokenSource _stopCts = new();
11+
private readonly Task _serverTask;
1312

1413
public ILoggerFactory LoggerFactory { get; }
1514
public McpClientOptions DefaultOptions { get; }
@@ -35,40 +34,20 @@ public SseServerIntegrationTestFixture()
3534
Location = "http://localhost:3001/sse"
3635
};
3736

38-
Start();
37+
_serverTask = TestSseServer.Program.MainAsync([], _stopCts.Token);
3938
}
4039

41-
[MemberNotNull(nameof(_process))]
42-
public void Start()
43-
{
44-
// Start the server (which is at TestSseServer.exe on windows and "dotnet TestSseServer.dll" on linux)
45-
var processStartInfo = new ProcessStartInfo
46-
{
47-
FileName = OperatingSystem.IsWindows() ? "TestSseServer.exe" : "dotnet",
48-
Arguments = "TestSseServer.dll",
49-
RedirectStandardInput = true,
50-
RedirectStandardOutput = true,
51-
RedirectStandardError = true,
52-
UseShellExecute = false,
53-
};
54-
55-
_process = Process.Start(processStartInfo)
56-
?? throw new InvalidOperationException($"Could not start process for {processStartInfo.FileName} with '{processStartInfo.Arguments}'.");
57-
58-
// Wait 1 second
59-
Thread.Sleep(1000);
60-
}
61-
62-
public void Dispose()
40+
public async ValueTask DisposeAsync()
6341
{
42+
LoggerFactory.Dispose();
43+
_stopCts.Cancel();
6444
try
6545
{
66-
LoggerFactory?.Dispose();
46+
await _serverTask.ConfigureAwait(false);
6747
}
68-
finally
48+
catch (OperationCanceledException)
6949
{
70-
// Kill the server process
71-
_process.Kill();
7250
}
51+
_stopCts.Dispose();
7352
}
7453
}

0 commit comments

Comments
 (0)