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.
93 lines
2.5 KiB
Bash
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"* ]]
|
|
}
|