diff --git a/tests/test_send_reply.py b/tests/test_send_reply.py index d794dd45..408ca996 100644 --- a/tests/test_send_reply.py +++ b/tests/test_send_reply.py @@ -22,9 +22,10 @@ def mock_address() -> Generator[None, None, None]: os.environ["DBUS_SESSION_BUS_ADDRESS"] = original_address -def test_send_reply_exception() -> None: - """Test that SendReply sends an error message when DBusError is raised.""" - +@pytest.fixture +def send_reply_setup() -> Generator[ + tuple[BaseMessageBus, Message, list[Message]], None, None +]: messages: list[Message] = [] class MockClosable: @@ -43,11 +44,23 @@ def _setup_socket(self) -> None: self._stream = MockClosable() # type: ignore with patch("socket.socket.connect"): - mock_message_bus = MockBus() - mock_message = Message( + bus = MockBus() + msg = Message( path="/test/path", interface="test.interface", member="test_member", serial=1 ) - send_reply = SendReply(mock_message_bus, mock_message) + try: + yield bus, msg, messages + finally: + bus.disconnect() + bus._finalize(None) + + +def test_send_reply_exception( + send_reply_setup: tuple[BaseMessageBus, Message, list[Message]], +) -> None: + """Test that SendReply sends an error message when DBusError is raised.""" + bus, msg, messages = send_reply_setup + send_reply = SendReply(bus, msg) with send_reply: raise DBusError(ErrorType.DISCONNECTED, "Disconnected", None) @@ -57,43 +70,60 @@ def _setup_socket(self) -> None: assert messages[0].error_name == "org.freedesktop.DBus.Error.Disconnected" assert messages[0].reply_serial == 1 - mock_message_bus.disconnect() - mock_message_bus._finalize(None) +def test_send_reply_generic_exception( + send_reply_setup: tuple[BaseMessageBus, Message, list[Message]], +) -> None: + """Non-DBusError exceptions become SERVICE_ERROR replies.""" + bus, msg, messages = send_reply_setup + send_reply = SendReply(bus, msg) -def test_send_reply_happy_path() -> None: - """Test that SendReply sends a message.""" + with send_reply: + raise RuntimeError("boom") - messages: list[Message] = [] + assert len(messages) == 1 + assert messages[0].message_type == MessageType.ERROR + assert messages[0].error_name == ErrorType.SERVICE_ERROR.value + assert messages[0].reply_serial == 1 + assert "boom" in messages[0].body[0] - class MockClosable: - def close(self) -> None: - pass - class MockBus(BaseMessageBus): - def send(self, msg: Message) -> None: - messages.append(msg) +def test_send_reply_send_error( + send_reply_setup: tuple[BaseMessageBus, Message, list[Message]], +) -> None: + """send_error() routes an exception through the same error reply path.""" + bus, msg, messages = send_reply_setup + send_reply = SendReply(bus, msg) - def send_message(self, msg: Message) -> None: - messages.append(msg) + send_reply.send_error(DBusError(ErrorType.FAILED, "explicit failure", None)) - def _setup_socket(self) -> None: - self._sock = MockClosable() # type: ignore - self._stream = MockClosable() # type: ignore + assert len(messages) == 1 + assert messages[0].message_type == MessageType.ERROR + assert messages[0].error_name == "org.freedesktop.DBus.Error.Failed" + assert messages[0].reply_serial == 1 - with patch("socket.socket.connect"): - mock_message_bus = MockBus() - mock_message = Message( - path="/test/path", interface="test.interface", member="test_member", serial=1 - ) - send_reply = SendReply(mock_message_bus, mock_message) + +def test_send_reply_no_exception_returns_false( + send_reply_setup: tuple[BaseMessageBus, Message, list[Message]], +) -> None: + """Exiting with no exception must not suppress and must not send a reply.""" + bus, msg, messages = send_reply_setup + send_reply = SendReply(bus, msg) + + assert send_reply._exit(None, None, None) is False + assert messages == [] + + +def test_send_reply_happy_path( + send_reply_setup: tuple[BaseMessageBus, Message, list[Message]], +) -> None: + """Test that SendReply sends a message.""" + bus, msg, messages = send_reply_setup + send_reply = SendReply(bus, msg) with send_reply as reply: - reply(mock_message) + reply(msg) assert len(messages) == 1 assert messages[0].message_type == MessageType.METHOD_CALL assert messages[0].error_name is None - - mock_message_bus.disconnect() - mock_message_bus._finalize(None)