134 lines
4.6 KiB
C#
134 lines
4.6 KiB
C#
using System.Text.Json;
|
|
using NATS.Server;
|
|
using NATS.Server.Events;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
namespace NATS.Server.Tests;
|
|
|
|
public class SystemEventsTests
|
|
{
|
|
[Fact]
|
|
public async Task Server_publishes_connect_event_on_client_auth()
|
|
{
|
|
using var server = CreateTestServer();
|
|
_ = server.StartAsync(CancellationToken.None);
|
|
await server.WaitForReadyAsync();
|
|
|
|
var received = new TaskCompletionSource<string>();
|
|
server.EventSystem!.SysSubscribe("$SYS.ACCOUNT.*.CONNECT", (sub, client, acc, subject, reply, hdr, msg) =>
|
|
{
|
|
received.TrySetResult(subject);
|
|
});
|
|
|
|
// Connect a real client
|
|
using var sock = new System.Net.Sockets.Socket(
|
|
System.Net.Sockets.AddressFamily.InterNetwork,
|
|
System.Net.Sockets.SocketType.Stream,
|
|
System.Net.Sockets.ProtocolType.Tcp);
|
|
await sock.ConnectAsync(System.Net.IPAddress.Loopback, server.Port);
|
|
|
|
// Read INFO
|
|
var buf = new byte[4096];
|
|
await sock.ReceiveAsync(buf);
|
|
|
|
// Send CONNECT
|
|
var connect = System.Text.Encoding.ASCII.GetBytes("CONNECT {}\r\n");
|
|
await sock.SendAsync(connect);
|
|
|
|
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
result.ShouldStartWith("$SYS.ACCOUNT.");
|
|
result.ShouldEndWith(".CONNECT");
|
|
|
|
await server.ShutdownAsync();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Server_publishes_disconnect_event_on_client_close()
|
|
{
|
|
using var server = CreateTestServer();
|
|
_ = server.StartAsync(CancellationToken.None);
|
|
await server.WaitForReadyAsync();
|
|
|
|
var received = new TaskCompletionSource<string>();
|
|
server.EventSystem!.SysSubscribe("$SYS.ACCOUNT.*.DISCONNECT", (sub, client, acc, subject, reply, hdr, msg) =>
|
|
{
|
|
received.TrySetResult(subject);
|
|
});
|
|
|
|
// Connect and then disconnect
|
|
using var sock = new System.Net.Sockets.Socket(
|
|
System.Net.Sockets.AddressFamily.InterNetwork,
|
|
System.Net.Sockets.SocketType.Stream,
|
|
System.Net.Sockets.ProtocolType.Tcp);
|
|
await sock.ConnectAsync(System.Net.IPAddress.Loopback, server.Port);
|
|
var buf = new byte[4096];
|
|
await sock.ReceiveAsync(buf);
|
|
await sock.SendAsync(System.Text.Encoding.ASCII.GetBytes("CONNECT {}\r\n"));
|
|
await Task.Delay(100);
|
|
sock.Shutdown(System.Net.Sockets.SocketShutdown.Both);
|
|
|
|
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
result.ShouldStartWith("$SYS.ACCOUNT.");
|
|
result.ShouldEndWith(".DISCONNECT");
|
|
|
|
await server.ShutdownAsync();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Server_publishes_statsz_periodically()
|
|
{
|
|
using var server = CreateTestServer();
|
|
_ = server.StartAsync(CancellationToken.None);
|
|
await server.WaitForReadyAsync();
|
|
|
|
var received = new TaskCompletionSource<string>();
|
|
server.EventSystem!.SysSubscribe("$SYS.SERVER.*.STATSZ", (sub, client, acc, subject, reply, hdr, msg) =>
|
|
{
|
|
received.TrySetResult(subject);
|
|
});
|
|
|
|
// Trigger a manual stats publish (don't wait 10s)
|
|
server.EventSystem!.PublishServerStats();
|
|
|
|
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
result.ShouldContain(".STATSZ");
|
|
|
|
await server.ShutdownAsync();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Server_publishes_shutdown_event()
|
|
{
|
|
using var server = CreateTestServer();
|
|
_ = server.StartAsync(CancellationToken.None);
|
|
await server.WaitForReadyAsync();
|
|
|
|
var received = new TaskCompletionSource<string>();
|
|
server.EventSystem!.SysSubscribe("$SYS.SERVER.*.SHUTDOWN", (sub, client, acc, subject, reply, hdr, msg) =>
|
|
{
|
|
received.TrySetResult(subject);
|
|
});
|
|
|
|
await server.ShutdownAsync();
|
|
|
|
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
|
result.ShouldContain(".SHUTDOWN");
|
|
}
|
|
|
|
private static NatsServer CreateTestServer()
|
|
{
|
|
var port = GetFreePort();
|
|
return new NatsServer(new NatsOptions { Port = port }, NullLoggerFactory.Instance);
|
|
}
|
|
|
|
private static int GetFreePort()
|
|
{
|
|
using var sock = new System.Net.Sockets.Socket(
|
|
System.Net.Sockets.AddressFamily.InterNetwork,
|
|
System.Net.Sockets.SocketType.Stream,
|
|
System.Net.Sockets.ProtocolType.Tcp);
|
|
sock.Bind(new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, 0));
|
|
return ((System.Net.IPEndPoint)sock.LocalEndPoint!).Port;
|
|
}
|
|
}
|