using AVEVA.Historian.Client.Models; using AVEVA.Historian.Client.Wcf; namespace AVEVA.Historian.Client.Tests; public sealed class WcfEventQueryProtocolTests { // Filter block (offset 0x1E into pRequestBuff) captured from a native // EventQuery.AddEventFilter("Area", Equal, "RetestFilterArea") StartEventQuery, via // instrument-wcf-writemessage. private const string CaptureFilterBlockHex = "000001000000010000000400000041007200650061000100000000000100000009100052657465737446696c7465724172656100"; private const int FilterBlockOffset = 0x1E; [Fact] public void SerializerMatchesInstrumentedNativeEventFilterBlock() { HistorianEventQueryAttempt attempt = Assert.Single(HistorianEventQueryProtocol.CreateStartEventQueryAttempts( new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2026, 1, 2, 0, 0, 0, DateTimeKind.Utc), 5, new HistorianEventFilter("Area", HistorianEventComparison.Equal, "RetestFilterArea"))); byte[] expectedBlock = Convert.FromHexString(CaptureFilterBlockHex); byte[] actualBlock = attempt.RequestBuffer[FilterBlockOffset..(FilterBlockOffset + expectedBlock.Length)]; Assert.Equal("native-filter-version5", attempt.Name); Assert.Equal(expectedBlock, actualBlock); } [Fact] public void FilterBlockEncodesComparisonOperatorAsUInt16() { // Equal = 0, Contains = 12 — the op field is the only byte that differs between them // (offset 0x38 in pRequestBuff = 0x1A into the filter block). byte[] equal = HistorianEventQueryProtocol.CreateStartEventQueryAttempts( new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2026, 1, 2, 0, 0, 0, DateTimeKind.Utc), 5, new HistorianEventFilter("Area", HistorianEventComparison.Equal, "X"))[0].RequestBuffer; byte[] contains = HistorianEventQueryProtocol.CreateStartEventQueryAttempts( new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2026, 1, 2, 0, 0, 0, DateTimeKind.Utc), 5, new HistorianEventFilter("Area", HistorianEventComparison.Contains, "X"))[0].RequestBuffer; Assert.Equal(0x38, FilterBlockOffset + 0x1A); Assert.Equal(0, BitConverter.ToUInt16(equal, 0x38)); Assert.Equal(12, BitConverter.ToUInt16(contains, 0x38)); } [Fact] public void NullFilterStillProducesTheEmptyFilterBuffer() { HistorianEventQueryAttempt withNull = HistorianEventQueryProtocol.CreateStartEventQueryAttempts( new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2026, 1, 1, 0, 1, 0, DateTimeKind.Utc), 3)[0]; Assert.Equal("native-empty-filter-version5", withNull.Name); Assert.Equal(65, withNull.RequestBuffer.Length); } [Fact] public void SerializerMatchesInstrumentedNativeEventRequest() { HistorianEventQueryAttempt attempt = Assert.Single(HistorianEventQueryProtocol.CreateStartEventQueryAttempts( new DateTime(2026, 4, 25, 14, 39, 36, 800, DateTimeKind.Utc).AddTicks(1646), new DateTime(2026, 5, 2, 14, 39, 36, 800, DateTimeKind.Utc).AddTicks(1646), 3)); byte[] expected = Convert.FromBase64String( "BQBuHAVXwdTcAW5c6X9B2twBAwAAAAAAAAAAAAEAAAAAAAAAAAAAAQADAAAAVQBUAEMAAQEAAAEAAAEAAAAAAAA="); Assert.Equal(expected, attempt.RequestBuffer); Assert.Equal("6b955b02087047a3199a8c74f3eee85c3b49aaa29b05de12eff2dd536f2da0d5", attempt.RequestSha256); } [Fact] public void NativeEmptyFilterAttemptMatchesDecompiledSaveOrder() { HistorianEventQueryAttempt attempt = Assert.Single(HistorianEventQueryProtocol.CreateStartEventQueryAttempts( new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2026, 1, 1, 0, 1, 0, DateTimeKind.Utc), 3)); byte[] actual = attempt.RequestBuffer; Assert.Equal("native-empty-filter-version5", attempt.Name); Assert.Equal(3, HistorianEventQueryProtocol.QueryRequestTypeEvent); Assert.Equal(65, actual.Length); Assert.Equal([0x05, 0x00], actual[..2]); Assert.Equal(3u, BitConverter.ToUInt32(actual, 18)); Assert.Equal(0u, BitConverter.ToUInt32(actual, 22)); Assert.Equal(0, BitConverter.ToUInt16(actual, 26)); Assert.Equal(1, BitConverter.ToUInt16(actual, 28)); Assert.Equal([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], actual[30..37]); Assert.Equal(65_536u, BitConverter.ToUInt32(actual, 37)); Assert.Equal([0x03, 0x00, 0x00, 0x00, 0x55, 0x00, 0x54, 0x00, 0x43, 0x00], actual[41..51]); Assert.Equal([0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00], actual[51..61]); Assert.Equal([0x00, 0x00, 0x00, 0x00], actual[^4..]); } }