44644ddc7f
v2-ci / build (pull_request) Failing after 45s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (pull_request) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (pull_request) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (pull_request) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (pull_request) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (pull_request) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (pull_request) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (pull_request) Has been skipped
Live validation against wonder-sql-vd03 caught that the gateway's SendEvent handler throws when the wire event carries a client-supplied Id — so every alarm send from OtOpcUa failed (PermanentFail). AlarmEventMapper now leaves HistorianEvent.Id unset (the historian assigns event identity) and preserves the alarm's id as an 'AlarmId' property. With this, the live alarm send acks. Also harden the env-gated live tests against two gateway/historian-side limitations surfaced during validation (neither an OtOpcUa defect): the write readback uses a timezone-tolerant window (an explicit-timestamp WriteLiveValues lands offset by the deployment's local-vs-UTC delta — reproducible via raw grpcurl; OtOpcUa sends correct UTC), and the alarm ReadEvents readback skips with a clear reason when the historian's server-gated event reads (C2, won't-fix) return nothing. Read + write-persist + alarm-send are all live-validated green; the alarm send-ack is split into its own test. Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
52 lines
2.4 KiB
C#
52 lines
2.4 KiB
C#
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian; // AlarmHistorianEvent
|
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions; // AlarmSeverity
|
|
using ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests.Mapping;
|
|
|
|
public sealed class AlarmEventMapperTests
|
|
{
|
|
[Fact]
|
|
public void Maps_source_time_type_and_rich_properties()
|
|
{
|
|
var a = new AlarmHistorianEvent("A1", "Area/Line/Pump1", "HiHi", "LimitAlarm",
|
|
AlarmSeverity.High, "Activated", "Temp high", "operator1", "ack note",
|
|
new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
|
var e = AlarmEventMapper.ToHistorianEvent(a);
|
|
Assert.Equal("Area/Line/Pump1", e.SourceName);
|
|
Assert.Equal("LimitAlarm", e.Type);
|
|
Assert.Equal(new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), e.EventTime.ToDateTime());
|
|
// The wire Id is deliberately left unset — the gateway's SendEvent rejects a client-supplied
|
|
// event id. The alarm's own id is carried as a property instead.
|
|
Assert.Equal(string.Empty, e.Id);
|
|
Assert.Equal("A1", e.Properties["AlarmId"]);
|
|
Assert.Equal("HiHi", e.Properties["AlarmName"]);
|
|
Assert.Equal("Activated", e.Properties["EventKind"]);
|
|
Assert.Equal("High", e.Properties["Severity"]);
|
|
Assert.Equal("operator1", e.Properties["User"]);
|
|
Assert.Equal("ack note", e.Properties["Comment"]);
|
|
Assert.Equal("Temp high", e.Properties["Message"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Null_comment_is_omitted_not_null()
|
|
{
|
|
var a = new AlarmHistorianEvent("A", "S", "N", "DiscreteAlarm", AlarmSeverity.Low, "Cleared", "m", "system", null,
|
|
new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
|
Assert.False(AlarmEventMapper.ToHistorianEvent(a).Properties.ContainsKey("Comment"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Wire_id_is_never_set_and_blank_alarm_id_adds_no_property()
|
|
{
|
|
// A blank AlarmId must NOT fall back to a generated wire Id (the gateway rejects any id) and
|
|
// must not add an empty AlarmId property.
|
|
var a = new AlarmHistorianEvent("", "S", "N", "DiscreteAlarm", AlarmSeverity.Low, "Cleared", "m", "system", null,
|
|
new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
|
var e = AlarmEventMapper.ToHistorianEvent(a);
|
|
Assert.Equal(string.Empty, e.Id);
|
|
Assert.False(e.Properties.ContainsKey("AlarmId"));
|
|
}
|
|
}
|