1f36d53f7b
test / run tests/run_tests.py (pull_request) Successful in 14s
Replace the TypedDict + 14 manifest_* free functions with frozen dataclasses (SshEntry, BottleEgress, Bottle, Agent, Manifest) carrying their own validators and constructors. Call sites import Manifest and chain attribute access; the manifest_* helpers and manifest_validate are gone. Behavior changes worth flagging: - Agent.bottle is now required (was optional with a "(none)" fallback). Manifest.from_json_obj dies if any agent lacks a 'bottle' field or references an undefined bottle, where previously start.py raised the error lazily for the specific agent being launched. - ssh.py now takes SshEntry instances; Host/IdentityFile shape checks moved upstream into Manifest construction, leaving only the IdentityFile filesystem-existence check in ssh_validate_entries. - pipelock_bottle_allowlist's per-element string check is dropped — the Manifest validator enforces it at load. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
"""Unit: bottle runtime — Manifest.from_json_obj defaults runtime to runc,
|
|
accepts runsc, and rejects unknown values, non-strings, and empty strings."""
|
|
|
|
import unittest
|
|
|
|
from claude_bottle.log import Die
|
|
from claude_bottle.manifest import Manifest
|
|
|
|
|
|
_ABSENT = object()
|
|
|
|
|
|
def _bottle(runtime_value: object) -> dict:
|
|
"""Build a minimal manifest JSON shape with one bottle whose runtime
|
|
field is set (or absent if `runtime_value is _ABSENT`)."""
|
|
bottle: dict = {}
|
|
if runtime_value is not _ABSENT:
|
|
bottle["runtime"] = runtime_value
|
|
return {
|
|
"bottles": {"dev": bottle},
|
|
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
|
}
|
|
|
|
|
|
class TestManifestBottleRuntime(unittest.TestCase):
|
|
def test_default_runc_when_absent(self):
|
|
m = Manifest.from_json_obj(_bottle(_ABSENT))
|
|
self.assertEqual("runc", m.bottles["dev"].runtime)
|
|
|
|
def test_explicit_runc(self):
|
|
m = Manifest.from_json_obj(_bottle("runc"))
|
|
self.assertEqual("runc", m.bottles["dev"].runtime)
|
|
|
|
def test_explicit_runsc(self):
|
|
m = Manifest.from_json_obj(_bottle("runsc"))
|
|
self.assertEqual("runsc", m.bottles["dev"].runtime)
|
|
|
|
def test_rejects_unknown_runtime(self):
|
|
with self.assertRaises(Die):
|
|
Manifest.from_json_obj(_bottle("kata-runtime"))
|
|
|
|
def test_rejects_non_string(self):
|
|
with self.assertRaises(Die):
|
|
Manifest.from_json_obj(_bottle(42))
|
|
|
|
def test_rejects_empty_string(self):
|
|
with self.assertRaises(Die):
|
|
Manifest.from_json_obj(_bottle(""))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|