fix: resolve slopwatch issues — add logging to empty catches and eliminate test timing delays
Replace empty catch blocks with meaningful log statements in NatsServer, NatsClient, and Program. Add WaitForReadyAsync() to NatsServer for deterministic server startup. Replace Task.Delay/Thread.Sleep in tests with PING/PONG protocol flush and SubscribeCoreAsync for reliable subscription synchronization.
This commit is contained in:
@@ -6,7 +6,7 @@ using NATS.Server;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class ServerTests : IAsyncDisposable
|
||||
public class ServerTests : IAsyncLifetime
|
||||
{
|
||||
private readonly NatsServer _server;
|
||||
private readonly int _port;
|
||||
@@ -19,7 +19,13 @@ public class ServerTests : IAsyncDisposable
|
||||
_server = new NatsServer(new NatsOptions { Port = _port }, NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
_ = _server.StartAsync(_cts.Token);
|
||||
await _server.WaitForReadyAsync();
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await _cts.CancelAsync();
|
||||
_server.Dispose();
|
||||
@@ -46,25 +52,35 @@ public class ServerTests : IAsyncDisposable
|
||||
return Encoding.ASCII.GetString(buf, 0, n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads from a socket until the accumulated data contains the expected substring.
|
||||
/// </summary>
|
||||
private static async Task<string> ReadUntilAsync(Socket sock, string expected, int timeoutMs = 5000)
|
||||
{
|
||||
using var cts = new CancellationTokenSource(timeoutMs);
|
||||
var sb = new StringBuilder();
|
||||
var buf = new byte[4096];
|
||||
while (!sb.ToString().Contains(expected))
|
||||
{
|
||||
var n = await sock.ReceiveAsync(buf, SocketFlags.None, cts.Token);
|
||||
if (n == 0) break;
|
||||
sb.Append(Encoding.ASCII.GetString(buf, 0, n));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Server_accepts_connection_and_sends_INFO()
|
||||
{
|
||||
var serverTask = _server.StartAsync(_cts.Token);
|
||||
await Task.Delay(100); // let server start
|
||||
|
||||
using var client = await ConnectClientAsync();
|
||||
var response = await ReadLineAsync(client);
|
||||
|
||||
response.ShouldStartWith("INFO ");
|
||||
await _cts.CancelAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Server_basic_pubsub()
|
||||
{
|
||||
var serverTask = _server.StartAsync(_cts.Token);
|
||||
await Task.Delay(100);
|
||||
|
||||
using var pub = await ConnectClientAsync();
|
||||
using var sub = await ConnectClientAsync();
|
||||
|
||||
@@ -72,46 +88,39 @@ public class ServerTests : IAsyncDisposable
|
||||
await ReadLineAsync(pub);
|
||||
await ReadLineAsync(sub);
|
||||
|
||||
// CONNECT + SUB on subscriber
|
||||
await sub.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nSUB foo 1\r\n"));
|
||||
await Task.Delay(50);
|
||||
// CONNECT + SUB on subscriber, then PING to flush
|
||||
await sub.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nSUB foo 1\r\nPING\r\n"));
|
||||
var pong = await ReadLineAsync(sub);
|
||||
pong.ShouldContain("PONG");
|
||||
|
||||
// CONNECT + PUB on publisher
|
||||
await pub.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nPUB foo 5\r\nHello\r\n"));
|
||||
await Task.Delay(100);
|
||||
|
||||
// Read MSG from subscriber
|
||||
var buf = new byte[4096];
|
||||
var n = await sub.ReceiveAsync(buf, SocketFlags.None);
|
||||
var msg = Encoding.ASCII.GetString(buf, 0, n);
|
||||
|
||||
// Read MSG from subscriber (may arrive across multiple TCP segments)
|
||||
var msg = await ReadUntilAsync(sub, "Hello\r\n");
|
||||
msg.ShouldContain("MSG foo 1 5\r\nHello\r\n");
|
||||
await _cts.CancelAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Server_wildcard_matching()
|
||||
{
|
||||
var serverTask = _server.StartAsync(_cts.Token);
|
||||
await Task.Delay(100);
|
||||
|
||||
using var pub = await ConnectClientAsync();
|
||||
using var sub = await ConnectClientAsync();
|
||||
|
||||
await ReadLineAsync(pub);
|
||||
await ReadLineAsync(sub);
|
||||
|
||||
await sub.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nSUB foo.* 1\r\n"));
|
||||
await Task.Delay(50);
|
||||
// CONNECT + SUB on subscriber, then PING to flush
|
||||
await sub.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nSUB foo.* 1\r\nPING\r\n"));
|
||||
var pong = await ReadLineAsync(sub);
|
||||
pong.ShouldContain("PONG");
|
||||
|
||||
await pub.SendAsync(Encoding.ASCII.GetBytes("CONNECT {}\r\nPUB foo.bar 5\r\nHello\r\n"));
|
||||
await Task.Delay(100);
|
||||
|
||||
var buf = new byte[4096];
|
||||
var n = await sub.ReceiveAsync(buf, SocketFlags.None);
|
||||
var msg = Encoding.ASCII.GetString(buf, 0, n);
|
||||
|
||||
msg.ShouldContain("MSG foo.bar 1 5\r\n");
|
||||
await _cts.CancelAsync();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user