import asyncio import pytest from app.rounds.events import RoundEventBroadcaster, RoundEventCapacityError async def test_publish_wakes_up_subscriber(): broadcaster = RoundEventBroadcaster() queue = broadcaster.subscribe() broadcaster.publish() await asyncio.wait_for(queue.get(), timeout=1) async def test_publish_with_no_subscribers_does_not_raise(): broadcaster = RoundEventBroadcaster() broadcaster.publish() # no subscribers yet — must be a no-op, not an error async def test_publish_coalesces_when_subscriber_has_not_drained(): """The queue is maxsize=1: a second publish() before the subscriber reads the first notification must not block or raise — it's fine to drop it, since the subscriber will refetch full state anyway on the first one.""" broadcaster = RoundEventBroadcaster() queue = broadcaster.subscribe() broadcaster.publish() broadcaster.publish() # would raise QueueFull if not guarded assert queue.qsize() == 1 async def test_unsubscribe_stops_delivery(): broadcaster = RoundEventBroadcaster() queue = broadcaster.subscribe() broadcaster.unsubscribe(queue) broadcaster.publish() assert queue.empty() async def test_subscribe_rejects_past_the_cap(): broadcaster = RoundEventBroadcaster(max_subscribers=3) for _ in range(3): broadcaster.subscribe() with pytest.raises(RoundEventCapacityError): broadcaster.subscribe() async def test_unsubscribe_frees_a_capacity_slot(): broadcaster = RoundEventBroadcaster(max_subscribers=1) queue = broadcaster.subscribe() with pytest.raises(RoundEventCapacityError): broadcaster.subscribe() broadcaster.unsubscribe(queue) broadcaster.subscribe() # no longer at capacity