tmux-party/tests/60-list-join-leave.bats
veg 6be0ac1877 Initial pre-release
tmux-party: share a tmux session with people on the same UNIX host.
Single-file POSIX shell (party) with a filesystem + tmux server-access
trust model. See README.md.
2026-06-01 15:31:54 +00:00

135 lines
4.3 KiB
Bash

#!/usr/bin/env bats
load 'helpers'
setup() {
setup_party_sandbox
require_party_group
}
teardown() { teardown_party_sandbox; }
party_rec() { printf '%s/party-%s:%s.d/roster\n' "$PARTY_SOCKET_DIR" "$USER" "$1"; }
@test "party list shows live parties only" {
"$PARTY_BIN" host alpha
"$PARTY_BIN" host bravo
# Inject a fake stale record. The per-party dir must exist with the
# right group + mode so roster_list can find the record inside.
zdir="$PARTY_SOCKET_DIR/party-$USER:zombie.d"
mkdir -p "$zdir"
chgrp "$TMUX_PARTY_GROUP" "$zdir"
chmod 0750 "$zdir"
rec="$zdir/roster"
cat > "$rec" <<EOF
HOST_USER=$USER
PARTY_NAME=zombie
SOCKET=$zdir/sock
SERVER_PID=999999
CREATED=2026-04-26T18:42:00Z
EOF
chgrp "$TMUX_PARTY_GROUP" "$rec"
chmod 0640 "$rec"
run "$PARTY_BIN" list
[ "$status" -eq 0 ]
[[ "$output" == *"alpha"* ]]
[[ "$output" == *"bravo"* ]]
[[ "$output" != *"zombie"* ]]
}
@test "party list with no parties is friendly, not noisy" {
run "$PARTY_BIN" list
[ "$status" -eq 0 ]
[[ "$output" == *"no parties"* ]]
}
# Cross-user discovery regression. Earlier revisions of is_party_alive
# probed the PID with `kill -0`, which returns EPERM under POSIX semantics
# when the caller can't signal the target — illumos, all BSDs, and macOS
# honor that, so guests couldn't discover parties hosted by other users
# on the same box. To simulate the foreign-uid case without privilege,
# rewrite the roster's SERVER_PID to 1 (init/launchd, root-owned on every
# supported platform) and confirm `party list`/`join` still find it. With
# the bug present this test fails on every non-Linux target; on Linux and
# Linux-ABI zones it passes regardless because Linux's kill(2) returns 0
# for "exists, even if not signalable."
@test "party list discovers parties whose host PID we cannot signal" {
"$PARTY_BIN" host crossuser
rec=$(party_rec crossuser)
[ -f "$rec" ]
# Rewrite SERVER_PID=<our-pid> -> SERVER_PID=1 in place. Avoids `sed -i`
# portability snags between GNU and BSD sed.
awk -F= 'BEGIN{OFS="="} $1=="SERVER_PID"{$2="1"} {print}' "$rec" >"$rec.new"
cat "$rec.new" >"$rec"
rm -f "$rec.new"
run "$PARTY_BIN" list
[ "$status" -eq 0 ]
[[ "$output" == *"crossuser"* ]]
PARTY_DRY_RUN=1 run "$PARTY_BIN" join crossuser
[ "$status" -eq 0 ]
}
@test "party join <name> attaches via a guest session in group mode" {
"$PARTY_BIN" host joinable
rec=$(party_rec joinable)
sock=$(awk -F= '$1=="SOCKET"{print $2}' "$rec")
# Joining is interactive (it execs into tmux). We can't test the attach
# without a real terminal, so we exercise the underlying path: with
# PARTY_DRY_RUN=1 the join function builds the guest session and prints
# the command that WOULD be exec'd, then exits.
PARTY_DRY_RUN=1 "$PARTY_BIN" join joinable
tmux -S "$sock" has-session -t "__party_guest_$USER"
}
@test "party join with no name auto-attaches single live party" {
"$PARTY_BIN" host onlyone
PARTY_DRY_RUN=1 "$PARTY_BIN" join
rec=$(party_rec onlyone)
sock=$(awk -F= '$1=="SOCKET"{print $2}' "$rec")
tmux -S "$sock" has-session -t "__party_guest_$USER"
}
@test "party join with no name and no parties errors clearly" {
run "$PARTY_BIN" join
[ "$status" -ne 0 ]
[[ "$output" == *"no parties"* ]]
}
@test "party join --passive attaches read-only to host session, no guest session" {
"$PARTY_BIN" host mirror
rec=$(party_rec mirror)
sock=$(awk -F= '$1=="SOCKET"{print $2}' "$rec")
# --passive must use `attach -r` so a write-capable invitee who chooses
# passive can't type into the host's panes (the README's "watcher"
# boundary). PARTY_DRY_RUN=1 prints the attach command instead of execing.
run env PARTY_DRY_RUN=1 "$PARTY_BIN" join mirror --passive
[ "$status" -eq 0 ]
[[ "$output" == *"attach-session -r -t mirror"* ]]
! tmux -S "$sock" has-session -t "__party_guest_$USER" 2>/dev/null
}
@test "party leave kills the guest session and detaches the client" {
"$PARTY_BIN" host leaveme
rec=$(party_rec leaveme)
sock=$(awk -F= '$1=="SOCKET"{print $2}' "$rec")
PARTY_DRY_RUN=1 "$PARTY_BIN" join leaveme
tmux -S "$sock" has-session -t "__party_guest_$USER"
"$PARTY_BIN" leave
! tmux -S "$sock" has-session -t "__party_guest_$USER" 2>/dev/null
}
@test "party leave with no joined party errors helpfully" {
run "$PARTY_BIN" leave
[ "$status" -ne 0 ]
[[ "$output" == *"not joined"* ]]
}