More tests for events.

This commit is contained in:
Nicholas Marriott
2026-07-10 10:56:13 +01:00
parent 4a5c3fb5d6
commit 458b607255
5 changed files with 281 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
#!/bin/sh
PATH=/bin:/usr/bin
TERM=screen
LC_ALL=C.UTF-8
LANG=C.UTF-8
export TERM LC_ALL LANG
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
TMPDIR=$(mktemp -d)
IN="$TMPDIR/in"
OUT="$TMPDIR/out"
PID=
cleanup()
{
[ -n "$PID" ] && kill "$PID" 2>/dev/null
$TMUX kill-server 2>/dev/null
rm -rf "$TMPDIR"
}
trap cleanup EXIT
wait_for()
{
pattern=$1
timeout=${2:-6}
i=0
while [ "$i" -lt "$timeout" ]; do
if grep -F -- "$pattern" "$OUT" >/dev/null 2>&1; then
return 0
fi
sleep 1
i=$((i + 1))
done
echo "missing: $pattern"
cat "$OUT"
return 1
}
wait_for_count()
{
pattern=$1
expected=$2
timeout=${3:-6}
i=0
while [ "$i" -lt "$timeout" ]; do
count=$(grep -F -- "$pattern" "$OUT" 2>/dev/null | wc -l)
if [ "$count" -ge "$expected" ]; then
return 0
fi
sleep 1
i=$((i + 1))
done
echo "missing count $expected for: $pattern"
cat "$OUT"
return 1
}
send()
{
printf '%s\n' "$*" >&3
}
$TMUX kill-server 2>/dev/null
$TMUX new-session -d -s notify -x 80 -y 24 || exit 1
wid=$($TMUX display-message -p -t notify:0 '#{window_id}') || exit 1
pane=$($TMUX display-message -p -t notify:0.0 '#{pane_id}') || exit 1
mkfifo "$IN"
: >"$OUT"
$TMUX -C attach-session -t notify <"$IN" >"$OUT" 2>&1 &
PID=$!
exec 3>"$IN"
send 'display-message -p ready'
wait_for 'ready' 3 || exit 1
send 'rename-window notify-renamed'
wait_for "%window-renamed $wid notify-renamed" || exit 1
send 'split-window -h'
wait_for "%layout-change $wid " || exit 1
send 'select-pane -t:.0'
wait_for "%window-pane-changed $wid $pane" || exit 1
send 'copy-mode -t:.0'
wait_for "%pane-mode-changed $pane" || exit 1
sessions_changed=$(grep -F -- '%sessions-changed' "$OUT" 2>/dev/null | \
wc -l)
send 'new-session -d -s notify-extra'
wait_for_count '%sessions-changed' $((sessions_changed + 1)) || exit 1
send 'kill-session -t notify-extra'
wait_for_count '%sessions-changed' $((sessions_changed + 2)) || exit 1
exit 0

View File

