Skip to content

Commit a7aaa3e

Browse files
committed
feat(pytest): Add TempServer for temporary tmux server management
Add TempServer function to pytest_plugin.py that creates a temporary tmux server that cleans up after itself. This is similar to the server pytest fixture but can be used outside of pytest contexts. - Move and rename TempTmuxServer to TempServer in pytest_plugin.py - Add comprehensive tests for TempServer functionality: - Basic server creation and cleanup - Custom socket name support - Config file loading - Multiple server isolation - Proper cleanup verification - Use fin() for cleanup instead of __del__ - Remove old implementation from test.py This provides a more flexible way to create temporary tmux servers for testing and development purposes, while ensuring proper cleanup.
1 parent f2fb144 commit a7aaa3e

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

src/libtmux/pytest_plugin.py

+48
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
import contextlib
6+
import functools
67
import getpass
78
import logging
89
import os
@@ -256,3 +257,50 @@ def session(
256257
assert TEST_SESSION_NAME != "tmuxp"
257258

258259
return session
260+
261+
262+
@pytest.fixture
263+
def TempServer(
264+
request: pytest.FixtureRequest,
265+
) -> t.Callable[[], t.Callable[..., Server]]:
266+
"""Create a temporary tmux server that cleans up after itself.
267+
268+
This is similar to the server pytest fixture, but can be used outside of pytest.
269+
The server will be killed when the test completes.
270+
271+
Returns
272+
-------
273+
Callable[[], Callable[..., Server]]
274+
A factory function that returns a partial'd Server with a unique socket_name
275+
276+
Examples
277+
--------
278+
>>> Server = request.getfixturevalue('TempServer')() # Get unique partial
279+
>>> server = Server() # Create server instance
280+
>>> server.new_session()
281+
Session($... ...)
282+
>>> server.is_alive()
283+
True
284+
>>> # Each call to TempServer() gets a new unique partial
285+
>>> Server2 = request.getfixturevalue('TempServer')()
286+
>>> server2 = Server2()
287+
>>> server2.socket_name != server.socket_name
288+
True
289+
"""
290+
created_sockets: list[str] = []
291+
292+
def get_server() -> t.Callable[..., Server]:
293+
socket_name = f"libtmux_test{next(namer)}"
294+
created_sockets.append(socket_name)
295+
return functools.partial(Server, socket_name=socket_name)
296+
297+
def fin() -> None:
298+
"""Kill all servers created with these sockets."""
299+
for socket_name in created_sockets:
300+
server = Server(socket_name=socket_name)
301+
if server.is_alive():
302+
server.kill()
303+
304+
request.addfinalizer(fin)
305+
306+
return get_server

tests/test_pytest_plugin.py

+81
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
from __future__ import annotations
44

55
import textwrap
6+
import time
67
import typing as t
78

89
if t.TYPE_CHECKING:
10+
import pathlib
11+
912
import pytest
1013

1114

@@ -71,3 +74,81 @@ def test_repo_git_remote_checkout(
7174
# Test
7275
result = pytester.runpytest(str(first_test_filename))
7376
result.assert_outcomes(passed=1)
77+
78+
79+
def test_temp_server(TempServer: t.Any) -> None:
80+
"""Test TempServer creates and cleans up server."""
81+
Server = TempServer() # Get partial'd Server
82+
server = Server() # Create server instance
83+
assert server.is_alive() is False # Server not started yet
84+
85+
session = server.new_session()
86+
assert server.is_alive() is True
87+
assert len(server.sessions) == 1
88+
assert session.session_name is not None
89+
90+
# Test socket name is unique
91+
assert server.socket_name is not None
92+
assert server.socket_name.startswith("libtmux_test")
93+
94+
95+
def test_temp_server_with_config(TempServer: t.Any, tmp_path: pathlib.Path) -> None:
96+
"""Test TempServer with custom config."""
97+
config_file = tmp_path / "tmux.conf"
98+
config_file.write_text("set -g status off", encoding="utf-8")
99+
100+
Server = TempServer() # Get partial'd Server
101+
server = Server(config_file=str(config_file)) # Create server with config
102+
session = server.new_session()
103+
104+
# Verify config was loaded by checking status
105+
assert session.cmd("show-options", "-g", "status").stdout[0] == "status off"
106+
107+
108+
def test_temp_server_cleanup(TempServer: t.Any) -> None:
109+
"""Test TempServer properly cleans up after itself."""
110+
Server = TempServer() # Get partial'd Server
111+
server = Server() # Create server instance
112+
socket_name = server.socket_name
113+
assert socket_name is not None
114+
115+
# Create multiple sessions
116+
server.new_session(session_name="test1")
117+
server.new_session(session_name="test2")
118+
assert len(server.sessions) == 2
119+
120+
# Verify server is alive
121+
assert server.is_alive() is True
122+
123+
# Delete server and verify cleanup
124+
server.kill()
125+
time.sleep(0.1) # Give time for cleanup
126+
127+
# Create new server to verify old one was cleaned up
128+
Server2 = TempServer() # Get new partial'd Server
129+
new_server = Server2() # Create new server instance
130+
assert new_server.is_alive() is False # Server not started yet
131+
new_server.new_session() # This should work if old server was cleaned up
132+
assert new_server.is_alive() is True
133+
134+
135+
def test_temp_server_multiple(TempServer: t.Any) -> None:
136+
"""Test multiple TempServer instances can coexist."""
137+
Server1 = TempServer() # Get first partial'd Server
138+
Server2 = TempServer() # Get second partial'd Server
139+
140+
server1 = Server1() # Create first server instance
141+
server2 = Server2() # Create second server instance
142+
143+
# Each server should have a unique socket
144+
assert server1.socket_name != server2.socket_name
145+
146+
# Create sessions in each server
147+
server1.new_session(session_name="test1")
148+
server2.new_session(session_name="test2")
149+
150+
# Verify sessions are in correct servers
151+
assert any(s.session_name == "test1" for s in server1.sessions)
152+
assert any(s.session_name == "test2" for s in server2.sessions)
153+
assert not any(s.session_name == "test1" for s in server2.sessions)
154+
assert not any(s.session_name == "test2" for s in server1.sessions)

0 commit comments

Comments
 (0)