add internal/infra/mqtt_test.go
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
package infra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMQTTConnectPacket(t *testing.T) {
|
||||||
|
p := mqttConnect("radio-go", "user1", "pass1")
|
||||||
|
// fixed header: 0x10, remaining length
|
||||||
|
if p[0] != 0x10 {
|
||||||
|
t.Fatalf("packet type = 0x%02x, want 0x10", p[0])
|
||||||
|
}
|
||||||
|
rl := int(p[1])
|
||||||
|
if rl != len(p)-2 {
|
||||||
|
t.Fatalf("remaining length %d != %d", rl, len(p)-2)
|
||||||
|
}
|
||||||
|
body := string(p[2:])
|
||||||
|
for _, want := range []string{"MQTT", "user1", "pass1", "radio-go"} {
|
||||||
|
if !bytes.Contains(p, []byte(want)) {
|
||||||
|
t.Fatalf("connect packet missing %q: %q", want, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// protocol level 4 (3.1.1): fixed hdr 2B + name len 2B + "MQTT" 4B => index 8
|
||||||
|
if p[8] != 4 {
|
||||||
|
t.Fatalf("protocol level = %d, want 4", p[8])
|
||||||
|
}
|
||||||
|
// connect flags: clean-session(0x02) | username(0x80) | password(0x40)
|
||||||
|
if p[9] != 0xC2 {
|
||||||
|
t.Fatalf("connect flags = 0x%02x, want 0xC2", p[9])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMQTTConnectNoAuth(t *testing.T) {
|
||||||
|
p := mqttConnect("c1", "", "")
|
||||||
|
if p[9]&0xC0 != 0 {
|
||||||
|
t.Fatalf("flags should have no user/pass bits: 0x%02x", p[9])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMQTTPublishPacket(t *testing.T) {
|
||||||
|
topic := "airstudio/nowplaying"
|
||||||
|
payload := `{"title":"Neon Rain"}`
|
||||||
|
p := mqttPublish(topic, []byte(payload))
|
||||||
|
// QoS 0 PUBLISH => 0x30
|
||||||
|
if p[0] != 0x30 {
|
||||||
|
t.Fatalf("packet type = 0x%02x, want 0x30", p[0])
|
||||||
|
}
|
||||||
|
rl := int(p[1])
|
||||||
|
if rl != len(p)-2 {
|
||||||
|
t.Fatalf("remaining length %d != %d", rl, len(p)-2)
|
||||||
|
}
|
||||||
|
// topic is first: 2-byte length + bytes
|
||||||
|
tl := int(p[2])<<8 | int(p[3])
|
||||||
|
if got := string(p[4 : 4+tl]); got != topic {
|
||||||
|
t.Fatalf("topic = %q, want %q", got, topic)
|
||||||
|
}
|
||||||
|
if got := string(p[4+tl:]); got != payload {
|
||||||
|
t.Fatalf("payload = %q, want %q", got, payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMQTTRemainingLengthMultiByte(t *testing.T) {
|
||||||
|
big := bytes.Repeat([]byte("x"), 200)
|
||||||
|
p := mqttPublish("t", big)
|
||||||
|
// 200 + topic overhead > 127 => two-byte remaining length
|
||||||
|
if p[1]&0x80 == 0 {
|
||||||
|
t.Fatalf("expected continuation bit set for >127 remaining, got 0x%02x", p[1])
|
||||||
|
}
|
||||||
|
// MQTT remaining length is base-128 (not bit-shifted): low7 + next*128
|
||||||
|
rl := int(p[1]&0x7F) + int(p[2])*128
|
||||||
|
want := 2 + len("t") + len(big) // topic len + topic + payload (QoS0, no packet id)
|
||||||
|
if rl != want {
|
||||||
|
t.Fatalf("remaining length %d, want %d", rl, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user