using NATS.Server.Protocol; namespace NATS.Server.Core.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(() => ProtoWire.ScanTag([0x00])); zeroFieldEx.Message.ShouldBe(ProtoWire.ErrProtoInvalidFieldNumber); var tooLargeTag = ProtoWire.EncodeVarint(((ulong)int.MaxValue + 1UL) << 3); var tooLargeEx = Should.Throw(() => 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(() => ProtoWire.ScanFieldValue(3, [0x00])); ex.Message.ShouldBe("unsupported type: 3"); } [Fact] public void ScanVarint_reports_insufficient_and_overflow_errors() { var insufficient = Should.Throw(() => ProtoWire.ScanVarint([0x80])); insufficient.Message.ShouldBe(ProtoWire.ErrProtoInsufficient); byte[] overflow = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02]; var tooLarge = Should.Throw(() => ProtoWire.ScanVarint(overflow)); tooLarge.Message.ShouldBe(ProtoWire.ErrProtoOverflow); } [Fact] public void ScanBytes_reports_insufficient_when_length_prefix_exceeds_payload() { var ex = Should.Throw(() => 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); } } }