tmux-party/tests/85-clean.bats
veg 8d10e62779 feat: party clean rescues an orphaned transcript before deleting
A server crash mid-logged-party is the one case close's rescue can
never have run, and host's EEXIST message funnels the host straight
into clean. Deleting the night's log there is exactly the accident
class the close-time rescue exists for, so clean applies the same
rescue: no quiescence poll needed, the liveness gate just proved the
writers are gone.
2026-07-11 13:13:05 +00:00

93 lines
2.5 KiB
Bash

#!/usr/bin/env bats
#
# party clean: remove the caller's own dead party dirs. Mistake-proofing
# gates mirror cmd_close: own-basename glob, no symlinks, [ -O ], and a
# dead socket. Liveness is faked through PARTY_TMUX stubs so no real
# server or group membership is needed.
load 'helpers'
setup() {
setup_party_sandbox
load_party_lib
}
teardown() { teardown_party_sandbox; }
@test "clean removes a dead leftover dir" {
ensure_party_dir "$USER" ghost
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[[ "$output" == *"removed"*"ghost"* ]]
[ ! -d "$PARTY_SOCKET_DIR/party-$USER:ghost.d" ]
}
@test "clean rescues a non-empty transcript before removing the dir" {
export HOME="$PARTY_TMP/home"
mkdir -p "$HOME"
ensure_party_dir "$USER" crashed
printf 'the night\n' > "$PARTY_SOCKET_DIR/party-$USER:crashed.d/log"
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[[ "$output" == *"transcript saved to"* ]]
[ ! -d "$PARTY_SOCKET_DIR/party-$USER:crashed.d" ]
grep -q "the night" "$HOME"/party-crashed-*.log
}
@test "clean removes a crash-before-bind dir (no sock at all)" {
mkdir "$PARTY_SOCKET_DIR/party-$USER:stillborn.d"
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[ ! -d "$PARTY_SOCKET_DIR/party-$USER:stillborn.d" ]
}
@test "clean skips a live party and says to use close" {
cat > "$PARTY_TMP/tmux-ok" <<'EOF'
#!/bin/sh
exit 0
EOF
chmod +x "$PARTY_TMP/tmux-ok"
export PARTY_TMUX="$PARTY_TMP/tmux-ok"
ensure_party_dir "$USER" running
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[[ "$output" == *"skipping"*"running"* ]]
[[ "$output" == *"party close"* ]]
[ -d "$PARTY_SOCKET_DIR/party-$USER:running.d" ]
}
@test "clean never follows a planted symlink" {
mkdir "$PARTY_TMP/target"
: > "$PARTY_TMP/target/precious"
ln -s "$PARTY_TMP/target" "$PARTY_SOCKET_DIR/party-$USER:lnk.d"
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[ -e "$PARTY_TMP/target/precious" ]
[ -L "$PARTY_SOCKET_DIR/party-$USER:lnk.d" ]
}
@test "clean ignores other users' dirs" {
ensure_party_dir nobody theirparty
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[ -d "$PARTY_SOCKET_DIR/party-nobody:theirparty.d" ]
}
@test "clean with nothing to do says so" {
run "$PARTY_BIN" clean
[ "$status" -eq 0 ]
[[ "$output" == *"nothing to clean"* ]]
}
@test "clean rejects arguments" {
run "$PARTY_BIN" clean extra
[ "$status" -eq 2 ]
}
@test "host's EEXIST message recommends party clean" {
ensure_party_dir "$USER" blocked
export TMUX_PARTY_GROUP="$(id -gn)"
run "$PARTY_BIN" host blocked
[ "$status" -eq 1 ]
[[ "$output" == *"party clean"* ]]
}