Resolve Contracts-002 code-review finding
MxCommandReply.payload has no by-name ack case: MX_COMMAND_KIND_ACKNOWLEDGE_ ALARM_BY_NAME reuses the acknowledge_alarm reply payload. Verified the worker (MxAccessCommandExecutor.ExecuteAcknowledgeAlarmByName) and gateway (WorkerAlarmRpcDispatcher) already implement this correctly — the gap was purely undocumented contract asymmetry. Documented the reuse on the proto oneof case and the AcknowledgeAlarmReplyPayload message comment (regenerating the .NET contract), and in docs/AlarmClientDiscovery.md. Added ProtobufContractRoundTripTests.MxCommandReply_AcknowledgeAlarmByName_Reuses AcknowledgeAlarmPayloadCase to pin the contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -342,6 +342,56 @@ public sealed class ProtobufContractRoundTripTests
|
||||
Assert.True(parsed.HasHresult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pins the documented command/reply payload-reuse contract: an
|
||||
/// <c>ACKNOWLEDGE_ALARM_BY_NAME</c> command's reply intentionally has no
|
||||
/// by-name-specific payload case and instead reuses the
|
||||
/// <c>acknowledge_alarm</c> (<see cref="AcknowledgeAlarmReplyPayload"/>)
|
||||
/// case. A future change that adds a separate by-name reply case — or
|
||||
/// drops the reuse — breaks this test. See Contracts-002 and
|
||||
/// docs/AlarmClientDiscovery.md section 4.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MxCommandReply_AcknowledgeAlarmByName_ReusesAcknowledgeAlarmPayloadCase()
|
||||
{
|
||||
// The reply oneof must NOT have a by-name-specific case. If a future
|
||||
// edit adds one, this assertion fails and forces the doc/test contract
|
||||
// to be revisited deliberately.
|
||||
foreach (MxCommandReply.PayloadOneofCase value in
|
||||
System.Enum.GetValues<MxCommandReply.PayloadOneofCase>())
|
||||
{
|
||||
Assert.NotEqual("AcknowledgeAlarmByName", value.ToString());
|
||||
}
|
||||
|
||||
var original = new MxCommandReply
|
||||
{
|
||||
SessionId = "session-1",
|
||||
CorrelationId = "gateway-correlation-7",
|
||||
Kind = MxCommandKind.AcknowledgeAlarmByName,
|
||||
ProtocolStatus = new ProtocolStatus { Code = ProtocolStatusCode.Ok },
|
||||
Hresult = 0,
|
||||
// By-name ack reuses the acknowledge_alarm payload case; see the
|
||||
// worker's MxAccessCommandExecutor.ExecuteAcknowledgeAlarmByName.
|
||||
AcknowledgeAlarm = new AcknowledgeAlarmReplyPayload
|
||||
{
|
||||
NativeStatus = 0,
|
||||
},
|
||||
};
|
||||
|
||||
var parsed = MxCommandReply.Parser.ParseFrom(original.ToByteArray());
|
||||
|
||||
Assert.Equal(original, parsed);
|
||||
// Kind distinguishes the by-name ack; the payload case is shared.
|
||||
Assert.Equal(MxCommandKind.AcknowledgeAlarmByName, parsed.Kind);
|
||||
Assert.Equal(MxCommandReply.PayloadOneofCase.AcknowledgeAlarm, parsed.PayloadCase);
|
||||
Assert.Equal(0, parsed.AcknowledgeAlarm.NativeStatus);
|
||||
// The by-name command has its own command payload case — the asymmetry
|
||||
// with the reply oneof is the documented contract under test.
|
||||
Assert.Contains(
|
||||
MxCommand.PayloadOneofCase.AcknowledgeAlarmByNameCommand,
|
||||
System.Enum.GetValues<MxCommand.PayloadOneofCase>());
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ActiveAlarmSnapshot round-trips with current state and operator metadata.</summary>
|
||||
[Fact]
|
||||
public void ActiveAlarmSnapshot_RoundTripsAllFields()
|
||||
|
||||
Reference in New Issue
Block a user