fix: resolve Client.Java + Worker.Tests findings (pending windev verification)

Client.Java-040..048, Worker.Tests-034/035/036. Edits applied on the Mac,
which has no JRE and cannot build the x86+MXAccess worker tests; findings are
marked In Progress pending gradle + x86 build verification on windev. Do not
mark Resolved until verified there.
This commit is contained in:
Joseph Doherty
2026-06-17 05:23:14 -04:00
parent 6b5fe6aa82
commit 8df0479b99
9 changed files with 252 additions and 116 deletions
@@ -980,7 +980,11 @@ public sealed class WorkerPipeSessionTests
Task runTask = session.RunAsync(cancellation.Token);
await CompleteGatewayHandshakeAsync(pipePair, cancellation.Token);
DateTimeOffset start = DateTimeOffset.UtcNow;
// The heartbeatWait CTS (5s cancel-after) already enforces the timing bound:
// if the first heartbeat is not received within 5s, ReadUntilAsync throws
// OperationCanceledException and the test fails. A redundant wall-clock
// elapsed < 5s assertion would add the same class of flakiness
// Workers.Tests-003/004/013/020 corrected elsewhere, so it is omitted here.
using CancellationTokenSource heartbeatWait = CancellationTokenSource
.CreateLinkedTokenSource(cancellation.Token);
heartbeatWait.CancelAfter(TimeSpan.FromSeconds(5));
@@ -988,12 +992,8 @@ public sealed class WorkerPipeSessionTests
pipePair.GatewayReader,
WorkerEnvelope.BodyOneofCase.WorkerHeartbeat,
heartbeatWait.Token);
TimeSpan elapsed = DateTimeOffset.UtcNow - start;
Assert.Equal(WorkerEnvelope.BodyOneofCase.WorkerHeartbeat, heartbeat.BodyCase);
Assert.True(
elapsed < TimeSpan.FromSeconds(5),
$"First heartbeat took {elapsed}, expected well under the 30s interval.");
await SendShutdownAndWaitAsync(pipePair, runTask, cancellation.Token);
}
@@ -1123,6 +1123,36 @@ public sealed class MxAccessCommandExecutorTests
Assert.Equal(500, fakeComObject.SetBufferedUpdateIntervalValue);
}
/// <summary>
/// Verifies that a command with an unknown <see cref="MxCommandKind"/> value returns an
/// <see cref="ProtocolStatusCode.InvalidRequest"/> reply whose diagnostic contains "Unsupported".
/// This pins the <c>_ =&gt; CreateInvalidRequestReply(...)</c> discard arm in
/// <c>MxAccessCommandExecutor.Execute</c>: a regression that changed the arm to
/// <c>throw</c> would propagate an unhandled exception through <c>WorkerPipeSession</c>
/// and no other test would catch it.
/// </summary>
[Fact]
public async Task DispatchAsync_WithUnknownCommandKind_ReturnsInvalidRequestWithUnsupportedDiagnostic()
{
FakeMxAccessComObjectFactory factory = new(new FakeMxAccessComObject(registerHandle: 999));
using StaRuntime runtime = CreateRuntime();
using MxAccessStaSession session = new(runtime, factory, new NoopEventSink());
await session.StartAsync(workerProcessId: 1234);
// Cast an integer outside the defined MxCommandKind range to an unknown kind value.
MxCommandKind unknownKind = (MxCommandKind)int.MaxValue;
MxCommandReply reply = await session.DispatchAsync(new StaCommand(
"session-1",
"unknown-kind-correlation",
new MxCommand
{
Kind = unknownKind,
}));
Assert.Equal(ProtocolStatusCode.InvalidRequest, reply.ProtocolStatus.Code);
Assert.Contains("Unsupported", reply.DiagnosticMessage, StringComparison.OrdinalIgnoreCase);
}
private static StaCommand CreateSuspendCommand(
string correlationId,
int serverHandle,
@@ -2229,21 +2259,6 @@ public sealed class MxAccessCommandExecutorTests
SetBufferedUpdateIntervalValue = updateIntervalMilliseconds;
}
/// <summary>Status stand-in reflected over by the worker's MxStatusProxy converter.</summary>
internal sealed class FakeMxStatus
{
/// <summary>Success indicator read by the status converter.</summary>
public int success;
/// <summary>Status category read by the status converter.</summary>
public int category;
/// <summary>Status detected-by read by the status converter.</summary>
public int detectedBy;
/// <summary>Status detail read by the status converter.</summary>
public int detail;
}
}
/// <summary>Factory for creating fake MXAccess COM objects in tests.</summary>
@@ -94,6 +94,11 @@ internal sealed class NoopMxAccessServer : IMxAccessServer
/// <c>success</c>, <c>category</c>, <c>detectedBy</c>, and <c>detail</c>
/// fields, so this fake exposes the same field shape with all-OK values.
/// </summary>
/// <remarks>
/// Previously duplicated as a nested class in <c>MxAccessCommandExecutorTests.FakeMxAccessComObject</c>.
/// Consolidated here per Worker.Tests-034 so a future field change to the real COM struct only
/// requires updating one place.
/// </remarks>
internal sealed class FakeMxStatus
{
// These public fields exist solely so MxStatusProxyConverter can reflect