"""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"}