From bd222105aecda14d7772c39e1ea673c63e02a3bd Mon Sep 17 00:00:00 2001 From: Jean-Pierre Martineau Date: Fri, 25 Sep 2026 04:16:26 -0400 Subject: [PATCH] Two tests stop racing CI: the chat waits for its send, the BlueZ fixture leaves os alone The BlueZ fixture patched os.getpid to return a string, and bluez.os is the global os module, so Python 3.14's event loop (which opens a pidfd for its own pid at startup) failed before any test ran. The agent path is now derived from the real pid instead. The end-to-end chat test piped Esc beside Enter, so a slow runner left the screen and cancelled the spawned send before the row was written. It now sends Esc only once the message is recorded. Co-Authored-By: Claude Opus 5.5 (1M context) --- tests/test_bluez.py | 6 +++--- tests/test_chat.py | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/test_bluez.py b/tests/test_bluez.py index a40afdb..3435a57 100644 --- a/tests/test_bluez.py +++ b/tests/test_bluez.py @@ -11,6 +11,7 @@ against a scripted stand-in for the system bus: no BlueZ, no radio, and no real from __future__ import annotations import asyncio +import os import pytest @@ -161,19 +162,18 @@ class _FakeBus: self.disconnected = True -_AGENT = "/net/meshterm/agent" +_AGENT = f"/net/meshterm/agent{os.getpid()}" @pytest.fixture def bus(monkeypatch): - """Point :mod:`bluez` at a fresh fake bus, with the agent at a fixed path.""" + """Point :mod:`bluez` at a fresh fake bus.""" holder: dict = {} async def _system_bus(): return holder["bus"] monkeypatch.setattr(bluez, "_system_bus", _system_bus) - monkeypatch.setattr(bluez.os, "getpid", lambda: "") def _make(**kwargs) -> _FakeBus: holder["bus"] = _FakeBus(**kwargs) diff --git a/tests/test_chat.py b/tests/test_chat.py index 284f9cb..3e9c86a 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -1693,9 +1693,25 @@ async def test_open_chat_sends_through_real_session(tmp_path: Path) -> None: session = TuiSession(input=inp, output=DummyOutput()) ctx.ui = TuiUi(session) + def stored_texts() -> list[str]: + rows = ctx.repo.recent_chat_messages(is_channel=False, peer="d4e5f6a7") + return [m.text for m in rows] + + async def drive() -> None: + # Esc only once the send has been recorded: the send runs in a task the + # screen spawns, and piping Esc beside Enter let a slow runner leave (and + # cancel it) before the row was written. + inp.send_text("hi\r") # type "hi", Enter (send) + while not stored_texts(): + await asyncio.sleep(0.01) + inp.send_text("\x1b") # Esc (leave) + async def main() -> None: - inp.send_text("hi\r\x1b") # type "hi", Enter (send), Esc (leave) - await open_chat(ctx, conv) + driver = asyncio.ensure_future(drive()) + try: + await open_chat(ctx, conv) + finally: + driver.cancel() await asyncio.wait_for(session.run(main()), timeout=5)