fix(scripts): reset-aware handshake refuses a null reset value; document additive timeouts (#36 review)
A null resetValue encoded to null, which wrote an empty string and then handed the waiter a null target (= any change), fast-pathing on the stale cache and reinstating the race the overload exists to close. The context parameter is now non-nullable and the accessor throws ArgumentException before any write. Also: additive-timeout note on all surfaces, batch-failure message no longer names the bool overload, and the error-message/batch-failure branches are pinned. Claude-Session: https://claude.ai/code/session_01XPsuy2ZZ5Gbyfpt8PrK5BV
This commit is contained in:
@@ -341,4 +341,33 @@ public class AttributeAccessorWaitAsyncTests : TestKit, IDisposable
|
||||
// Nothing else was written: no batch, no trigger.
|
||||
probe.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gitea #36 review: a null <c>resetValue</c> would encode to null, which writes an empty
|
||||
/// string on leg 1 and then hands the waiter a null target — "any change" — which fast-paths
|
||||
/// on the stale cached value and reinstates exactly the race this overload exists to close.
|
||||
/// The accessor rejects it before anything reaches the InstanceActor.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WriteBatchAndWaitAsync_ResetAware_NullResetValue_ThrowsBeforeAnyWrite()
|
||||
{
|
||||
var probe = CreateTestProbe();
|
||||
var ctx = MakeContext(probe.Ref);
|
||||
|
||||
var acc = new AttributeAccessor(ctx, "RightMESReceiver");
|
||||
|
||||
// Block body (not an expression lambda) so this binds the Action overload: the throw is
|
||||
// SYNCHRONOUS — a faulted task would leave nothing for Assert.Throws to catch.
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
_ = acc.WriteBatchAndWaitAsync(
|
||||
new Dictionary<string, object?> { ["MoveOutBatchID"] = 28950 },
|
||||
"MoveOutFlag", true, "MoveOutCompleteFlag", true, TimeSpan.FromSeconds(25),
|
||||
"MoveOutCompleteFlag", null);
|
||||
});
|
||||
Assert.Equal("resetValue", ex.ParamName);
|
||||
|
||||
// Thrown before leg 1: the reset write never left the accessor.
|
||||
probe.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user