feat(scripts): reset-aware Attributes.WriteBatchAndWaitAsync overload + deploy-gate mirror (#36)
Claude-Session: https://claude.ai/code/session_01XPsuy2ZZ5Gbyfpt8PrK5BV
This commit is contained in:
@@ -294,4 +294,51 @@ public class AttributeAccessorWaitAsyncTests : TestKit, IDisposable
|
||||
Assert.True(result.TimedOut);
|
||||
Assert.Null(result.Value);
|
||||
}
|
||||
|
||||
// ── Reset-aware WriteBatchAndWaitAsync overload (Gitea #36) ──────────────
|
||||
|
||||
/// <summary>
|
||||
/// The reset-aware overload must scope-resolve and codec-encode the reset key/value
|
||||
/// exactly like every other accessor, must default <c>resetTimeout</c> to
|
||||
/// <c>timeout</c>, and — when the reset echo never arrives — must return a
|
||||
/// <see cref="HandshakeResult.ResetFailed"/> result WITHOUT writing the batch or
|
||||
/// the trigger (the ExpectNoMsg at the end is that assertion).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task WriteBatchAndWaitAsync_ResetAware_ResolvesScopeAndDefaultsResetTimeout()
|
||||
{
|
||||
var probe = CreateTestProbe();
|
||||
var ctx = MakeContext(probe.Ref);
|
||||
|
||||
// Composed scope "RightMESReceiver" — every key is prefixed before it leaves the accessor.
|
||||
var acc = new AttributeAccessor(ctx, "RightMESReceiver");
|
||||
|
||||
var call = acc.WriteBatchAndWaitAsync(
|
||||
new Dictionary<string, object?> { ["MoveOutBatchID"] = 28950 },
|
||||
"MoveOutFlag", true, "MoveOutCompleteFlag", true, TimeSpan.FromSeconds(25),
|
||||
"MoveOutCompleteFlag", false);
|
||||
|
||||
// Leg 1 — the reset write.
|
||||
var reset = probe.ExpectMsg<SetStaticAttributeCommand>(TimeSpan.FromSeconds(5));
|
||||
Assert.Equal("RightMESReceiver.MoveOutCompleteFlag", reset.AttributeName);
|
||||
Assert.Equal(AttributeValueCodec.Encode(false), reset.Value);
|
||||
probe.Reply(new SetStaticAttributeResponse(
|
||||
reset.CorrelationId, "Pump1", reset.AttributeName, true, null, DateTimeOffset.UtcNow));
|
||||
|
||||
// Leg 2 — the reset echo wait, bounded by the defaulted resetTimeout.
|
||||
var resetWait = probe.ExpectMsg<WaitForAttributeRequest>(TimeSpan.FromSeconds(5));
|
||||
Assert.Equal("RightMESReceiver.MoveOutCompleteFlag", resetWait.AttributeName);
|
||||
Assert.Equal(AttributeValueCodec.Encode(false), resetWait.TargetValueEncoded);
|
||||
Assert.Equal(TimeSpan.FromSeconds(25), resetWait.Timeout); // defaulted to `timeout`
|
||||
probe.Reply(new WaitForAttributeResponse(
|
||||
resetWait.CorrelationId, Matched: false, Value: null, Quality: null, TimedOut: true));
|
||||
|
||||
var result = await call;
|
||||
Assert.True(result.ResetFailed);
|
||||
Assert.False(result.Matched);
|
||||
Assert.True(result.TimedOut);
|
||||
|
||||
// Nothing else was written: no batch, no trigger.
|
||||
probe.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user