using System.Net; using System.Net.Sockets; using Microsoft.Extensions.Logging.Abstractions; using NATS.Server.Configuration; namespace NATS.Server.Tests; public class MonitorClusterEndpointTests { [Fact] public async Task Routez_gatewayz_leafz_accountz_return_non_stub_runtime_data() { await using var fx = await MonitorFixture.StartClusterEnabledAsync(); (await fx.GetJsonAsync("/routez")).ShouldContain("routes"); (await fx.GetJsonAsync("/gatewayz")).ShouldContain("gateways"); (await fx.GetJsonAsync("/leafz")).ShouldContain("leafs"); (await fx.GetJsonAsync("/accountz")).ShouldContain("accounts"); } } internal sealed class MonitorFixture : IAsyncDisposable { private readonly NatsServer _server; private readonly CancellationTokenSource _cts; private readonly HttpClient _http; private readonly int _monitorPort; private MonitorFixture(NatsServer server, CancellationTokenSource cts, HttpClient http, int monitorPort) { _server = server; _cts = cts; _http = http; _monitorPort = monitorPort; } public static async Task StartClusterEnabledAsync() { var monitorPort = GetFreePort(); var options = new NatsOptions { Host = "127.0.0.1", Port = 0, MonitorPort = monitorPort, Cluster = new ClusterOptions { Host = "127.0.0.1", Port = 0, }, Gateway = new GatewayOptions { Host = "127.0.0.1", Port = 0, Name = "M", }, LeafNode = new LeafNodeOptions { Host = "127.0.0.1", Port = 0, }, }; var server = new NatsServer(options, NullLoggerFactory.Instance); var cts = new CancellationTokenSource(); _ = server.StartAsync(cts.Token); await server.WaitForReadyAsync(); var http = new HttpClient(); for (var i = 0; i < 50; i++) { try { var response = await http.GetAsync($"http://127.0.0.1:{monitorPort}/healthz"); if (response.IsSuccessStatusCode) break; } catch { } await Task.Delay(50); } return new MonitorFixture(server, cts, http, monitorPort); } public Task GetJsonAsync(string path) { return _http.GetStringAsync($"http://127.0.0.1:{_monitorPort}{path}"); } public async ValueTask DisposeAsync() { _http.Dispose(); await _cts.CancelAsync(); _server.Dispose(); _cts.Dispose(); } private static int GetFreePort() { using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); return ((IPEndPoint)socket.LocalEndPoint!).Port; } }