test(fleet): hermetic heartbeat tests — temp run-dir + no leaked sidecars
Tests 3, 4, 5 previously returned synthetic pane PIDs (99999/99998/99997) from their fake list-panes shims but did not set MOSAIC_HEARTBEAT_RUN_DIR, causing the launcher to fall back to the real ~/.config/mosaic/fleet/run and potentially spawn a background sidecar against an arbitrary host PID. Fix: - list-panes in tests 3/4/5 now returns empty string → PANE_PID stays unset → no sidecar is spawned for tests where heartbeat is not under test. - MOSAIC_HEARTBEAT_RUN_DIR is exported to a per-test mktemp dir in each fake-tmux test (3, 4, 5) as defence-in-depth so even if the sidecar code path changes, it can never write to the real fleet run dir. - New temp dirs are registered in CLEANUP_DIRS so they are removed by the existing EXIT trap. - Tests 6 and 7 (the dedicated heartbeat tests) are unchanged: test 6 uses a real tmux pane PID + its own HB_RUN_DIR, test 7 intercepts via a fake setsid shim that captures args and exits immediately. - All 7 tests pass; verify-sanitized.sh passes; no stray sidecar processes or unexpected .hb files are written to ~/.config/mosaic/fleet/run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMoEx7hfdFGjUiCHuN1RRi
This commit is contained in:
@@ -50,8 +50,10 @@ grep -qF 'already running' /tmp/mosaic-start-agent-idempotent.out || fail "dupli
|
|||||||
# - Intercepts 'new-session' calls and records its arguments to a file.
|
# - Intercepts 'new-session' calls and records its arguments to a file.
|
||||||
# - For 'has-session' calls, exits 1 (session does not exist) so the script
|
# - For 'has-session' calls, exits 1 (session does not exist) so the script
|
||||||
# proceeds to launch instead of printing "already running".
|
# proceeds to launch instead of printing "already running".
|
||||||
# - For 'list-panes' calls, returns a synthetic PID so the heartbeat sidecar
|
# - For 'list-panes' calls, returns empty so PANE_PID stays unset and the
|
||||||
# path is exercised without needing a real tmux session.
|
# heartbeat sidecar is NOT spawned (heartbeat is not the focus of this test;
|
||||||
|
# test 6 and 7 cover that path). This prevents any real-filesystem side
|
||||||
|
# effects or leaked background processes.
|
||||||
# - For all other subcommands, exits 0.
|
# - For all other subcommands, exits 0.
|
||||||
#
|
#
|
||||||
# Assertions:
|
# Assertions:
|
||||||
@@ -62,7 +64,8 @@ grep -qF 'already running' /tmp/mosaic-start-agent-idempotent.out || fail "dupli
|
|||||||
FAKE_BIN=$(mktemp -d)
|
FAKE_BIN=$(mktemp -d)
|
||||||
FAKE_RUNTIME_BIN=$(mktemp -d)
|
FAKE_RUNTIME_BIN=$(mktemp -d)
|
||||||
TMUX_ARGS_FILE=$(mktemp)
|
TMUX_ARGS_FILE=$(mktemp)
|
||||||
CLEANUP_DIRS+=("$FAKE_BIN" "$FAKE_RUNTIME_BIN")
|
HB_RUN_DIR3=$(mktemp -d)
|
||||||
|
CLEANUP_DIRS+=("$FAKE_BIN" "$FAKE_RUNTIME_BIN" "$HB_RUN_DIR3")
|
||||||
|
|
||||||
# Write the fake tmux shim (uses only positional args, no sourced vars).
|
# Write the fake tmux shim (uses only positional args, no sourced vars).
|
||||||
cat > "$FAKE_BIN/tmux" <<SHIM
|
cat > "$FAKE_BIN/tmux" <<SHIM
|
||||||
@@ -77,7 +80,8 @@ if [ "\$subcmd" = "new-session" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [ "\$subcmd" = "list-panes" ]; then
|
if [ "\$subcmd" = "list-panes" ]; then
|
||||||
echo "99999" # synthetic pane PID for heartbeat path
|
# Return empty: no sidecar spawned (heartbeat is not the focus of this test).
|
||||||
|
echo ""
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
@@ -95,6 +99,7 @@ MOSAIC_AGENT_WORKDIR="$WORKDIR3" \
|
|||||||
MOSAIC_AGENT_RUNTIME="pi" \
|
MOSAIC_AGENT_RUNTIME="pi" \
|
||||||
MOSAIC_RUNTIME_BIN="$FAKE_RUNTIME_BIN" \
|
MOSAIC_RUNTIME_BIN="$FAKE_RUNTIME_BIN" \
|
||||||
MOSAIC_AGENT_COMMAND="mosaic yolo pi --model openai-codex/gpt-5.5:high" \
|
MOSAIC_AGENT_COMMAND="mosaic yolo pi --model openai-codex/gpt-5.5:high" \
|
||||||
|
MOSAIC_HEARTBEAT_RUN_DIR="$HB_RUN_DIR3" \
|
||||||
"$START" "$AGENT3"
|
"$START" "$AGENT3"
|
||||||
|
|
||||||
all_args=$(cat "$TMUX_ARGS_FILE" 2>/dev/null || true)
|
all_args=$(cat "$TMUX_ARGS_FILE" 2>/dev/null || true)
|
||||||
@@ -118,7 +123,8 @@ echo "$all_args" | grep -qF "mosaic yolo pi --model openai-codex/gpt-5.5:high" |
|
|||||||
# ── Test 4: when no extra runtime-bin dirs exist, exec still appears ───────────
|
# ── Test 4: when no extra runtime-bin dirs exist, exec still appears ───────────
|
||||||
TMUX_ARGS_FILE2=$(mktemp)
|
TMUX_ARGS_FILE2=$(mktemp)
|
||||||
FAKE_BIN2=$(mktemp -d)
|
FAKE_BIN2=$(mktemp -d)
|
||||||
CLEANUP_DIRS+=("$FAKE_BIN2")
|
HB_RUN_DIR4=$(mktemp -d)
|
||||||
|
CLEANUP_DIRS+=("$FAKE_BIN2" "$HB_RUN_DIR4")
|
||||||
|
|
||||||
cat > "$FAKE_BIN2/tmux" <<SHIM2
|
cat > "$FAKE_BIN2/tmux" <<SHIM2
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
@@ -129,7 +135,8 @@ if [ "\$subcmd" = "new-session" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [ "\$subcmd" = "list-panes" ]; then
|
if [ "\$subcmd" = "list-panes" ]; then
|
||||||
echo "99998"
|
# Return empty: no sidecar spawned (heartbeat is not the focus of this test).
|
||||||
|
echo ""
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
@@ -149,6 +156,7 @@ MOSAIC_AGENT_WORKDIR="$WORKDIR4" \
|
|||||||
MOSAIC_AGENT_RUNTIME="pi" \
|
MOSAIC_AGENT_RUNTIME="pi" \
|
||||||
MOSAIC_RUNTIME_BIN="/nonexistent-dir-$$" \
|
MOSAIC_RUNTIME_BIN="/nonexistent-dir-$$" \
|
||||||
MOSAIC_AGENT_COMMAND="mosaic yolo pi" \
|
MOSAIC_AGENT_COMMAND="mosaic yolo pi" \
|
||||||
|
MOSAIC_HEARTBEAT_RUN_DIR="$HB_RUN_DIR4" \
|
||||||
"$START" "$AGENT4"
|
"$START" "$AGENT4"
|
||||||
|
|
||||||
all_args4=$(cat "$TMUX_ARGS_FILE2" 2>/dev/null || true)
|
all_args4=$(cat "$TMUX_ARGS_FILE2" 2>/dev/null || true)
|
||||||
@@ -171,7 +179,8 @@ echo "$all_args4" | grep -qF "mosaic yolo pi" || fail "pane command does not inc
|
|||||||
TMUX_ARGS_FILE5=$(mktemp)
|
TMUX_ARGS_FILE5=$(mktemp)
|
||||||
FAKE_BIN5=$(mktemp -d)
|
FAKE_BIN5=$(mktemp -d)
|
||||||
FAKE_RUNTIME_BIN5=$(mktemp -d) # this dir IS on the launcher's PATH below
|
FAKE_RUNTIME_BIN5=$(mktemp -d) # this dir IS on the launcher's PATH below
|
||||||
CLEANUP_DIRS+=("$FAKE_BIN5" "$FAKE_RUNTIME_BIN5")
|
HB_RUN_DIR5=$(mktemp -d)
|
||||||
|
CLEANUP_DIRS+=("$FAKE_BIN5" "$FAKE_RUNTIME_BIN5" "$HB_RUN_DIR5")
|
||||||
|
|
||||||
cat > "$FAKE_BIN5/tmux" <<SHIM5
|
cat > "$FAKE_BIN5/tmux" <<SHIM5
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
@@ -182,7 +191,8 @@ if [ "\$subcmd" = "new-session" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [ "\$subcmd" = "list-panes" ]; then
|
if [ "\$subcmd" = "list-panes" ]; then
|
||||||
echo "99997"
|
# Return empty: no sidecar spawned (heartbeat is not the focus of this test).
|
||||||
|
echo ""
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
@@ -204,6 +214,7 @@ MOSAIC_AGENT_WORKDIR="$WORKDIR5" \
|
|||||||
MOSAIC_AGENT_RUNTIME="pi" \
|
MOSAIC_AGENT_RUNTIME="pi" \
|
||||||
MOSAIC_RUNTIME_BIN="$FAKE_RUNTIME_BIN5" \
|
MOSAIC_RUNTIME_BIN="$FAKE_RUNTIME_BIN5" \
|
||||||
MOSAIC_AGENT_COMMAND="mosaic yolo pi" \
|
MOSAIC_AGENT_COMMAND="mosaic yolo pi" \
|
||||||
|
MOSAIC_HEARTBEAT_RUN_DIR="$HB_RUN_DIR5" \
|
||||||
"$START" "$AGENT5"
|
"$START" "$AGENT5"
|
||||||
|
|
||||||
all_args5=$(cat "$TMUX_ARGS_FILE5" 2>/dev/null || true)
|
all_args5=$(cat "$TMUX_ARGS_FILE5" 2>/dev/null || true)
|
||||||
|
|||||||
Reference in New Issue
Block a user