#!/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/.json + goals/.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" echo "---" echo "Results: $PASS passed, $FAIL failed" [[ $FAIL -eq 0 ]] || exit 1