diff --git a/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs b/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs index 70ce43e..c921fd7 100644 --- a/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs +++ b/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs @@ -1175,8 +1175,11 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output) TestWorkerProcessFactory processFactory = new(output); await using GatewayServiceFixture fixture = new(workerExecutablePath, processFactory, output); + using RecordingServerStreamWriter eventWriter = new(); string? sessionId = null; + Task? streamTask = null; + using CancellationTokenSource streamCancellation = new(); try { @@ -1192,6 +1195,14 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output) sessionId = openReply.SessionId; Assert.Equal(ProtocolStatusCode.Ok, openReply.ProtocolStatus.Code); + // The gateway observes a worker's pipe closing through the event-stream read loop + // (the same path the abnormal-exit fact relies on); without a subscriber the session + // would sit in Ready until the heartbeat grace expired. + streamTask = fixture.Service.StreamEvents( + new StreamEventsRequest { SessionId = sessionId }, + eventWriter, + new TestServerCallContext(streamCancellation.Token)); + MxCommandReply shutdownReply = await fixture.Service.Invoke( CreateControlRequest(sessionId, "live-shutdown-worker", new MxCommand { @@ -1237,7 +1248,8 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output) finally { // The worker is gone; a CloseSession round-trip would only log a cleanup failure. - await ShutDownAsync(fixture, processFactory, sessionId: null, streamTask: null).ConfigureAwait(false); + streamCancellation.Cancel(); + await ShutDownAsync(fixture, processFactory, sessionId: null, streamTask).ConfigureAwait(false); } }