refactor(tests): consolidate FakeWorkerProcess onto TestSupport canonical

This commit is contained in:
Joseph Doherty
2026-06-16 17:14:03 -04:00
parent 3bb4d5a082
commit 01bdb484de
4 changed files with 47 additions and 155 deletions
@@ -4,10 +4,21 @@ namespace ZB.MOM.WW.MxGateway.Tests.TestSupport;
/// <summary>
/// Lightweight in-process stand-in for <see cref="IWorkerProcess"/> used by fake worker
/// launchers in end-to-end tests. Call <see cref="MarkExited"/> from the fake worker
/// body once the shutdown-ack handshake is complete so that callers awaiting
/// <see cref="WaitForExitAsync"/> observe real exit rather than a timeout.
/// launchers and lifecycle tests.
/// </summary>
/// <remarks>
/// <para>
/// <see cref="WaitForExitAsync"/> awaits a <see cref="TaskCompletionSource"/> that is
/// completed only by <see cref="Kill"/> or <see cref="MarkExited"/>, so a caller observing
/// completion can trust that exit actually happened rather than passing spuriously.
/// </para>
/// <para>
/// The disposal and kill bookkeeping is exposed under several aliases
/// (<see cref="IsDisposed"/>/<see cref="DisposeCalled"/>/<see cref="Disposed"/>;
/// <see cref="KillCount"/>/<see cref="KillCalled"/>) so the various lifecycle tests can
/// keep their existing assertion vocabulary while sharing one definition.
/// </para>
/// </remarks>
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
/// <summary>Gets the process identifier.</summary>
public int Id { get; } = processId;
/// <summary>Gets a value indicating whether the process has exited.</summary>
public bool HasExited { get; private set; }
/// <summary>Gets or sets a value indicating whether the process has exited.</summary>
public bool HasExited { get; set; }
/// <summary>Gets the exit code of the process, or <see langword="null"/> if it has not exited.</summary>
public int? ExitCode { get; private set; }
/// <summary>Gets or sets the exit code of the process, or <see langword="null"/> if it has not exited.</summary>
public int? ExitCode { get; set; }
/// <summary>Gets the number of times <see cref="Kill"/> was called.</summary>
public int KillCount { get; private set; }
/// <summary>Gets a value indicating whether <see cref="Kill"/> was called at least once.</summary>
public bool KillCalled => KillCount > 0;
/// <summary>Gets the <c>entireProcessTree</c> flag from the most recent <see cref="Kill"/> call.</summary>
public bool KillEntireProcessTree { get; private set; }
/// <summary>Gets a value indicating whether <see cref="Dispose"/> was called.</summary>
public bool IsDisposed { get; private set; }
/// <summary>Gets a value indicating whether <see cref="Dispose"/> was called.</summary>
public bool DisposeCalled => IsDisposed;
/// <summary>Gets a value indicating whether <see cref="Dispose"/> was called.</summary>
public bool Disposed => IsDisposed;
/// <inheritdoc />
public ValueTask WaitForExitAsync(CancellationToken cancellationToken) =>
new(_exited.Task.WaitAsync(cancellationToken));
/// <inheritdoc />
public void Kill(bool entireProcessTree) => MarkExited(-1);
public void Kill(bool entireProcessTree)
{
KillCount++;
KillEntireProcessTree = entireProcessTree;
MarkExited(-1);
}
/// <inheritdoc />
public void Dispose()
{
}
public void Dispose() => IsDisposed = true;
/// <summary>
/// Marks the process as exited with the specified exit code and unblocks