mirror of
https://github.com/tmux/tmux.git
synced 2026-10-07 01:55:49 +00:00
152 lines
4.1 KiB
Bash
Executable File
152 lines
4.1 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Damage redraws must show each client's own pane status, even though the
|
|
# cached status screen is shared between clients.
|
|
|
|
PATH=/bin:/usr/bin
|
|
TERM=screen
|
|
LC_ALL=C.UTF-8
|
|
export PATH TERM LC_ALL
|
|
|
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
|
|
DIR=$(mktemp -d) || exit 1
|
|
INNER="$TEST_TMUX -Lstatuscc-inner-$$ -f/dev/null"
|
|
OUTER="$TEST_TMUX -Lstatuscc-outer-$$ -f/dev/null"
|
|
CAPTURE=$DIR/capture
|
|
|
|
fail()
|
|
{
|
|
echo "$*" >&2
|
|
[ -s "$CAPTURE" ] && cat "$CAPTURE" >&2
|
|
exit 1
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
$OUTER kill-server 2>/dev/null
|
|
$INNER kill-server 2>/dev/null
|
|
rm -rf "$DIR"
|
|
}
|
|
trap cleanup 0 1 15
|
|
|
|
wait_for_clients()
|
|
{
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
count=$($INNER list-clients 2>/dev/null | wc -l)
|
|
[ "$count" -eq 2 ] && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "two inner clients did not attach"
|
|
}
|
|
|
|
wait_for_marker()
|
|
{
|
|
target=$1
|
|
marker=$2
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
$OUTER capture-pane -p -t "$target" >"$CAPTURE" || exit 1
|
|
grep -q "$marker" "$CAPTURE" && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "client in $target did not receive $marker"
|
|
}
|
|
|
|
cat >"$DIR/emitter.pl" <<'PERL'
|
|
use strict;
|
|
use warnings;
|
|
|
|
$| = 1;
|
|
for my $phase (1 .. 4) {
|
|
while (!-e "$ENV{TRIGGER}-$phase") {
|
|
select undef, undef, undef, 0.01;
|
|
}
|
|
# Change an unused palette entry and acknowledge it in the pane body.
|
|
print "\e]4;200;rgb:11/22/0$phase\a\e[1;1HDAMAGE$phase";
|
|
}
|
|
sleep 100;
|
|
PERL
|
|
|
|
$INNER new-session -d -s inner -x 60 -y 20 \
|
|
"TRIGGER='$DIR/trigger' perl '$DIR/emitter.pl'" || exit 1
|
|
$INNER set -g status off || exit 1
|
|
$INNER set -g window-size manual || exit 1
|
|
$INNER set -g automatic-rename off || exit 1
|
|
$INNER set -g status-interval 0 || exit 1
|
|
$INNER set -g pane-border-lines simple || exit 1
|
|
$INNER set -g pane-border-status top || exit 1
|
|
$INNER set -g pane-border-format 'CLIENT=<#{client_name}>' || exit 1
|
|
FLOAT=$($INNER new-pane -d -PF '#{pane_id}' -x 35 -y 6 -X 5 -Y 5 \
|
|
'sleep 100') || exit 1
|
|
|
|
$OUTER new-session -d -s outer -x 121 -y 20 'sleep 100' || exit 1
|
|
$OUTER set -g status off || exit 1
|
|
$OUTER set -g window-size manual || exit 1
|
|
$OUTER set -g default-terminal screen || exit 1
|
|
LEFT=$($OUTER display-message -p -t outer:0.0 '#{pane_id}') || exit 1
|
|
RIGHT=$($OUTER split-window -h -PF '#{pane_id}' 'sleep 100') || exit 1
|
|
for target in "$LEFT" "$RIGHT"; do
|
|
$OUTER respawn-pane -k -t "$target" "$INNER attach-session -t inner" ||
|
|
exit 1
|
|
done
|
|
wait_for_clients
|
|
|
|
NAME1=$($OUTER display-message -p -t "$LEFT" '#{pane_tty}') || exit 1
|
|
NAME2=$($OUTER display-message -p -t "$RIGHT" '#{pane_tty}') || exit 1
|
|
|
|
# Disable periodic status updates above and trigger damage without a command
|
|
# that also requests a status redraw. Each client must keep its own title.
|
|
$INNER refresh-client -t "$NAME1" || exit 1
|
|
$INNER refresh-client -t "$NAME2" || exit 1
|
|
sleep 0.5
|
|
for phase in 0 1 2; do
|
|
if [ "$phase" -ne 0 ]; then
|
|
: >"$DIR/trigger-$phase"
|
|
wait_for_marker "$LEFT" "DAMAGE$phase"
|
|
wait_for_marker "$RIGHT" "DAMAGE$phase"
|
|
sleep 0.2
|
|
fi
|
|
for target in "$LEFT" "$RIGHT"; do
|
|
if [ "$target" = "$LEFT" ]; then
|
|
name=$NAME1
|
|
other=$NAME2
|
|
else
|
|
name=$NAME2
|
|
other=$NAME1
|
|
fi
|
|
$OUTER capture-pane -p -S 5 -E 10 -t "$target" \
|
|
>"$CAPTURE" || exit 1
|
|
grep -Fq "CLIENT=<$name>" "$CAPTURE" ||
|
|
fail "phase $phase: missing $name's pane status"
|
|
if grep -Fq "CLIENT=<$other>" "$CAPTURE"; then
|
|
fail "phase $phase: $name received $other's pane status"
|
|
fi
|
|
done
|
|
done
|
|
|
|
# Leave just one client so a cache keyed only by client would remain stale.
|
|
$OUTER respawn-pane -k -t "$RIGHT" 'sleep 100' || exit 1
|
|
i=0
|
|
while [ "$($INNER list-clients | wc -l)" -ne 1 ]; do
|
|
[ "$i" -lt 50 ] || fail "second client did not detach"
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
$INNER set-environment -g TEST_STATUS_VALUE initial || exit 1
|
|
$INNER set -g pane-border-format 'VALUE=#{TEST_STATUS_VALUE}' || exit 1
|
|
$INNER refresh-client -t "$NAME1" || exit 1
|
|
wait_for_marker "$LEFT" VALUE=initial
|
|
for phase in 3 4; do
|
|
# Changing the environment does not itself request a status redraw.
|
|
$INNER set-environment -g TEST_STATUS_VALUE "phase$phase" || exit 1
|
|
: >"$DIR/trigger-$phase"
|
|
wait_for_marker "$LEFT" "DAMAGE$phase"
|
|
wait_for_marker "$LEFT" "VALUE=phase$phase"
|
|
done
|
|
|
|
exit 0
|