using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using MxGateway.Contracts; using MxGateway.Contracts.Proto; namespace MxGateway.Tests.Contracts; public sealed class ProtobufContractRoundTripTests { [Fact] public void GatewayDescriptor_ContainsInitialPublicServiceMethods() { var service = Assert.Single( MxaccessGatewayReflection.Descriptor.Services, descriptor => descriptor.Name == "MxAccessGateway"); Assert.Contains(service.Methods, method => method.Name == "OpenSession"); Assert.Contains(service.Methods, method => method.Name == "CloseSession"); Assert.Contains(service.Methods, method => method.Name == "Invoke"); Assert.Contains(service.Methods, method => method.Name == "StreamEvents"); } [Fact] public void WorkerEnvelopeDescriptor_ContainsRequiredCorrelationFields() { var fields = WorkerEnvelope.Descriptor.Fields.InDeclarationOrder(); Assert.Contains(fields, field => field.Name == "protocol_version"); Assert.Contains(fields, field => field.Name == "session_id"); Assert.Contains(fields, field => field.Name == "sequence"); Assert.Contains(fields, field => field.Name == "correlation_id"); } [Fact] public void CommandRequest_RoundTripsMethodSpecificPayload() { var original = new MxCommandRequest { SessionId = "session-1", ClientCorrelationId = "client-correlation-1", Command = new MxCommand { Kind = MxCommandKind.Register, Register = new RegisterCommand { ClientName = "mxaccessgw-test-client", }, }, }; var parsed = MxCommandRequest.Parser.ParseFrom(original.ToByteArray()); Assert.Equal(original, parsed); Assert.Equal(MxCommand.PayloadOneofCase.Register, parsed.Command.PayloadCase); } [Fact] public void CommandReply_RoundTripsHResultReturnValueOutParamsAndStatuses() { var original = new MxCommandReply { SessionId = "session-1", CorrelationId = "gateway-correlation-1", Kind = MxCommandKind.AddItem, ProtocolStatus = new ProtocolStatus { Code = ProtocolStatusCode.Ok, }, Hresult = 0, ReturnValue = new MxValue { DataType = MxDataType.Integer, Int32Value = 1234, VariantType = "VT_I4", }, AddItem = new AddItemReply { ItemHandle = 1234, }, }; original.Statuses.Add(new MxStatusProxy { Success = 1, Category = MxStatusCategory.Ok, DetectedBy = MxStatusSource.RespondingLmx, Detail = 0, }); var parsed = MxCommandReply.Parser.ParseFrom(original.ToByteArray()); Assert.Equal(original, parsed); Assert.True(parsed.HasHresult); Assert.Equal(MxCommandReply.PayloadOneofCase.AddItem, parsed.PayloadCase); Assert.Single(parsed.Statuses); } [Fact] public void Event_RoundTripsValueStatusSequenceAndBufferedBody() { var timestamp = Timestamp.FromDateTime(new DateTime(2026, 4, 26, 20, 0, 0, DateTimeKind.Utc)); var original = new MxEvent { Family = MxEventFamily.OnBufferedDataChange, SessionId = "session-1", ServerHandle = 10, ItemHandle = 20, Value = new MxValue { DataType = MxDataType.Float, ArrayValue = new MxArray { ElementDataType = MxDataType.Float, FloatValues = new FloatArray { Values = { 1.5f, 2.5f }, }, Dimensions = { 2 }, VariantType = "VT_ARRAY|VT_R4", }, }, Quality = 192, SourceTimestamp = timestamp, WorkerSequence = 42, WorkerTimestamp = timestamp, GatewayReceiveTimestamp = timestamp, OnBufferedDataChange = new OnBufferedDataChangeEvent { DataType = MxDataType.Float, QualityValues = new MxArray { ElementDataType = MxDataType.Integer, Int32Values = new Int32Array { Values = { 192, 192 }, }, Dimensions = { 2 }, }, TimestampValues = new MxArray { ElementDataType = MxDataType.Time, TimestampValues = new TimestampArray { Values = { timestamp, timestamp }, }, Dimensions = { 2 }, }, }, }; original.Statuses.Add(new MxStatusProxy { Success = 1, Category = MxStatusCategory.Ok, DetectedBy = MxStatusSource.RespondingNmx, Detail = 0, }); var parsed = MxEvent.Parser.ParseFrom(original.ToByteArray()); Assert.Equal(original, parsed); Assert.Equal(MxEvent.BodyOneofCase.OnBufferedDataChange, parsed.BodyCase); Assert.Single(parsed.Statuses); } [Fact] public void WorkerEnvelope_RoundTripsProtocolFieldsAndCommandBody() { var original = new WorkerEnvelope { ProtocolVersion = GatewayContractInfo.WorkerProtocolVersion, SessionId = "session-1", Sequence = 7, CorrelationId = "gateway-correlation-1", WorkerCommand = new WorkerCommand { EnqueueTimestamp = Timestamp.FromDateTime( new DateTime(2026, 4, 26, 20, 5, 0, DateTimeKind.Utc)), Command = new MxCommand { Kind = MxCommandKind.Advise, Advise = new AdviseCommand { ServerHandle = 10, ItemHandle = 20, }, }, }, }; var parsed = WorkerEnvelope.Parser.ParseFrom(original.ToByteArray()); Assert.Equal(original, parsed); Assert.Equal(WorkerEnvelope.BodyOneofCase.WorkerCommand, parsed.BodyCase); Assert.Equal(MxCommand.PayloadOneofCase.Advise, parsed.WorkerCommand.Command.PayloadCase); } }