using System; using MxGateway.Contracts.Proto; using MxGateway.Worker.MxAccess; namespace MxGateway.Worker.Tests.MxAccess; public sealed class MxAccessEventMapperTests { private readonly MxAccessEventMapper mapper = new(); [Fact] public void CreateOnDataChange_ConvertsValueTimestampQualityAndStatuses() { DateTime timestamp = new(2026, 4, 26, 12, 30, 0, DateTimeKind.Utc); FakeStatus[] statuses = { new() { success = -1, category = 0, detectedBy = 5, detail = 0, }, }; MxEvent mxEvent = mapper.CreateOnDataChange( "session-1", serverHandle: 12, itemHandle: 34, value: 42, quality: 192, timestamp: timestamp, statuses: statuses); Assert.Equal(MxEventFamily.OnDataChange, mxEvent.Family); Assert.Equal("session-1", mxEvent.SessionId); Assert.Equal(12, mxEvent.ServerHandle); Assert.Equal(34, mxEvent.ItemHandle); Assert.Equal(42, mxEvent.Value.Int32Value); Assert.Equal(192, mxEvent.Quality); Assert.Equal(timestamp, mxEvent.SourceTimestamp.ToDateTime()); Assert.Equal(MxEvent.BodyOneofCase.OnDataChange, mxEvent.BodyCase); MxStatusProxy status = Assert.Single(mxEvent.Statuses); Assert.Equal(-1, status.Success); Assert.Equal(MxStatusCategory.Ok, status.Category); Assert.Equal(MxStatusSource.RespondingAutomationObject, status.DetectedBy); } [Fact] public void CreateOnWriteCompleteAndOperationComplete_PreservesDistinctFamilies() { MxEvent writeComplete = mapper.CreateOnWriteComplete( "session-1", serverHandle: 1, itemHandle: 2, statuses: Array.Empty()); MxEvent operationComplete = mapper.CreateOperationComplete( "session-1", serverHandle: 1, itemHandle: 2, statuses: Array.Empty()); Assert.Equal(MxEventFamily.OnWriteComplete, writeComplete.Family); Assert.Equal(MxEvent.BodyOneofCase.OnWriteComplete, writeComplete.BodyCase); Assert.Equal(MxEventFamily.OperationComplete, operationComplete.Family); Assert.Equal(MxEvent.BodyOneofCase.OperationComplete, operationComplete.BodyCase); } [Fact] public void CreateOnBufferedDataChange_PreservesRawDataTypeAndArrayMetadata() { DateTime firstTimestamp = new(2026, 4, 26, 13, 0, 0, DateTimeKind.Utc); DateTime secondTimestamp = new(2026, 4, 26, 13, 1, 0, DateTimeKind.Utc); MxEvent mxEvent = mapper.CreateOnBufferedDataChange( "session-1", serverHandle: 10, itemHandle: 20, rawDataType: 2, value: new[] { 7, 8 }, quality: new[] { 192, 0 }, timestamp: new[] { firstTimestamp, secondTimestamp }, statuses: null); Assert.Equal(MxEventFamily.OnBufferedDataChange, mxEvent.Family); Assert.Equal(MxDataType.Integer, mxEvent.OnBufferedDataChange.DataType); Assert.Equal(2, mxEvent.OnBufferedDataChange.RawDataType); Assert.Equal(MxDataType.Integer, mxEvent.Value.ArrayValue.ElementDataType); Assert.Equal(new[] { 7, 8 }, mxEvent.Value.ArrayValue.Int32Values.Values); Assert.Equal(new[] { 192, 0 }, mxEvent.OnBufferedDataChange.QualityValues.Int32Values.Values); Assert.Equal(2, mxEvent.OnBufferedDataChange.TimestampValues.TimestampValues.Values.Count); } [Theory] [InlineData(-1, MxDataType.Unknown)] [InlineData(0, MxDataType.NoData)] [InlineData(1, MxDataType.Boolean)] [InlineData(2, MxDataType.Integer)] [InlineData(6, MxDataType.Time)] [InlineData(15, MxDataType.InternationalizedString)] [InlineData(999, MxDataType.Unknown)] public void MapMxDataType_MapsInstalledMxAccessValues( int rawDataType, MxDataType expectedDataType) { Assert.Equal(expectedDataType, MxAccessEventMapper.MapMxDataType(rawDataType)); } private sealed class FakeStatus { public int success; public int category; public int detectedBy; public int detail; } }