using Xunit; namespace ZB.MOM.WW.ScadaBridge.Host.Tests; /// /// Pins , which re-declares central's HTTP surface /// after the gRPC listener switches Kestrel into explicit-endpoints mode. /// /// /// This exists because the regression it guards is invisible to every other test: a central /// node that binds only the gRPC port boots clean, joins the cluster and serves gRPC, while /// the Central UI, Management/Inbound API and /health/* are silently dead. TestServer /// never binds real Kestrel, so the parser is the one seam that can be asserted in-process. /// The rig caught the original defect; this keeps it caught. /// public class CentralHttpBindPortsTests { [Theory] [InlineData("http://+:5000", new[] { 5000 })] [InlineData("http://0.0.0.0:5000", new[] { 5000 })] [InlineData("http://[::]:5000", new[] { 5000 })] [InlineData("http://localhost:5000", new[] { 5000 })] [InlineData("http://*:8085", new[] { 8085 })] [InlineData("http://+:5000;http://+:5001", new[] { 5000, 5001 })] [InlineData("http://+:5000 ; http://+:5001", new[] { 5000, 5001 })] [InlineData("http://+:5000;http://+:5000", new[] { 5000 })] // de-duped public void ParsesPortsFromServerUrls(string urls, int[] expected) { Assert.Equal(expected, Program.ParseHttpBindPorts(urls)); } [Theory] [InlineData("https://+:443", 443)] // scheme default when no explicit port [InlineData("http://+:80", 80)] public void HandlesSchemeDefaultAndExplicitPort(string url, int expected) { Assert.Equal(new[] { expected }, Program.ParseHttpBindPorts(url)); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void EmptyOrNull_YieldsNoPorts(string? urls) { Assert.Empty(Program.ParseHttpBindPorts(urls)); } [Fact] public void UnparseableEntry_IsSkipped_NotThrown() { // A malformed URL must not take the node down at boot; the good one still binds. var ports = Program.ParseHttpBindPorts("not-a-url;http://+:5000"); Assert.Equal(new[] { 5000 }, ports); } }