test: add unit tests to pass diff-coverage gate (91%)
test / unit (pull_request) Successful in 57s
test / integration (pull_request) Successful in 16s
test / coverage (pull_request) Successful in 1m4s
lint / lint (push) Successful in 1m56s
prd-number / assign-numbers (push) Successful in 19s
test / unit (push) Successful in 1m0s
test / integration (push) Successful in 19s
test / coverage (push) Successful in 1m5s
Update Quality Badges / update-badges (push) Failing after 59s
test / unit (pull_request) Successful in 57s
test / integration (pull_request) Successful in 16s
test / coverage (pull_request) Successful in 1m4s
lint / lint (push) Successful in 1m56s
prd-number / assign-numbers (push) Successful in 19s
test / unit (push) Successful in 1m0s
test / integration (push) Successful in 19s
test / coverage (push) Successful in 1m5s
Update Quality Badges / update-badges (push) Failing after 59s
Cover the new production lines added on this branch: - cli/__init__: MissingEnvVarError maps to return 1 - cli/start: no-agents-defined path, prepare_with_preflight calls render_preflight, _text_render_preflight backend name output - env: resolve_env raises MissingEnvVarError for missing interpolated var - smolmachines/launch: _proxy_host Linux/non-Linux branches, _discover_urls git-gate host and supervise URL stamping Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit was merged in pull request #284.
This commit is contained in:
@@ -64,6 +64,15 @@ class TestMainDispatch(unittest.TestCase):
|
|||||||
main(["x", "a", "b"])
|
main(["x", "a", "b"])
|
||||||
self.assertEqual([["a", "b"]], seen)
|
self.assertEqual([["a", "b"]], seen)
|
||||||
|
|
||||||
|
def test_missing_env_var_error_maps_to_1(self) -> None:
|
||||||
|
from bot_bottle.errors import MissingEnvVarError
|
||||||
|
|
||||||
|
def boom(_rest: list[str]) -> int:
|
||||||
|
raise MissingEnvVarError("MY_VAR", "MY_VAR is not set")
|
||||||
|
|
||||||
|
with patch.dict(climod.COMMANDS, {"x": boom}), patch("sys.stderr", io.StringIO()):
|
||||||
|
self.assertEqual(1, main(["x"]))
|
||||||
|
|
||||||
def test_manifest_error_maps_to_1(self) -> None:
|
def test_manifest_error_maps_to_1(self) -> None:
|
||||||
def boom(_rest: list[str]) -> int:
|
def boom(_rest: list[str]) -> int:
|
||||||
raise ManifestError("bad manifest")
|
raise ManifestError("bad manifest")
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ is created.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
@@ -184,5 +185,55 @@ class TestCmdStartHeadless(unittest.TestCase):
|
|||||||
self.assertEqual("docker", self._launch_mock.call_args[1]["backend_name"])
|
self.assertEqual("docker", self._launch_mock.call_args[1]["backend_name"])
|
||||||
|
|
||||||
|
|
||||||
|
class TestPrepareWithPreflight(unittest.TestCase):
|
||||||
|
"""prepare_with_preflight calls render_preflight with the plan and backend name."""
|
||||||
|
|
||||||
|
def test_render_preflight_called(self):
|
||||||
|
from pathlib import Path
|
||||||
|
mock_backend = MagicMock()
|
||||||
|
mock_plan = MagicMock()
|
||||||
|
mock_backend.prepare.return_value = mock_plan
|
||||||
|
mock_backend.name = "test-backend"
|
||||||
|
render = MagicMock()
|
||||||
|
|
||||||
|
with patch("bot_bottle.cli.start.get_bottle_backend", return_value=mock_backend), \
|
||||||
|
patch("bot_bottle.cli.start._identity_from_plan", return_value="id"), \
|
||||||
|
patch("bot_bottle.cli.start.info"):
|
||||||
|
start_mod.prepare_with_preflight(
|
||||||
|
MagicMock(),
|
||||||
|
stage_dir=Path("/tmp"),
|
||||||
|
render_preflight=render,
|
||||||
|
prompt_yes=MagicMock(),
|
||||||
|
dry_run=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
render.assert_called_once_with(mock_plan, "test-backend")
|
||||||
|
|
||||||
|
|
||||||
|
class TestNoAgentsDefined(unittest.TestCase):
|
||||||
|
"""cmd_start prints an error and returns 1 when the manifest has no agents."""
|
||||||
|
|
||||||
|
def test_no_agents_defined_returns_1(self):
|
||||||
|
manifest = _make_manifest([], [])
|
||||||
|
with patch(
|
||||||
|
"bot_bottle.cli.start.ManifestIndex.resolve", return_value=manifest
|
||||||
|
), patch("sys.stderr", io.StringIO()) as err:
|
||||||
|
rc = start_mod.cmd_start([])
|
||||||
|
self.assertEqual(1, rc)
|
||||||
|
self.assertIn("no agents defined", err.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
class TestTextRenderPreflight(unittest.TestCase):
|
||||||
|
"""_text_render_preflight returns a renderer that prints the backend name."""
|
||||||
|
|
||||||
|
def test_backend_name_in_output(self):
|
||||||
|
render = start_mod._text_render_preflight()
|
||||||
|
plan = MagicMock()
|
||||||
|
with patch("bot_bottle.cli.start._manifest_to_yaml", return_value=""), \
|
||||||
|
patch("sys.stderr", io.StringIO()) as err:
|
||||||
|
render(plan, "my-backend")
|
||||||
|
self.assertIn("my-backend", err.getvalue())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from bot_bottle.manifest import ManifestBottle, ManifestIndex
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from bot_bottle.env import resolve_env
|
||||||
|
from bot_bottle.errors import MissingEnvVarError
|
||||||
|
from bot_bottle.manifest import Manifest, ManifestBottle, ManifestIndex
|
||||||
from bot_bottle.manifest_agent import (
|
from bot_bottle.manifest_agent import (
|
||||||
ManifestAgent,
|
ManifestAgent,
|
||||||
ManifestAgentProvider,
|
ManifestAgentProvider,
|
||||||
@@ -238,5 +242,26 @@ class TestEagerIndexLookups(unittest.TestCase):
|
|||||||
self.assertIsNone(m.git_identity_summary())
|
self.assertIsNone(m.git_identity_summary())
|
||||||
|
|
||||||
|
|
||||||
|
class TestResolveEnv(unittest.TestCase):
|
||||||
|
"""resolve_env raises MissingEnvVarError when an interpolated entry's
|
||||||
|
host var is unset."""
|
||||||
|
|
||||||
|
def _manifest(self, env_dict: dict[str, str]) -> Manifest:
|
||||||
|
idx = ManifestIndex.from_json_obj({
|
||||||
|
"bottles": {"dev": {"env": env_dict}},
|
||||||
|
"agents": {"demo": {"bottle": "dev"}},
|
||||||
|
})
|
||||||
|
return idx.load_for_agent("demo")
|
||||||
|
|
||||||
|
def test_missing_interpolated_host_var_raises(self):
|
||||||
|
manifest = self._manifest({"API_KEY": "${HOST_API_KEY}"})
|
||||||
|
with patch.dict("os.environ", {}, clear=False):
|
||||||
|
import os
|
||||||
|
os.environ.pop("HOST_API_KEY", None)
|
||||||
|
with self.assertRaises(MissingEnvVarError) as cm:
|
||||||
|
resolve_env(manifest)
|
||||||
|
self.assertIn("HOST_API_KEY", str(cm.exception))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -506,5 +506,54 @@ class TestProvisionGitUser(unittest.TestCase):
|
|||||||
self.assertIn("bot@example.com", calls[0][0])
|
self.assertIn("bot@example.com", calls[0][0])
|
||||||
|
|
||||||
|
|
||||||
|
class TestProxyHost(unittest.TestCase):
|
||||||
|
"""_proxy_host returns the bridge gateway on Linux and the loopback
|
||||||
|
alias on other platforms."""
|
||||||
|
|
||||||
|
def test_linux_returns_bundle_gateway(self):
|
||||||
|
plan = _plan()
|
||||||
|
with patch("bot_bottle.backend.smolmachines.launch.platform.system",
|
||||||
|
return_value="Linux"):
|
||||||
|
result = _launch._proxy_host(plan, "127.0.0.16")
|
||||||
|
self.assertEqual(plan.bundle_gateway, result)
|
||||||
|
|
||||||
|
def test_non_linux_returns_loopback(self):
|
||||||
|
plan = _plan()
|
||||||
|
with patch("bot_bottle.backend.smolmachines.launch.platform.system",
|
||||||
|
return_value="Darwin"):
|
||||||
|
result = _launch._proxy_host(plan, "127.0.0.16")
|
||||||
|
self.assertEqual("127.0.0.16", result)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDiscoverUrls(unittest.TestCase):
|
||||||
|
"""_discover_urls stamps git-gate host + supervise URL into the plan."""
|
||||||
|
|
||||||
|
def test_git_gate_host_set_when_upstreams_present(self):
|
||||||
|
plan = _plan()
|
||||||
|
plan = replace(
|
||||||
|
plan,
|
||||||
|
git_gate_plan=replace(
|
||||||
|
plan.git_gate_plan,
|
||||||
|
upstreams=(GitGateUpstream(
|
||||||
|
name="bot-bottle",
|
||||||
|
upstream_url="ssh://git@host/repo.git",
|
||||||
|
upstream_host="host",
|
||||||
|
upstream_port="22",
|
||||||
|
identity_file="/tmp/key",
|
||||||
|
known_host_key="",
|
||||||
|
),),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
with patch.object(_launch._bundle, "bundle_host_port", return_value="9420"):
|
||||||
|
stamped = _launch._discover_urls(plan, "127.0.0.16")
|
||||||
|
self.assertEqual("127.0.0.16:9420", stamped.agent_git_gate_host)
|
||||||
|
|
||||||
|
def test_supervise_url_set_when_supervise_present(self):
|
||||||
|
plan = _plan(supervise=True)
|
||||||
|
with patch.object(_launch._bundle, "bundle_host_port", return_value="55556"):
|
||||||
|
stamped = _launch._discover_urls(plan, "127.0.0.16")
|
||||||
|
self.assertEqual("http://127.0.0.16:55556/", stamped.agent_supervise_url)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user