mirror of
https://github.com/tmux/tmux.git
synced 2026-07-03 10:22:29 +00:00
Targets tests.
This commit is contained in:
150
regress/targets-panes.sh
Executable file
150
regress/targets-panes.sh
Executable file
@@ -0,0 +1,150 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Tests of pane target resolution in cmd-find.c.
|
||||
#
|
||||
# Building on targets.sh (session/window resolution), this exercises the pane
|
||||
# half of cmd_find_target() in a known 2x2 split:
|
||||
#
|
||||
# - pane ids (%n), pane indices, and the +/- offset and ! last-pane tokens;
|
||||
# - positional tokens {top-left}/{top-right}/{bottom-left}/{bottom-right}
|
||||
# and {top}/{bottom}/{left}/{right};
|
||||
# - directional tokens {up-of}/{down-of}/{left-of}/{right-of} relative to
|
||||
# the active pane;
|
||||
# - the ".pane" and "sess:win.pane" combined forms;
|
||||
# - the marked pane, reached with ~ / {marked} and cleared with -M;
|
||||
# - and the error paths: a pane id in the wrong window, a directional token
|
||||
# with no neighbour, and an unset marked pane.
|
||||
#
|
||||
# The 2x2 split is created in a fixed order so pane ids are deterministic:
|
||||
#
|
||||
# +--------+--------+
|
||||
# | %0 | %1 | top-left = %0 top-right = %1
|
||||
# +--------+--------+ bottom-left = %2 bottom-right = %3
|
||||
# | %2 | %3 |
|
||||
# +--------+--------+
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
# check $target $expected [format]
|
||||
#
|
||||
# The default format is the pane id.
|
||||
check()
|
||||
{
|
||||
fmt=${3:-'#{pane_id}'}
|
||||
out=$($TMUX display-message -p -t "$1" "$fmt" 2>&1)
|
||||
if [ "$out" != "$2" ]; then
|
||||
echo "target '$1' resolved wrong."
|
||||
echo "Expected: '$2'"
|
||||
echo "But got: '$out'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_ok()
|
||||
{
|
||||
if ! $TMUX "$@"; then
|
||||
echo "Command failed (expected success): $*"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_fail()
|
||||
{
|
||||
out=$($TMUX has-session -t "$2" 2>&1)
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "target '$2' resolved (expected failure)."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$out" != "$1" ]; then
|
||||
echo "Wrong error for target '$2'."
|
||||
echo "Expected: '$1'"
|
||||
echo "But got: '$out'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_alive()
|
||||
{
|
||||
if [ "$($TMUX display-message -p alive 2>&1)" != "alive" ]; then
|
||||
echo "Server died: $1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# --- fixture: a 2x2 split plus a single-pane window -----------------------
|
||||
check_ok new-session -d -s p -x 80 -y 24
|
||||
check_ok split-window -h -t p:0 # %0 left, %1 right
|
||||
check_ok split-window -v -t p:0.%0 # split left: %0 top, %2 bottom
|
||||
check_ok split-window -v -t p:0.%1 # split right: %1 top, %3 bottom
|
||||
check_ok new-window -d -t p: -n solo # a second, single-pane window
|
||||
|
||||
# --- pane ids, index, offsets ---------------------------------------------
|
||||
check "p:0.%3" "%3" # exact pane id
|
||||
check "p:0.3" "%3" # pane by index
|
||||
check "p:0.%1" "%1" # sess:win.pane form
|
||||
check ".%1" "%1" # .pane form (current window)
|
||||
# "sess:.pane" (empty window part) resolves the pane in the session's current
|
||||
# window. Make window 0 current first.
|
||||
check_ok select-window -t p:0
|
||||
check "p:.%1" "%1"
|
||||
check "p:.{top-left}" "%0"
|
||||
# Offsets are relative to the active pane; make %0 active first.
|
||||
check_ok select-pane -t p:0.%0
|
||||
check "p:0.+" "1" '#{pane_index}' # next pane
|
||||
check "p:0.-" "3" '#{pane_index}' # previous pane (wraps)
|
||||
|
||||
# --- last pane (!) --------------------------------------------------------
|
||||
check_ok select-pane -t p:0.%2
|
||||
check_ok select-pane -t p:0.%0 # now the last pane is %2
|
||||
check "p:0.!" "%2"
|
||||
|
||||
# --- positional tokens (absolute geometry) --------------------------------
|
||||
check "p:0.{top-left}" "%0"
|
||||
check "p:0.{top-right}" "%1"
|
||||
check "p:0.{bottom-left}" "%2"
|
||||
check "p:0.{bottom-right}" "%3"
|
||||
check "p:0.{top}" "%0" # leftmost of the top row
|
||||
check "p:0.{bottom}" "%2" # leftmost of the bottom row
|
||||
check "p:0.{left}" "%0" # top of the left column
|
||||
check "p:0.{right}" "%1" # top of the right column
|
||||
|
||||
# --- directional tokens (relative to the active pane) ---------------------
|
||||
#
|
||||
# From the top-left pane the real neighbours are below and to the right.
|
||||
check_ok select-pane -t p:0.%0
|
||||
check "p:0.{down-of}" "%2"
|
||||
check "p:0.{right-of}" "%1"
|
||||
# From the bottom-right pane the real neighbours are above and to the left.
|
||||
check_ok select-pane -t p:0.%3
|
||||
check "p:0.{up-of}" "%1"
|
||||
check "p:0.{left-of}" "%2"
|
||||
|
||||
# --- pane error paths -----------------------------------------------------
|
||||
check_fail "can't find pane: %0" "p:solo.%0" # pane id, wrong window
|
||||
check_fail "can't find pane: {up-of}" "p:solo.{up-of}" # no neighbour
|
||||
check_fail "can't find pane: 9" "p:0.9" # no such index
|
||||
|
||||
# --- marked pane ----------------------------------------------------------
|
||||
#
|
||||
# ~ / {marked} resolve to the marked pane from anywhere; -M clears it.
|
||||
check_fail "no marked target" "~" # nothing marked yet
|
||||
check_ok select-pane -m -t p:0.%1
|
||||
check "~" "%1"
|
||||
check "{marked}" "%1"
|
||||
# The mark is global: it resolves even with a different current window.
|
||||
check_ok select-window -t p:solo
|
||||
check "~" "%1"
|
||||
check_ok select-window -t p:0
|
||||
check_ok select-pane -M # clear the mark
|
||||
check_fail "no marked target" "~"
|
||||
check_fail "no marked target" "{marked}"
|
||||
|
||||
assert_alive "after pane target tests"
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
exit 0
|
||||
224
regress/targets.sh
Executable file
224
regress/targets.sh
Executable file
@@ -0,0 +1,224 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Tests of target (session and window) resolution in cmd-find.c.
|
||||
#
|
||||
# A target string like "session:window.pane" is parsed by cmd_find_target()
|
||||
# and resolved to a concrete session/window/pane. This exercises the session
|
||||
# and window halves of that machinery:
|
||||
#
|
||||
# - session and window ids ($n, @n) and names;
|
||||
# - exact (=name), prefix and fnmatch matching, and the ambiguous/missing
|
||||
# error paths for each;
|
||||
# - the combined "sess:", "sess:win", ":win" and "sess:win.pane" forms and
|
||||
# the empty (current) target;
|
||||
# - the offset and special window tokens (^ $ ! + - and their {start},
|
||||
# {end}, {last}, {next}, {previous} spellings), including +N/-N with
|
||||
# wrap-around;
|
||||
# - the special whole-target tokens {active}/@/{current} and {mouse}/=;
|
||||
# - the CMD_FIND_WINDOW_INDEX "can't specify pane here" guard; and
|
||||
# - -s versus -t resolution on link-window/move-window.
|
||||
#
|
||||
# Positive cases are asserted with display-message -p -t (which renders the
|
||||
# resolved target); error cases with has-session -t, which resolves strictly
|
||||
# and prints the cmd-find error text.
|
||||
#
|
||||
# Pane resolution (directional/positional tokens, marked pane) is covered by
|
||||
# targets-panes.sh.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
# check $target $expected [format]
|
||||
#
|
||||
# Resolve $target and compare the rendered value. The default format is the
|
||||
# window index; pass a third argument to override.
|
||||
check()
|
||||
{
|
||||
fmt=${3:-'#{window_index}'}
|
||||
out=$($TMUX display-message -p -t "$1" "$fmt" 2>&1)
|
||||
if [ "$out" != "$2" ]; then
|
||||
echo "target '$1' resolved wrong."
|
||||
echo "Expected: '$2'"
|
||||
echo "But got: '$out'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_ok()
|
||||
{
|
||||
if ! $TMUX "$@"; then
|
||||
echo "Command failed (expected success): $*"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# check_fail $expected_error $target
|
||||
#
|
||||
# has-session resolves the target strictly and prints the cmd-find error.
|
||||
check_fail()
|
||||
{
|
||||
out=$($TMUX has-session -t "$2" 2>&1)
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "target '$2' resolved (expected failure)."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$out" != "$1" ]; then
|
||||
echo "Wrong error for target '$2'."
|
||||
echo "Expected: '$1'"
|
||||
echo "But got: '$out'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_alive()
|
||||
{
|
||||
if [ "$($TMUX display-message -p alive 2>&1)" != "alive" ]; then
|
||||
echo "Server died: $1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# --- fixture --------------------------------------------------------------
|
||||
#
|
||||
# Session alpha with four named windows (0 editor, 1 editing, 2 shell,
|
||||
# 3 logs); "editor"/"editing" share a prefix for the ambiguity tests. Two
|
||||
# grp* sessions share a prefix for the session ambiguity tests.
|
||||
check_ok new-session -d -s alpha -x 80 -y 24
|
||||
check_ok rename-window -t alpha:0 editor
|
||||
check_ok new-window -d -t alpha: -n editing
|
||||
check_ok new-window -d -t alpha: -n shell
|
||||
check_ok new-window -d -t alpha: -n logs
|
||||
check_ok new-session -d -s beta -x 80 -y 24
|
||||
check_ok new-window -d -t beta: -n bw1
|
||||
check_ok new-session -d -s grp1 -x 80 -y 24
|
||||
check_ok new-session -d -s grp2 -x 80 -y 24
|
||||
|
||||
# Give alpha a last-window (2) with the current window left at 0.
|
||||
check_ok select-window -t alpha:2
|
||||
check_ok select-window -t alpha:0
|
||||
|
||||
# --- session ids and names ------------------------------------------------
|
||||
sid=$($TMUX display-message -p -t alpha: '#{session_id}')
|
||||
check "$sid:" "alpha" '#{session_name}'
|
||||
check "=alpha:" "alpha" '#{session_name}' # exact
|
||||
check "alpha:" "alpha" '#{session_name}' # full name
|
||||
check "al:" "alpha" '#{session_name}' # prefix
|
||||
check "al*:" "alpha" '#{session_name}' # fnmatch
|
||||
|
||||
# --- session error paths --------------------------------------------------
|
||||
check_fail "can't find session: grp" "grp:" # ambiguous prefix
|
||||
check_fail "can't find session: grp*" "grp*:" # ambiguous fnmatch
|
||||
check_fail "can't find session: al" "=al:" # exact-only, no such session
|
||||
check_fail "can't find session: nosuch" "nosuch:"
|
||||
|
||||
# --- window ids and names -------------------------------------------------
|
||||
wid=$($TMUX display-message -p -t alpha:editing '#{window_id}')
|
||||
# A bare @id (no session) resolves both window and session.
|
||||
check "$wid" "alpha:1" '#{session_name}:#{window_index}'
|
||||
check "alpha:shell" "2" # exact name
|
||||
check "alpha:edito" "0" # prefix
|
||||
check "alpha:=editor" "0" # exact match flag
|
||||
check "alpha:sh*" "2" # fnmatch
|
||||
check "alpha:1" "1" # index
|
||||
|
||||
# A window id qualified by a session resolves within that session; a window id
|
||||
# belonging to a different session is rejected.
|
||||
w2=$($TMUX display-message -p -t alpha:shell '#{window_id}')
|
||||
check "alpha:$w2" "2"
|
||||
bw=$($TMUX display-message -p -t beta: '#{window_id}')
|
||||
check_fail "can't find window: $bw" "alpha:$bw" # window id, wrong session
|
||||
|
||||
# --- window error paths ---------------------------------------------------
|
||||
check_fail "can't find window: edit" "alpha:edit" # ambiguous prefix
|
||||
check_fail "can't find window: e*" "alpha:e*" # ambiguous fnmatch
|
||||
check_fail "can't find window: nope" "alpha:nope" # missing
|
||||
check_fail "can't find window: @999" "@999" # missing window id
|
||||
|
||||
# --- offset and special window tokens -------------------------------------
|
||||
#
|
||||
# alpha's current window is 0; offsets wrap around the four windows.
|
||||
check "alpha:^" "0" # start
|
||||
check "alpha:\$" "3" # end
|
||||
check "alpha:+" "1" # next
|
||||
check "alpha:-" "3" # previous (wraps)
|
||||
check "alpha:+2" "2"
|
||||
check "alpha:-2" "2" # wraps
|
||||
check "alpha:{start}" "0"
|
||||
check "alpha:{end}" "3"
|
||||
check "alpha:{next}" "1"
|
||||
check "alpha:{previous}" "3"
|
||||
check "alpha:!" "2" # last window
|
||||
check "alpha:{last}" "2"
|
||||
|
||||
# --- combined and empty forms ---------------------------------------------
|
||||
#
|
||||
# ":win" uses the current session; confirm that is alpha first so the test is
|
||||
# unambiguous, then resolve a window inside it with an empty session part.
|
||||
check "" "alpha" '#{session_name}' # empty target is current
|
||||
check "" "alpha:0" '#{session_name}:#{window_index}'
|
||||
check ":shell" "alpha:2" '#{session_name}:#{window_index}'
|
||||
check "alpha:shell.0" "alpha:2" '#{session_name}:#{window_index}'
|
||||
check "alpha:.0" "alpha:0" '#{session_name}:#{window_index}' # empty window part
|
||||
|
||||
# --- bare-name fallbacks --------------------------------------------------
|
||||
#
|
||||
# A bare pane target that is not a pane falls back to a window, then to a
|
||||
# session, using the current session (alpha).
|
||||
check "editor" "0" '#{window_index}' # bare window name
|
||||
check "beta" "beta" '#{session_name}' # bare session name
|
||||
|
||||
# --- whole-target special tokens ------------------------------------------
|
||||
#
|
||||
# {active}/@/{current} need a client with a session; with only a detached
|
||||
# command client they must error cleanly (regression: this used to crash the
|
||||
# server via a NULL session dereference). {mouse}/= need a mouse event.
|
||||
check_fail "no current client" "{active}"
|
||||
check_fail "no current client" "@"
|
||||
check_fail "no current client" "{current}"
|
||||
check_fail "no mouse target" "{mouse}"
|
||||
check_fail "no mouse target" "="
|
||||
assert_alive "after whole-target special tokens"
|
||||
|
||||
# --- CMD_FIND_WINDOW_INDEX rejects a pane part ----------------------------
|
||||
out=$($TMUX new-window -d -t 'alpha:1.%0' 2>&1)
|
||||
[ $? -ne 0 ] || { echo "new-window with pane target succeeded"; exit 1; }
|
||||
[ "$out" = "can't specify pane here" ] || \
|
||||
{ echo "wrong pane-here error: '$out'"; exit 1; }
|
||||
|
||||
# --- window index targets: offsets resolve to an index --------------------
|
||||
#
|
||||
# new-window's -t is a window index (CMD_FIND_WINDOW_INDEX); an offset from
|
||||
# the current window (0) picks the numeric index rather than an existing
|
||||
# window, so "+6" creates window 6.
|
||||
check_ok select-window -t alpha:0
|
||||
check_ok new-window -d -t 'alpha:+6' -n offwin
|
||||
check "alpha:6" "offwin" '#{window_name}'
|
||||
check_ok kill-window -t alpha:6
|
||||
|
||||
# --- -s versus -t resolution ----------------------------------------------
|
||||
#
|
||||
# link-window takes a source window (-s) and a destination index (-t); each
|
||||
# side is resolved independently by cmd-find.
|
||||
check_ok new-session -d -s src -x 80 -y 24
|
||||
check_ok new-window -d -t src: -n payload
|
||||
check_ok link-window -s src:payload -t alpha:9
|
||||
check "alpha:9" "payload" '#{window_name}'
|
||||
# move-window relocates it; the old index must be gone.
|
||||
check_ok move-window -s alpha:9 -t alpha:5
|
||||
check "alpha:5" "payload" '#{window_name}'
|
||||
check_fail "can't find window: 9" "alpha:9"
|
||||
|
||||
# --- default state with no client -----------------------------------------
|
||||
#
|
||||
# run-shell with no target and no attached client has cmd-find build the
|
||||
# current state from nothing (the best session).
|
||||
check_ok run-shell 'true'
|
||||
|
||||
assert_alive "after target tests"
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
exit 0
|
||||
Reference in New Issue
Block a user