diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
index a61cb96..11b09d5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
@@ -7,6 +7,7 @@ using ZB.MOM.WW.MxGateway.Server.Metrics;
using ZB.MOM.WW.MxGateway.Server.Sessions;
using ZB.MOM.WW.MxGateway.Server.Workers;
using ZB.MOM.WW.MxGateway.Tests.Gateway.Workers.Fakes;
+using ZB.MOM.WW.MxGateway.Tests.TestSupport;
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Sessions;
@@ -330,62 +331,4 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
DateTimeOffset.UtcNow);
}
- ///
- /// Fake worker process for testing process lifecycle.
- /// awaits a completed only by
- /// or , so a caller observing
- /// completion can trust that exit actually happened — bringing this fake into
- /// parity with the smoke-test variant in GatewayEndToEndFakeWorkerSmokeTests
- /// (Tests-015 / Tests-023). This removes the latent regression vector where a
- /// future Assert.True(launcher.Process.HasExited) in this file would
- /// pass spuriously regardless of whether the worker truly exited.
- ///
- private sealed class FakeWorkerProcess(int processId) : IWorkerProcess
- {
- private readonly TaskCompletionSource _exited = new(TaskCreationOptions.RunContinuationsAsynchronously);
- private bool _disposed;
-
- ///
- public int Id { get; } = processId;
-
- /// Gets a value indicating whether the process has exited.
- public bool HasExited { get; private set; }
-
- /// Gets the process exit code, or null if the process has not exited.
- public int? ExitCode { get; private set; }
-
- /// Gets the number of times the Kill method was called.
- public int KillCount { get; private set; }
-
- ///
- public ValueTask WaitForExitAsync(CancellationToken cancellationToken)
- {
- return new ValueTask(_exited.Task.WaitAsync(cancellationToken));
- }
-
- ///
- public void Kill(bool entireProcessTree)
- {
- KillCount++;
- MarkExited(-1);
- }
-
- ///
- public void Dispose()
- {
- _disposed = true;
- }
-
- /// Gets a value indicating whether this process has been disposed.
- public bool IsDisposed => _disposed;
-
- /// Marks the process as exited with the specified exit code.
- /// The process exit code.
- public void MarkExited(int exitCode)
- {
- HasExited = true;
- ExitCode = exitCode;
- _exited.TrySetResult();
- }
- }
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
index 7d46680..9750c14 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
@@ -158,7 +158,7 @@ public sealed class WorkerClientTests
public async Task ReadLoop_WhenClientFaults_KillsOwnedWorkerProcess()
{
await using PipePair pipePair = await PipePair.CreateAsync();
- FakeWorkerProcess process = new();
+ FakeWorkerProcess process = new(WorkerProcessId);
await using WorkerClient client = CreateClient(
pipePair,
new WorkerClientOptions
@@ -309,7 +309,7 @@ public sealed class WorkerClientTests
public async Task DisposeAsync_WhenOwnedWorkerStillRuns_KillsProcessBeforeDisposing()
{
await using PipePair pipePair = await PipePair.CreateAsync();
- FakeWorkerProcess process = new();
+ FakeWorkerProcess process = new(WorkerProcessId);
WorkerClient client = CreateClient(pipePair, processHandle: CreateProcessHandle(process));
await client.DisposeAsync().AsTask().WaitAsync(TestTimeout);
@@ -764,49 +764,4 @@ public sealed class WorkerClientTests
}
}
- private sealed class FakeWorkerProcess : IWorkerProcess
- {
- private readonly TaskCompletionSource _exited = new(TaskCreationOptions.RunContinuationsAsynchronously);
-
- /// Gets the process ID.
- public int Id { get; } = WorkerProcessId;
-
- /// Gets a value indicating whether the process has exited.
- public bool HasExited { get; private set; }
-
- /// Gets the process exit code.
- public int? ExitCode { get; private set; }
-
- /// Gets the number of times kill was called.
- public int KillCount { get; private set; }
-
- /// Gets the last kill request's entire process tree flag.
- public bool KillEntireProcessTree { get; private set; }
-
- /// Gets a value indicating whether dispose was called.
- public bool Disposed { get; private set; }
-
- ///
- public ValueTask WaitForExitAsync(CancellationToken cancellationToken)
- {
- return new ValueTask(_exited.Task.WaitAsync(cancellationToken));
- }
-
- /// Records a kill request.
- /// Whether to kill the entire process tree.
- public void Kill(bool entireProcessTree)
- {
- KillCount++;
- KillEntireProcessTree = entireProcessTree;
- HasExited = true;
- ExitCode = -1;
- _exited.TrySetResult();
- }
-
- ///
- public void Dispose()
- {
- Disposed = true;
- }
- }
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs
index f8f93a5..adeacf1 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs
@@ -4,6 +4,7 @@ using ZB.MOM.WW.MxGateway.Contracts;
using ZB.MOM.WW.MxGateway.Server.Configuration;
using ZB.MOM.WW.MxGateway.Server.Metrics;
using ZB.MOM.WW.MxGateway.Server.Workers;
+using ZB.MOM.WW.MxGateway.Tests.TestSupport;
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Workers;
@@ -240,45 +241,6 @@ public sealed class WorkerProcessLauncherTests
}
}
- /// Fake worker process for testing process lifecycle and exit behavior.
- private sealed class FakeWorkerProcess(int processId) : IWorkerProcess
- {
- ///
- public int Id { get; } = processId;
-
- /// Gets or sets a value indicating whether the process has exited.
- public bool HasExited { get; set; }
-
- /// Gets or sets the process exit code.
- public int? ExitCode { get; set; }
-
- /// Gets a value indicating whether the Dispose method was called.
- public bool DisposeCalled { get; private set; }
-
- /// Gets a value indicating whether the Kill method was called.
- public bool KillCalled { get; private set; }
-
- ///
- public ValueTask WaitForExitAsync(CancellationToken cancellationToken)
- {
- return ValueTask.CompletedTask;
- }
-
- ///
- public void Kill(bool entireProcessTree)
- {
- Assert.True(entireProcessTree);
- KillCalled = true;
- HasExited = true;
- }
-
- ///
- public void Dispose()
- {
- DisposeCalled = true;
- }
- }
-
/// Fake startup probe that immediately succeeds.
private sealed class SucceedingStartupProbe : IWorkerStartupProbe
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/FakeWorkerProcess.cs b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/FakeWorkerProcess.cs
index f65897f..2bb0386 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/FakeWorkerProcess.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/TestSupport/FakeWorkerProcess.cs
@@ -4,10 +4,21 @@ namespace ZB.MOM.WW.MxGateway.Tests.TestSupport;
///
/// Lightweight in-process stand-in for used by fake worker
-/// launchers in end-to-end tests. Call from the fake worker
-/// body once the shutdown-ack handshake is complete so that callers awaiting
-/// observe real exit rather than a timeout.
+/// launchers and lifecycle tests.
///
+///
+///
+/// awaits a that is
+/// completed only by or , so a caller observing
+/// completion can trust that exit actually happened rather than passing spuriously.
+///
+///
+/// The disposal and kill bookkeeping is exposed under several aliases
+/// (//;
+/// /) so the various lifecycle tests can
+/// keep their existing assertion vocabulary while sharing one definition.
+///
+///
public sealed class FakeWorkerProcess(int processId) : IWorkerProcess
{
private readonly TaskCompletionSource _exited = new(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -15,23 +26,44 @@ public sealed class FakeWorkerProcess(int processId) : IWorkerProcess
/// Gets the process identifier.
public int Id { get; } = processId;
- /// Gets a value indicating whether the process has exited.
- public bool HasExited { get; private set; }
+ /// Gets or sets a value indicating whether the process has exited.
+ public bool HasExited { get; set; }
- /// Gets the exit code of the process, or if it has not exited.
- public int? ExitCode { get; private set; }
+ /// Gets or sets the exit code of the process, or if it has not exited.
+ public int? ExitCode { get; set; }
+
+ /// Gets the number of times was called.
+ public int KillCount { get; private set; }
+
+ /// Gets a value indicating whether was called at least once.
+ public bool KillCalled => KillCount > 0;
+
+ /// Gets the entireProcessTree flag from the most recent call.
+ public bool KillEntireProcessTree { get; private set; }
+
+ /// Gets a value indicating whether was called.
+ public bool IsDisposed { get; private set; }
+
+ /// Gets a value indicating whether was called.
+ public bool DisposeCalled => IsDisposed;
+
+ /// Gets a value indicating whether was called.
+ public bool Disposed => IsDisposed;
///
public ValueTask WaitForExitAsync(CancellationToken cancellationToken) =>
new(_exited.Task.WaitAsync(cancellationToken));
///
- public void Kill(bool entireProcessTree) => MarkExited(-1);
+ public void Kill(bool entireProcessTree)
+ {
+ KillCount++;
+ KillEntireProcessTree = entireProcessTree;
+ MarkExited(-1);
+ }
///
- public void Dispose()
- {
- }
+ public void Dispose() => IsDisposed = true;
///
/// Marks the process as exited with the specified exit code and unblocks