Files
vllm-omni/tests/engine/test_rpc_result_router.py
05b794f29b [Full Duplex] Feat: Support Full-Duplex realtime runtime & add MiniCPM-o 4.5 demo (#3907)
Signed-off-by: Sy03 <1370724210@qq.com>
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: StormMelody <22371184@zju.edu.cn>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-23 16:45:18 +08:00

110 lines
3.4 KiB
Python

import queue
from typing import Literal
import pytest
from vllm_omni.engine.messages import (
CollectiveRPCResultMessage,
EngineQueueMessage,
ErrorMessage,
)
from vllm_omni.engine.rpc_result_router import RpcResultRouter
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
class GenericCorrelatedResultMessage(EngineQueueMessage, kw_only=True):
type: Literal["generic_correlated_result"] = "generic_correlated_result"
namespace: str
correlation_id: str
@property
def rpc_correlation_key(self) -> tuple[str, str]:
return (self.namespace, self.correlation_id)
def _generic_result(correlation_id: str) -> GenericCorrelatedResultMessage:
return GenericCorrelatedResultMessage(
namespace="plugin",
correlation_id=correlation_id,
)
def test_rpc_result_router_routes_out_of_order_results_by_correlation_id():
source: queue.Queue = queue.Queue()
router = RpcResultRouter(source)
first = router.register(("plugin", "first"))
second = router.register(("plugin", "second"))
source.put(_generic_result("second"))
source.put(_generic_result("first"))
assert first.get(timeout=1).correlation_id == "first"
assert second.get(timeout=1).correlation_id == "second"
router.close()
def test_rpc_result_router_drops_only_the_late_result_after_unregister():
source: queue.Queue = queue.Queue()
router = RpcResultRouter(source)
expired = router.register(("plugin", "expired"))
active = router.register(("collective", "active"))
router.unregister(("plugin", "expired"), expired)
source.put(_generic_result("expired"))
source.put(
CollectiveRPCResultMessage(
rpc_id="active",
method="health",
stage_ids=[0],
results=["ok"],
)
)
assert active.get(timeout=1).rpc_id == "active"
assert expired.empty()
router.close()
def test_rpc_result_router_broadcasts_fatal_errors_to_pending_waiters():
source: queue.Queue = queue.Queue()
router = RpcResultRouter(source)
plugin = router.register(("plugin", "one"))
collective = router.register(("collective", "two"))
source.put(ErrorMessage(error="orchestrator failed", fatal=True))
assert plugin.get(timeout=1).error == "orchestrator failed"
assert collective.get(timeout=1).error == "orchestrator failed"
with pytest.raises(RuntimeError, match="orchestrator failed"):
router.register(("plugin", "after-failure"))
router.close()
def test_rpc_result_router_does_not_broadcast_uncorrelated_nonfatal_errors():
source: queue.Queue = queue.Queue()
router = RpcResultRouter(source)
waiter = router.register(("plugin", "active"))
source.put(ErrorMessage(error="request failed", fatal=False, request_id="other"))
source.put(_generic_result("active"))
assert waiter.get(timeout=1).correlation_id == "active"
router.close()
def test_rpc_result_router_close_unblocks_waiters_and_stops_consumer():
source: queue.Queue = queue.Queue()
router = RpcResultRouter(source)
waiter = router.register(("plugin", "pending"))
router.close()
result = waiter.get(timeout=1)
assert isinstance(result, ErrorMessage)
assert result.fatal is True
assert result.error == "RPC result router closed"
assert not router._thread.is_alive()
with pytest.raises(RuntimeError, match="router is closed"):
router.register(("plugin", "after-close"))