Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 62 additions & 32 deletions tests/test_send_reply.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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)
Loading