feat: phase A foundation test parity — 64 new tests across 11 subsystems

Port Go NATS server test behaviors to .NET:
- Client pub/sub (5 tests): simple, no-echo, reply, queue distribution, empty body
- Client UNSUB (4 tests): unsub, auto-unsub max, unsub after auto, disconnect cleanup
- Client headers (3 tests): HPUB/HMSG, server info headers, no-responders 503
- Client lifecycle (3 tests): connect proto, max subscriptions, auth timeout
- Client slow consumer (1 test): pending limit detection and disconnect
- Parser edge cases (3 tests + 2 bug fixes): PUB arg variations, malformed protocol, max control line
- SubList concurrency (13 tests): race on remove/insert/match, large lists, invalid subjects, wildcards
- Server config (4 tests): ephemeral port, server name, name defaults, lame duck
- Route config (3 tests): cluster formation, cross-cluster messaging, reconnect
- Gateway basic (2 tests): cross-cluster forwarding, no echo to origin
- Leaf node basic (2 tests): hub-to-spoke and spoke-to-hub forwarding
- Account import/export (2 tests): stream export/import delivery, isolation

Also fixes NatsParser.ParseSub/ParseUnsub to throw ProtocolViolationException
for short command lines instead of ArgumentOutOfRangeException.

Full suite: 933 passed, 0 failed (up from 869).
This commit is contained in:
Joseph Doherty
2026-02-23 19:26:30 -05:00
parent 36847b732d
commit 7ffee8741f
13 changed files with 2355 additions and 0 deletions

View File

@@ -336,6 +336,8 @@ public sealed class NatsParser
private static ParsedCommand ParseSub(Span<byte> line)
{
// SUB subject [queue] sid -- skip "SUB "
if (line.Length < 5)
throw new ProtocolViolationException("Invalid SUB arguments");
Span<Range> ranges = stackalloc Range[4];
var argsSpan = line[4..];
int argCount = SplitArgs(argsSpan, ranges);
@@ -366,6 +368,8 @@ public sealed class NatsParser
private static ParsedCommand ParseUnsub(Span<byte> line)
{
// UNSUB sid [max_msgs] -- skip "UNSUB "
if (line.Length < 7)
throw new ProtocolViolationException("Invalid UNSUB arguments");
Span<Range> ranges = stackalloc Range[3];
var argsSpan = line[6..];
int argCount = SplitArgs(argsSpan, ranges);