Files
agentic-mobile-control/tests/test_cloud_composition_safety.py
T
2026-07-15 11:46:27 +08:00

103 lines
3.4 KiB
Python

"""Composition safety checks (task 9.1).
Verifies that the cloud workspace package is purely additive: every existing
module it composes (``runtime.task``, ``workflow.runner``, ``driver.registry``,
``api.mcp``) remains unaware of the ``cloud`` package in its source.
"""
from __future__ import annotations
import importlib
import os
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
CLOUD_SOURCE_ROOT = PROJECT_ROOT / "packages" / "cloud-platform" / "cloud"
def _module_source(path: Path) -> str:
return path.read_text(encoding="utf-8")
def _existing_module_paths() -> list[Path]:
"""Return source files cloud/ must not edit or import-back into."""
folders = [
"core",
"driver",
"device",
"runtime",
"tools",
"workflow",
"agents",
"storage",
]
files: list[Path] = []
for folder in folders:
root = PROJECT_ROOT / folder
if not root.exists():
continue
for path in root.rglob("*.py"):
files.append(path)
mcp = PROJECT_ROOT / "api" / "mcp.py"
if mcp.exists():
files.append(mcp)
return files
def test_existing_modules_do_not_import_cloud() -> None:
"""No composed-over module imports ``cloud`` (cloud is one-directional)."""
offenders: list[str] = []
for path in _existing_module_paths():
try:
source = _module_source(path)
except OSError:
continue
# Look for an actual import of cloud, not the literal word "cloud" in comments.
for line in source.splitlines():
stripped = line.strip()
if stripped.startswith("#"):
continue
if (
"import cloud" in stripped
or "from cloud" in stripped
or "import cloud." in stripped
):
offenders.append(f"{path}: {stripped}")
assert not offenders, (
"cloud/ must compose other packages by import only; the following "
"existing modules import cloud back (forbidden): " + "; ".join(offenders)
)
def test_cloud_dispatch_imports_existing_runners_by_name() -> None:
"""dispatch.py should reference runtime.task.TaskRunner and workflow.runner.WorkflowRunner."""
dispatch = importlib.import_module("cloud.dispatch")
source = _module_source(Path(dispatch.__file__)) # type: ignore[arg-type]
# TaskRunner/WorkflowRunner are referenced via factory callables, not direct
# imports, so we check for the contract being composed over in docstrings/types.
assert "TaskRunner" in source or "task_runner_factory" in source
assert "WorkflowRunner" in source or "workflow_runner_factory" in source
def test_cloud_source_files_exist_only_under_cloud_workspace_member() -> None:
"""Cloud source files are owned by the cloud-platform workspace member."""
assert CLOUD_SOURCE_ROOT.exists()
expected_files = {
"__init__.py",
"config.py",
"pool.py",
"store.py",
"scheduler.py",
"dispatch.py",
"plugins.py",
"sdk/__init__.py",
"sdk/api.py",
"sdk/client.py",
"sdk/models.py",
}
found: set[str] = set()
for path in CLOUD_SOURCE_ROOT.rglob("*.py"):
found.add(str(path.relative_to(CLOUD_SOURCE_ROOT)).replace(os.sep, "/"))
missing = expected_files - found
assert not missing, f"missing cloud source files: {sorted(missing)}"