generated from coulomb/repo-seed
Add meta-framework spec, pydantic schemas, profile/extension YAML, extension registry, ext.compose-ssh backend, SandboxManager with State Hub events, CLI commands, integration docs, capability registry entry, and compose-e2e runbook. Nine unit tests pass. T10 remote smoke test remains for operator.
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
"""Schema and loader tests."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from sandboxer.extensions.registry import load_all_extensions, load_extension
|
|
from sandboxer.models import Consumer, Profile, SandboxCreateRequest
|
|
from sandboxer.profiles.loader import load_profile
|
|
|
|
|
|
def test_load_compose_e2e_profile() -> None:
|
|
profile = load_profile("profile.compose-e2e")
|
|
assert profile.extension == "ext.compose-ssh"
|
|
assert profile.placement.prefer == ["sandboxer01"]
|
|
|
|
|
|
def test_load_compose_ssh_extension() -> None:
|
|
ext = load_extension("ext.compose-ssh")
|
|
assert ext.handler.endswith("ComposeSSHExtension")
|
|
assert "container" in ext.capabilities.isolation_levels
|
|
|
|
|
|
def test_load_all_extensions_no_duplicates() -> None:
|
|
extensions = load_all_extensions()
|
|
assert "ext.compose-ssh" in extensions
|
|
assert len(extensions) == len(set(extensions))
|
|
|
|
|
|
def test_profile_roundtrip(tmp_path: Path) -> None:
|
|
data = load_profile("profile.compose-e2e").model_dump()
|
|
path = tmp_path / "profile.test.yaml"
|
|
path.write_text(yaml.dump(data))
|
|
loaded = Profile.model_validate(yaml.safe_load(path.read_text()))
|
|
assert loaded.id == "profile.compose-e2e"
|
|
|
|
|
|
def test_sandbox_create_request() -> None:
|
|
req = SandboxCreateRequest(
|
|
profile="profile.compose-e2e",
|
|
inputs={"repo": "/tmp/foo"},
|
|
consumer=Consumer(actor="adm", project="sand-boxer"),
|
|
)
|
|
assert req.inputs["repo"] == "/tmp/foo"
|
|
|
|
|
|
def test_extension_missing_handler(tmp_path: Path) -> None:
|
|
bad = tmp_path / "ext.bad.yaml"
|
|
bad.write_text(
|
|
yaml.dump(
|
|
{
|
|
"id": "ext.bad",
|
|
"title": "Bad",
|
|
"handler": "",
|
|
"capabilities": {"isolation_levels": ["container"], "pricing_model": "self-hosted"},
|
|
}
|
|
)
|
|
)
|
|
with pytest.raises(ValueError, match="missing handler"):
|
|
load_extension("ext.bad", extensions_root=tmp_path) |