using System; using System.Buffers.Binary; using AVEVA.Historian.Client.Wcf; using Xunit; namespace AVEVA.Historian.Client.Tests; /// /// Golden-byte coverage for the 2023 R2 gRPC event-SEND registration buffers, pinned against a live /// native capture (capture-send-event scenario, 2026-06-23). The send itself rides /// HistoryService.AddStreamValues with the same "OS" buffer the WCF path uses /// (, already golden-tested in /// WcfEventWriteProtocolTests); what is gRPC-specific is the CM_EVENT registration the event /// connection performs first (RegisterTags + the 86-byte gRPC EnsureTags). These fixtures are the raw /// bytes the native client sent on the wire — they carry no identity (CM_EVENT / "AnE Event" / /// constant tag + event-type GUIDs / a registration FILETIME). /// public class GrpcEventSendProtocolTests { // GrpcHistoryClient.RegisterTags.tagInfos captured from the native event connection: the packet // header 50 67 02 00 + count(1) + the 16-byte CM_EVENT tag GUID. private const string CapturedRegisterTagsHex = "506702000100000045813b35f05d464da253871aef49b321"; // GrpcHistoryClient.EnsureTags.tagInfos captured from the native event connection (86 bytes): the // 8-byte EnsureTags header + CM_EVENT CTagMetadata + a registration FILETIME + the …e01f2f27 // event-type GUID. private const string CapturedEnsureTagsHex = "4e670300010000000386000545813b35f05d464da253871aef49b321090800434d5f4556454e54090900416e45204576656e7402020100000001000000004e18d6bd4503dd0142ae595fb63b604791a5ab0be01f2f27"; [Fact] public void BuildRegisterCmEventInputBuffer_MatchesNativeGrpcCapture() { byte[] expected = Convert.FromHexString(CapturedRegisterTagsHex); byte[] actual = HistorianEventRegistrationProtocol.BuildRegisterCmEventInputBuffer(); Assert.Equal(expected, actual); } [Fact] public void SerializeCmEventEnsureTagsGrpc_MatchesNativeGrpcCapture() { byte[] expected = Convert.FromHexString(CapturedEnsureTagsHex); Assert.Equal(86, expected.Length); // The only run-varying field is the registration FILETIME (the 8 bytes immediately before the // trailing 16-byte event-type GUID). Feed the captured time back so the comparison is exact. long filetime = BinaryPrimitives.ReadInt64LittleEndian(expected.AsSpan(expected.Length - 24, 8)); DateTime createdUtc = DateTime.FromFileTimeUtc(filetime); byte[] actual = HistorianAddTagsProtocol.SerializeCmEventEnsureTagsGrpc(createdUtc); Assert.Equal(expected, actual); } }