46954d8584
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
128 lines
5.0 KiB
Bash
128 lines
5.0 KiB
Bash
#!/usr/bin/env bash
|
|
# Tests para kill_fleet_agent. Usa fixtures en dirs temporales (FN_FLEET_*) y
|
|
# --dry-run para no matar procesos ni cerrar windows reales.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/kill_fleet_agent.sh"
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
assert_contains() {
|
|
local test_name="$1" needle="$2" haystack="$3"
|
|
if echo "$haystack" | grep -qF "$needle"; then
|
|
echo "PASS: $test_name"
|
|
PASS=$((PASS+1))
|
|
else
|
|
echo "FAIL: $test_name — expected to contain '$needle'"
|
|
echo " got: $haystack"
|
|
FAIL=$((FAIL+1))
|
|
fi
|
|
}
|
|
|
|
assert_rc() {
|
|
local test_name="$1" expected="$2" actual="$3"
|
|
if [[ "$actual" == "$expected" ]]; then
|
|
echo "PASS: $test_name (rc=$actual)"
|
|
PASS=$((PASS+1))
|
|
else
|
|
echo "FAIL: $test_name — expected rc=$expected, got rc=$actual"
|
|
FAIL=$((FAIL+1))
|
|
fi
|
|
}
|
|
|
|
# --- Fixtures: sessions/<pid>.json + goals/<sid>.json en dirs temporales ---
|
|
TMP="$(mktemp -d)"
|
|
SESS="$TMP/sessions"
|
|
GOALS="$TMP/goals"
|
|
mkdir -p "$SESS" "$GOALS"
|
|
|
|
# Ejecutor: PID 4242, sessionId executor-aaa-111, role=executor.
|
|
echo '{"sessionId":"executor-aaa-111","cwd":"/tmp/x"}' > "$SESS/4242.json"
|
|
echo '{"goal":"hacer X","role":"executor","dod_contract":"golden..."}' > "$GOALS/executor-aaa-111.json"
|
|
|
|
# Orquestador: PID 5555, sessionId orchestrator-bbb-222, role=orchestrator.
|
|
echo '{"sessionId":"orchestrator-bbb-222","cwd":"/tmp/y"}' > "$SESS/5555.json"
|
|
echo '{"goal":"orquestar","role":"orchestrator"}' > "$GOALS/orchestrator-bbb-222.json"
|
|
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
|
|
export FN_FLEET_SESSIONS_DIR="$SESS"
|
|
export FN_FLEET_GOALS_DIR="$GOALS"
|
|
# Forzar self_pid a un valor que NO colisione con los fixtures (salvo el test self).
|
|
export FN_FLEET_SELF_PID=999999
|
|
|
|
# --- Test 1 (golden): resolver ejecutor por sessionId, dry-run imprime plan ---
|
|
set +e
|
|
out=$(kill_fleet_agent executor-aaa-111 --socket nope --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "golden: ejecutor por sessionId sale 0" 0 "$rc"
|
|
assert_contains "golden: plan muestra el PID resuelto" "PID: 4242" "$out"
|
|
assert_contains "golden: plan muestra el sessionId" "executor-aaa-111" "$out"
|
|
assert_contains "golden: plan muestra role executor" "role: executor" "$out"
|
|
assert_contains "golden: dry-run no mata" "DRY-RUN" "$out"
|
|
|
|
# --- Test 2 (golden por PID + prefijo de sessionId) ---
|
|
set +e
|
|
out=$(kill_fleet_agent 4242 --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "golden: target por PID sale 0" 0 "$rc"
|
|
assert_contains "golden: PID resuelve su sessionId" "executor-aaa-111" "$out"
|
|
|
|
set +e
|
|
out=$(kill_fleet_agent executor-aaa --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "edge: prefijo de sessionId resuelve" 0 "$rc"
|
|
assert_contains "edge: prefijo resuelve al PID 4242" "PID: 4242" "$out"
|
|
|
|
# --- Test 3 (EDGE guard role): negar matar a un orchestrator ---
|
|
set +e
|
|
out=$(kill_fleet_agent orchestrator-bbb-222 --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "guard: matar orchestrator devuelve rc=3" 3 "$rc"
|
|
assert_contains "guard: mensaje menciona role=orchestrator" "role=orchestrator" "$out"
|
|
|
|
# --- Test 4 (EDGE guard self): negar matar a la sesion actual ---
|
|
set +e
|
|
out=$(FN_FLEET_SELF_PID=4242 kill_fleet_agent executor-aaa-111 --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "guard: matar self devuelve rc=3" 3 "$rc"
|
|
assert_contains "guard: mensaje self menciona no suicidarse" "No me suicido" "$out"
|
|
|
|
# --- Test 5 (ERROR): target no resuelto a un PID ---
|
|
set +e
|
|
out=$(kill_fleet_agent sesion-inexistente-zzz --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "error: target inexistente devuelve rc=2" 2 "$rc"
|
|
assert_contains "error: mensaje de no resuelto" "no se pudo resolver" "$out"
|
|
|
|
# --- Test 6 (ERROR): falta el target ---
|
|
set +e
|
|
out=$(kill_fleet_agent --dry-run 2>&1); rc=$?
|
|
set -e
|
|
assert_rc "error: sin target devuelve rc=2" 2 "$rc"
|
|
assert_contains "error: mensaje falta target" "falta el target" "$out"
|
|
|
|
# --- Test 7 (Guard 3 predicado): _fleet_window_hosts_tui ---
|
|
# La window 'console' SIEMPRE se considera que aloja la TUI (no se cierra entera).
|
|
assert_predicate() {
|
|
local test_name="$1" expected="$2"; shift 2
|
|
set +e
|
|
_fleet_window_hosts_tui "$@"; local rc=$?
|
|
set -e
|
|
assert_rc "$test_name" "$expected" "$rc"
|
|
}
|
|
# Nombre de window 'console' -> aloja TUI (rc 0), aunque ningun pane sea fleetview.
|
|
assert_predicate "guard3: window 'console' aloja la TUI" 0 "console" $'1234 claude\n5678 bash'
|
|
# Algun pane corre 'fleetview' -> aloja TUI (rc 0), aunque la window no sea console.
|
|
assert_predicate "guard3: pane fleetview aloja la TUI" 0 "claude" $'1111 bash\n2222 fleetview'
|
|
# Ni console ni fleetview -> NO aloja la TUI (rc 1): kill-window normal.
|
|
assert_predicate "guard3: window normal no aloja la TUI" 1 "claude" $'3333 claude\n4444 bash'
|
|
# Substring que contiene 'fleetview' pero no es el comando exacto -> NO matchea (grep -qx).
|
|
assert_predicate "guard3: comando 'fleetviewer' no falsea positivo" 1 "work" $'7777 fleetviewer'
|
|
|
|
echo "---"
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
[[ $FAIL -eq 0 ]] || exit 1
|