fix(r2-04): Galaxy fail-closed write when AdviseSupervisory fails - Bad status feeds #5 node revert (06/S-1)
This commit is contained in:
+45
@@ -36,6 +36,51 @@ public sealed class GatewayGalaxyDataWriterFailClosedTests
|
||||
ops.RawWriteHandles.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
// ---------------- T6: fail-closed on advise failure ----------------
|
||||
|
||||
/// <summary>When AdviseSupervisory fails (non-OK protocol status), the raw Write must NOT be issued and
|
||||
/// the writer returns Bad (which fires the #5 node revert). The handle must not linger in the supervised
|
||||
/// cache so the next write retries the advise.</summary>
|
||||
[Fact]
|
||||
public async Task WriteOne_AdviseFails_ReturnsBadCommunicationError_AndNeverIssuesRawWrite()
|
||||
{
|
||||
var ops = new FakeMxWriteOps
|
||||
{
|
||||
InvokeResponder = _ => new MxCommandReply
|
||||
{
|
||||
ProtocolStatus = new ProtocolStatus { Code = ProtocolStatusCode.MxaccessFailure, Message = "advise boom" },
|
||||
},
|
||||
};
|
||||
var writer = NewWriter();
|
||||
|
||||
var result = await writer.WriteOneForTestAsync(
|
||||
ops, new WriteRequest("Tag.A", true), SecurityClassification.FreeAccess, CancellationToken.None);
|
||||
|
||||
result.StatusCode.ShouldBe(StatusCodeMap.BadCommunicationError);
|
||||
ops.Invokes.Count(r => r.Command.Kind == MxCommandKind.AdviseSupervisory).ShouldBe(1);
|
||||
ops.RawWriteHandles.ShouldBeEmpty(); // the knowingly-lost raw write was NOT issued
|
||||
writer.CachedSupervisedHandleCount.ShouldBe(0); // advise failure forgot the handle → next write retries
|
||||
}
|
||||
|
||||
/// <summary>When advise succeeds, the raw Write proceeds and a clean reply returns Good (regression).</summary>
|
||||
[Fact]
|
||||
public async Task WriteOne_AdviseSucceeds_RawWriteProceeds()
|
||||
{
|
||||
var ops = new FakeMxWriteOps
|
||||
{
|
||||
InvokeResponder = _ => new MxCommandReply { ProtocolStatus = new ProtocolStatus { Code = ProtocolStatusCode.Ok } },
|
||||
};
|
||||
var writer = NewWriter();
|
||||
|
||||
var result = await writer.WriteOneForTestAsync(
|
||||
ops, new WriteRequest("Tag.B", 42), SecurityClassification.FreeAccess, CancellationToken.None);
|
||||
|
||||
result.StatusCode.ShouldBe(StatusCodeMap.Good);
|
||||
ops.Invokes.Count(r => r.Command.Kind == MxCommandKind.AdviseSupervisory).ShouldBe(1);
|
||||
ops.RawWriteHandles.ShouldHaveSingleItem(); // the raw write was issued after the successful advise
|
||||
writer.CachedSupervisedHandleCount.ShouldBe(1);
|
||||
}
|
||||
|
||||
// ---------------- fakes ----------------
|
||||
|
||||
/// <summary>A fake <see cref="IMxWriteOps"/> that records every call and returns canned replies.</summary>
|
||||
|
||||
Reference in New Issue
Block a user