Skip to content

Commit 34824d9

Browse files
yotsudaclaude
andcommitted
test(proxy): allocate unique sub-agent id per test instance to deflake parallel runs
PipeDiscoveryServiceTests and PowerShellToolsTests both used the constant agent id "default" while reaching into the static ConsoleSessionManager.Instance for state mutations (SetActivePipeName / SetLastAiCwd / MarkPipeBusy / ClearDeadPipe / TryAssignNameToPid). xunit parallelizes test classes by default, so two classes touching state keyed by the same "default" id can race — seen in CI on Windows as a transient null AllPipesStatusInfo from FindReadyPipeAsync_ActivePipeBusy_RecordsStatusInfo, while the same test was green on the next run with no code change. Switch to ConsoleSessionManager.Instance.AllocateSubAgentId() in each class''s constructor (xunit creates a fresh instance per test method, so each test gets its own id). The session manager already uses this id everywhere as an opaque dictionary key, and IPipeDiscoveryService / PowerShellTools accept any non-empty agent id once it''s in the allocated set, so no production-code change is needed. For PowerShellToolsTests the TestPipeName format string is also derived from the new TestAgentId so any code that re-derives the agent id from a pipe name segment sees a consistent value. ConsoleSessionManagerTests was already mostly clean (it allocates per-test ids via the same helper) so no change there. Its one "default"-using test has a comment acknowledging the leak is benign because no other test reads that key. xunit local: net8 162/162, net9 275/275. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 97f4002 commit 34824d9

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

Tests/Unit/Proxy/PipeDiscoveryServiceTests.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@ public class PipeDiscoveryServiceTests
99
{
1010
private readonly Mock<IPowerShellService> _mockPowerShellService;
1111
private readonly PipeDiscoveryService _service;
12-
private const string DefaultAgentId = "default";
12+
// Allocate a unique sub-agent id per test instance (xunit creates one per test
13+
// method) so concurrent test classes touching the static ConsoleSessionManager.Instance
14+
// — which keys all state by agent id — can't trample each other. A previous run hit
15+
// a flaky failure on Windows where another suite''s "default" entry had cleared this
16+
// class''s active-pipe registration mid-test. The variable name stays for diff clarity.
17+
private readonly string DefaultAgentId;
1318

1419
public PipeDiscoveryServiceTests()
1520
{
1621
_mockPowerShellService = new Mock<IPowerShellService>();
1722
_service = new PipeDiscoveryService(_mockPowerShellService.Object);
23+
DefaultAgentId = ConsoleSessionManager.Instance.AllocateSubAgentId();
1824
}
1925

2026
#region DetectClosedConsoles Tests

Tests/Unit/Proxy/PowerShellToolsTests.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,23 @@ public class PowerShellToolsTests
1717
{
1818
private readonly Mock<IPowerShellService> _mockPowerShellService;
1919
private readonly Mock<IPipeDiscoveryService> _mockPipeDiscoveryService;
20-
private const string TestAgentId = "default";
21-
private const string TestPipeName = "PSMCP.1000.default.2000";
20+
// Allocate a unique sub-agent id per test instance (xunit creates one per test
21+
// method) so concurrent test classes touching the static ConsoleSessionManager.Instance
22+
// — which keys all state by agent id — can't trample each other. A previous run hit
23+
// a flaky failure on Windows where another suite''s "default" entry had cleared this
24+
// class''s active-pipe registration mid-test. Names kept for diff clarity.
25+
private readonly string TestAgentId;
26+
private readonly string TestPipeName;
2227

2328
public PowerShellToolsTests()
2429
{
2530
_mockPowerShellService = new Mock<IPowerShellService>();
2631
_mockPipeDiscoveryService = new Mock<IPipeDiscoveryService>();
32+
TestAgentId = ConsoleSessionManager.Instance.AllocateSubAgentId();
33+
// Pipe name format: PSMCP.{proxyPid}.{agentId}.{pwshPid}. Match the agent id
34+
// so any code that re-derives agentId from the pipe name (or filters by it)
35+
// sees consistent values.
36+
TestPipeName = $"PSMCP.1000.{TestAgentId}.2000";
2737
}
2838

2939
#region GetCurrentLocation Tests

0 commit comments

Comments
 (0)