Skip to content

Commit c3ec17b

Browse files
committed
ControlMode(test[logging]): Add raw control client logging fixtures and diagnostics
why: Provide a real control-mode logging harness for debugging control stream issues. what: - Add control_client_logs fixture that spawns tmux -C with per-test stdout/stderr logs - Add diagnostic tests parsing control stream with ControlProtocol - Add control_sandbox contextmanager fixture and smoke test for isolated control server
1 parent 6832719 commit c3ec17b

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

conftest.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import contextlib
1414
import pathlib
1515
import shutil
16+
import subprocess
1617
import typing as t
1718
import uuid
1819

@@ -118,6 +119,47 @@ def control_sandbox(
118119
server.kill()
119120

120121

122+
@pytest.fixture
123+
def control_client_logs(
124+
control_sandbox: t.ContextManager[Server],
125+
tmp_path_factory: pytest.TempPathFactory,
126+
) -> t.Iterator[tuple[subprocess.Popen[str], pathlib.Path, pathlib.Path]]:
127+
"""Spawn a raw tmux -C client against the sandbox and log stdout/stderr."""
128+
base = tmp_path_factory.mktemp("ctrl_logs")
129+
stdout_path = base / "control_stdout.log"
130+
stderr_path = base / "control_stderr.log"
131+
132+
with control_sandbox as server:
133+
cmd = [
134+
"tmux",
135+
"-L",
136+
server.socket_name or "",
137+
"-C",
138+
"attach-session",
139+
"-t",
140+
"ctrltest",
141+
]
142+
# Ensure ctrltest exists
143+
server.cmd("new-session", "-d", "-s", "ctrltest")
144+
proc = subprocess.Popen(
145+
cmd,
146+
stdin=subprocess.PIPE,
147+
stdout=stdout_path.open("w+", buffering=1),
148+
stderr=stderr_path.open("w+", buffering=1),
149+
text=True,
150+
bufsize=1,
151+
)
152+
try:
153+
yield proc, stdout_path, stderr_path
154+
finally:
155+
with contextlib.suppress(Exception):
156+
if proc.stdin:
157+
proc.stdin.write("kill-session -t ctrltest\n")
158+
proc.stdin.flush()
159+
proc.terminate()
160+
proc.wait(timeout=2)
161+
162+
121163
def pytest_addoption(parser: pytest.Parser) -> None:
122164
"""Add CLI options for selecting tmux engine."""
123165
parser.addoption(

tests/test_control_client_logs.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""Diagnostic tests using raw control client logs."""
2+
3+
from __future__ import annotations
4+
5+
import typing as t
6+
7+
import pytest
8+
9+
from libtmux._internal.engines.control_protocol import CommandContext, ControlProtocol
10+
11+
12+
@pytest.mark.engines(["control"])
13+
def test_control_client_lists_clients(
14+
control_client_logs: tuple[t.Any, t.Any, t.Any],
15+
) -> None:
16+
"""Raw control client should report itself with control-mode flag."""
17+
proc, stdout_path, _stderr_path = control_client_logs
18+
19+
assert proc.stdin is not None
20+
proc.stdin.write('list-clients -F"#{client_pid} #{client_flags} #{session_name}"\n')
21+
proc.stdin.flush()
22+
23+
# Read what the control client wrote
24+
lines = stdout_path.read_text().splitlines()
25+
assert any(len(line.split()) >= 2 and "C" in line.split()[1] for line in lines)
26+
27+
28+
@pytest.mark.engines(["control"])
29+
def test_control_client_capture_stream_parses(
30+
control_client_logs: tuple[t.Any, t.Any, t.Any],
31+
) -> None:
32+
"""Ensure ControlProtocol can parse raw stream from the logged control client."""
33+
proc, stdout_path, _stderr_path = control_client_logs
34+
assert proc.stdin is not None
35+
36+
proc.stdin.write("display-message -p hello\n")
37+
proc.stdin.flush()
38+
39+
lines = stdout_path.read_text().splitlines()
40+
41+
proto = ControlProtocol()
42+
ctx = CommandContext(argv=["tmux", "display-message", "-p", "hello"])
43+
proto.register_command(ctx)
44+
45+
# Feed lines; expect begin/payload/end
46+
for line in lines:
47+
proto.feed_line(line)
48+
49+
# If tmux emitted begin/end, ctx should be done
50+
if ctx.done.is_set():
51+
result = proto.build_result(ctx)
52+
assert "hello" in result.stdout

0 commit comments

Comments
 (0)