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:
@@ -7,22 +7,26 @@ using NATS.Server;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class IntegrationTests : IAsyncDisposable
|
||||
public class IntegrationTests : IAsyncLifetime
|
||||
{
|
||||
private readonly NatsServer _server;
|
||||
private readonly int _port;
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
private readonly Task _serverTask;
|
||||
private Task _serverTask = null!;
|
||||
|
||||
public IntegrationTests()
|
||||
{
|
||||
_port = GetFreePort();
|
||||
_server = new NatsServer(new NatsOptions { Port = _port }, NullLoggerFactory.Instance);
|
||||
_serverTask = _server.StartAsync(_cts.Token);
|
||||
Thread.Sleep(200); // Let server start
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
_serverTask = _server.StartAsync(_cts.Token);
|
||||
await _server.WaitForReadyAsync();
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await _cts.CancelAsync();
|
||||
_server.Dispose();
|
||||
@@ -50,23 +54,14 @@ public class IntegrationTests : IAsyncDisposable
|
||||
await pub.ConnectAsync();
|
||||
await sub.ConnectAsync();
|
||||
|
||||
var received = new TaskCompletionSource<string>();
|
||||
|
||||
var subscription = Task.Run(async () =>
|
||||
{
|
||||
await foreach (var msg in sub.SubscribeAsync<string>("test.subject"))
|
||||
{
|
||||
received.TrySetResult(msg.Data!);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
await Task.Delay(100); // let subscription register
|
||||
await using var subscription = await sub.SubscribeCoreAsync<string>("test.subject");
|
||||
await sub.PingAsync();
|
||||
|
||||
await pub.PublishAsync("test.subject", "Hello NATS!");
|
||||
|
||||
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
result.ShouldBe("Hello NATS!");
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
var msg = await subscription.Msgs.ReadAsync(timeout.Token);
|
||||
msg.Data.ShouldBe("Hello NATS!");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -78,22 +73,14 @@ public class IntegrationTests : IAsyncDisposable
|
||||
await pub.ConnectAsync();
|
||||
await sub.ConnectAsync();
|
||||
|
||||
var received = new TaskCompletionSource<string>();
|
||||
await using var subscription = await sub.SubscribeCoreAsync<string>("test.*");
|
||||
await sub.PingAsync();
|
||||
|
||||
var subscription = Task.Run(async () =>
|
||||
{
|
||||
await foreach (var msg in sub.SubscribeAsync<string>("test.*"))
|
||||
{
|
||||
received.TrySetResult(msg.Subject);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
await Task.Delay(100);
|
||||
await pub.PublishAsync("test.hello", "data");
|
||||
|
||||
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
result.ShouldBe("test.hello");
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
var msg = await subscription.Msgs.ReadAsync(timeout.Token);
|
||||
msg.Subject.ShouldBe("test.hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -105,22 +92,14 @@ public class IntegrationTests : IAsyncDisposable
|
||||
await pub.ConnectAsync();
|
||||
await sub.ConnectAsync();
|
||||
|
||||
var received = new TaskCompletionSource<string>();
|
||||
await using var subscription = await sub.SubscribeCoreAsync<string>("test.>");
|
||||
await sub.PingAsync();
|
||||
|
||||
var subscription = Task.Run(async () =>
|
||||
{
|
||||
await foreach (var msg in sub.SubscribeAsync<string>("test.>"))
|
||||
{
|
||||
received.TrySetResult(msg.Subject);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
await Task.Delay(100);
|
||||
await pub.PublishAsync("test.foo.bar.baz", "data");
|
||||
|
||||
var result = await received.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
result.ShouldBe("test.foo.bar.baz");
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
var msg = await subscription.Msgs.ReadAsync(timeout.Token);
|
||||
msg.Subject.ShouldBe("test.foo.bar.baz");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -134,38 +113,18 @@ public class IntegrationTests : IAsyncDisposable
|
||||
await sub1.ConnectAsync();
|
||||
await sub2.ConnectAsync();
|
||||
|
||||
var count1 = 0;
|
||||
var count2 = 0;
|
||||
var done = new TaskCompletionSource();
|
||||
await using var s1 = await sub1.SubscribeCoreAsync<string>("fanout");
|
||||
await using var s2 = await sub2.SubscribeCoreAsync<string>("fanout");
|
||||
await sub1.PingAsync();
|
||||
await sub2.PingAsync();
|
||||
|
||||
var s1 = Task.Run(async () =>
|
||||
{
|
||||
await foreach (var msg in sub1.SubscribeAsync<string>("fanout"))
|
||||
{
|
||||
Interlocked.Increment(ref count1);
|
||||
if (Volatile.Read(ref count1) + Volatile.Read(ref count2) >= 2)
|
||||
done.TrySetResult();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
var s2 = Task.Run(async () =>
|
||||
{
|
||||
await foreach (var msg in sub2.SubscribeAsync<string>("fanout"))
|
||||
{
|
||||
Interlocked.Increment(ref count2);
|
||||
if (Volatile.Read(ref count1) + Volatile.Read(ref count2) >= 2)
|
||||
done.TrySetResult();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
await Task.Delay(100);
|
||||
await pub.PublishAsync("fanout", "hello");
|
||||
|
||||
await done.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
count1.ShouldBe(1);
|
||||
count2.ShouldBe(1);
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
var msg1 = await s1.Msgs.ReadAsync(timeout.Token);
|
||||
var msg2 = await s2.Msgs.ReadAsync(timeout.Token);
|
||||
msg1.Data.ShouldBe("hello");
|
||||
msg2.Data.ShouldBe("hello");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user