@@ -181,6 +181,99 @@ $TMUX set-hook -gu pane-title-changed ||
fail "unset pane-title-changed failed"
$TMUX killp -t "$pane" || fail "kill-pane title failed"
# pane-created payload from a command pane, an empty pane, and a respawn.
$TMUX set -g @pc 0 || fail "set @pc failed"
$TMUX set-hook -g pane-created \
'set -gF @pc "#{hook}:#{hook_pane}:#{hook_pane_command}:#{hook_created_empty}:#{hook_created_respawn}"' ||
fail "set-hook pane-created failed"
pane=$($TMUX splitw -d -t main:0 -P -F '#{pane_id}' 'sleep 30') ||
fail "split-window pane-created command failed"
wait_for @pc "pane-created:$pane:\"sleep 30\":0:0"
$TMUX killp -t "$pane" || fail "kill-pane pane-created command failed"
$TMUX set -g @pc 0 || fail "reset @pc failed"
empty_command=$($TMUX show -gqv default-shell) ||
fail "show default-shell failed"
pane=$($TMUX splitw -d -E -t main:0 -P -F '#{pane_id}') ||
fail "split-window pane-created empty failed"
wait_for @pc "pane-created:$pane:$empty_command:1:0"
$TMUX set -g @pc 0 || fail "reset @pc respawn failed"
$TMUX respawnp -k -t "$pane" 'sleep 30' || fail "respawn-pane failed"
wait_for @pc "pane-created:$pane:\"sleep 30\":0:1"
$TMUX killp -t "$pane" || fail "kill-pane pane-created respawn failed"
$TMUX set-hook -gu pane-created || fail "unset pane-created failed"
# pane-resized carries old and new dimensions.
pane=$($TMUX splitw -d -t main:0 -P -F '#{pane_id}' 'sleep 30') ||
fail "split-window pane-resized failed"
old_size=$($TMUX display -pt "$pane" '#{pane_width},#{pane_height}') ||
fail "display old pane size failed"
$TMUX set -g @pr 0 || fail "set @pr failed"
$TMUX set-hook -g pane-resized \
'set -gF @pr "#{hook}:#{hook_pane}:#{hook_old_width},#{hook_old_height}->#{hook_width},#{hook_height}"' ||
fail "set-hook pane-resized failed"
$TMUX resizep -t "$pane" -x 20 -y 10 || fail "resize-pane failed"
new_size=$($TMUX display -pt "$pane" '#{pane_width},#{pane_height}') ||
fail "display new pane size failed"
wait_for @pr "pane-resized:$pane:$old_size->$new_size"
$TMUX set-hook -gu pane-resized || fail "unset pane-resized failed"
$TMUX killp -t "$pane" || fail "kill-pane pane-resized failed"
# pane-mode-entered and pane-mode-exited expose split transition payloads.
$TMUX set -g @me 0 || fail "set @me failed"
$TMUX set -g @mx 0 || fail "set @mx failed"
pane=$($TMUX splitw -d -t main:0 -P -F '#{pane_id}' 'sleep 30') ||
fail "split-window pane-mode failed"
$TMUX set-hook -g pane-mode-entered \
'set -gF @me "#{hook}:#{hook_pane}:#{hook_mode_entered}:#{hook_current_mode}:#{hook_previous_mode}"' ||
fail "set-hook pane-mode-entered failed"
$TMUX set-hook -g pane-mode-exited \
'set -gF @mx "#{hook}:#{hook_pane}:#{hook_mode_entered}:#{hook_current_mode}:#{hook_previous_mode}"' ||
fail "set-hook pane-mode-exited failed"
$TMUX copy-mode -t "$pane" || fail "copy-mode split event failed"
wait_for @me "pane-mode-entered:$pane:1:copy-mode:"
$TMUX send-keys -t "$pane" -X cancel || fail "cancel split mode failed"
wait_for @mx "pane-mode-exited:$pane:0::copy-mode"
$TMUX set-hook -gu pane-mode-entered || fail "unset pane-mode-entered failed"
$TMUX set-hook -gu pane-mode-exited || fail "unset pane-mode-exited failed"
$TMUX killp -t "$pane" || fail "kill-pane pane-mode failed"
# marked-pane-changed carries the new/old marked pane and marked flag.
$TMUX set -g @mk 0 || fail "set @mk failed"
pane=$($TMUX splitw -d -t main:0 -P -F '#{pane_id}' 'sleep 30') ||
fail "split-window marked-pane failed"
$TMUX set-hook -g marked-pane-changed \
'set -gF @mk "#{hook}:#{hook_marked}:#{hook_pane}:#{hook_new_pane}:#{hook_old_pane}"' ||
fail "set-hook marked-pane-changed failed"
$TMUX selectp -t "$pane" -m || fail "mark pane failed"
wait_for @mk "marked-pane-changed:1:$pane:$pane:"
$TMUX selectp -t "$pane" -m || fail "unmark pane failed"
wait_for @mk "marked-pane-changed:0:$pane::$pane"
$TMUX set-hook -gu marked-pane-changed ||
fail "unset marked-pane-changed failed"
$TMUX killp -t "$pane" || fail "kill-pane marked-pane failed"
# window-zoomed and window-unzoomed fire on resize-pane -Z.
$TMUX set -g @zoom 0 || fail "set @zoom failed"
pane=$($TMUX splitw -d -t main:0 -P -F '#{pane_id}' 'sleep 30') ||
fail "split-window zoom failed"
window=$($TMUX display -pt "$pane" '#{window_id}') ||
fail "display zoom window failed"
$TMUX set-hook -g window-zoomed \
'set -gF @zoom "#{hook}:#{hook_window}"' ||
fail "set-hook window-zoomed failed"
$TMUX set-hook -g window-unzoomed \
'set -gF @zoom "#{hook}:#{hook_window}"' ||
fail "set-hook window-unzoomed failed"
$TMUX resizep -Z -t "$pane" || fail "zoom pane failed"
wait_for @zoom "window-zoomed:$window"
$TMUX resizep -Z -t "$pane" || fail "unzoom pane failed"
wait_for @zoom "window-unzoomed:$window"
$TMUX set-hook -gu window-zoomed || fail "unset window-zoomed failed"
$TMUX set-hook -gu window-unzoomed || fail "unset window-unzoomed failed"
$TMUX killp -t "$pane" || fail "kill-pane zoom failed"
# client-attached and client-detached using a control client.
$TMUX set -g @a 0 || fail "set @a failed"
$TMUX set-hook -g client-attached 'set -gF @a "#{hook}"' ||

View File

