test(worker): deterministic pump-wait ordering, env hermeticity, ResolveWriteCompletionTimeout coverage
This commit is contained in:
@@ -956,6 +956,9 @@ public sealed class MxAccessCommandExecutorTests
|
|||||||
sink.WriteCompletionCache.Record(82, 820, CreateCompletionRows(detail: 4321));
|
sink.WriteCompletionCache.Record(82, 820, CreateCompletionRows(detail: 4321));
|
||||||
using StaRuntime runtime = CreateRuntime();
|
using StaRuntime runtime = CreateRuntime();
|
||||||
using MxAccessStaSession session = new(runtime, factory, sink);
|
using MxAccessStaSession session = new(runtime, factory, sink);
|
||||||
|
// Hermetic: don't inherit MXGATEWAY_WORKER_WRITE_COMPLETION_WAIT_MS
|
||||||
|
// from the test runner's environment.
|
||||||
|
session.WriteCompletionTimeout = TimeSpan.FromSeconds(10);
|
||||||
await session.StartAsync(workerProcessId: 1234);
|
await session.StartAsync(workerProcessId: 1234);
|
||||||
|
|
||||||
MxCommandReply reply = await session.DispatchAsync(CreateWriteSecuredCommand(
|
MxCommandReply reply = await session.DispatchAsync(CreateWriteSecuredCommand(
|
||||||
@@ -981,6 +984,12 @@ public sealed class MxAccessCommandExecutorTests
|
|||||||
FakeMxAccessComObject fakeComObject = new(registerHandle: 83);
|
FakeMxAccessComObject fakeComObject = new(registerHandle: 83);
|
||||||
FakeMxAccessComObjectFactory factory = new(fakeComObject);
|
FakeMxAccessComObjectFactory factory = new(fakeComObject);
|
||||||
CompletionCacheEventSink sink = new();
|
CompletionCacheEventSink sink = new();
|
||||||
|
// Deterministic ordering: the executor captures its version baseline
|
||||||
|
// BEFORE the COM call, so once the fake's WriteSecured has run the
|
||||||
|
// baseline is committed and a Record from the test thread is
|
||||||
|
// guaranteed to be "newer" — no fixed sleep racing the STA thread.
|
||||||
|
using System.Threading.ManualResetEventSlim comCallReached = new(initialState: false);
|
||||||
|
fakeComObject.OnWriteSecuredCallback = () => comCallReached.Set();
|
||||||
using StaRuntime runtime = CreateRuntime();
|
using StaRuntime runtime = CreateRuntime();
|
||||||
using MxAccessStaSession session = new(runtime, factory, sink);
|
using MxAccessStaSession session = new(runtime, factory, sink);
|
||||||
session.WriteCompletionTimeout = TimeSpan.FromSeconds(10);
|
session.WriteCompletionTimeout = TimeSpan.FromSeconds(10);
|
||||||
@@ -988,7 +997,7 @@ public sealed class MxAccessCommandExecutorTests
|
|||||||
|
|
||||||
Task<MxCommandReply> pending = session.DispatchAsync(CreateWriteSecuredCommand(
|
Task<MxCommandReply> pending = session.DispatchAsync(CreateWriteSecuredCommand(
|
||||||
"write-secured-waiting", serverHandle: 83, itemHandle: 830, value: 1, currentUserId: 11, verifierUserId: 22));
|
"write-secured-waiting", serverHandle: 83, itemHandle: 830, value: 1, currentUserId: 11, verifierUserId: 22));
|
||||||
await Task.Delay(50);
|
Assert.True(comCallReached.Wait(TimeSpan.FromSeconds(5)));
|
||||||
sink.WriteCompletionCache.Record(83, 830, CreateCompletionRows(detail: 99));
|
sink.WriteCompletionCache.Record(83, 830, CreateCompletionRows(detail: 99));
|
||||||
|
|
||||||
MxCommandReply reply = await pending;
|
MxCommandReply reply = await pending;
|
||||||
@@ -1063,6 +1072,8 @@ public sealed class MxAccessCommandExecutorTests
|
|||||||
sink.WriteCompletionCache.Record(86, 860, CreateCompletionRows(detail: 2222));
|
sink.WriteCompletionCache.Record(86, 860, CreateCompletionRows(detail: 2222));
|
||||||
using StaRuntime runtime = CreateRuntime();
|
using StaRuntime runtime = CreateRuntime();
|
||||||
using MxAccessStaSession session = new(runtime, factory, sink);
|
using MxAccessStaSession session = new(runtime, factory, sink);
|
||||||
|
// Hermetic: same rationale as the WriteSecured fast-completion test.
|
||||||
|
session.WriteCompletionTimeout = TimeSpan.FromSeconds(10);
|
||||||
await session.StartAsync(workerProcessId: 1234);
|
await session.StartAsync(workerProcessId: 1234);
|
||||||
|
|
||||||
MxCommandReply reply = await session.DispatchAsync(CreateWriteSecured2Command(
|
MxCommandReply reply = await session.DispatchAsync(CreateWriteSecured2Command(
|
||||||
|
|||||||
@@ -15,6 +15,48 @@ namespace ZB.MOM.WW.MxGateway.Worker.Tests.MxAccess;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class MxAccessStaSessionTests
|
public sealed class MxAccessStaSessionTests
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Verifies the launcher-env-var parse branches of
|
||||||
|
/// <see cref="MxAccessStaSession.ResolveWriteCompletionTimeout"/>:
|
||||||
|
/// a valid non-negative value is honored (0 = disabled), while a
|
||||||
|
/// missing, malformed, or negative value falls back to the executor
|
||||||
|
/// default. Env mutation is restored in a finally so parallel tests
|
||||||
|
/// never observe the temporary value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rawValue">Raw env-var value, or null for unset.</param>
|
||||||
|
/// <param name="expectedMilliseconds">Expected resolved wait, or null for the executor default.</param>
|
||||||
|
[Theory]
|
||||||
|
[InlineData(null, null)]
|
||||||
|
[InlineData("", null)]
|
||||||
|
[InlineData("junk", null)]
|
||||||
|
[InlineData("-5", null)]
|
||||||
|
[InlineData("0", 0)]
|
||||||
|
[InlineData("250", 250)]
|
||||||
|
public void ResolveWriteCompletionTimeout_ParsesEnvironmentValue(string? rawValue, int? expectedMilliseconds)
|
||||||
|
{
|
||||||
|
string? original = Environment.GetEnvironmentVariable(
|
||||||
|
MxAccessStaSession.WriteCompletionWaitEnvironmentVariableName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable(
|
||||||
|
MxAccessStaSession.WriteCompletionWaitEnvironmentVariableName,
|
||||||
|
rawValue);
|
||||||
|
|
||||||
|
TimeSpan resolved = MxAccessStaSession.ResolveWriteCompletionTimeout();
|
||||||
|
|
||||||
|
TimeSpan expected = expectedMilliseconds is null
|
||||||
|
? MxAccessCommandExecutor.DefaultWriteCompletionTimeout
|
||||||
|
: TimeSpan.FromMilliseconds(expectedMilliseconds.Value);
|
||||||
|
Assert.Equal(expected, resolved);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable(
|
||||||
|
MxAccessStaSession.WriteCompletionWaitEnvironmentVariableName,
|
||||||
|
original);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies that StartAsync creates the MXAccess COM object and attaches the event sink on the STA thread.
|
/// Verifies that StartAsync creates the MXAccess COM object and attaches the event sink on the STA thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user