contracts: round-trip degraded provenance/watch-list/mode-changed; proto doc (Contracts-018,019)

This commit is contained in:
Joseph Doherty
2026-06-15 02:46:06 -04:00
parent 56dd56954b
commit ddf2d84fbc
4 changed files with 221 additions and 6 deletions
@@ -1427,4 +1427,120 @@ public sealed class ProtobufContractRoundTripTests
Assert.Single(parsed.ReadBulk.Results);
Assert.True(parsed.ReadBulk.Results[0].WasCached);
}
/// <summary>
/// Verifies that an <see cref="ActiveAlarmSnapshot"/> carrying the
/// alarm-provider provenance fields <c>degraded</c> (14) and
/// <c>source_provider</c> (15) round-trips with their values preserved,
/// pinning the wire shape of the byte-identical provenance fields that
/// also appear on <see cref="OnAlarmTransitionEvent"/>.
/// </summary>
[Fact]
public void ActiveAlarmSnapshot_RoundTripsDegradedProvenance()
{
var raise = Timestamp.FromDateTime(new DateTime(2026, 6, 13, 12, 0, 0, DateTimeKind.Utc));
var original = new ActiveAlarmSnapshot
{
AlarmFullReference = "Galaxy!Area.Tank01.Level.HiHi",
SourceObjectReference = "Tank01",
AlarmTypeName = "AnalogLimitAlarm.HiHi",
Severity = 750,
OriginalRaiseTimestamp = raise,
CurrentState = AlarmConditionState.Active,
Degraded = true,
SourceProvider = AlarmProviderMode.Subtag,
};
var parsed = ActiveAlarmSnapshot.Parser.ParseFrom(original.ToByteArray());
Assert.Equal(original, parsed);
Assert.True(parsed.Degraded);
Assert.Equal(AlarmProviderMode.Subtag, parsed.SourceProvider);
}
/// <summary>
/// Verifies that a <see cref="SubscribeAlarmsCommand"/> populating the
/// alarm-provider fallback extensions — <c>forced_mode</c> (2), a
/// <c>watch_list</c> entry with all six <see cref="AlarmSubtagTarget"/>
/// string fields (3), and a <c>failover</c>
/// <see cref="AlarmFailoverConfig"/> (4) — round-trips end to end,
/// pinning the wire shape that the forced-subtag-mode fix depends on.
/// </summary>
[Fact]
public void SubscribeAlarmsCommand_RoundTripsForcedModeWatchListAndFailover()
{
var original = new SubscribeAlarmsCommand
{
SubscriptionExpression = @"\\node\Galaxy!Area",
ForcedMode = AlarmProviderMode.Subtag,
WatchList =
{
new AlarmSubtagTarget
{
AlarmFullReference = "Galaxy!Area.Tank01.Level.HiHi",
SourceObjectReference = "Tank01",
ActiveSubtag = "Tank01.Level.HiHi.InAlarm",
AckedSubtag = "Tank01.Level.HiHi.Acked",
AckCommentSubtag = "Tank01.Level.HiHi.AckMsg",
PrioritySubtag = "Tank01.Level.HiHi.Priority",
},
},
Failover = new AlarmFailoverConfig
{
ConsecutiveFailureThreshold = 3,
FailbackProbeIntervalSeconds = 10,
FailbackStableProbes = 5,
},
};
var parsed = SubscribeAlarmsCommand.Parser.ParseFrom(original.ToByteArray());
Assert.Equal(original, parsed);
Assert.Equal(AlarmProviderMode.Subtag, parsed.ForcedMode);
var target = Assert.Single(parsed.WatchList);
Assert.Equal("Galaxy!Area.Tank01.Level.HiHi", target.AlarmFullReference);
Assert.Equal("Tank01", target.SourceObjectReference);
Assert.Equal("Tank01.Level.HiHi.InAlarm", target.ActiveSubtag);
Assert.Equal("Tank01.Level.HiHi.Acked", target.AckedSubtag);
Assert.Equal("Tank01.Level.HiHi.AckMsg", target.AckCommentSubtag);
Assert.Equal("Tank01.Level.HiHi.Priority", target.PrioritySubtag);
Assert.Equal(3, parsed.Failover.ConsecutiveFailureThreshold);
Assert.Equal(10, parsed.Failover.FailbackProbeIntervalSeconds);
Assert.Equal(5, parsed.Failover.FailbackStableProbes);
}
/// <summary>
/// Verifies that an <see cref="MxEvent"/> carrying an
/// <see cref="OnAlarmProviderModeChangedEvent"/> body (the
/// <c>MxEvent.body</c> oneof tag 25 paired with
/// <see cref="MxEventFamily.OnAlarmProviderModeChanged"/>, family 6)
/// round-trips and resolves to
/// <see cref="MxEvent.BodyOneofCase.OnAlarmProviderModeChanged"/>.
/// </summary>
[Fact]
public void MxEvent_RoundTripsOnAlarmProviderModeChangedBody()
{
var at = Timestamp.FromDateTime(new DateTime(2026, 6, 13, 9, 30, 0, DateTimeKind.Utc));
var original = new MxEvent
{
Family = MxEventFamily.OnAlarmProviderModeChanged,
SessionId = "session-1",
WorkerSequence = 42,
OnAlarmProviderModeChanged = new OnAlarmProviderModeChangedEvent
{
Mode = AlarmProviderMode.Subtag,
Reason = "wnwrap poll failed 3x",
Hresult = unchecked((int)0x80004005),
At = at,
},
};
var parsed = MxEvent.Parser.ParseFrom(original.ToByteArray());
Assert.Equal(original, parsed);
Assert.Equal(MxEvent.BodyOneofCase.OnAlarmProviderModeChanged, parsed.BodyCase);
Assert.Equal(MxEventFamily.OnAlarmProviderModeChanged, parsed.Family);
Assert.Equal(AlarmProviderMode.Subtag, parsed.OnAlarmProviderModeChanged.Mode);
Assert.Equal(unchecked((int)0x80004005), parsed.OnAlarmProviderModeChanged.Hresult);
}
}