@@ -36,6 +36,21 @@ check_value()
fi
}
check_wait_value()
{
i=0
while [ "$i" -lt 30 ]; do
out=$($TMUX show $1 2>&1)
[ "$out" = "$2" ] && return 0
i=$((i + 1))
sleep 0.2
done
echo "show $1 failed."
echo "Expected: '$2'"
echo "But got: '$out'"
exit 1
}
# check_array $args $expected
#
# Compare the full (multi-line) show output for an array option with a
@@ -162,6 +177,39 @@ check_ok set-hook -g window-renamed[notify] "display-message renamed"
check_value "-gv window-renamed[notify]" "display-message renamed"
check_ok set-hook -gu window-renamed[notify]
check_value "-gv window-renamed[notify]" ""
check_ok set -g @hook_first 0
check_ok set -g @hook_second 0
check_ok set-hook -g window-renamed[first] "set -g @hook_first 1"
check_ok set-hook -g window-renamed[second] "set -g @hook_second 1"
shown=$($TMUX show-hooks -g window-renamed) || {
echo "show-hooks -g window-renamed failed"
exit 1
}
echo "$shown" | grep -q '^window-renamed\[first\]' || {
echo "missing first hook key: $shown"
exit 1
}
echo "$shown" | grep -q '^window-renamed\[second\]' || {
echo "missing second hook key: $shown"
exit 1
}
check_ok rename-window -t main:0 array-hooks
check_wait_value "-gqv @hook_first" "1"
check_wait_value "-gqv @hook_second" "1"
check_ok set-hook -gu window-renamed[first]
shown=$($TMUX show-hooks -g window-renamed) || {
echo "show-hooks -g window-renamed after unset failed"
exit 1
}
echo "$shown" | grep -q '^window-renamed\[first\]' && {
echo "first hook key was not unset: $shown"
exit 1
}
echo "$shown" | grep -q '^window-renamed\[second\]' || {
echo "second hook key did not remain: $shown"
exit 1
}
check_ok set-hook -gu window-renamed[second]
# --- colour-type array ----------------------------------------------------
#

View File

@@ -49,6 +49,19 @@ status_line() {
got() {
$IN show -gv @r
}
wait_opt() {
option=$1
expected=$2
i=0
while [ $i -lt 30 ]; do
value=$($IN show -gqv "$option" 2>/dev/null || true)
[ "$value" = "$expected" ] && return 0
i=$((i + 1))
sleep 0.2
done
fail "expected $option to be '$expected' but got '$value'"
}
reset() {
$IN set -g @r "SENTINEL" || exit 1
}
@@ -85,6 +98,12 @@ $IN bind -n M-j command-prompt -P -I hello -p '(pre)' "set -g @r '%%'" || e
$IN bind -n M-m command-prompt -p 'first,second' "set -g @r '%1/%2'" || exit 1
$IN bind -n M-c command-prompt -p '(cmd)' "set -g @r '%%'" || exit 1
$IN bind -n M-h command-prompt -T search -p '(srch)' "set -g @r '%%'" || exit 1
$IN set-hook -g pane-prompt-opened \
'set -gF @prompt_open "#{hook}:#{hook_pane}:#{hook_prompt_type}"' ||
exit 1
$IN set-hook -g pane-prompt-closed \
'set -gF @prompt_close "#{hook}:#{hook_pane}:#{hook_prompt_type}"' ||
exit 1
# --- Outer session: attach the inner one inside its pane. -------------------
$OUT new -d -x80 -y24 || exit 1
@@ -111,14 +130,17 @@ settle
# --- 1b. window.c: drawn over the pane, not on the status line. ---
reset
pane=$($IN display-message -p '#{pane_id}') || exit 1
$OUT send-keys M-p || exit 1
settle
wait_opt @prompt_open "pane-prompt-opened:$pane:command"
capture | grep -qF '(pane)' || fail "pane prompt not drawn in the pane"
status_line | grep -qF '(pane)' && \
fail "pane prompt drawn on the status line, not over the pane"
$OUT send-keys -l "deep" || exit 1
$OUT send-keys Enter || exit 1
settle
wait_opt @prompt_close "pane-prompt-closed:$pane:command"
[ "$(got)" = "deep" ] || fail "pane prompt accept recovered '$(got)', wanted 'deep'"
# --- 1c. mode-tree.c: search prompt drawn in the pane. ---

View File

@@ -187,4 +187,20 @@ $TMUX rename-window -t wf2:0 renamed-again ||
fail "rename-window renamed-again failed"
wait_channel wf-hook-renamed
$TMUX set -g @builtin_filtered 0 || fail "set @builtin_filtered failed"
target=$($TMUX splitw -d -t wf2:0 -P -F '#{pane_id}' 'sleep 30') ||
fail "split-window target failed"
$TMUX wait-for -E -F "#{==:#{pane},$target}" pane-exited \; \
set -g @builtin_filtered 1 \; wait-for -S wf-builtin-filtered &
builtin_filtered_pid=$!
assert_unchanged @builtin_filtered 0 5
$TMUX splitw -d -t wf2:0 'true' || fail "split-window nonmatching failed"
assert_unchanged @builtin_filtered 0 5
$TMUX send-keys -t "$target" C-c || fail "send C-c to target failed"
wait_channel wf-builtin-filtered
wait "$builtin_filtered_pid" ||
fail "filtered wait-for -E pane-exited command failed"
exit 0