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:
87
tests/NATS.Server.Tests/Protocol/ProtoWireParityTests.cs
Normal file
87
tests/NATS.Server.Tests/Protocol/ProtoWireParityTests.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using NATS.Server.Protocol;
|
||||
|
||||
namespace NATS.Server.Tests.ProtocolParity;
|
||||
|
||||
public class ProtoWireParityTests
|
||||
{
|
||||
[Fact]
|
||||
public void ScanField_reads_tag_and_value_size_for_length_delimited_field()
|
||||
{
|
||||
// field=2, type=2, len=3, bytes=abc
|
||||
byte[] bytes = [0x12, 0x03, (byte)'a', (byte)'b', (byte)'c'];
|
||||
|
||||
var (number, wireType, size) = ProtoWire.ScanField(bytes);
|
||||
|
||||
number.ShouldBe(2);
|
||||
wireType.ShouldBe(2);
|
||||
size.ShouldBe(5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScanTag_rejects_invalid_field_numbers()
|
||||
{
|
||||
var zeroFieldEx = Should.Throw<ProtoWireException>(() => ProtoWire.ScanTag([0x00]));
|
||||
zeroFieldEx.Message.ShouldBe(ProtoWire.ErrProtoInvalidFieldNumber);
|
||||
|
||||
var tooLargeTag = ProtoWire.EncodeVarint(((ulong)int.MaxValue + 1UL) << 3);
|
||||
var tooLargeEx = Should.Throw<ProtoWireException>(() => ProtoWire.ScanTag(tooLargeTag));
|
||||
tooLargeEx.Message.ShouldBe(ProtoWire.ErrProtoInvalidFieldNumber);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScanFieldValue_supports_expected_wire_types()
|
||||
{
|
||||
ProtoWire.ScanFieldValue(5, [0, 0, 0, 0]).ShouldBe(4);
|
||||
ProtoWire.ScanFieldValue(1, [0, 0, 0, 0, 0, 0, 0, 0]).ShouldBe(8);
|
||||
ProtoWire.ScanFieldValue(0, [0x01]).ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScanFieldValue_rejects_unsupported_wire_type()
|
||||
{
|
||||
var ex = Should.Throw<ProtoWireException>(() => ProtoWire.ScanFieldValue(3, [0x00]));
|
||||
ex.Message.ShouldBe("unsupported type: 3");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScanVarint_reports_insufficient_and_overflow_errors()
|
||||
{
|
||||
var insufficient = Should.Throw<ProtoWireException>(() => ProtoWire.ScanVarint([0x80]));
|
||||
insufficient.Message.ShouldBe(ProtoWire.ErrProtoInsufficient);
|
||||
|
||||
byte[] overflow = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02];
|
||||
var tooLarge = Should.Throw<ProtoWireException>(() => ProtoWire.ScanVarint(overflow));
|
||||
tooLarge.Message.ShouldBe(ProtoWire.ErrProtoOverflow);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ScanBytes_reports_insufficient_when_length_prefix_exceeds_payload()
|
||||
{
|
||||
var ex = Should.Throw<ProtoWireException>(() => ProtoWire.ScanBytes([0x04, 0x01, 0x02]));
|
||||
ex.Message.ShouldBe(ProtoWire.ErrProtoInsufficient);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EncodeVarint_round_trips_values_via_scan_varint()
|
||||
{
|
||||
ulong[] values =
|
||||
[
|
||||
0UL,
|
||||
1UL,
|
||||
127UL,
|
||||
128UL,
|
||||
16_383UL,
|
||||
16_384UL,
|
||||
(1UL << 32) - 1,
|
||||
ulong.MaxValue,
|
||||
];
|
||||
|
||||
foreach (var value in values)
|
||||
{
|
||||
var encoded = ProtoWire.EncodeVarint(value);
|
||||
var (decoded, size) = ProtoWire.ScanVarint(encoded);
|
||||
decoded.ShouldBe(value);
|
||||
size.ShouldBe(encoded.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user