using Google.Protobuf.WellKnownTypes; using ScadaLink.Communication.Grpc; namespace ScadaLink.Communication.Tests.Grpc; /// /// Guardrail tests that verify all oneof variants in SiteStreamEvent have /// corresponding conversion handlers. Adding a new proto field without /// implementing the conversion will cause these tests to fail. /// public class ProtoContractTests { /// /// The set of EventOneofCase values we handle in ConvertToDomainEvent. /// Update this array when adding a new oneof variant. /// private static readonly SiteStreamEvent.EventOneofCase[] HandledCases = [ SiteStreamEvent.EventOneofCase.AttributeChanged, SiteStreamEvent.EventOneofCase.AlarmChanged ]; [Fact] public void AllOneofVariants_HaveConversionHandlers() { var allCases = System.Enum.GetValues() .Where(c => c != SiteStreamEvent.EventOneofCase.None) .ToArray(); Assert.Equal(allCases.Length, HandledCases.Length); foreach (var c in allCases) Assert.Contains(c, HandledCases); } [Theory] [InlineData(SiteStreamEvent.EventOneofCase.AttributeChanged)] [InlineData(SiteStreamEvent.EventOneofCase.AlarmChanged)] public void ConvertToDomainEvent_HandlesAllOneofVariants(SiteStreamEvent.EventOneofCase eventCase) { var evt = CreateTestEvent(eventCase); var result = SiteStreamGrpcClient.ConvertToDomainEvent(evt); Assert.NotNull(result); } private static SiteStreamEvent CreateTestEvent(SiteStreamEvent.EventOneofCase eventCase) { var ts = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow); return eventCase switch { SiteStreamEvent.EventOneofCase.AttributeChanged => new SiteStreamEvent { CorrelationId = "test", AttributeChanged = new AttributeValueUpdate { InstanceUniqueName = "Site1.Inst1", AttributePath = "Path", AttributeName = "Attr", Value = "42", Quality = Quality.Good, Timestamp = ts } }, SiteStreamEvent.EventOneofCase.AlarmChanged => new SiteStreamEvent { CorrelationId = "test", AlarmChanged = new AlarmStateUpdate { InstanceUniqueName = "Site1.Inst1", AlarmName = "HighTemp", State = AlarmStateEnum.AlarmStateActive, Priority = 1, Timestamp = ts } }, _ => throw new ArgumentOutOfRangeException(nameof(eventCase), eventCase, "Unhandled event case") }; } }