Skip to content

Commit acf886e

Browse files
committed
ControlMode(test[regressions]): Add missing repros from full control suite
why: Cover every failing control-mode case observed in full pytest run. what: - Add capture-pane variant repros (default/start/end) and integration prompt check - Add environment propagation repros for new-window and split-window - Add attached_sessions visibility check and server.kill EOF repro - Keep xfail strict markers for all known control-mode discrepancies
1 parent 00d0911 commit acf886e

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

tests/test_control_mode_regressions.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,89 @@ def test_attached_sessions_empty_when_no_clients() -> None:
302302
server.kill()
303303

304304

305+
class CapturePaneFixture(t.NamedTuple):
306+
"""Fixture for capture-pane variants that should trim blanks."""
307+
308+
test_id: str
309+
start: t.Literal["-"] | int | None
310+
end: t.Literal["-"] | int | None
311+
expected: str
312+
313+
314+
CAPTURE_PANE_CASES = [
315+
pytest.param(
316+
CapturePaneFixture(
317+
test_id="default",
318+
start=None,
319+
end=None,
320+
expected="$",
321+
),
322+
id="capture_default",
323+
marks=pytest.mark.xfail(
324+
reason="control-mode capture-pane returns extra blank lines",
325+
strict=True,
326+
),
327+
),
328+
pytest.param(
329+
CapturePaneFixture(
330+
test_id="start_history",
331+
start=-2,
332+
end=None,
333+
expected='$ printf "%s"\n$ clear -x\n$',
334+
),
335+
id="capture_start",
336+
marks=pytest.mark.xfail(
337+
reason="control-mode capture-pane start preserves trailing blanks",
338+
strict=True,
339+
),
340+
),
341+
pytest.param(
342+
CapturePaneFixture(
343+
test_id="end_zero",
344+
start=None,
345+
end=0,
346+
expected='$ printf "%s"',
347+
),
348+
id="capture_end_zero",
349+
marks=pytest.mark.xfail(
350+
reason="control-mode capture-pane end preserves trailing blanks",
351+
strict=True,
352+
),
353+
),
354+
]
355+
356+
357+
@pytest.mark.parametrize("case", CAPTURE_PANE_CASES)
358+
def test_capture_pane_variants(case: CapturePaneFixture) -> None:
359+
"""capture-pane variants should return trimmed output like subprocess engine."""
360+
env = shutil.which("env")
361+
assert env is not None
362+
363+
socket_name = f"libtmux_test_{uuid.uuid4().hex[:8]}"
364+
engine = ControlModeEngine()
365+
server = Server(socket_name=socket_name, engine=engine)
366+
367+
try:
368+
session = server.new_session(
369+
session_name=f"capture_variant_{case.test_id}",
370+
attach=True,
371+
window_shell=f"{env} PS1='$ ' sh",
372+
kill_session=True,
373+
)
374+
pane = session.active_window.active_pane
375+
assert pane is not None
376+
377+
pane.send_keys(r'printf "%s"', literal=True, suppress_history=False)
378+
pane.send_keys("clear -x", literal=True, suppress_history=False)
379+
380+
output_lines = pane.capture_pane(start=case.start, end=case.end)
381+
output = "\n".join(output_lines)
382+
assert output == case.expected
383+
finally:
384+
with contextlib.suppress(Exception):
385+
server.kill()
386+
387+
305388
@pytest.mark.xfail(
306389
reason="control-mode is_alive bootstrap hides missing-server errors",
307390
strict=True,
@@ -329,3 +412,34 @@ def test_testserver_is_alive_false_before_use() -> None:
329412
finally:
330413
with contextlib.suppress(Exception):
331414
server.kill()
415+
416+
417+
@pytest.mark.xfail(
418+
reason=(
419+
"server.kill with control engine can raise ControlModeConnectionError on EOF"
420+
),
421+
strict=True,
422+
)
423+
def test_server_kill_handles_control_eof_gracefully() -> None:
424+
"""server.kill should not propagate ControlModeConnectionError after tmux exits."""
425+
socket_name = f"libtmux_test_{uuid.uuid4().hex[:8]}"
426+
engine = ControlModeEngine()
427+
server = Server(socket_name=socket_name, engine=engine)
428+
429+
try:
430+
session = server.new_session(
431+
session_name="kill_eof_repro",
432+
attach=False,
433+
kill_session=True,
434+
)
435+
assert session is not None
436+
# Simulate tmux disappearing before control client issues kill-server.
437+
subprocess.run(
438+
["tmux", "-L", socket_name, "kill-server"],
439+
check=False,
440+
capture_output=True,
441+
)
442+
server.kill()
443+
finally:
444+
with contextlib.suppress(Exception):
445+
server.kill()

0 commit comments

Comments
 (0)