One liveness primitive instead of two. The PID argument was a vestige (format-checked, never probed, since the kill -0 removal); dropping it means a roster with a garbage SERVER_PID can no longer mask a live socket in host/moderation/role resolution.
108 lines
3.5 KiB
Bash
108 lines
3.5 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
load 'helpers'
|
|
|
|
setup() {
|
|
setup_party_sandbox
|
|
load_party_lib
|
|
}
|
|
|
|
@test "roster_record_path composes deterministically" {
|
|
out=$(roster_record_path "veg" "debug-the-deploy")
|
|
[ "$out" = "$PARTY_SOCKET_DIR/party-veg:debug-the-deploy.d/roster" ]
|
|
}
|
|
|
|
@test "party_dir_path composes deterministically" {
|
|
out=$(party_dir_path "veg" "debug-the-deploy")
|
|
[ "$out" = "$PARTY_SOCKET_DIR/party-veg:debug-the-deploy.d" ]
|
|
}
|
|
|
|
@test "socket_path lives inside the per-party private dir" {
|
|
out=$(socket_path "veg" "debug-the-deploy")
|
|
[ "$out" = "$PARTY_SOCKET_DIR/party-veg:debug-the-deploy.d/sock" ]
|
|
}
|
|
|
|
@test "roster_write then roster_read round-trips all fields" {
|
|
ensure_party_dir "$USER" "rt-test"
|
|
rec=$(roster_record_path "$USER" "rt-test")
|
|
# roster_read derives RR_HOST_USER, RR_PARTY_NAME, and RR_SOCKET from
|
|
# the dir basename and filesystem; SERVER_PID, GROUP, and CREATED come
|
|
# from the file. The values written here for HOST_USER/PARTY_NAME/
|
|
# SOCKET are advisory and overlap with what roster_read derives.
|
|
derived_sock="$PARTY_SOCKET_DIR/party-$USER:rt-test.d/sock"
|
|
roster_write "$rec" \
|
|
HOST_USER "$USER" \
|
|
PARTY_NAME "rt-test" \
|
|
SOCKET "$derived_sock" \
|
|
SERVER_PID 12345 \
|
|
CREATED "2026-04-26T18:42:00Z"
|
|
[ -f "$rec" ]
|
|
roster_read "$rec"
|
|
[ "$RR_HOST_USER" = "$USER" ]
|
|
[ "$RR_PARTY_NAME" = "rt-test" ]
|
|
[ "$RR_SOCKET" = "$derived_sock" ]
|
|
[ "$RR_SERVER_PID" = "12345" ]
|
|
[ "$RR_CREATED" = "2026-04-26T18:42:00Z" ]
|
|
}
|
|
|
|
@test "roster_write is atomic: no partial files on failure" {
|
|
ensure_party_dir "$USER" "atomic"
|
|
rec=$(roster_record_path "$USER" "atomic")
|
|
roster_write "$rec" HOST_USER "$USER" PARTY_NAME "atomic" \
|
|
SOCKET "/tmp/sock" SERVER_PID 1 CREATED 0
|
|
# The write goes via a temp file; no .tmp leftover should remain in
|
|
# the per-party dir.
|
|
! ls "${rec%/*}"/*.tmp 2>/dev/null
|
|
}
|
|
|
|
@test "roster_read fails on missing file" {
|
|
run roster_read "$PARTY_SOCKET_DIR/party-nobody:nope.d/roster"
|
|
[ "$status" -ne 0 ]
|
|
}
|
|
|
|
# Helper: write a $PARTY_TMUX stub that exits with the given code on
|
|
# every invocation. Used to test party_conn_state's probe in isolation.
|
|
_stub_tmux() {
|
|
cat > "$PARTY_TMP/tmux-stub" <<EOF
|
|
#!/bin/sh
|
|
exit $1
|
|
EOF
|
|
chmod +x "$PARTY_TMP/tmux-stub"
|
|
PARTY_TMUX="$PARTY_TMP/tmux-stub"
|
|
}
|
|
|
|
@test "party_conn_state: silent rc-0 probe answers ok" {
|
|
_stub_tmux 0
|
|
[ "$(party_conn_state /dev/null)" = ok ]
|
|
}
|
|
|
|
@test "party_conn_state: failing probe answers dead" {
|
|
# PID-reuse / planted nc -lU socket scenario: nothing at the socket
|
|
# speaks the tmux protocol, so the probe fails and the party is dead,
|
|
# regardless of any PID recorded in the roster.
|
|
_stub_tmux 1
|
|
[ "$(party_conn_state /dev/null)" = dead ]
|
|
}
|
|
|
|
@test "party_conn_state: rc 0 with stderr output answers unauthorized" {
|
|
cat > "$PARTY_TMP/tmux-stub" <<'EOF'
|
|
#!/bin/sh
|
|
echo "access not allowed" >&2
|
|
exit 0
|
|
EOF
|
|
chmod +x "$PARTY_TMP/tmux-stub"
|
|
PARTY_TMUX="$PARTY_TMP/tmux-stub"
|
|
[ "$(party_conn_state /dev/null)" = unauthorized ]
|
|
}
|
|
|
|
@test "roster_list returns full record paths under PARTY_SOCKET_DIR" {
|
|
for n in alpha beta gamma; do
|
|
ensure_party_dir "$USER" "$n"
|
|
rec=$(roster_record_path "$USER" "$n")
|
|
roster_write "$rec" HOST_USER "$USER" PARTY_NAME "$n" \
|
|
SOCKET "/tmp/s" SERVER_PID 1 CREATED 0
|
|
done
|
|
out=$(roster_list | sort | tr '\n' ' ')
|
|
expected="$PARTY_SOCKET_DIR/party-$USER:alpha.d/roster $PARTY_SOCKET_DIR/party-$USER:beta.d/roster $PARTY_SOCKET_DIR/party-$USER:gamma.d/roster "
|
|
[ "$out" = "$expected" ]
|
|
}
|