test: factor skip guards into _require_* helpers (phase 5)
30 host-Wayland, 6 Xwayland and 5 helper-binary skip guards become _require_host_wayland() / _require_xwayland() / _require_file(path, reason). Binary checks keep their own triage messages; os.access checks and skipif/flaky markers are untouched. Full suite: 152 passed, 2 skipped.
This commit is contained in:
parent
f10fff910c
commit
838876ff65
1 changed files with 60 additions and 82 deletions
|
|
@ -655,8 +655,7 @@ class Session:
|
|||
|
||||
@pytest.fixture(scope="function")
|
||||
def session():
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
for path in (BIN, WL):
|
||||
if not os.access(path, os.X_OK):
|
||||
pytest.skip(f"build first: {path}")
|
||||
|
|
@ -1287,6 +1286,25 @@ def _assert_no_crash(log):
|
|||
assert pat not in log, f"crash indicator {pat!r} in log"
|
||||
|
||||
|
||||
def _require_host_wayland():
|
||||
"""Skip unless running under a live host Wayland session."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
|
||||
|
||||
def _require_xwayland():
|
||||
"""Skip unless Xwayland and xmessage are available."""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
|
||||
|
||||
def _require_file(path, reason):
|
||||
"""Skip unless a helper binary exists. Each caller keeps its own
|
||||
triage message (missing binary vs missing dev headers)."""
|
||||
if not os.path.exists(path):
|
||||
pytest.skip(reason)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def globals_session():
|
||||
"""One shared standalone kick for all protocol-globals tests.
|
||||
|
|
@ -1833,8 +1851,7 @@ def test_nested_primary_selection_bridged(tmp_path):
|
|||
"""Nested mode: a tab's primary selection is fanned out to a second tab
|
||||
exactly as standalone, and the host-side bridge publishes it over
|
||||
ext-data-control (when the host implements it) without echo-looping."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
out = tmp_path / "primary.out"
|
||||
with _run_nested("%s --primary-set 'hello' '#ff0000'" % WL,
|
||||
"%s --primary-demand-expect '%s' hello '#00ff00'"
|
||||
|
|
@ -1874,8 +1891,7 @@ def test_nested_host_primary_to_kick(tmp_path):
|
|||
Skipped on hosts without ext-data-control (e.g. GNOME/mutter): the
|
||||
host->nested primary mirror only exists on that backend, so this test
|
||||
needs an ext-data-control host -- run it on a compositor like labwc/sway."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
token = f"kick-h2n-{os.getpid()}-{time.monotonic_ns()}"
|
||||
out = tmp_path / "primary.out"
|
||||
with _run_nested("%s --primary-demand-expect '%s' '%s' '#00ff00'"
|
||||
|
|
@ -2646,8 +2662,7 @@ def test_hold_alt_down_repeats():
|
|||
# This test asserts wall-clock repeat behavior itself, so it opts out
|
||||
# of the suite-wide stretched repeat delay (repeat_off=False) with a
|
||||
# private session; it stays marked flaky (starved timers repeat late).
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{BLUE}'",
|
||||
repeat_off=False) as session:
|
||||
start = session.wait_any_active()
|
||||
|
|
@ -2878,8 +2893,7 @@ def test_sub_window_hidden_when_parent_not_active():
|
|||
its own slot glued right after the parent tab, and because the parent is
|
||||
not the tab being shown it must NOT steal focus (no churn -- the crowned
|
||||
tab stays active)."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
# Tab 0 (RED) opens a green extra toplevel from the same client.
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'", f"{WL} '{BLUE}'",
|
||||
extra_args=("--tab-groups", "off"), wait="any") as s:
|
||||
|
|
@ -2970,8 +2984,7 @@ def test_sub_window_activates_when_parent_active():
|
|||
"""--tab-groups off: a related window whose parent tab is the one being
|
||||
shown becomes the active tab on map (the second exception to the
|
||||
no-steal rule)."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'",
|
||||
extra_args=("--tab-groups", "off")) as s:
|
||||
s.wait_any_active() # the single tab is crowned, then ...
|
||||
|
|
@ -2989,8 +3002,7 @@ def test_sub_windows_stack_mode_never_claims_a_slot():
|
|||
rides on its owner's tab -- it logs [sub] stack, never claims a slot of
|
||||
its own, and takes the keyboard only because its parent tab is the one
|
||||
being shown."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'",
|
||||
extra_args=("--tab-groups", "on")) as s:
|
||||
s.wait_any_active() # app 0 crowned on its first map
|
||||
|
|
@ -3025,8 +3037,7 @@ def test_sub_windows_stack_mode_never_claims_a_slot():
|
|||
def test_sub_windows_stack_mode_focus_follows_tab():
|
||||
"""--tab-groups on: a stacked window of a background tab maps
|
||||
without taking the keyboard; showing its tab hands focus to it."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
# Tab 0 (RED) opens a green extra; tab 1 (BLUE) is the startup-selected
|
||||
# active tab, so the extra must map hidden.
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'", f"{WL} '{BLUE}'",
|
||||
|
|
@ -3080,8 +3091,7 @@ def test_sub_windows_stack_mode_unstack_refocuses_then_close():
|
|||
"""--tab-groups on: closing the stacked window ('X' in wltest)
|
||||
refocuses the tab's own surface without killing the tab; Alt+Delete on
|
||||
the tab then tears the whole unit down."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'",
|
||||
extra_args=("--tab-groups", "on"), wait="any") as s:
|
||||
s.wait_for(r"\[sub\] focus app=0\b") # extra holds the keyboard
|
||||
|
|
@ -3103,8 +3113,7 @@ def test_sub_windows_stack_mode_row_title_follows_top():
|
|||
"""--tab-groups on: the overlay row shows the topmost stacked
|
||||
window's title while it is mapped, and falls back to the tab's own
|
||||
surface title when it closes ('X' in wltest)."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'",
|
||||
extra_args=("--tab-groups", "on"), wait="any") as s:
|
||||
s.wait_for(r"\[sub\] focus app=0\b")
|
||||
|
|
@ -3121,8 +3130,7 @@ def test_alt_delete_closes_active_window_not_tab():
|
|||
only that window -- the tab stays up (the compositor stays alive, no new
|
||||
slot is claimed) and the stacked member unstacks instead of the tab being
|
||||
torn down."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'",
|
||||
extra_args=("--tab-groups", "on"), wait="any") as s:
|
||||
# [sub] stack logs when the member is *created*, before its Wayland
|
||||
|
|
@ -3160,8 +3168,7 @@ def _wait_exit(s, code, timeout=10.0):
|
|||
def test_quit_confirm_multi_window():
|
||||
"""Ctrl+Alt+Q with more than one window open raises the confirm modal
|
||||
instead of quitting; Y/Enter confirms and quits cleanly with 0."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{GREEN}'", wait="any") as s:
|
||||
s.wait_for(r"\[claim\] app=0\b")
|
||||
s.wait_for(r"\[claim\] app=1\b")
|
||||
|
|
@ -3177,8 +3184,7 @@ def test_quit_confirm_multi_window():
|
|||
def test_quit_confirm_dialog_renders():
|
||||
"""The confirm-quit modal actually draws: with the question pending, a
|
||||
frame dump shows the dark dialog box over the client content."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{GREEN}'", wait="any") as s:
|
||||
s.wait_for(r"\[claim\] app=0\b")
|
||||
s.wait_for(r"\[claim\] app=1\b")
|
||||
|
|
@ -3195,8 +3201,7 @@ def test_quit_confirm_dialog_renders():
|
|||
def test_quit_cancel_keeps_running():
|
||||
"""Ctrl+Alt+Q confirmation can be declined: N and Escape both dismiss it,
|
||||
the compositor keeps running, and a later quit request re-asks."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{GREEN}'", wait="any") as s:
|
||||
s.wait_for(r"\[claim\] app=1\b")
|
||||
|
||||
|
|
@ -3219,8 +3224,7 @@ def test_quit_cancel_keeps_running():
|
|||
def test_quit_single_window_no_confirm():
|
||||
"""With a single window there is nothing to lose, so Ctrl+Alt+Q quits
|
||||
immediately -- no confirm modal, clean exit 0."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", wait="any") as s:
|
||||
s.wait_for(r"\[claim\] app=0\b")
|
||||
# Keys sent before the surface maps are silently dropped: the claim
|
||||
|
|
@ -3238,8 +3242,7 @@ def test_alt_left_right_cycle_tab_group_members():
|
|||
consumed even with no stack. With a main surface (RED) plus a stacked
|
||||
extra (GREEN), the newest window (extra) is shown first; Alt+Left steps
|
||||
back to the main, Alt+Right forward to the extra again."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} --extra '{GREEN}' '{RED}'",
|
||||
extra_args=("--tab-groups", "on"), wait="any") as s:
|
||||
s.wait_for(r"\[sub\] stack app=0\b")
|
||||
|
|
@ -3260,8 +3263,7 @@ def test_alt_delete_activates_right_neighbor():
|
|||
"""Alt+Delete closes the active tab, making the tab to its right active
|
||||
(SIGTERM, escalated to SIGKILL only if the client lingers). With three
|
||||
tabs [0,1,2] and 1 active, closing 1 must activate 2, not 0."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{GREEN}'", f"{WL} '{BLUE}'") as s:
|
||||
start = s.wait_any_active()
|
||||
assert start in (0, 1, 2)
|
||||
|
|
@ -3287,8 +3289,7 @@ def test_alt_delete_activates_right_neighbor():
|
|||
def test_alt_delete_rightmost_falls_left():
|
||||
"""Closing the rightmost tab has no right neighbor to hand active off to,
|
||||
so it falls back to the left neighbor (index 1 of [0,1,2])."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{GREEN}'", f"{WL} '{BLUE}'", wait="any") as s:
|
||||
# Ensure the third tab has claimed a slot so index 2 really exists.
|
||||
s.wait_for(r"\[claim\] app=2 pid=(\d+)")
|
||||
|
|
@ -3307,8 +3308,7 @@ def test_alt_delete_rightmost_falls_left():
|
|||
|
||||
def test_alt_delete_second_tab_right_neighbor_two_tabs():
|
||||
"""Two-tab session: closing tab 0 makes its right neighbor (1) active."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{BLUE}'") as s:
|
||||
# Settle the startup crown (last mapper promotes itself under load),
|
||||
# then navigate to tab 0 deterministically before closing it.
|
||||
|
|
@ -3330,8 +3330,7 @@ def test_alt_shift_arrows_reorder_and_wrap():
|
|||
every other tab pushed one place, not swapped into place). The resulting
|
||||
order is provable behaviorally: an Alt+Shift+T terminal claims the slot
|
||||
right after the active tab's new position."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
old_term = os.environ.get("TERMINAL")
|
||||
os.environ["TERMINAL"] = f"{WL} '{RED}'"
|
||||
try:
|
||||
|
|
@ -3396,8 +3395,7 @@ def test_alt_shift_arrows_reorder_and_wrap():
|
|||
def test_modifier_super_flag():
|
||||
"""--modifier super moves the tab-management chords to Super/Mod4: cycle,
|
||||
reorder and close all work, while the Alt chords stop doing anything."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{BLUE}'",
|
||||
extra_args=["--modifier", "super"]) as s:
|
||||
# Settle: under load either tab can hold the startup crown (last
|
||||
|
|
@ -3440,8 +3438,7 @@ def test_modifier_super_flag():
|
|||
def test_alt_delete_escalates_sigkill(tmp_path):
|
||||
"""A client that traps SIGTERM must still be reaped by the SIGKILL
|
||||
escalation, so Alt+Delete never strands a lingering tab."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
# A wrapper that ignores SIGTERM, then execs the test client so the
|
||||
# tab's process group carries SIG_IGN for TERM across the exec.
|
||||
wrapper = tmp_path / "trap-term.sh"
|
||||
|
|
@ -3547,8 +3544,7 @@ def test_dash_h_prints_usage():
|
|||
|
||||
def test_no_args_opens_terminal():
|
||||
"""With no command-line tabs, a single terminal tab opens and maps."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
for path in (BIN, WL):
|
||||
if not os.access(path, os.X_OK):
|
||||
pytest.skip(f"build first: {path}")
|
||||
|
|
@ -3617,8 +3613,7 @@ def test_close_black_tab_active_last():
|
|||
"""Alt+Delete on a black tab (its command has not connected yet) closes
|
||||
it outright: the surviving tab becomes active, the black slot is removed
|
||||
(closed tabs leave no hole), and closing the survivor exits cleanly."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
# CLI #0 (RED) maps hidden; the active tab is the still-black `sleep`.
|
||||
with _run_nested(f"{WL} '{RED}'", "sleep 999") as s:
|
||||
s.wait_for(r"\[diag\] map app=0")
|
||||
|
|
@ -3649,8 +3644,7 @@ def test_start_cmd_index_selects_command():
|
|||
"""--start-cmd-index N (1-based) starts focused on command N instead of
|
||||
the default last command: index 1 makes the first command the active,
|
||||
black tab from the very first frame, revealed when it maps."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{GREEN}'", f"{WL} '{BLUE}'",
|
||||
extra_args=["--start-cmd-index", "1"]) as s:
|
||||
assert s.wait_any_active() == 0, \
|
||||
|
|
@ -3881,8 +3875,7 @@ def xwayland_session():
|
|||
The compositor starts focused on the *last* command, so the session
|
||||
boots on the Wayland tab and Alt+Down wraps to the X11 one.
|
||||
"""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
_require_xwayland()
|
||||
s = _spawn_kick_standalone([f"{XMSG} hi", f"{WL} '{RED}'"])
|
||||
try:
|
||||
yield s
|
||||
|
|
@ -3921,8 +3914,7 @@ def test_xwayland_ready_and_claim(xwayland_session):
|
|||
def test_xwayland_display_env_exported():
|
||||
"""Children see DISPLAY pointing at the embedded Xwayland; without
|
||||
XWayland support the variable would be unset entirely."""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
_require_xwayland()
|
||||
with _run_kick(["sh -c 'echo DISPLAY=$DISPLAY'"]) as s:
|
||||
s.wait_for(r"DISPLAY=:(\d+)", timeout=15.0)
|
||||
m = re.search(r"DISPLAY=:(\d+)", s.read_log())
|
||||
|
|
@ -4016,10 +4008,8 @@ def test_x11_client_requests_driven():
|
|||
fullscreen, move/resize, raise, maximize and a WM_DELETE close. The
|
||||
fullscreen mirror, the raise-to-focus and the close-teardown are
|
||||
asserted on the log; the rest ride on coverage plus survival."""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
if not os.path.exists(XR):
|
||||
pytest.skip("needs build/xreqs (libX11 dev headers)")
|
||||
_require_xwayland()
|
||||
_require_file(XR, "needs build/xreqs (libX11 dev headers)")
|
||||
with _run_kick(
|
||||
["sh -c 'sleep 1; exec %s managed'" % XR,
|
||||
"%s --app-id keep '#ff0000' 320x240" % WL]) as s:
|
||||
|
|
@ -4057,10 +4047,8 @@ def test_x11_client_requests_driven():
|
|||
def test_x11_unmapped_window_destroyed_untracked():
|
||||
"""A window destroyed before ever mapping drops its pending surface
|
||||
without a tab, a member or a trace."""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
if not os.path.exists(XR):
|
||||
pytest.skip("needs build/xreqs (libX11 dev headers)")
|
||||
_require_xwayland()
|
||||
_require_file(XR, "needs build/xreqs (libX11 dev headers)")
|
||||
with _run_kick(
|
||||
["sh -c 'sleep 1; exec %s unmapped'" % XR,
|
||||
"%s --app-id keep '#0000ff' 320x240" % WL], wait="any") as s:
|
||||
|
|
@ -4073,8 +4061,7 @@ def test_x11_unmapped_window_destroyed_untracked():
|
|||
def test_x11_or_menu_move_repositions(tmp_path):
|
||||
"""An override-redirect menu that moves after mapping is repositioned
|
||||
through the compositor's geometry path without disturbing the session."""
|
||||
if not os.path.exists(XM):
|
||||
pytest.skip("needs build/xormenu (libX11 dev headers)")
|
||||
_require_file(XM, "needs build/xormenu (libX11 dev headers)")
|
||||
disp_file = tmp_path / "xdisplay"
|
||||
frame = menu = None
|
||||
with _run_standalone(
|
||||
|
|
@ -4215,8 +4202,7 @@ def test_x11_leader_window_never_becomes_tab():
|
|||
permanent black tab while the frame was demoted to a tab-group member,
|
||||
and Alt+Right onto the phantom main member crashed on a NULL surface
|
||||
(wlr_seat_keyboard_notify_enter assertion)."""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
_require_xwayland()
|
||||
if not os.access(XL, os.X_OK):
|
||||
pytest.skip("build first: build/xleader")
|
||||
# The short delay mirrors real toolkit init time: a raw-X client that
|
||||
|
|
@ -4270,8 +4256,7 @@ def test_x11_menu_popup_attaches_as_member():
|
|||
scene surface, so emacs menus "did nothing" silently. Real-emacs menu
|
||||
rendering on this path is additionally verified by hand (white dropdown
|
||||
pixels appear immediately after clicking the menu bar)."""
|
||||
if not HAVE_XWAYLAND:
|
||||
pytest.skip("needs Xwayland and xmessage on PATH")
|
||||
_require_xwayland()
|
||||
if not os.access(XP, os.X_OK):
|
||||
pytest.skip("build first: build/xpopup")
|
||||
with _run_kick(
|
||||
|
|
@ -4347,8 +4332,7 @@ def test_alt_shift_move_no_member_is_noop():
|
|||
"""Shift+Left/Right with the prefix held on a tab whose focused member
|
||||
is the main surface still gets consumed (never leaks Shift+arrow to
|
||||
the client) and never crashes, even though nothing moves."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '#ff0000'",
|
||||
extra_args=("--tab-groups", "on"), wait="any") as s:
|
||||
s.chord_ack(ALT | SHIFT, LEFT)
|
||||
|
|
@ -4371,8 +4355,7 @@ def test_layer_exclusive_reserves_tabs():
|
|||
"""A layer surface with exclusive_zone > 0 must shrink the usable area
|
||||
that maximized tabs are sized into (platform-verifies the two-pass
|
||||
layout fix)."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'") as s:
|
||||
s.wait_for(r"\[claim\] app=0")
|
||||
s.wait_for(r"\[diag\] commit app=0")
|
||||
|
|
@ -4413,8 +4396,7 @@ def test_layer_exclusive_reserves_tabs():
|
|||
def test_layer_zero_exclusive_does_not_resize():
|
||||
"""A layer surface with exclusive_zone == 0 must NOT shrink the usable
|
||||
area -- tabs keep their full output size."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'") as s:
|
||||
s.wait_for(r"\[claim\] app=0")
|
||||
s.wait_for(r"\[diag\] commit app=0")
|
||||
|
|
@ -4459,8 +4441,7 @@ def test_panel_menu_flush_under_bar():
|
|||
top bar -- not shifted down by the bar's reserved edge (the menu-offset
|
||||
regression). Deterministic: waits on kick's own log signals ([layer] map,
|
||||
then the panel client's [popup] out= line), no pixel diffing or sleeps."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
panel = shutil.which("wf-panel-pi")
|
||||
if not panel:
|
||||
pytest.skip("wf-panel-pi not installed")
|
||||
|
|
@ -5113,8 +5094,7 @@ def test_standalone_headless_or_menu_owner_closed(tmp_path):
|
|||
drop keyboard focus, not activate freed memory (heap-use-after-free,
|
||||
caught by ASan; on stock builds this guards the scenario stays alive
|
||||
and crash-indicator-free)."""
|
||||
if not os.path.exists(XM):
|
||||
pytest.skip("needs build/xormenu (libX11 dev headers)")
|
||||
_require_file(XM, "needs build/xormenu (libX11 dev headers)")
|
||||
disp_file = tmp_path / "xdisplay"
|
||||
frame = menu = None
|
||||
with _run_standalone(
|
||||
|
|
@ -5464,8 +5444,7 @@ def test_standalone_headless_x11_class_deleted(tmp_path):
|
|||
"""An X11 window whose WM_CLASS is deleted keeps the compositor alive:
|
||||
set_class with a NULL class must mirror "" (not raw NULL) onto the
|
||||
foreign-toplevel handles (raw NULL segfaulted in wlroots' strdup)."""
|
||||
if not os.path.exists(XC):
|
||||
pytest.skip("needs build/xclass (libX11 dev headers)")
|
||||
_require_file(XC, "needs build/xclass (libX11 dev headers)")
|
||||
disp_file = tmp_path / "xdisplay"
|
||||
probe_log = tmp_path / "xclass.log"
|
||||
probe = None
|
||||
|
|
@ -5565,8 +5544,7 @@ def test_alt_tab_hold_repeats():
|
|||
without reshuffling the stack mid-hold."""
|
||||
# Needs real wall-clock repeats like the Alt+Down hold test: private
|
||||
# session with repeat_off=False (the suite default stretches the delay).
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
_require_host_wayland()
|
||||
with _run_nested(f"{WL} '{RED}'", f"{WL} '{BLUE}'",
|
||||
repeat_off=False, wait="any") as session:
|
||||
session.wait_surface_mapped(1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue