feat(e2e): Meshtasticator radio-level validation harness for the adapter #2

Closed
eric wants to merge 9 commits from feat/meshtasticator-e2e into main
2 changed files with 33 additions and 2 deletions
Showing only changes of commit 6125130e6a - Show all commits
+21 -1
View File
@@ -226,10 +226,11 @@ def test_adapter_receives_broadcast_from_peer(node0):
return any(getattr(e, "text", None) == sent for e in node0.received_events) return any(getattr(e, "text", None) == sent for e in node0.received_events)
# Radio delivery is not guaranteed per attempt; retry a few times. # Radio delivery is not guaranteed per attempt; retry a few times.
# (meshtastic client >=2.8: sendText lives on the Interface, not Node.)
for _ in range(3): for _ in range(3):
if _got(): if _got():
break break
peer.localNode.sendText( peer.sendText(
text=sent, destinationId="^all", channelIndex=E2E_CHANNEL_INDEX text=sent, destinationId="^all", channelIndex=E2E_CHANNEL_INDEX
) )
time.sleep(1) time.sleep(1)
@@ -271,6 +272,25 @@ def test_adapter_chunked_send_reaches_peer(node0, loop):
return any(str(r).rstrip().endswith("word59") for r in received) return any(str(r).rstrip().endswith("word59") for r in received)
_wait_for(_all_chunks_arrived, timeout_s=45, what="chunked outbound send at peer") _wait_for(_all_chunks_arrived, timeout_s=45, what="chunked outbound send at peer")
except Exception as exc:
# Fast-fail diagnostics: what arrived at the peer, and what the
# simulator itself logged (RF forwarding/routing noise).
tail = ""
try:
sim_log = os.path.join(os.getcwd(), "..", "..", "meshtasticator-sim.log")
if not os.path.exists(sim_log):
sim_log = os.path.join(os.getcwd(), "meshtasticator-sim.log")
if os.path.exists(sim_log):
tail = "\n".join(
open(sim_log, errors="replace").read().splitlines()[-40:]
)
except OSError:
pass
raise AssertionError(
f"{exc}\nreceived at peer so far: {received[-10:]!r}\n"
f"--- meshtasticator-sim.log tail ---\n{tail}"
) from exc
finally: finally:
pub.unsubscribe(_on_receive, "meshtastic.receive.text") pub.unsubscribe(_on_receive, "meshtastic.receive.text")
peer.close() peer.close()
+12 -1
View File
@@ -93,7 +93,7 @@ start_forwards() {
} }
SIM_LOG="$REPO_ROOT/meshtasticator-sim.log" SIM_LOG="$REPO_ROOT/meshtasticator-sim.log"
SIM_ARGS=("$NODES") SIM_ARGS=("$NODES" -v) # -v: meshtastic/debug logging for RF diagnostics
if [ "$MODE" = native ]; then if [ "$MODE" = native ]; then
[ -n "$PROGRAM" ] && [ -d "$PROGRAM" ] || { echo "--mode native needs --program <dir>" >&2; exit 2; } [ -n "$PROGRAM" ] && [ -d "$PROGRAM" ] || { echo "--mode native needs --program <dir>" >&2; exit 2; }
SIM_ARGS+=(-p "$PROGRAM") SIM_ARGS+=(-p "$PROGRAM")
@@ -222,3 +222,14 @@ echo "== running radio-level e2e tests =="
E2E_CHANNEL_INDEX="$CHANNEL_INDEX" \ E2E_CHANNEL_INDEX="$CHANNEL_INDEX" \
"$VENV/bin/python" -m pytest plugin/tests/e2e -q "$@" "$VENV/bin/python" -m pytest plugin/tests/e2e -q "$@"
) )
RC=$?
if [ $RC -ne 0 ] && [ "$MODE" = docker ]; then
# Capture per-node meshtasticd logs before cleanup removes the container.
echo "== dumping node logs (pytest rc=$RC) =="
docker exec Meshtastic sh -c 'for f in /home/out_*.log; do echo "----- $f -----"; tail -n 60 "$f" 2>/dev/null; done' \
>"$REPO_ROOT/meshtasticator-nodes.log" 2>&1 || true
echo " node logs: $REPO_ROOT/meshtasticator-nodes.log"
fi
exit $RC