85 lines
3.0 KiB
Bash
Executable File
85 lines
3.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# Unit tests for netinfra/mdns/hap-bridge.py [#619]
|
|
# Verifies record capture normalization + packet encode/decode round-trip.
|
|
set -euo pipefail
|
|
|
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
SCRIPT="$PROJECT_ROOT/netinfra/mdns/hap-bridge.py"
|
|
|
|
TMP="$(mktemp -d)"
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
|
|
cat > "$TMP/test_bridge.py" <<'PY'
|
|
import importlib.util
|
|
import struct
|
|
import sys
|
|
|
|
spec = importlib.util.spec_from_file_location("hap_bridge", sys.argv[1])
|
|
hb = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(hb)
|
|
|
|
failed = 0
|
|
|
|
def check(name, cond):
|
|
global failed
|
|
print(("PASS " if cond else "FAIL ") + name)
|
|
if not cond:
|
|
failed += 1
|
|
|
|
# --- encode_name / read_name round trip
|
|
enc = hb.encode_name("Main Floor._hap._tcp.local")
|
|
back, off = hb.read_name(enc, 0)
|
|
check("name round-trip", back == "Main Floor._hap._tcp.local" and off == len(enc))
|
|
|
|
# --- encode_record + build_packet round trip for PTR/SRV/TXT
|
|
recs = [
|
|
{"name": "_hap._tcp.local", "type": 12, "ttl": 10, "ptr_target": "Main Floor._hap._tcp.local"},
|
|
{"name": "Main Floor._hap._tcp.local", "type": 33, "ttl": 10,
|
|
"srv_prio": 0, "srv_weight": 0, "srv_port": 58528, "srv_target": "Main-Floor.local"},
|
|
{"name": "Main Floor._hap._tcp.local", "type": 16, "ttl": 10, "rdata_hex": "0268310568656c6c6f"},
|
|
{"name": "Main-Floor.local", "type": 1, "ttl": 10, "rdata_hex": "c0a801d4"},
|
|
]
|
|
packet = hb.build_packet(recs)
|
|
check("packet header ancount", struct.unpack(">H", packet[6:8])[0] == 4)
|
|
|
|
# parse the packet back
|
|
qd = struct.unpack(">H", packet[4:6])[0]
|
|
an = struct.unpack(">H", packet[6:8])[0]
|
|
off = 12
|
|
parsed = []
|
|
for _ in range(qd):
|
|
_, off = hb.read_name(packet, off)
|
|
off += 4
|
|
for _ in range(an):
|
|
name, name_end = hb.read_name(packet, off)
|
|
rtype, _rc, ttl, rlen = struct.unpack(">HHIH", packet[name_end:name_end + 10])
|
|
rdata_start = name_end + 10
|
|
rec = {"name": name, "type": rtype, "ttl": ttl}
|
|
if rtype == 12:
|
|
rec["ptr_target"] = hb.read_name(packet, rdata_start)[0]
|
|
elif rtype == 33:
|
|
pri, w, port = struct.unpack(">HHH", packet[rdata_start:rdata_start + 6])
|
|
rec["srv_target"] = hb.read_name(packet, rdata_start + 6)[0]
|
|
rec["srv_port"] = port
|
|
else:
|
|
rec["rdata_hex"] = packet[rdata_start:rdata_start + rlen].hex()
|
|
parsed.append(rec)
|
|
off = rdata_start + rlen
|
|
|
|
check("ptr round-trip", parsed[0]["ptr_target"] == "Main Floor._hap._tcp.local")
|
|
check("srv target round-trip", parsed[1]["srv_target"] == "Main-Floor.local")
|
|
check("srv port round-trip", parsed[1]["srv_port"] == 58528)
|
|
check("txt round-trip", parsed[2]["rdata_hex"] == "0268310568656c6c6f")
|
|
check("a round-trip", parsed[3]["rdata_hex"] == "c0a801d4")
|
|
check("consumed whole packet", off == len(packet))
|
|
|
|
sys.exit(1 if failed else 0)
|
|
PY
|
|
|
|
if timeout 60 docker run --rm -v "$SCRIPT:/b.py" -v "$TMP/test_bridge.py:/t.py" python:3.12-alpine python /t.py /b.py; then
|
|
echo "✅ hap-bridge packet round-trip tests passed"
|
|
else
|
|
echo "❌ hap-bridge tests failed"
|
|
exit 1
|
|
fi
|