docs(src): add missing XML docs and strip tracking-ID comments
Sweep of 203 source files resolving CommentChecker findings: add <summary>/<param>/<returns>/<inheritdoc> where missing, and remove resolved task/issue tracking markers (Tests-NNN, Worker-NNN, Server-NNN, Task N) from code comments. Comment/doc-only — no logic changes. Server+Tests build clean under TreatWarningsAsErrors.
This commit is contained in:
@@ -11,6 +11,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>Verifies that completing startup with hello and ready transitions the client to ready state.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task CompleteStartupAsync_WithHelloAndReady_TransitionsClientToReady()
|
||||
{
|
||||
@@ -28,6 +29,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a protocol version mismatch during startup fails the client.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task StartAsync_WithProtocolMismatch_FailsStartup()
|
||||
{
|
||||
@@ -47,6 +49,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a scripted reply completes a pending command invocation.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WithScriptedReply_CompletesCommand()
|
||||
{
|
||||
@@ -69,6 +72,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that scripted events are yielded in order through the event stream.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadEventsAsync_WithScriptedEvents_YieldsOrderedEvents()
|
||||
{
|
||||
@@ -93,6 +97,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a scripted fault from the worker faults the client.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WithScriptedFault_FaultsClient()
|
||||
{
|
||||
@@ -116,6 +121,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
/// <see cref="ManualTimeProvider"/> so the timestamp advance is deterministic rather
|
||||
/// than relying on a wall-clock <c>Task.Delay</c> exceeding clock resolution.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task SendHeartbeatAsync_UpdatesClientHeartbeatState()
|
||||
{
|
||||
@@ -138,6 +144,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a hung worker times out pending command invocations.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WithHungWorker_TimesOutPendingCommand()
|
||||
{
|
||||
@@ -159,6 +166,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a malformed frame in the read loop faults the client.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WithMalformedFrame_FaultsClient()
|
||||
{
|
||||
@@ -176,6 +184,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a shutdown acknowledgment from the worker closes the client.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ShutdownAsync_WithShutdownAck_ClosesClient()
|
||||
{
|
||||
@@ -196,6 +205,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
/// Verifies that RespondToControlCommandAsync echoes the Ping message back
|
||||
/// in the DiagnosticMessage field, matching the real worker's ping reply shape.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RespondToControlCommandAsync_Ping_EchoesMessageInDiagnostic()
|
||||
{
|
||||
@@ -220,6 +230,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
/// Verifies that RespondToControlCommandAsync returns a SessionStateReply
|
||||
/// with state Ready for a GetSessionState command.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RespondToControlCommandAsync_GetSessionState_ReturnsReadyState()
|
||||
{
|
||||
@@ -245,6 +256,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
/// Verifies that RespondToControlCommandAsync returns a WorkerInfoReply
|
||||
/// with the fake worker's process ID, version, and MXAccess identifiers.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RespondToControlCommandAsync_GetWorkerInfo_ReturnsFakeWorkerInfo()
|
||||
{
|
||||
@@ -273,6 +285,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
/// Verifies that RespondToControlCommandAsync returns an empty DrainEventsReply
|
||||
/// for a DrainEvents command (the fake harness has no queued events).
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RespondToControlCommandAsync_DrainEvents_ReturnsEmptyReply()
|
||||
{
|
||||
@@ -298,6 +311,7 @@ public sealed class FakeWorkerHarnessTests
|
||||
/// Verifies that RespondToControlCommandAsync for ShutdownWorker sends an OK
|
||||
/// reply followed by a WorkerShutdownAck, which closes the client.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RespondToControlCommandAsync_ShutdownWorker_SendsReplyThenAck()
|
||||
{
|
||||
|
||||
@@ -52,6 +52,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="protocolVersion">Protocol version for frame communication.</param>
|
||||
/// <param name="maxMessageBytes">Maximum message size in bytes.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>The connected fake worker harness.</returns>
|
||||
public static async Task<FakeWorkerHarness> CreateConnectedPairAsync(
|
||||
string sessionId = DefaultSessionId,
|
||||
string nonce = DefaultNonce,
|
||||
@@ -87,6 +88,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="protocolVersion">Protocol version for frame communication.</param>
|
||||
/// <param name="maxMessageBytes">Maximum message size in bytes.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>The connected fake worker harness.</returns>
|
||||
public static async Task<FakeWorkerHarness> ConnectToGatewayPipeAsync(
|
||||
string sessionId,
|
||||
string nonce,
|
||||
@@ -205,6 +207,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="workerProtocolVersion">Protocol version override.</param>
|
||||
/// <param name="nonce">Nonce override.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task SendWorkerHelloAsync(
|
||||
int workerProcessId = DefaultWorkerProcessId,
|
||||
string workerVersion = "fake-worker",
|
||||
@@ -230,6 +233,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="mxaccessProgid">MXAccess COM ProgID.</param>
|
||||
/// <param name="mxaccessClsid">MXAccess COM CLSID.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task SendWorkerReadyAsync(
|
||||
int workerProcessId = DefaultWorkerProcessId,
|
||||
string mxaccessProgid = "LMXProxy.LMXProxyServer.1",
|
||||
@@ -255,6 +259,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="statusMessage">Human-readable status message.</param>
|
||||
/// <param name="configureReply">Optional callback to customize the reply.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task ReplyToCommandAsync(
|
||||
WorkerEnvelope commandEnvelope,
|
||||
ProtocolStatusCode statusCode = ProtocolStatusCode.Ok,
|
||||
@@ -296,6 +301,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="family">Family of the event to emit.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <param name="configureEvent">Optional callback to customize the event.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task EmitEventAsync(
|
||||
MxEventFamily family,
|
||||
CancellationToken cancellationToken = default,
|
||||
@@ -325,6 +331,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="category">Category of the fault.</param>
|
||||
/// <param name="diagnosticMessage">Diagnostic message describing the fault.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task EmitFaultAsync(
|
||||
WorkerFaultCategory category,
|
||||
string diagnosticMessage,
|
||||
@@ -350,6 +357,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <param name="state">Current worker state.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <param name="configureHeartbeat">Optional callback to customize the heartbeat.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task SendHeartbeatAsync(
|
||||
WorkerState state = WorkerState.Ready,
|
||||
CancellationToken cancellationToken = default,
|
||||
@@ -373,6 +381,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <summary>Sends a shutdown acknowledgment message to the gateway.</summary>
|
||||
/// <param name="statusCode">Protocol status code for the acknowledgment.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task SendShutdownAckAsync(
|
||||
ProtocolStatusCode statusCode = ProtocolStatusCode.Ok,
|
||||
CancellationToken cancellationToken = default)
|
||||
@@ -506,6 +515,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <summary>Writes a malformed payload directly to the worker stream.</summary>
|
||||
/// <param name="payload">Malformed payload bytes to write.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task WriteMalformedPayloadAsync(
|
||||
ReadOnlyMemory<byte> payload,
|
||||
CancellationToken cancellationToken = default)
|
||||
@@ -524,6 +534,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
/// <summary>Writes an oversized frame header to the worker stream for testing frame size limits.</summary>
|
||||
/// <param name="payloadLength">Length of the oversized payload in bytes.</param>
|
||||
/// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task WriteOversizedFrameHeaderAsync(
|
||||
uint payloadLength,
|
||||
CancellationToken cancellationToken = default)
|
||||
@@ -542,6 +553,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>Disposes the worker-side stream.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeWorkerSideAsync()
|
||||
{
|
||||
if (_workerSideDisposed)
|
||||
@@ -553,7 +565,8 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
|
||||
_workerSideDisposed = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Disposes the worker-side and (if owned) gateway-side pipe streams.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await DisposeWorkerSideAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -6,7 +6,7 @@ using ZB.MOM.WW.MxGateway.Server.Workers;
|
||||
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Workers;
|
||||
|
||||
/// <summary>
|
||||
/// Server-002 regression: per <c>gateway.md</c> the gateway must terminate
|
||||
/// Per <c>gateway.md</c> the gateway must terminate
|
||||
/// orphaned worker processes on startup. These tests pin that the terminator
|
||||
/// kills leftover workers (matched by executable path, or by image name when
|
||||
/// the path is unreadable) without touching unrelated processes or itself.
|
||||
@@ -129,12 +129,10 @@ public sealed class OrphanWorkerTerminatorTests
|
||||
/// <summary>Gets or sets the process ID that should throw when killed.</summary>
|
||||
public int? ThrowOnKillProcessId { get; init; }
|
||||
|
||||
/// <summary>Gets the list of running processes by name.</summary>
|
||||
/// <param name="processName">The process name to search for.</param>
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<RunningProcessInfo> GetProcessesByName(string processName) => processes;
|
||||
|
||||
/// <summary>Kills the specified process or records the kill attempt.</summary>
|
||||
/// <param name="processId">The process identifier to kill.</param>
|
||||
/// <inheritdoc />
|
||||
public void Kill(int processId)
|
||||
{
|
||||
if (ThrowOnKillProcessId == processId)
|
||||
|
||||
@@ -16,6 +16,7 @@ public sealed class WorkerClientTests
|
||||
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>Verifies that StartAsync enters ready state after receiving worker hello and ready messages.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task StartAsync_WithWorkerHelloAndReady_EntersReadyState()
|
||||
{
|
||||
@@ -29,6 +30,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that InvokeAsync completes a pending command when a matching reply arrives.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WithMatchingReply_CompletesPendingCommand()
|
||||
{
|
||||
@@ -55,6 +57,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that InvokeAsync ignores late replies and keeps the client ready.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WithLateReply_IgnoresLateReplyAndKeepsClientReady()
|
||||
{
|
||||
@@ -93,6 +96,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ReadEventsAsync yields events in pipe order from the worker.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadEventsAsync_WithWorkerEvents_YieldsEventsInPipeOrder()
|
||||
{
|
||||
@@ -119,6 +123,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the read loop faults the client when the event queue overflows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WhenEventQueueOverflows_FaultsClient()
|
||||
{
|
||||
@@ -154,6 +159,7 @@ public sealed class WorkerClientTests
|
||||
/// <c>Faulted</c> state before it calls <c>KillOwnedProcess</c>, so a state-based
|
||||
/// wait can observe <c>Faulted</c> while <c>KillCount</c> is still 0.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WhenClientFaults_KillsOwnedWorkerProcess()
|
||||
{
|
||||
@@ -192,6 +198,7 @@ public sealed class WorkerClientTests
|
||||
/// invoke task with a <see cref="WorkerClientException"/> carrying the
|
||||
/// pipe-disconnected error code rather than hanging until the command timeout.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WhenPipeDisconnectsMidCommand_FailsPendingInvokeWithPipeDisconnected()
|
||||
{
|
||||
@@ -223,6 +230,7 @@ public sealed class WorkerClientTests
|
||||
/// task with a <see cref="WorkerClientException"/> carrying the worker-faulted
|
||||
/// error code.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WhenWorkerFaultsMidCommand_FailsPendingInvokeWithWorkerFaulted()
|
||||
{
|
||||
@@ -248,6 +256,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that pipe disconnect faults the client.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WhenPipeDisconnects_FaultsClient()
|
||||
{
|
||||
@@ -265,6 +274,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the read loop stops the running worker metric when the pipe disconnects.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WhenPipeDisconnects_StopsRunningWorkerMetric()
|
||||
{
|
||||
@@ -288,6 +298,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that DisposeAsync returns within a bounded timeout when the pipe read is blocked.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task DisposeAsync_WhenPipeReadIsBlocked_ReturnsWithinBoundedTimeout()
|
||||
{
|
||||
@@ -304,7 +315,8 @@ public sealed class WorkerClientTests
|
||||
$"DisposeAsync took {elapsed.TotalMilliseconds:N0}ms.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the read loop updates the last heartbeat and worker process when a heartbeat arrives.</summary>
|
||||
/// <summary>Verifies that DisposeAsync kills the still-running owned worker process before disposing.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task DisposeAsync_WhenOwnedWorkerStillRuns_KillsProcessBeforeDisposing()
|
||||
{
|
||||
@@ -325,6 +337,7 @@ public sealed class WorkerClientTests
|
||||
/// deterministic instead of relying on a wall-clock <c>Task.Delay</c> exceeding
|
||||
/// <see cref="DateTimeOffset.UtcNow"/> resolution.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadLoop_WhenHeartbeatArrives_UpdatesLastHeartbeatAndWorkerProcess()
|
||||
{
|
||||
@@ -352,6 +365,7 @@ public sealed class WorkerClientTests
|
||||
/// <see cref="WorkerClientOptions.HeartbeatCheckInterval"/> timer stays on the real clock and
|
||||
/// observes the manually-advanced grace on its next tick.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task HeartbeatMonitor_WhenHeartbeatExpires_FaultsClient()
|
||||
{
|
||||
@@ -378,13 +392,14 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server-031 regression: while a command is in flight on the
|
||||
/// While a command is in flight on the
|
||||
/// gateway↔worker pipe and the oldest pending command is younger
|
||||
/// than <see cref="WorkerClientOptions.HeartbeatStuckCeiling"/>, the
|
||||
/// heartbeat watchdog must NOT fault on heartbeat-expired alone — the
|
||||
/// gap is more likely caused by pipe-write contention than by a hung
|
||||
/// worker. Mirrors Worker-023 on the worker side.
|
||||
/// worker.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task HeartbeatMonitor_WhenCommandInFlightWithinCeiling_DoesNotFaultOnExpiredHeartbeat()
|
||||
{
|
||||
@@ -422,11 +437,12 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server-031 regression: once the oldest pending command exceeds
|
||||
/// Once the oldest pending command exceeds
|
||||
/// <see cref="WorkerClientOptions.HeartbeatStuckCeiling"/>, the
|
||||
/// heartbeat watchdog fires anyway — a truly stuck COM call shouldn't
|
||||
/// keep the watchdog suppressed indefinitely.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task HeartbeatMonitor_WhenPendingCommandExceedsStuckCeiling_FaultsClient()
|
||||
{
|
||||
@@ -463,7 +479,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server-032 regression: a transient burst that exceeds
|
||||
/// A transient burst that exceeds
|
||||
/// <see cref="WorkerClientOptions.EventChannelCapacity"/> must be
|
||||
/// absorbed for up to <see cref="WorkerClientOptions.EventChannelFullModeTimeout"/>
|
||||
/// (the channel is configured for <c>BoundedChannelFullMode.Wait</c>);
|
||||
@@ -471,6 +487,7 @@ public sealed class WorkerClientTests
|
||||
/// and the diagnostic must name the channel capacity, depth, and
|
||||
/// actionable remediation.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task EnqueueWorkerEvent_WhenChannelFullPastTimeout_FaultsWithRichDiagnostic()
|
||||
{
|
||||
@@ -722,6 +739,7 @@ public sealed class WorkerClientTests
|
||||
public WorkerFrameWriter WorkerWriter { get; }
|
||||
|
||||
/// <summary>Creates a connected pipe pair for testing.</summary>
|
||||
/// <returns>The connected <see cref="PipePair"/>.</returns>
|
||||
public static async Task<PipePair> CreateAsync()
|
||||
{
|
||||
string pipeName = $"mxaccessgw-workerclient-tests-{Guid.NewGuid():N}";
|
||||
@@ -745,6 +763,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Disposes the worker side of the pipe.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeWorkerSideAsync()
|
||||
{
|
||||
if (_workerSideDisposed)
|
||||
@@ -757,6 +776,7 @@ public sealed class WorkerClientTests
|
||||
}
|
||||
|
||||
/// <summary>Disposes the duplex stream.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await DisposeWorkerSideAsync();
|
||||
|
||||
@@ -5,8 +5,8 @@ using ZB.MOM.WW.MxGateway.Server.Workers;
|
||||
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Workers;
|
||||
|
||||
/// <summary>
|
||||
/// Coverage for <see cref="WorkerExecutableValidator"/> PE-header architecture parsing
|
||||
/// (finding Server-013). The validator reads the DOS <c>MZ</c> stub, follows the PE
|
||||
/// Coverage for <see cref="WorkerExecutableValidator"/> PE-header architecture parsing.
|
||||
/// The validator reads the DOS <c>MZ</c> stub, follows the PE
|
||||
/// header offset at <c>0x3c</c>, checks the <c>PE\0\0</c> signature, and compares the
|
||||
/// machine field against the required <see cref="WorkerArchitecture"/>.
|
||||
/// </summary>
|
||||
@@ -129,7 +129,7 @@ public sealed class WorkerExecutableValidatorTests : IDisposable
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Deletes the temporary PE fixture files created by this test class, best-effort.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (string path in _tempFiles)
|
||||
|
||||
@@ -11,6 +11,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
private const string SessionId = "session-1";
|
||||
|
||||
/// <summary>Verifies that writing and reading a valid envelope round-trips the frame correctly.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task WriteAndReadAsync_WithValidEnvelope_RoundTripsFrame()
|
||||
{
|
||||
@@ -29,6 +30,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with partial reads reassembles the frame correctly.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithPartialReads_ReassemblesFrame()
|
||||
{
|
||||
@@ -45,6 +47,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with zero length throws a malformed length exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithZeroLengthFrame_ThrowsMalformedLength()
|
||||
{
|
||||
@@ -60,6 +63,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with oversized length throws before allocating the payload.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithOversizedLength_ThrowsBeforePayloadAllocation()
|
||||
{
|
||||
@@ -77,6 +81,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with wrong protocol version throws a protocol version mismatch exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithWrongProtocolVersion_ThrowsProtocolVersionMismatch()
|
||||
{
|
||||
@@ -94,6 +99,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with wrong session ID throws a session mismatch exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithWrongSessionId_ThrowsSessionMismatch()
|
||||
{
|
||||
@@ -111,6 +117,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with malformed payload throws an invalid envelope exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithMalformedPayload_ThrowsInvalidEnvelope()
|
||||
{
|
||||
@@ -127,6 +134,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reading a frame with missing envelope body throws an invalid envelope exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithMissingEnvelopeBody_ThrowsInvalidEnvelope()
|
||||
{
|
||||
@@ -144,6 +152,7 @@ public sealed class WorkerFrameProtocolTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that writing an oversized envelope throws a message too large exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task WriteAsync_WithOversizedEnvelope_ThrowsMessageTooLarge()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
private const string Nonce = "super-secret-nonce";
|
||||
|
||||
/// <summary>Verifies that a valid worker executable starts with correct bootstrap arguments and nonce environment variable.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WithValidWorker_StartsProcessWithBootstrapArgumentsAndNonceEnvironment()
|
||||
{
|
||||
@@ -49,6 +50,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a failed startup probe kills and disposes the worker process.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WhenStartupProbeFails_KillsAndDisposesWorker()
|
||||
{
|
||||
@@ -76,6 +78,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that transient startup probe failures are retried without respawning the worker process.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WhenStartupProbeFailsTransiently_RetriesWithoutRespawningWorker()
|
||||
{
|
||||
@@ -103,6 +106,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a startup probe timeout kills and disposes the worker process.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WhenStartupTimesOut_KillsAndDisposesWorker()
|
||||
{
|
||||
@@ -129,6 +133,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a missing worker executable fails before attempting to start the process.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WhenExecutableDoesNotExist_FailsBeforeStartingProcess()
|
||||
{
|
||||
@@ -146,6 +151,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a worker executable with mismatched architecture fails before attempting to start.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WhenExecutableArchitectureDoesNotMatch_FailsBeforeStartingProcess()
|
||||
{
|
||||
@@ -163,6 +169,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a worker that has already exited fails and disposes without additional killing.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task LaunchAsync_WhenWorkerAlreadyExited_FailsAndDisposesWorkerWithoutKill()
|
||||
{
|
||||
@@ -308,7 +315,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
/// <summary>Gets a value indicating whether the Dispose method was called.</summary>
|
||||
public bool DisposeCalled { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Records that the pipe reservation was released.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeCalled = true;
|
||||
@@ -327,6 +334,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
public string Path { get; }
|
||||
|
||||
/// <summary>Creates a new temporary directory for testing.</summary>
|
||||
/// <returns>The created <see cref="TestDirectory"/> wrapper.</returns>
|
||||
public static TestDirectory Create()
|
||||
{
|
||||
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"mxgateway-tests-{Guid.NewGuid():N}");
|
||||
@@ -355,7 +363,7 @@ public sealed class WorkerProcessLauncherTests
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Deletes the temporary test directory and its contents.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Directory.Delete(Path, recursive: true);
|
||||
|
||||
Reference in New Issue
Block a user