The destination name has one-second granularity and mv overwrites. Closing, re-hosting and closing the same party name within a second would lose the first transcript while reporting success. Fall back to a PID-suffixed name when the destination already exists.
109 lines
3.2 KiB
Bash
109 lines
3.2 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 "a rescue never replaces an earlier transcript of the same second" {
|
|
export HOME="$PARTY_TMP/home"
|
|
mkdir -p "$HOME" "$PARTY_TMP/bin"
|
|
# Freeze the clock so both rescues compute the same destination.
|
|
printf '#!/bin/sh\necho 20260101-000000\n' > "$PARTY_TMP/bin/date"
|
|
chmod +x "$PARTY_TMP/bin/date"
|
|
printf 'earlier\n' > "$HOME/party-crashed-20260101-000000.log"
|
|
ensure_party_dir "$USER" crashed
|
|
printf 'later\n' > "$PARTY_SOCKET_DIR/party-$USER:crashed.d/log"
|
|
|
|
PATH="$PARTY_TMP/bin:$PATH" run "$PARTY_BIN" clean
|
|
[ "$status" -eq 0 ]
|
|
grep -q earlier "$HOME/party-crashed-20260101-000000.log"
|
|
grep -lq later "$HOME"/party-crashed-20260101-000000-*.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"* ]]
|
|
}
|