80 lines
3.0 KiB
C#
80 lines
3.0 KiB
C#
using ZB.MOM.WW.MxGateway.Server.Workers;
|
|
|
|
namespace ZB.MOM.WW.MxGateway.Tests.TestSupport;
|
|
|
|
/// <summary>
|
|
/// Lightweight in-process stand-in for <see cref="IWorkerProcess"/> used by fake worker
|
|
/// 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);
|
|
|
|
/// <summary>Gets the process identifier.</summary>
|
|
public int Id { get; } = processId;
|
|
|
|
/// <summary>Gets or sets a value indicating whether the process has exited.</summary>
|
|
public bool HasExited { get; 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)
|
|
{
|
|
KillCount++;
|
|
KillEntireProcessTree = entireProcessTree;
|
|
MarkExited(-1);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose() => IsDisposed = true;
|
|
|
|
/// <summary>
|
|
/// Marks the process as exited with the specified exit code and unblocks
|
|
/// any callers of <see cref="WaitForExitAsync"/>.
|
|
/// </summary>
|
|
/// <param name="exitCode">The process exit code.</param>
|
|
public void MarkExited(int exitCode)
|
|
{
|
|
HasExited = true;
|
|
ExitCode = exitCode;
|
|
_exited.TrySetResult();
|
|
}
|
|
}
|