Fix resize and poller races; add coverage

- Fix resize message handling when session already exists
- Guard poller selector.modify against removed fds
- Handle send_bytes race when master_fd closes
- Add tests for resize edge case, poller write KeyError, send_bytes race
This commit is contained in:
GitHub Copilot
2026-01-26 20:07:40 +00:00
parent 245849ba9f
commit 63e8cba0ac
6 changed files with 56 additions and 6 deletions
+13
View File
@@ -679,6 +679,19 @@ class TestLocalServerMoreCoverage:
session.send_bytes.assert_awaited_once_with(b"")
@pytest.mark.asyncio
@pytest.mark.asyncio
async def test_dispatch_ws_message_resize_existing_session_flag_false(self, server_with_no_apps, monkeypatch):
session = MagicMock()
session.set_terminal_size = AsyncMock()
monkeypatch.setattr(server_with_no_apps.session_manager, "get_session_by_route_key", lambda _rk: session)
ws = MagicMock()
created = await server_with_no_apps._dispatch_ws_message(
["resize", {"width": 100, "height": 50}], "rk", ws, False
)
assert created is False
session.set_terminal_size.assert_awaited_once_with(100, 50)
async def test_dispatch_ws_message_resize_updates_existing_session(self, server_with_no_apps, monkeypatch):
session = MagicMock()
session.set_terminal_size = AsyncMock()
+11
View File
@@ -71,6 +71,17 @@ class TestPoller:
# Should not raise
poller.remove_file(999)
@pytest.mark.asyncio
async def test_write_handles_removed_fd(self):
poller = Poller()
poller._loop = asyncio.get_event_loop()
with patch.object(poller._selector, "register"):
poller.add_file(42)
with patch.object(poller._selector, "modify", side_effect=KeyError()):
await poller.write(42, b"test")
@pytest.mark.asyncio
async def test_write_creates_queue(self):
"""Test that write creates a write queue if needed."""
+12
View File
@@ -288,6 +288,18 @@ class TestTerminalSession:
mock_exit.assert_called_once_with(1)
@pytest.mark.asyncio
async def test_send_bytes_handles_closed_fd(self):
from textual_webterm.terminal_session import TerminalSession
poller = MagicMock()
poller.write = AsyncMock(side_effect=KeyError)
session = TerminalSession(poller, "sid", "bash")
session.master_fd = 10
ok = await session.send_bytes(b"test")
assert ok is False
@pytest.mark.asyncio
async def test_run_reads_from_poller_and_closes(self):
from textual_webterm.terminal_session import TerminalSession