"""Unit: the orchestrator dev-harness entrypoint (`python -m bot_bottle.orchestrator`). Exercises broker selection (stub / docker / http) and the fail-closed http path, patching `make_server` so the serve loop returns instead of blocking. """ from __future__ import annotations import os import secrets import tempfile import unittest from pathlib import Path from unittest.mock import MagicMock, patch from bot_bottle.orchestrator.__main__ import main def _fake_server() -> MagicMock: fake = MagicMock() fake.server_address = ("127.0.0.1", 0) # Break out of serve_forever immediately, exercising the try/finally. fake.serve_forever.side_effect = KeyboardInterrupt return fake class TestMain(unittest.TestCase): def _run(self, broker: str, env: dict[str, str] | None = None) -> tuple[int, MagicMock]: fake = _fake_server() with tempfile.TemporaryDirectory() as d: argv = ["--db", str(Path(d) / "r.db"), "--port", "0", "--broker", broker] with patch("bot_bottle.orchestrator.__main__.make_server", return_value=fake), \ patch.dict("os.environ", env or {}, clear=False): if env is None: os.environ.pop("BOT_BOTTLE_BROKER_SECRET", None) rc = main(argv) return rc, fake def test_stub_broker_serves_and_closes(self) -> None: rc, fake = self._run("stub") self.assertEqual(0, rc) fake.serve_forever.assert_called_once() fake.server_close.assert_called_once() def test_docker_broker_serves(self) -> None: rc, _ = self._run("docker") self.assertEqual(0, rc) def test_http_broker_with_secret_serves(self) -> None: rc, _ = self._run( "http", env={"BOT_BOTTLE_BROKER_SECRET": secrets.token_bytes(16).hex()}) self.assertEqual(0, rc) def test_http_broker_without_secret_exits(self) -> None: # Fail-closed: --broker http with no shared secret is a usage error. with tempfile.TemporaryDirectory() as d: with patch.dict("os.environ", {}, clear=False): os.environ.pop("BOT_BOTTLE_BROKER_SECRET", None) with self.assertRaises(SystemExit): main(["--db", str(Path(d) / "r.db"), "--broker", "http"]) if __name__ == "__main__": unittest.main()