using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Commons.Messages.Redundancy; using ZB.MOM.WW.OtOpcUa.Runtime.Drivers; namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers; /// /// archreview 03/S4 — the single Primary data-plane gate decision. A KNOWN role wins outright; an /// UNKNOWN role (no snapshot yet, or the snapshot never mentioned this node) is resolved by cluster /// membership: a single-driver cluster stays default-ALLOW (boot-window / single-node posture), a /// multi-driver cluster is default-DENY (a real Primary peer exists — don't touch the shared field /// device until the snapshot proves this node is Primary). /// public sealed class PrimaryGatePolicyTests { [Theory] // Primary → always service, regardless of member count. [InlineData(RedundancyRole.Primary, 0, true)] [InlineData(RedundancyRole.Primary, 1, true)] [InlineData(RedundancyRole.Primary, 2, true)] // Secondary / Detached → never service, regardless of member count. [InlineData(RedundancyRole.Secondary, 0, false)] [InlineData(RedundancyRole.Secondary, 2, false)] [InlineData(RedundancyRole.Detached, 0, false)] [InlineData(RedundancyRole.Detached, 2, false)] public void Known_role_wins_regardless_of_member_count(RedundancyRole role, int members, bool expected) => PrimaryGatePolicy.ShouldServiceAsPrimary(role, members).ShouldBe(expected); [Theory] // Unknown role: allow only when no driver peer exists (count <= 1). [InlineData(0, true)] [InlineData(1, true)] [InlineData(2, false)] [InlineData(3, false)] public void Unknown_role_resolves_by_membership(int members, bool expected) => PrimaryGatePolicy.ShouldServiceAsPrimary(null, members).ShouldBe(expected); }