Files
natsdotnet/tests/NATS.Server.Tests/Mqtt/MqttProtocolConstantsParityBatch1Tests.cs
Joseph Doherty c30e67a69d 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
2026-03-12 14:09:23 -04:00

75 lines
2.6 KiB
C#

using System.Text;
using NATS.Server.Mqtt;
namespace NATS.Server.Tests.Mqtt;
public class MqttProtocolConstantsParityBatch1Tests
{
[Fact]
public void Constants_match_mqtt_go_reference_values()
{
MqttProtocolConstants.SubscribeFlags.ShouldBe((byte)0x02);
MqttProtocolConstants.ConnAckAccepted.ShouldBe((byte)0x00);
MqttProtocolConstants.ConnAckUnacceptableProtocolVersion.ShouldBe((byte)0x01);
MqttProtocolConstants.ConnAckIdentifierRejected.ShouldBe((byte)0x02);
MqttProtocolConstants.ConnAckServerUnavailable.ShouldBe((byte)0x03);
MqttProtocolConstants.ConnAckBadUserNameOrPassword.ShouldBe((byte)0x04);
MqttProtocolConstants.ConnAckNotAuthorized.ShouldBe((byte)0x05);
MqttProtocolConstants.MaxPayloadSize.ShouldBe(268_435_455);
MqttProtocolConstants.DefaultAckWait.ShouldBe(TimeSpan.FromSeconds(30));
MqttProtocolConstants.MaxAckTotalLimit.ShouldBe(0xFFFF);
}
[Fact]
public void ParseSubscribe_accepts_required_subscribe_flags()
{
var payload = CreateSubscribePayload(packetId: 7, ("sport/tennis/#", 1));
var info = MqttBinaryDecoder.ParseSubscribe(payload, flags: MqttProtocolConstants.SubscribeFlags);
info.PacketId.ShouldBe((ushort)7);
info.Filters.Count.ShouldBe(1);
info.Filters[0].TopicFilter.ShouldBe("sport/tennis/#");
info.Filters[0].QoS.ShouldBe((byte)1);
}
[Fact]
public void ParseSubscribe_rejects_invalid_subscribe_flags()
{
var payload = CreateSubscribePayload(packetId: 5, ("topic/one", 0));
var ex = Should.Throw<FormatException>(() => MqttBinaryDecoder.ParseSubscribe(payload, flags: 0x00));
ex.Message.ShouldContain("invalid fixed-header flags");
}
private static byte[] CreateSubscribePayload(ushort packetId, params (string Topic, byte Qos)[] filters)
{
using var ms = new MemoryStream();
using var writer = new BinaryWriter(ms);
WriteUInt16BigEndian(writer, packetId);
foreach (var (topic, qos) in filters)
{
WriteString(writer, topic);
writer.Write(qos);
}
return ms.ToArray();
}
private static void WriteString(BinaryWriter writer, string value)
{
var bytes = Encoding.UTF8.GetBytes(value);
WriteUInt16BigEndian(writer, (ushort)bytes.Length);
writer.Write(bytes);
}
private static void WriteUInt16BigEndian(BinaryWriter writer, ushort value)
{
writer.Write((byte)(value >> 8));
writer.Write((byte)(value & 0xFF));
}
}