Files
trex-core/tests/application/test_control_dispatch.py
T

88 lines
2.9 KiB
Python

"""Control channel action dispatch tests (REQ-043 / BAT-012)."""
from __future__ import annotations
import pytest
from trex_core.application.messaging import RpcRequest
from trex_core.application.messaging_handlers import make_control_rpc_handler
from trex_core.application.portfolio import InMemoryPauseStore
class _FakeKillSwitch:
def __init__(self):
self.fired = []
self.resumed = []
def fire(self, *, scope, portfolio_id=None, actor="operator"):
self.fired.append((scope, portfolio_id, actor))
return 3
def resume(self, *, scope, portfolio_id=None):
self.resumed.append((scope, portfolio_id))
def _req(**body):
return RpcRequest(payload=body, correlation_id="c1")
@pytest.fixture
def ks():
return _FakeKillSwitch()
@pytest.fixture
def handler(ks):
return make_control_rpc_handler(InMemoryPauseStore(), kill_switch_service=ks)
def test_pause_action_delegates(handler):
"""AC-1: pause delegates to REQ-032 pause handler."""
resp = handler(_req(action="pause", portfolio_id="pf-A"))
assert resp.payload["status"] == "ok"
assert "pf-A" in resp.payload["paused"]
def test_resume_and_list_actions(handler):
"""AC-2: resume/list delegate to pause handler."""
handler(_req(action="pause", portfolio_id="pf-A"))
assert handler(_req(action="resume", portfolio_id="pf-A")).payload["status"] == "ok"
assert handler(_req(action="list")).payload["status"] == "ok"
def test_kill_switch_routed(handler, ks):
"""AC-3: kill_switch routes to the kill-switch service."""
resp = handler(_req(action="kill_switch", scope="global"))
assert resp.payload["status"] == "ok"
assert resp.payload["liquidated"] == 3
assert ks.fired == [("global", None, "operator")]
def test_resume_kill_switch_routed(handler, ks):
"""AC-4: resume_kill_switch routes to the kill-switch service."""
resp = handler(_req(action="resume_kill_switch", scope="portfolio", portfolio_id="pf-A"))
assert resp.payload["status"] == "ok"
assert ks.resumed == [("portfolio", "pf-A")]
def test_unknown_action(handler):
"""AC-5: unknown action → error."""
resp = handler(_req(action="bogus"))
assert resp.payload["status"] == "error"
assert resp.payload["reason"] == "unknown_action:bogus"
def test_kill_switch_portfolio_requires_id(handler):
resp = handler(_req(action="kill_switch", scope="portfolio"))
assert resp.payload == {"status": "error", "reason": "portfolio_id_required"}
def test_kill_switch_bad_scope(handler):
resp = handler(_req(action="kill_switch", scope="weird"))
assert resp.payload["reason"] == "bad_scope:weird"
def test_kill_switch_unsupported_without_service():
handler = make_control_rpc_handler(InMemoryPauseStore()) # no service
resp = handler(_req(action="kill_switch", scope="global"))
assert resp.payload == {"status": "error", "reason": "kill_switch_unsupported"}