merge: testing → main (reconcile 2-week divergence)
This commit is contained in:
64
tests/bus/test_publish.py
Normal file
64
tests/bus/test_publish.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""Tests for :mod:`decnet.bus.publish`.
|
||||
|
||||
The whole point of ``publish_safely`` is that it never raises back at the
|
||||
caller. These tests pin that contract: ``None`` bus is a no-op, a real
|
||||
bus publishes, and a raising bus is swallowed + logged.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from decnet.bus.base import BaseBus, Event, Subscription
|
||||
from decnet.bus.fake import FakeBus
|
||||
from decnet.bus.publish import publish_safely
|
||||
|
||||
|
||||
class _ExplodingBus(BaseBus):
|
||||
"""Minimal bus whose ``publish`` always raises."""
|
||||
|
||||
async def connect(self) -> None: # pragma: no cover - trivial
|
||||
return None
|
||||
|
||||
async def publish(self, topic, payload, *, event_type=""):
|
||||
raise RuntimeError("transport exploded")
|
||||
|
||||
def subscribe(self, pattern: str) -> Subscription: # pragma: no cover
|
||||
raise NotImplementedError
|
||||
|
||||
async def close(self) -> None: # pragma: no cover - trivial
|
||||
return None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_publish_safely_none_bus_is_noop() -> None:
|
||||
# Must not raise. A worker that couldn't connect at startup passes
|
||||
# bus=None and expects every call to silently no-op.
|
||||
await publish_safely(None, "system.log", {"msg": "hi"})
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_publish_safely_delivers_on_live_bus() -> None:
|
||||
bus = FakeBus()
|
||||
await bus.connect()
|
||||
try:
|
||||
sub = bus.subscribe("system.log")
|
||||
async with sub:
|
||||
await publish_safely(bus, "system.log", {"msg": "hi"}, event_type="log")
|
||||
event = await sub.__anext__()
|
||||
assert isinstance(event, Event)
|
||||
assert event.topic == "system.log"
|
||||
assert event.type == "log"
|
||||
assert event.payload == {"msg": "hi"}
|
||||
finally:
|
||||
await bus.close()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_publish_safely_swallows_transport_errors(caplog: pytest.LogCaptureFixture) -> None:
|
||||
caplog.set_level(logging.WARNING, logger="bus.publish")
|
||||
# The exploding bus would crash the caller without publish_safely.
|
||||
# After wrapping, the caller sees nothing but a log line.
|
||||
await publish_safely(_ExplodingBus(), "system.log", {"msg": "hi"})
|
||||
assert any("bus publish failed" in rec.message for rec in caplog.records)
|
||||
Reference in New Issue
Block a user