using System.IO.Pipelines; using System.Net; using System.Net.Sockets; using System.Text; using System.Text.Json; using NATS.Server; using NATS.Server.Protocol; namespace NATS.Server.Tests; public class ClientTests : IAsyncDisposable { private readonly Socket _serverSocket; private readonly Socket _clientSocket; private readonly NatsClient _natsClient; private readonly CancellationTokenSource _cts = new(); public ClientTests() { // Create connected socket pair via loopback var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); listener.Listen(1); var port = ((IPEndPoint)listener.LocalEndPoint!).Port; _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _clientSocket.Connect(IPAddress.Loopback, port); _serverSocket = listener.Accept(); listener.Dispose(); var serverInfo = new ServerInfo { ServerId = "test", ServerName = "test", Version = "0.1.0", Host = "127.0.0.1", Port = 4222, }; _natsClient = new NatsClient(1, _serverSocket, new NatsOptions(), serverInfo); } public async ValueTask DisposeAsync() { await _cts.CancelAsync(); _natsClient.Dispose(); _clientSocket.Dispose(); } [Fact] public async Task Client_sends_INFO_on_start() { var runTask = _natsClient.RunAsync(_cts.Token); // Read from client socket — should get INFO var buf = new byte[4096]; var n = await _clientSocket.ReceiveAsync(buf, SocketFlags.None); var response = Encoding.ASCII.GetString(buf, 0, n); Assert.StartsWith("INFO ", response); Assert.Contains("server_id", response); Assert.Contains("\r\n", response); await _cts.CancelAsync(); } [Fact] public async Task Client_responds_PONG_to_PING() { var runTask = _natsClient.RunAsync(_cts.Token); // Read INFO var buf = new byte[4096]; await _clientSocket.ReceiveAsync(buf, SocketFlags.None); // Send CONNECT then PING await _clientSocket.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nPING\r\n")); // Read response — should get PONG var n = await _clientSocket.ReceiveAsync(buf, SocketFlags.None); var response = Encoding.ASCII.GetString(buf, 0, n); Assert.Contains("PONG\r\n", response); await _cts.CancelAsync(); } }