generated from coulomb/repo-seed
Implement SAND-WP-0002 meta-framework foundation (T01–T09)
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.
This commit is contained in:
61
tests/test_models.py
Normal file
61
tests/test_models.py
Normal file
@@ -0,0 +1,61 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user