Files
natsdotnet/tests/NATS.Server.Tests/Routes/RouteBatchProtoParityBatch3Tests.cs
Joseph Doherty c30e67a69d Fix E2E test gaps and add comprehensive E2E + parity test suites
- Fix pull consumer fetch: send original stream subject in HMSG (not inbox)
  so NATS client distinguishes data messages from control messages
- Fix MaxAge expiry: add background timer in StreamManager for periodic pruning
- Fix JetStream wire format: Go-compatible anonymous objects with string enums,
  proper offset-based pagination for stream/consumer list APIs
- Add 42 E2E black-box tests (core messaging, auth, TLS, accounts, JetStream)
- Add ~1000 parity tests across all subsystems (gaps closure)
- Update gap inventory docs to reflect implementation status
2026-03-12 14:09:23 -04:00

104 lines
3.0 KiB
C#

using System.Net;
using System.Net.Sockets;
using System.Text;
using NATS.Server.Routes;
using NATS.Server.Subscriptions;
namespace NATS.Server.Tests.Routes;
public class RouteBatchProtoParityBatch3Tests
{
[Fact]
public async Task SendRouteSubProtosAsync_writes_batched_rs_plus_frames()
{
var (connection, peer) = CreateRoutePair();
try
{
await connection.SendRouteSubProtosAsync(
[
new RemoteSubscription("orders.*", null, "r1", Account: "A"),
new RemoteSubscription("orders.q", "workers", "r1", Account: "A", QueueWeight: 2),
],
CancellationToken.None);
var data = ReadFromPeer(peer);
data.ShouldContain("RS+ A orders.*");
data.ShouldContain("RS+ A orders.q workers 2");
}
finally
{
await connection.DisposeAsync();
peer.Dispose();
}
}
[Fact]
public async Task SendRouteUnSubProtosAsync_writes_batched_rs_minus_frames()
{
var (connection, peer) = CreateRoutePair();
try
{
await connection.SendRouteUnSubProtosAsync(
[
new RemoteSubscription("orders.*", null, "r1", Account: "A"),
new RemoteSubscription("orders.q", "workers", "r1", Account: "A"),
],
CancellationToken.None);
var data = ReadFromPeer(peer);
data.ShouldContain("RS- A orders.*");
data.ShouldContain("RS- A orders.q workers");
}
finally
{
await connection.DisposeAsync();
peer.Dispose();
}
}
[Fact]
public async Task SendRouteSubOrUnSubProtosAsync_skips_empty_lines_and_flushes_once()
{
var (connection, peer) = CreateRoutePair();
try
{
await connection.SendRouteSubOrUnSubProtosAsync(
["RS+ A foo.bar", "", " ", "RS- A foo.bar"],
CancellationToken.None);
var data = ReadFromPeer(peer);
data.ShouldContain("RS+ A foo.bar");
data.ShouldContain("RS- A foo.bar");
data.ShouldNotContain("\r\n\r\n");
}
finally
{
await connection.DisposeAsync();
peer.Dispose();
}
}
private static (RouteConnection Route, Socket Peer) CreateRoutePair()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var endpoint = (IPEndPoint)listener.LocalEndpoint;
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(endpoint);
var server = listener.AcceptSocket();
listener.Stop();
return (new RouteConnection(client), server);
}
private static string ReadFromPeer(Socket peer)
{
peer.ReceiveTimeout = 2_000;
var buffer = new byte[4096];
var read = peer.Receive(buffer);
return Encoding.ASCII.GetString(buffer, 0, read);
}
}