Files
natsdotnet/tests/NATS.Server.Tests/Events/RemoteServerEventTests.cs
Joseph Doherty 10ac904b5c feat: add remote server events for cluster visibility (Gap 10.8)
Add RemoteServerShutdownEvent, RemoteServerUpdateEvent, LeafNodeConnectEvent,
and LeafNodeDisconnectEvent types plus matching EventSubjects constants, with
10 unit tests covering type identity, field assignment, format placeholders,
and JSON roundtrip serialization.
2026-02-25 13:11:59 -05:00

201 lines
7.2 KiB
C#

using System.Text.Json;
using NATS.Server.Events;
namespace NATS.Server.Tests.Events;
/// <summary>
/// Tests for remote server and leaf node event DTOs and subject constants.
/// Go reference: events.go — remote server lifecycle, leaf node advisory subjects.
/// Gap 10.8: RemoteServerShutdown, RemoteServerUpdate, LeafNodeConnected events.
/// </summary>
public class RemoteServerEventTests
{
// --- RemoteServerShutdownEvent ---
[Fact]
public void RemoteServerShutdownEvent_HasCorrectEventType()
{
RemoteServerShutdownEvent.EventType.ShouldBe("io.nats.server.advisory.v1.remote_shutdown");
var ev = new RemoteServerShutdownEvent();
ev.Type.ShouldBe(RemoteServerShutdownEvent.EventType);
}
[Fact]
public void RemoteServerShutdownEvent_GeneratesUniqueId()
{
var ev1 = new RemoteServerShutdownEvent();
var ev2 = new RemoteServerShutdownEvent();
ev1.Id.ShouldNotBeNullOrEmpty();
ev2.Id.ShouldNotBeNullOrEmpty();
ev1.Id.ShouldNotBe(ev2.Id);
}
// --- RemoteServerUpdateEvent ---
[Fact]
public void RemoteServerUpdateEvent_HasCorrectEventType()
{
RemoteServerUpdateEvent.EventType.ShouldBe("io.nats.server.advisory.v1.remote_update");
var ev = new RemoteServerUpdateEvent();
ev.Type.ShouldBe(RemoteServerUpdateEvent.EventType);
}
[Fact]
public void RemoteServerUpdateEvent_AllFieldsSettable()
{
var server = new EventServerInfo { Id = "srv1", Name = "my-server" };
var ev = new RemoteServerUpdateEvent
{
Server = server,
RemoteServerId = "remote-id-123",
RemoteServerName = "remote-server",
UpdateType = "routes_changed",
};
ev.Server.ShouldBeSameAs(server);
ev.RemoteServerId.ShouldBe("remote-id-123");
ev.RemoteServerName.ShouldBe("remote-server");
ev.UpdateType.ShouldBe("routes_changed");
}
// --- LeafNodeConnectEvent ---
[Fact]
public void LeafNodeConnectEvent_HasCorrectEventType()
{
LeafNodeConnectEvent.EventType.ShouldBe("io.nats.server.advisory.v1.leafnode_connect");
var ev = new LeafNodeConnectEvent();
ev.Type.ShouldBe(LeafNodeConnectEvent.EventType);
}
[Fact]
public void LeafNodeConnectEvent_AllFieldsSettable()
{
var server = new EventServerInfo { Id = "srv1", Name = "hub" };
var ev = new LeafNodeConnectEvent
{
Server = server,
LeafNodeId = "leaf-id-abc",
LeafNodeName = "leaf-node-1",
RemoteUrl = "nats://10.0.0.1:7422",
Account = "ACC",
};
ev.Server.ShouldBeSameAs(server);
ev.LeafNodeId.ShouldBe("leaf-id-abc");
ev.LeafNodeName.ShouldBe("leaf-node-1");
ev.RemoteUrl.ShouldBe("nats://10.0.0.1:7422");
ev.Account.ShouldBe("ACC");
}
// --- LeafNodeDisconnectEvent ---
[Fact]
public void LeafNodeDisconnectEvent_HasCorrectEventType()
{
LeafNodeDisconnectEvent.EventType.ShouldBe("io.nats.server.advisory.v1.leafnode_disconnect");
var ev = new LeafNodeDisconnectEvent();
ev.Type.ShouldBe(LeafNodeDisconnectEvent.EventType);
}
[Fact]
public void LeafNodeDisconnectEvent_AllFieldsSettable()
{
var server = new EventServerInfo { Id = "srv1", Name = "hub" };
var ev = new LeafNodeDisconnectEvent
{
Server = server,
LeafNodeId = "leaf-id-xyz",
Reason = "connection closed",
};
ev.Server.ShouldBeSameAs(server);
ev.LeafNodeId.ShouldBe("leaf-id-xyz");
ev.Reason.ShouldBe("connection closed");
}
// --- EventSubjects ---
[Fact]
public void EventSubjects_RemoteShutdown_HasPlaceholder()
{
EventSubjects.RemoteServerShutdown.ShouldContain("{0}");
EventSubjects.RemoteServerUpdate.ShouldContain("{0}");
EventSubjects.LeafNodeConnected.ShouldContain("{0}");
EventSubjects.LeafNodeDisconnected.ShouldContain("{0}");
// Verify format strings produce expected subjects when formatted
var serverId = "ABCDEF123456";
string.Format(EventSubjects.RemoteServerShutdown, serverId)
.ShouldBe($"$SYS.SERVER.{serverId}.REMOTE.SHUTDOWN");
string.Format(EventSubjects.LeafNodeConnected, serverId)
.ShouldBe($"$SYS.SERVER.{serverId}.LEAFNODE.CONNECT");
}
// --- JSON serialization ---
[Fact]
public void AllRemoteEvents_SerializeToJson()
{
var server = new EventServerInfo { Id = "srv-id", Name = "test-server" };
var shutdown = new RemoteServerShutdownEvent
{
Server = server,
RemoteServerId = "r1",
RemoteServerName = "remote",
Reason = "graceful",
};
var shutdownJson = JsonSerializer.Serialize(shutdown);
var shutdownDoc = JsonDocument.Parse(shutdownJson).RootElement;
shutdownDoc.GetProperty("type").GetString().ShouldBe(RemoteServerShutdownEvent.EventType);
shutdownDoc.GetProperty("id").GetString().ShouldNotBeNullOrEmpty();
shutdownDoc.GetProperty("remote_server_id").GetString().ShouldBe("r1");
shutdownDoc.GetProperty("reason").GetString().ShouldBe("graceful");
var update = new RemoteServerUpdateEvent
{
Server = server,
RemoteServerId = "r2",
RemoteServerName = "remote2",
UpdateType = "config_updated",
};
var updateJson = JsonSerializer.Serialize(update);
var updateDoc = JsonDocument.Parse(updateJson).RootElement;
updateDoc.GetProperty("type").GetString().ShouldBe(RemoteServerUpdateEvent.EventType);
updateDoc.GetProperty("update_type").GetString().ShouldBe("config_updated");
var connect = new LeafNodeConnectEvent
{
Server = server,
LeafNodeId = "leaf1",
LeafNodeName = "leaf-node",
RemoteUrl = "nats://10.0.0.1:7422",
Account = "ACC",
};
var connectJson = JsonSerializer.Serialize(connect);
var connectDoc = JsonDocument.Parse(connectJson).RootElement;
connectDoc.GetProperty("type").GetString().ShouldBe(LeafNodeConnectEvent.EventType);
connectDoc.GetProperty("leaf_node_id").GetString().ShouldBe("leaf1");
connectDoc.GetProperty("account").GetString().ShouldBe("ACC");
var disconnect = new LeafNodeDisconnectEvent
{
Server = server,
LeafNodeId = "leaf1",
Reason = "timeout",
};
var disconnectJson = JsonSerializer.Serialize(disconnect);
var disconnectDoc = JsonDocument.Parse(disconnectJson).RootElement;
disconnectDoc.GetProperty("type").GetString().ShouldBe(LeafNodeDisconnectEvent.EventType);
disconnectDoc.GetProperty("leaf_node_id").GetString().ShouldBe("leaf1");
disconnectDoc.GetProperty("reason").GetString().ShouldBe("timeout");
// Roundtrip: deserialize back and verify type field survives
var shutdownRt = JsonSerializer.Deserialize<RemoteServerShutdownEvent>(shutdownJson);
shutdownRt.ShouldNotBeNull();
shutdownRt!.Type.ShouldBe(RemoteServerShutdownEvent.EventType);
shutdownRt.RemoteServerId.ShouldBe("r1");
}
}