- 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
2.2 KiB
2.2 KiB
NATS.E2E.Tests — Design
Date: 2026-03-12 Status: Approved
Overview
A true black-box E2E test project that launches NATS.Server.Host as a child process and connects using only NATS.Client.Core from NuGet. No project references to any server code.
Components
1. NatsServerProcess — Server Lifecycle Helper
- Builds the host binary once (or locates pre-built output)
- Launches
dotnet exec <path>/NATS.Server.Host.dll -p <port>as a child process - Allocates a free port per instance
- Waits for the server to be ready by polling TCP connect (with timeout)
- On dispose: sends SIGINT / kills process, waits for exit
- Captures stdout/stderr for diagnostics on failure
2. NatsServerFixture — xUnit Collection Fixture
- Implements
IAsyncLifetime - Creates one
NatsServerProcessper test class (or shared via collection) - Exposes
Portand aCreateClient()helper that returns a connectedNatsConnection
3. Initial Tests
ConnectAndPingTest— Client connects, PING/PONG succeedsPubSubTest— Two clients, publish on a subject, subscriber receives the messageRequestReplyTest— One client subscribes and replies, another sends a request and gets the response
Project Structure
tests/NATS.E2E.Tests/
NATS.E2E.Tests.csproj # xUnit + NATS.Client.Core only, no server refs
Infrastructure/
NatsServerProcess.cs # Process lifecycle management
NatsServerFixture.cs # xUnit fixture
BasicTests.cs # Connect, PubSub, Request/Reply
Key Decisions
- Binary discovery: The fixture runs
dotnet buildon the host project and locates the output DLL via the known relative path from the solution root. - Ready detection: TCP connect poll to the allocated port with 10s timeout, 100ms interval.
- Process cleanup:
Process.Kill()with a graceful SIGINT attempt first. - No shared state: Each test class gets its own server process and port — full isolation.
- Timeout: All async test operations use 10s CancellationTokenSource to avoid hangs.
Out of Scope (YAGNI)
- No TLS/auth E2E tests in the initial project
- No cluster/route/gateway/leaf-node multi-server tests
- No JetStream E2E
- No custom config file testing