using System.Net; using System.Net.Sockets; using System.Text; using Microsoft.Extensions.Logging.Abstractions; using NATS.Client.Core; using NATS.Server; using NATS.Server.TestUtilities; namespace NATS.Server.Core.Tests; public class IntegrationTests : IAsyncLifetime { private readonly NatsServer _server; private readonly int _port; private readonly CancellationTokenSource _cts = new(); private Task _serverTask = null!; public IntegrationTests() { _port = TestPortAllocator.GetFreePort(); _server = new NatsServer(new NatsOptions { Port = _port }, NullLoggerFactory.Instance); } public async Task InitializeAsync() { _serverTask = _server.StartAsync(_cts.Token); await _server.WaitForReadyAsync(); } public async Task DisposeAsync() { await _cts.CancelAsync(); _server.Dispose(); } private NatsConnection CreateClient() { var opts = new NatsOpts { Url = $"nats://127.0.0.1:{_port}" }; return new NatsConnection(opts); } [Fact] public async Task PubSub_basic() { await using var pub = CreateClient(); await using var sub = CreateClient(); await pub.ConnectAsync(); await sub.ConnectAsync(); await using var subscription = await sub.SubscribeCoreAsync("test.subject"); await sub.PingAsync(); await pub.PublishAsync("test.subject", "Hello NATS!"); using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); var msg = await subscription.Msgs.ReadAsync(timeout.Token); msg.Data.ShouldBe("Hello NATS!"); } [Fact] public async Task PubSub_wildcard_star() { await using var pub = CreateClient(); await using var sub = CreateClient(); await pub.ConnectAsync(); await sub.ConnectAsync(); await using var subscription = await sub.SubscribeCoreAsync("test.*"); await sub.PingAsync(); await pub.PublishAsync("test.hello", "data"); using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); var msg = await subscription.Msgs.ReadAsync(timeout.Token); msg.Subject.ShouldBe("test.hello"); } [Fact] public async Task PubSub_wildcard_gt() { await using var pub = CreateClient(); await using var sub = CreateClient(); await pub.ConnectAsync(); await sub.ConnectAsync(); await using var subscription = await sub.SubscribeCoreAsync("test.>"); await sub.PingAsync(); await pub.PublishAsync("test.foo.bar.baz", "data"); using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); var msg = await subscription.Msgs.ReadAsync(timeout.Token); msg.Subject.ShouldBe("test.foo.bar.baz"); } [Fact] public async Task PubSub_fan_out() { await using var pub = CreateClient(); await using var sub1 = CreateClient(); await using var sub2 = CreateClient(); await pub.ConnectAsync(); await sub1.ConnectAsync(); await sub2.ConnectAsync(); await using var s1 = await sub1.SubscribeCoreAsync("fanout"); await using var s2 = await sub2.SubscribeCoreAsync("fanout"); await sub1.PingAsync(); await sub2.PingAsync(); await pub.PublishAsync("fanout", "hello"); 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] public async Task PingPong() { await using var client = CreateClient(); await client.ConnectAsync(); // If we got here, the connection is alive and PING/PONG works await client.PingAsync(); } }