using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using ScadaLink.Communication.Grpc; namespace ScadaLink.Communication.Tests.Protos; /// /// Wire-format round-trip tests for the Audit Log (#23) M6 reconciliation /// pull proto messages (, /// ). Locks the additive contract the /// central→site reconciliation puller depends on. /// public class PullAuditEventsProtoTests { private static AuditEventDto NewAuditDto(Guid? id = null) => new() { EventId = (id ?? Guid.NewGuid()).ToString(), OccurredAtUtc = Timestamp.FromDateTimeOffset( new DateTimeOffset(2026, 5, 20, 10, 15, 30, 123, TimeSpan.Zero)), Channel = "ApiOutbound", Kind = "ApiCall", Status = "Delivered", SourceSiteId = "site-1", }; [Fact] public void PullAuditEventsRequest_RoundTrip() { var sinceUtc = Timestamp.FromDateTimeOffset( new DateTimeOffset(2026, 5, 20, 9, 0, 0, TimeSpan.Zero)); var original = new PullAuditEventsRequest { SinceUtc = sinceUtc, BatchSize = 250, }; var bytes = original.ToByteArray(); var deserialized = PullAuditEventsRequest.Parser.ParseFrom(bytes); Assert.Equal(sinceUtc, deserialized.SinceUtc); Assert.Equal(250, deserialized.BatchSize); } [Fact] public void PullAuditEventsResponse_RoundTrip_WithEvents_And_MoreAvailable() { var dtos = Enumerable.Range(0, 4).Select(_ => NewAuditDto()).ToList(); var original = new PullAuditEventsResponse { MoreAvailable = true, }; original.Events.AddRange(dtos); var bytes = original.ToByteArray(); var deserialized = PullAuditEventsResponse.Parser.ParseFrom(bytes); Assert.True(deserialized.MoreAvailable); Assert.Equal(4, deserialized.Events.Count); for (int i = 0; i < dtos.Count; i++) { Assert.Equal(dtos[i].EventId, deserialized.Events[i].EventId); Assert.Equal(dtos[i].Status, deserialized.Events[i].Status); Assert.Equal(dtos[i].SourceSiteId, deserialized.Events[i].SourceSiteId); Assert.Equal(dtos[i].OccurredAtUtc, deserialized.Events[i].OccurredAtUtc); } } [Fact] public void PullAuditEventsResponse_Empty_Yields_EmptyEvents() { var original = new PullAuditEventsResponse(); Assert.Empty(original.Events); Assert.False(original.MoreAvailable); var bytes = original.ToByteArray(); var deserialized = PullAuditEventsResponse.Parser.ParseFrom(bytes); Assert.Empty(deserialized.Events); Assert.False(deserialized.MoreAvailable); } }