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:
Joseph Doherty
2026-07-07 14:09:49 -04:00
parent 8914472706
commit fca978de07
203 changed files with 1834 additions and 1383 deletions
@@ -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);