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:
Joseph Doherty
2026-03-12 14:09:23 -04:00
parent 79c1ee8776
commit c30e67a69d
226 changed files with 17801 additions and 709 deletions

View File

@@ -120,7 +120,7 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| `SequenceSet.Union` (method) | `golang/nats-server/server/avl/seqset.go:191` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:203` | |
| `Union` (function) | `golang/nats-server/server/avl/seqset.go:208` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:228` | `SequenceSet.CreateUnion` static method |
| `SequenceSet.EncodeLen` | `golang/nats-server/server/avl/seqset.go:238` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:252` | `EncodeLength()` in .NET |
| `SequenceSet.Encode` | `golang/nats-server/server/avl/seqset.go:242` | PARTIAL | `src/NATS.Server/Internal/Avl/SequenceSet.cs:255` | Go signature takes optional buf to reuse; .NET always allocates new. Behavior equivalent. |
| `SequenceSet.Encode` | `golang/nats-server/server/avl/seqset.go:242` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:266` | Added destination-buffer overload (`Encode(byte[] destination)`) enabling caller buffer reuse parity |
| `ErrBadEncoding` | `golang/nats-server/server/avl/seqset.go:276` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:288` | Thrown as `InvalidOperationException` |
| `ErrBadVersion` | `golang/nats-server/server/avl/seqset.go:277` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:295` | Thrown as `InvalidOperationException` |
| `ErrSetNotEmpty` | `golang/nats-server/server/avl/seqset.go:278` | PORTED | `src/NATS.Server/Internal/Avl/SequenceSet.cs:93` | Thrown as `InvalidOperationException` |
@@ -166,9 +166,9 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| `SubjectTree.match` (internal) | `golang/nats-server/server/stree/stree.go:318` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:383` | `MatchInternal` |
| `SubjectTree.iter` (internal) | `golang/nats-server/server/stree/stree.go:418` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:512` | `IterInternal` |
| `LazyIntersect[TL,TR]` | `golang/nats-server/server/stree/stree.go:463` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:584` | `SubjectTreeHelper.LazyIntersect` static |
| `IntersectGSL[T,SL]` | `golang/nats-server/server/stree/stree.go:488` | MISSING | — | No .NET equivalent. Intersects stree with gsl.GenericSublist. Used in JetStream consumer NumPending. |
| `_intersectGSL` (internal) | `golang/nats-server/server/stree/stree.go:496` | MISSING | — | Helper for IntersectGSL |
| `hasInterestForTokens` (internal) | `golang/nats-server/server/stree/stree.go:521` | MISSING | — | Token-boundary interest check for GSL intersection |
| `IntersectGSL[T,SL]` | `golang/nats-server/server/stree/stree.go:488` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:675` | Added GSL intersection traversal for subject tree entries |
| `_intersectGSL` (internal) | `golang/nats-server/server/stree/stree.go:496` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:686` | Added recursive intersection helper |
| `hasInterestForTokens` (internal) | `golang/nats-server/server/stree/stree.go:521` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:717` | Added token-boundary short-circuit using `HasInterestStartingIn` |
| `bytesToString` (internal) | `golang/nats-server/server/stree/stree.go:534` | NOT_APPLICABLE | — | Go `unsafe` zero-copy string conversion. In .NET, `System.Text.Encoding.UTF8.GetString` or `MemoryMarshal.Cast` used instead |
---
@@ -276,10 +276,10 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|-----------|:-------------|--------|:----------------|-------|
| `SubjectTree.Dump` | `golang/nats-server/server/stree/dump.go:23` | MISSING | — | Debug utility for printing tree structure to an `io.Writer`. No .NET equivalent. Low priority — debug/diagnostic only. |
| `SubjectTree.dump` (internal) | `golang/nats-server/server/stree/dump.go:29` | MISSING | — | Internal helper for Dump |
| `dumpPre` | `golang/nats-server/server/stree/dump.go:59` | MISSING | — | Indentation helper for Dump |
| `leaf.kind`, `node4.kind`, etc. | `golang/nats-server/server/stree/dump.go:51` | PARTIAL | `src/NATS.Server/Internal/SubjectTree/Nodes.cs` | `INode.Kind` property exists on each node type, but `Dump` method is not implemented |
| `SubjectTree.Dump` | `golang/nats-server/server/stree/dump.go:23` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:172` | Added debug dump writer with root traversal and trailing newline |
| `SubjectTree.dump` (internal) | `golang/nats-server/server/stree/dump.go:29` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:180` | Added recursive node/leaf dump helper |
| `dumpPre` | `golang/nats-server/server/stree/dump.go:59` | PORTED | `src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:205` | Added indentation helper matching Go depth formatting |
| `leaf.kind`, `node4.kind`, etc. | `golang/nats-server/server/stree/dump.go:51` | PORTED | `src/NATS.Server/Internal/SubjectTree/Nodes.cs:21` | `INode.Kind` values are now actively consumed by `SubjectTree.Dump` output |
---
@@ -291,7 +291,7 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| `ErrInvalidVersion` | `golang/nats-server/server/thw/thw.go:28` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:289` | Thrown as `InvalidOperationException` |
| `slot` (struct) | `golang/nats-server/server/thw/thw.go:39` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:406` | `Slot` internal class |
| `HashWheel` (struct) | `golang/nats-server/server/thw/thw.go:45` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:17` | `HashWheel` class |
| `HashWheelEntry` (struct) | `golang/nats-server/server/thw/thw.go:52` | MISSING | — | Go uses this struct for entry representation in some contexts; .NET uses `(ulong, long)` tuples inline instead |
| `HashWheelEntry` (struct) | `golang/nats-server/server/thw/thw.go:52` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:407` | Added `HashWheelEntry` record struct (`Sequence`, `Expires`) |
| `NewHashWheel` | `golang/nats-server/server/thw/thw.go:58` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:34` | Constructor in .NET |
| `HashWheel.getPosition` (internal) | `golang/nats-server/server/thw/thw.go:66` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:50` | `GetPosition` private static |
| `newSlot` (internal) | `golang/nats-server/server/thw/thw.go:71` | PORTED | `src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:406` | Inline slot initialization in .NET |
@@ -315,7 +315,7 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| `ErrNotFound` | `golang/nats-server/server/gsl/gsl.go:42` | PORTED | `src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:12` | `GslErrors.NotFound` |
| `ErrNilChan` | `golang/nats-server/server/gsl/gsl.go:43` | NOT_APPLICABLE | — | Go channel-specific error; channels don't apply to .NET pattern |
| `ErrAlreadyRegistered` | `golang/nats-server/server/gsl/gsl.go:44` | NOT_APPLICABLE | — | Used by notification channels in Go; no notification channel pattern in .NET port |
| `SimpleSublist` (type alias) | `golang/nats-server/server/gsl/gsl.go:49` | PARTIAL | `src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:650` | `SimpleSubjectList` uses `int` instead of `struct{}`. Functionally equivalent but not a true zero-allocation alias |
| `SimpleSublist` (type alias) | `golang/nats-server/server/gsl/gsl.go:49` | PORTED | `src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:656` | `SimpleSubjectList` now aliases `GenericSubjectList<SimpleSublistValue>` where marker value mirrors Go's empty struct payload |
| `NewSimpleSublist` | `golang/nats-server/server/gsl/gsl.go:52` | PORTED | `src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:650` | `new SimpleSubjectList()` |
| `GenericSublist[T]` (struct) | `golang/nats-server/server/gsl/gsl.go:57` | PORTED | `src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:76` | `GenericSubjectList<T>` |
| `node[T]` (struct) | `golang/nats-server/server/gsl/gsl.go:64` | PORTED | `src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:52` | `Node<T>` |
@@ -359,7 +359,7 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| `ProcUsage` (freebsd/netbsd/openbsd/dragonfly/solaris/zos) | `golang/nats-server/server/pse/pse_*.go` | NOT_APPLICABLE | — | Platform-specific Go build-tagged files. .NET runtime abstracts these OS differences. |
| `ProcUsage` (wasm/rumprun) | `golang/nats-server/server/pse/pse_wasm.go` | NOT_APPLICABLE | — | Stub/no-op implementations for unsupported platforms; not needed in .NET |
| `updateUsage` (darwin, internal) | `golang/nats-server/server/pse/pse_darwin.go:56` | PORTED | `src/NATS.Server/Monitoring/VarzHandler.cs:39` | CPU sampling logic in VarzHandler |
| `periodic` (darwin, internal) | `golang/nats-server/server/pse/pse_darwin.go:76` | PARTIAL | `src/NATS.Server/Monitoring/VarzHandler.cs:39` | Go runs periodic background timer; .NET samples on each `/varz` request with 1s cache. Semantics slightly different. |
| `periodic` (darwin, internal) | `golang/nats-server/server/pse/pse_darwin.go:76` | PORTED | `src/NATS.Server/Monitoring/VarzHandler.cs:30` | Added 1s background timer sampler (`SampleCpuUsage`) with synchronized cached CPU reads in `/varz`, matching periodic semantics instead of request-only sampling |
---
@@ -367,9 +367,9 @@ Add rows to the Gap Inventory table below. Group by Go source file. Include the
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|-----------|:-------------|--------|:----------------|-------|
| `Memory` (darwin) | `golang/nats-server/server/sysmem/mem_darwin.go:18` | MISSING | — | Queries total physical RAM via `hw.memsize` sysctl. No .NET equivalent in codebase. Used by JetStream for sizing decisions. |
| `Memory` (linux) | `golang/nats-server/server/sysmem/mem_linux.go:20` | MISSING | — | Queries via `syscall.Sysinfo`. No .NET equivalent found. |
| `Memory` (windows) | `golang/nats-server/server/sysmem/mem_windows.go` | MISSING | — | No .NET equivalent found. Can be implemented via `GC.GetGCMemoryInfo().TotalAvailableMemoryBytes`. |
| `Memory` (darwin) | `golang/nats-server/server/sysmem/mem_darwin.go:18` | PORTED | `src/NATS.Server/Internal/SysMem/SystemMemory.cs:12` | Added cross-platform `SystemMemory.Memory()` backed by runtime memory info |
| `Memory` (linux) | `golang/nats-server/server/sysmem/mem_linux.go:20` | PORTED | `src/NATS.Server/Internal/SysMem/SystemMemory.cs:12` | Added cross-platform `SystemMemory.Memory()` backed by runtime memory info |
| `Memory` (windows) | `golang/nats-server/server/sysmem/mem_windows.go` | PORTED | `src/NATS.Server/Internal/SysMem/SystemMemory.cs:12` | Added cross-platform `SystemMemory.Memory()` backed by runtime memory info |
| `Memory` (bsd/solaris/wasm/zos) | `golang/nats-server/server/sysmem/mem_bsd.go` etc. | NOT_APPLICABLE | — | Platform-specific stubs; .NET runtime abstracts these. `GCMemoryInfo` is the cross-platform equivalent. |
| `sysctlInt64` | `golang/nats-server/server/sysmem/sysctl.go:23` | NOT_APPLICABLE | — | Darwin/BSD internal helper using unsafe sysctl; .NET abstracts this entirely |
@@ -400,3 +400,4 @@ After porting work is completed:
|------|--------|----|
| 2026-02-25 | File created with LLM analysis instructions | auto |
| 2026-02-25 | Full gap inventory populated: 157 PORTED, 4 PARTIAL, 10 MISSING, 8 NOT_APPLICABLE, 0 DEFERRED | auto |
| 2026-02-25 | Completed periodic PSE parity by moving CPU sampling to a 1s background timer in `VarzHandler` and adding targeted parity test coverage | codex |