feat: execute post-baseline jetstream parity plan
This commit is contained in:
84
tests/NATS.Server.Tests/InterServerAccountProtocolTests.cs
Normal file
84
tests/NATS.Server.Tests/InterServerAccountProtocolTests.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using NATS.Server.Gateways;
|
||||
using NATS.Server.Subscriptions;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class InterServerAccountProtocolTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Aplus_Aminus_frames_include_account_scope_and_do_not_leak_interest_across_accounts()
|
||||
{
|
||||
using var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
listener.Start();
|
||||
|
||||
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
using var remoteSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
await remoteSocket.ConnectAsync(IPAddress.Loopback, port);
|
||||
using var gatewaySocket = await listener.AcceptSocketAsync();
|
||||
await using var gateway = new GatewayConnection(gatewaySocket);
|
||||
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
var handshakeTask = gateway.PerformOutboundHandshakeAsync("LOCAL", timeout.Token);
|
||||
(await ReadLineAsync(remoteSocket, timeout.Token)).ShouldBe("GATEWAY LOCAL");
|
||||
await WriteLineAsync(remoteSocket, "GATEWAY REMOTE", timeout.Token);
|
||||
await handshakeTask;
|
||||
|
||||
var received = new TaskCompletionSource<RemoteSubscription>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
gateway.RemoteSubscriptionReceived = sub =>
|
||||
{
|
||||
received.TrySetResult(sub);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
gateway.StartLoop(timeout.Token);
|
||||
|
||||
await WriteLineAsync(remoteSocket, "A+ A orders.*", timeout.Token);
|
||||
var aPlus = await received.Task.WaitAsync(timeout.Token);
|
||||
aPlus.Account.ShouldBe("A");
|
||||
aPlus.Subject.ShouldBe("orders.*");
|
||||
aPlus.IsRemoval.ShouldBeFalse();
|
||||
|
||||
var subList = new SubList();
|
||||
subList.ApplyRemoteSub(aPlus);
|
||||
subList.HasRemoteInterest("A", "orders.created").ShouldBeTrue();
|
||||
subList.HasRemoteInterest("B", "orders.created").ShouldBeFalse();
|
||||
|
||||
var removedTcs = new TaskCompletionSource<RemoteSubscription>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
gateway.RemoteSubscriptionReceived = sub =>
|
||||
{
|
||||
removedTcs.TrySetResult(sub);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await WriteLineAsync(remoteSocket, "A- A orders.*", timeout.Token);
|
||||
var aMinus = await removedTcs.Task.WaitAsync(timeout.Token);
|
||||
aMinus.Account.ShouldBe("A");
|
||||
aMinus.IsRemoval.ShouldBeTrue();
|
||||
|
||||
subList.ApplyRemoteSub(aMinus);
|
||||
subList.HasRemoteInterest("A", "orders.created").ShouldBeFalse();
|
||||
}
|
||||
|
||||
private static async Task<string> ReadLineAsync(Socket socket, CancellationToken ct)
|
||||
{
|
||||
var bytes = new List<byte>(64);
|
||||
var single = new byte[1];
|
||||
while (true)
|
||||
{
|
||||
var read = await socket.ReceiveAsync(single, SocketFlags.None, ct);
|
||||
if (read == 0)
|
||||
break;
|
||||
if (single[0] == (byte)'\n')
|
||||
break;
|
||||
if (single[0] != (byte)'\r')
|
||||
bytes.Add(single[0]);
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetString([.. bytes]);
|
||||
}
|
||||
|
||||
private static Task WriteLineAsync(Socket socket, string line, CancellationToken ct)
|
||||
=> socket.SendAsync(Encoding.ASCII.GetBytes($"{line}\r\n"), SocketFlags.None, ct).AsTask();
|
||||
}
|
||||
Reference in New Issue
Block a user