using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Commons.Protos; using ZB.MOM.WW.OtOpcUa.Commons.Protos.MeshTransport.V1; namespace ZB.MOM.WW.OtOpcUa.Commons.Tests; /// /// Contract-lock for the mesh command envelope's oneof. If a fifth command is added /// to mesh_transport.proto without adding a matching entry to /// , this test goes red — the single guard /// that keeps the wire contract and the handled-case set from silently drifting apart. A drift /// here is exactly the failure the whole transport exists to avoid: a command that crosses the /// mesh boundary, decodes to a case nobody handles, and is dropped without a trace. /// public class MeshTransportProtoContractTests { [Fact] public void EveryOneofVariant_IsAccountedFor() { var variants = System.Enum.GetValues() .Where(c => c != CommandEnvelope.CommandOneofCase.None).ToArray(); variants.ShouldBe(MeshTransportProtoContract.HandledCases, ignoreOrder: true); } [Fact] public void The_service_base_and_client_types_generate() { // Referencing these types is the whole assertion — GrpcServices="Both" must emit both halves // of both services: central hosts CentralCommandService and dials NodeCommandService, and a // driver node does the mirror image, so neither service can ship client-only or server-only. typeof(NodeCommandService.NodeCommandServiceBase).ShouldNotBeNull(); typeof(NodeCommandService.NodeCommandServiceClient).ShouldNotBeNull(); typeof(CentralCommandService.CentralCommandServiceBase).ShouldNotBeNull(); typeof(CentralCommandService.CentralCommandServiceClient).ShouldNotBeNull(); } [Fact] public void The_apply_outcome_enum_reserves_zero_as_unspecified() { // proto3 decodes an absent enum field as 0. If 0 meant "Applied", a message that lost the // field in transit — or was written by a peer that predates it — would report a deployment // as successfully applied when nothing was said at all. 0 must stay meaningless. ((int)ApplyOutcome.Unspecified).ShouldBe(0); ((int)ApplyOutcome.Applied).ShouldNotBe(0); ((int)ApplyOutcome.Failed).ShouldNotBe(0); } }