aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/tests
diff options
context:
space:
mode:
Diffstat (limited to '.ai/scripts/tests')
-rw-r--r--.ai/scripts/tests/agent-roster.bats141
1 files changed, 141 insertions, 0 deletions
diff --git a/.ai/scripts/tests/agent-roster.bats b/.ai/scripts/tests/agent-roster.bats
new file mode 100644
index 0000000..939a7df
--- /dev/null
+++ b/.ai/scripts/tests/agent-roster.bats
@@ -0,0 +1,141 @@
+#!/usr/bin/env bats
+# Tests for agent-roster: report other live Claude agents in a project.
+#
+# pgrep and /proc are the system boundary, so the test injects both and runs
+# the real include/exclude logic against fixtures — no Claude processes are
+# spawned. Injection points:
+# ROSTER_PGREP command standing in for pgrep (a stub printing $FAKE_PIDS)
+# ROSTER_PROC proc dir (a fixture of <pid>/cwd symlinks + <pid>/status)
+# ROSTER_SELF_PID the scanner's own pid, so the ancestry walk is testable
+#
+# Fixture process tree: pid 1000 (the scanner) is a child of 999 (the current
+# session's claude), which is a child of init (1). So 999 must always be
+# excluded as scanner ancestry; other claude pids are judged by cwd.
+
+setup() {
+ SCRIPT_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
+ ROSTER="$SCRIPT_DIR/agent-roster"
+
+ PROC="$BATS_TEST_TMPDIR/proc"
+ ROOT="$BATS_TEST_TMPDIR/project"
+ mkdir -p "$PROC" "$ROOT/sub" "$BATS_TEST_TMPDIR/elsewhere"
+
+ PGREP_STUB="$BATS_TEST_TMPDIR/pgrep"
+ cat >"$PGREP_STUB" <<'EOF'
+#!/usr/bin/env bash
+printf '%s\n' $FAKE_PIDS
+EOF
+ chmod +x "$PGREP_STUB"
+
+ SELF=1000
+ # scanner (1000) <- session claude (999) <- init (1)
+ mkproc 1000 "$ROOT" 999
+ mkproc 999 "$ROOT" 1
+}
+
+# mkproc PID CWD PPID — register a fake process in the fixture proc dir.
+mkproc() {
+ mkdir -p "$PROC/$1"
+ ln -sf "$2" "$PROC/$1/cwd"
+ printf 'PPid:\t%s\n' "$3" >"$PROC/$1/status"
+}
+
+run_roster() {
+ ROSTER_PGREP="$PGREP_STUB" ROSTER_PROC="$PROC" ROSTER_SELF_PID="$SELF" \
+ FAKE_PIDS="$FAKE_PIDS" run "$ROSTER" "$ROOT"
+}
+
+@test "agent-roster: alone (only the session's own claude) exits 0, no output" {
+ FAKE_PIDS="999"
+ run_roster
+ [ "$status" -eq 0 ]
+ [ -z "$output" ]
+}
+
+@test "agent-roster: one other agent in-project is printed, exit 1" {
+ mkproc 2000 "$ROOT" 1
+ FAKE_PIDS="999 2000"
+ run_roster
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"2000"* ]]
+ [[ "$output" == *"$ROOT"* ]]
+}
+
+@test "agent-roster: two other agents both printed, exit 1" {
+ mkproc 2000 "$ROOT" 1
+ mkproc 2001 "$ROOT/sub" 1
+ FAKE_PIDS="999 2000 2001"
+ run_roster
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"2000"* ]]
+ [[ "$output" == *"2001"* ]]
+ [ "${#lines[@]}" -eq 2 ]
+}
+
+@test "agent-roster: the scanner's session-claude ancestor is excluded even with matching cwd" {
+ # 999 has cwd == ROOT but is scanner ancestry; must not appear.
+ FAKE_PIDS="999"
+ run_roster
+ [ "$status" -eq 0 ]
+ [[ "$output" != *"999"* ]]
+}
+
+@test "agent-roster: cwd outside the project root is excluded" {
+ mkproc 3000 "$BATS_TEST_TMPDIR/elsewhere" 1
+ FAKE_PIDS="999 3000"
+ run_roster
+ [ "$status" -eq 0 ]
+ [ -z "$output" ]
+}
+
+@test "agent-roster: cwd in a subdirectory of root is included" {
+ mkproc 2002 "$ROOT/sub" 1
+ FAKE_PIDS="999 2002"
+ run_roster
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"2002"* ]]
+}
+
+@test "agent-roster: a sibling path sharing a prefix is not a false match" {
+ # ROOT is .../project; .../project-other must not count as inside it.
+ mkdir -p "$BATS_TEST_TMPDIR/project-other"
+ mkproc 3100 "$BATS_TEST_TMPDIR/project-other" 1
+ FAKE_PIDS="999 3100"
+ run_roster
+ [ "$status" -eq 0 ]
+ [ -z "$output" ]
+}
+
+@test "agent-roster: a pid that vanished between pgrep and the proc read is skipped" {
+ # 4000 has no fixture dir, simulating a process gone by readlink time.
+ FAKE_PIDS="999 4000"
+ run_roster
+ [ "$status" -eq 0 ]
+ [ -z "$output" ]
+}
+
+@test "agent-roster: missing proc reports unavailable on stderr, exit 2, never silent-alone" {
+ ROSTER_PGREP="$PGREP_STUB" ROSTER_PROC="$BATS_TEST_TMPDIR/nonexistent" \
+ ROSTER_SELF_PID="$SELF" FAKE_PIDS="999 2000" run "$ROSTER" "$ROOT"
+ [ "$status" -eq 2 ]
+ [[ "$output" == *"roster unavailable"* ]]
+}
+
+@test "agent-roster: a missing pgrep reports unavailable, exit 2, never silent-alone" {
+ # If pgrep itself is absent, the scan can't run; reporting "alone" would be a
+ # false negative the "never silent-alone" invariant forbids.
+ mkproc 2000 "$ROOT" 1
+ ROSTER_PGREP="$BATS_TEST_TMPDIR/no-such-pgrep" ROSTER_PROC="$PROC" \
+ ROSTER_SELF_PID="$SELF" FAKE_PIDS="999 2000" run "$ROSTER" "$ROOT"
+ [ "$status" -eq 2 ]
+ [[ "$output" == *"roster unavailable"* ]]
+}
+
+@test "agent-roster: defaults project root to PWD when no argument is given" {
+ mkproc 2000 "$ROOT" 1
+ FAKE_PIDS="999 2000"
+ ROSTER_PGREP="$PGREP_STUB" ROSTER_PROC="$PROC" ROSTER_SELF_PID="$SELF" \
+ FAKE_PIDS="$FAKE_PIDS" run env -C "$ROOT" "$ROSTER"
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"2000"* ]]
+}