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
This commit is contained in:
170
tests/NATS.Server.Tests/Routes/RouteParityHelpersBatch1Tests.cs
Normal file
170
tests/NATS.Server.Tests/Routes/RouteParityHelpersBatch1Tests.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NATS.Server.Configuration;
|
||||
using NATS.Server.Protocol;
|
||||
using NATS.Server.Routes;
|
||||
|
||||
namespace NATS.Server.Tests.Routes;
|
||||
|
||||
public class RouteParityHelpersBatch1Tests
|
||||
{
|
||||
[Fact]
|
||||
public void BuildConnectInfoJson_includes_connectinfo_compat_fields()
|
||||
{
|
||||
var json = RouteConnection.BuildConnectInfoJson("S1", ["A"], "topo-v1");
|
||||
|
||||
json.ShouldContain("\"verbose\":false");
|
||||
json.ShouldContain("\"pedantic\":false");
|
||||
json.ShouldContain("\"echo\":false");
|
||||
json.ShouldContain("\"tls_required\":false");
|
||||
json.ShouldContain("\"headers\":true");
|
||||
json.ShouldContain("\"name\":\"S1\"");
|
||||
json.ShouldContain("\"cluster\":\"\"");
|
||||
json.ShouldContain("\"dynamic\":false");
|
||||
json.ShouldContain("\"lnoc\":false");
|
||||
json.ShouldContain("\"lnocu\":false");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasThisRouteConfigured_matches_explicit_routes_with_scheme_normalization()
|
||||
{
|
||||
var manager = CreateManager(new ClusterOptions
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 0,
|
||||
Routes = ["127.0.0.1:7222"],
|
||||
});
|
||||
|
||||
manager.HasThisRouteConfigured("127.0.0.1:7222").ShouldBeTrue();
|
||||
manager.HasThisRouteConfigured("nats-route://127.0.0.1:7222").ShouldBeTrue();
|
||||
manager.HasThisRouteConfigured("nats://127.0.0.1:7222").ShouldBeTrue();
|
||||
manager.HasThisRouteConfigured("127.0.0.1:7999").ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessImplicitRoute_skips_configured_routes_and_tracks_new_routes()
|
||||
{
|
||||
var manager = CreateManager(new ClusterOptions
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 0,
|
||||
Routes = ["127.0.0.1:7222"],
|
||||
});
|
||||
|
||||
var serverInfo = new ServerInfo
|
||||
{
|
||||
ServerId = "S2",
|
||||
ServerName = "S2",
|
||||
Version = NatsProtocol.Version,
|
||||
Host = "127.0.0.1",
|
||||
Port = 7222,
|
||||
ConnectUrls = ["127.0.0.1:7222", "nats-route://127.0.0.1:7444"],
|
||||
};
|
||||
|
||||
manager.ProcessImplicitRoute(serverInfo);
|
||||
|
||||
manager.DiscoveredRoutes.ShouldNotContain("127.0.0.1:7222");
|
||||
manager.DiscoveredRoutes.ShouldContain("nats-route://127.0.0.1:7444");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RouteStillValid_checks_configured_and_discovered_routes()
|
||||
{
|
||||
var manager = CreateManager(new ClusterOptions
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 0,
|
||||
Routes = ["127.0.0.1:7222"],
|
||||
});
|
||||
|
||||
manager.RouteStillValid("nats://127.0.0.1:7222").ShouldBeTrue();
|
||||
manager.RouteStillValid("127.0.0.1:7555").ShouldBeFalse();
|
||||
|
||||
manager.ProcessImplicitRoute(new ServerInfo
|
||||
{
|
||||
ServerId = "S2",
|
||||
ServerName = "S2",
|
||||
Version = NatsProtocol.Version,
|
||||
Host = "127.0.0.1",
|
||||
Port = 7444,
|
||||
ConnectUrls = ["127.0.0.1:7444"],
|
||||
});
|
||||
|
||||
manager.RouteStillValid("nats-route://127.0.0.1:7444").ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Solicited_route_helpers_upgrade_and_query_status()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
await using var connection = MakeRouteConnection();
|
||||
|
||||
manager.RegisterRoute("S2", connection);
|
||||
manager.HasSolicitedRoute("S2").ShouldBeFalse();
|
||||
|
||||
manager.UpgradeRouteToSolicited("S2").ShouldBeTrue();
|
||||
connection.IsSolicitedRoute().ShouldBeTrue();
|
||||
manager.HasSolicitedRoute("S2").ShouldBeTrue();
|
||||
manager.IsDuplicateServerName("S2").ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoveRoute_cleans_hash_and_account_route_indexes()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var connection = MakeRouteConnection();
|
||||
|
||||
manager.RegisterRoute("S2", connection);
|
||||
manager.RegisterRouteByHash("S2", connection);
|
||||
manager.RegisterAccountRoute("A", connection);
|
||||
|
||||
manager.HashedRouteCount.ShouldBe(1);
|
||||
manager.DedicatedRouteCount.ShouldBe(1);
|
||||
|
||||
manager.RemoveRoute("S2").ShouldBeTrue();
|
||||
manager.HashedRouteCount.ShouldBe(0);
|
||||
manager.DedicatedRouteCount.ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryParseRemoteUnsub_parses_rs_minus_and_ls_minus()
|
||||
{
|
||||
RouteConnection.TryParseRemoteUnsub("RS- ACCT_A foo.bar q1", out var account1, out var subject1, out var queue1).ShouldBeTrue();
|
||||
account1.ShouldBe("ACCT_A");
|
||||
subject1.ShouldBe("foo.bar");
|
||||
queue1.ShouldBe("q1");
|
||||
|
||||
RouteConnection.TryParseRemoteUnsub("LS- ACCT_B foo.>", out var account2, out var subject2, out var queue2).ShouldBeTrue();
|
||||
account2.ShouldBe("ACCT_B");
|
||||
subject2.ShouldBe("foo.>");
|
||||
queue2.ShouldBeNull();
|
||||
|
||||
RouteConnection.TryParseRemoteUnsub("RS+ ACCT_A foo.bar", out _, out _, out _).ShouldBeFalse();
|
||||
}
|
||||
|
||||
private static RouteManager CreateManager(ClusterOptions? options = null)
|
||||
=> new(
|
||||
options ?? new ClusterOptions { Host = "127.0.0.1", Port = 0 },
|
||||
new ServerStats(),
|
||||
"S1",
|
||||
_ => { },
|
||||
_ => { },
|
||||
NullLogger<RouteManager>.Instance);
|
||||
|
||||
private static RouteConnection MakeRouteConnection()
|
||||
{
|
||||
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();
|
||||
server.Dispose();
|
||||
listener.Stop();
|
||||
|
||||
return new RouteConnection(client);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user