Port multi-task unit tests from pipecat-subagents
Brings over 215 tests across 15 files covering the new multi-task framework: BaseTask / PipelineTask bus lifecycle, job RPC and job groups, the bus message hierarchy and serializers, TaskBus + AsyncQueueBus + RedisBus + PgmqBus (with direct and isolated backends), TaskRegistry, the BusBridgeProcessor, the WebSocket proxy tasks, the LLMTask deferral logic, and the PipelineRunner spawn-and-attach flow.
This commit is contained in:
97
tests/test_messages.py
Normal file
97
tests/test_messages.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#
|
||||
# Copyright (c) 2026, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
import asyncio
|
||||
import unittest
|
||||
|
||||
from pipecat.bus import (
|
||||
AsyncQueueBus,
|
||||
BusDataMessage,
|
||||
BusFrameMessage,
|
||||
BusSubscriber,
|
||||
)
|
||||
from pipecat.frames.frames import TextFrame
|
||||
from pipecat.processors.frame_processor import FrameDirection
|
||||
from pipecat.utils.asyncio.task_manager import TaskManager, TaskManagerParams
|
||||
|
||||
|
||||
class TestBusMessageRouting(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_broadcast_message_no_target(self):
|
||||
"""A BusMessage with no target is broadcast (target is None)."""
|
||||
msg = BusDataMessage(source="task_a")
|
||||
self.assertIsNone(msg.target)
|
||||
|
||||
async def test_targeted_message(self):
|
||||
"""A BusMessage with target set is only for that task."""
|
||||
msg = BusDataMessage(source="task_a", target="task_b")
|
||||
self.assertEqual(msg.target, "task_b")
|
||||
|
||||
async def test_broadcast_reaches_all_subscribers(self):
|
||||
"""Broadcast messages (no target) reach all subscribers."""
|
||||
bus = AsyncQueueBus()
|
||||
tm = TaskManager()
|
||||
tm.setup(TaskManagerParams(loop=asyncio.get_running_loop()))
|
||||
await bus.setup(tm)
|
||||
received_a = []
|
||||
received_b = []
|
||||
|
||||
class SubA(BusSubscriber):
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "sub_a"
|
||||
|
||||
async def on_bus_message(self, message):
|
||||
received_a.append(message)
|
||||
|
||||
class SubB(BusSubscriber):
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "sub_b"
|
||||
|
||||
async def on_bus_message(self, message):
|
||||
received_b.append(message)
|
||||
|
||||
await bus.subscribe(SubA())
|
||||
await bus.subscribe(SubB())
|
||||
|
||||
await bus.start()
|
||||
msg = BusDataMessage(source="task_x") # no target
|
||||
await bus.send(msg)
|
||||
await asyncio.sleep(0.05)
|
||||
await bus.stop()
|
||||
|
||||
# Both subscribers see the broadcast
|
||||
self.assertEqual(len(received_a), 1)
|
||||
self.assertEqual(len(received_b), 1)
|
||||
|
||||
async def test_bus_frame_message_wraps_frame(self):
|
||||
"""BusFrameMessage wraps a frame with source and direction."""
|
||||
frame = TextFrame(text="hello")
|
||||
msg = BusFrameMessage(
|
||||
source="task_a",
|
||||
frame=frame,
|
||||
direction=FrameDirection.DOWNSTREAM,
|
||||
)
|
||||
self.assertIs(msg.frame, frame)
|
||||
self.assertEqual(msg.direction, FrameDirection.DOWNSTREAM)
|
||||
self.assertEqual(msg.source, "task_a")
|
||||
self.assertIsNone(msg.target)
|
||||
|
||||
async def test_bus_frame_message_with_target(self):
|
||||
"""BusFrameMessage can carry a target for directed delivery."""
|
||||
frame = TextFrame(text="hello")
|
||||
msg = BusFrameMessage(
|
||||
source="task_a",
|
||||
target="task_b",
|
||||
frame=frame,
|
||||
direction=FrameDirection.DOWNSTREAM,
|
||||
)
|
||||
self.assertEqual(msg.target, "task_b")
|
||||
self.assertIs(msg.frame, frame)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user