diff --git a/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs b/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs index 13bea7ae4..8b9126b8b 100644 --- a/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs +++ b/dotnet/test/E2E/RpcShellEdgeCaseE2ETests.cs @@ -35,7 +35,9 @@ public async Task Shell_Exec_With_Timeout_Kills_Long_Running_Command() ? $"echo started>\"{startedPath}\" & for /L %i in (1,1,2147483647) do @rem & echo should-not-exist>\"{markerPath}\"" : $"printf 'started' > '{startedPath}'; sleep 30; printf 'should-not-exist' > '{markerPath}'"; - var result = await session.Rpc.Shell.ExecAsync(command, timeout: TimeSpan.FromMilliseconds(200)); + // On Windows, terminating the shell wrapper can briefly leave children alive. + // Keep this long-running command outside the fixture workspace so cleanup is not blocked by cwd handles. + var result = await session.Rpc.Shell.ExecAsync(command, cwd: Path.GetTempPath(), timeout: TimeSpan.FromMilliseconds(200)); Assert.False(string.IsNullOrWhiteSpace(result.ProcessId)); await TestHelper.WaitForConditionAsync( @@ -120,7 +122,9 @@ public async Task Shell_Kill_Cleans_Up_After_Terminating_Signal(ShellKillSignal ? "powershell -NoLogo -NoProfile -Command \"Start-Sleep -Seconds 60\"" : "sleep 60"; - var execResult = await session.Rpc.Shell.ExecAsync(command); + // On Windows, terminating the shell wrapper can briefly leave grandchildren alive. + // Keep this command outside the fixture workspace so cleanup is not blocked by cwd handles. + var execResult = await session.Rpc.Shell.ExecAsync(command, cwd: Path.GetTempPath()); Assert.False(string.IsNullOrWhiteSpace(execResult.ProcessId)); var killResult = await session.Rpc.Shell.KillAsync(execResult.ProcessId, signal); diff --git a/dotnet/test/E2E/SessionE2ETests.cs b/dotnet/test/E2E/SessionE2ETests.cs index 50b4dc1f5..15aa3543d 100644 --- a/dotnet/test/E2E/SessionE2ETests.cs +++ b/dotnet/test/E2E/SessionE2ETests.cs @@ -5,6 +5,7 @@ using GitHub.Copilot.SDK.Test.Harness; using GitHub.Copilot.SDK.Rpc; using Microsoft.Extensions.AI; +using System.Collections.Concurrent; using System.ComponentModel; using Xunit; using Xunit.Abstractions; @@ -401,9 +402,9 @@ public async Task Send_Returns_Immediately_While_Events_Stream_In_Background() { OnPermissionRequest = PermissionHandler.ApproveAll, }); - var events = new List(); + var events = new ConcurrentQueue(); - session.On(evt => events.Add(evt.Type)); + session.On(evt => events.Enqueue(evt.Type)); // Use a slow command so we can verify SendAsync() returns before completion await session.SendAsync(new MessageOptions { Prompt = "Run 'sleep 2 && echo done'" }); @@ -423,9 +424,9 @@ public async Task Send_Returns_Immediately_While_Events_Stream_In_Background() public async Task SendAndWait_Blocks_Until_Session_Idle_And_Returns_Final_Assistant_Message() { var session = await CreateSessionAsync(); - var events = new List(); + var events = new ConcurrentQueue(); - session.On(evt => events.Add(evt.Type)); + session.On(evt => events.Enqueue(evt.Type)); var response = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2+2?" });