138 lines
5.2 KiB
Python
138 lines
5.2 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import json
|
||
|
|
import subprocess
|
||
|
|
import tempfile
|
||
|
|
import unittest
|
||
|
|
from pathlib import Path
|
||
|
|
from unittest import mock
|
||
|
|
|
||
|
|
from tools.milestone4_adoption import (
|
||
|
|
AdoptionProofError,
|
||
|
|
find_wheel,
|
||
|
|
parse_evidence,
|
||
|
|
run_adoption_proof,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def _evidence() -> dict[str, object]:
|
||
|
|
return {
|
||
|
|
"schema_version": 1,
|
||
|
|
"base_frontend_modules": [],
|
||
|
|
"base_frontend_distributions": [],
|
||
|
|
"python": {"build_status": "ok", "check_status": "ok", "node_count": 3},
|
||
|
|
"mcp": {
|
||
|
|
"bootstrap_status": "ok",
|
||
|
|
"node_id": "python.class.service",
|
||
|
|
"read_tool_count": 20,
|
||
|
|
},
|
||
|
|
"cpp_without_extra": {
|
||
|
|
"code": "optional_dependency_missing",
|
||
|
|
"install": "docforge[cpp]",
|
||
|
|
"missing_module": "tree_sitter",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class Milestone4AdoptionTests(unittest.TestCase):
|
||
|
|
def test_evidence_requires_base_isolation_python_mcp_and_actionable_cpp_failure(
|
||
|
|
self,
|
||
|
|
) -> None:
|
||
|
|
self.assertEqual(_evidence(), parse_evidence(json.dumps(_evidence())))
|
||
|
|
|
||
|
|
for mutation in (
|
||
|
|
{"base_frontend_modules": ["tree_sitter"]},
|
||
|
|
{"python": {"build_status": "error", "check_status": "ok"}},
|
||
|
|
{"mcp": {"bootstrap_status": "error"}},
|
||
|
|
{
|
||
|
|
"cpp_without_extra": {
|
||
|
|
"code": "optional_dependency_missing",
|
||
|
|
"install": "docforge[languages]",
|
||
|
|
}
|
||
|
|
},
|
||
|
|
):
|
||
|
|
evidence = {**_evidence(), **mutation}
|
||
|
|
with self.subTest(mutation=mutation), self.assertRaises(AdoptionProofError):
|
||
|
|
parse_evidence(json.dumps(evidence))
|
||
|
|
|
||
|
|
def test_wheel_discovery_rejects_missing_or_ambiguous_artifacts(self) -> None:
|
||
|
|
with tempfile.TemporaryDirectory() as directory:
|
||
|
|
root = Path(directory)
|
||
|
|
with self.assertRaises(AdoptionProofError):
|
||
|
|
find_wheel(root)
|
||
|
|
first = root / "docforge-1-py3-none-any.whl"
|
||
|
|
first.touch()
|
||
|
|
self.assertEqual(first, find_wheel(root))
|
||
|
|
(root / "docforge-2-py3-none-any.whl").touch()
|
||
|
|
with self.assertRaises(AdoptionProofError):
|
||
|
|
find_wheel(root)
|
||
|
|
|
||
|
|
def test_orchestration_is_offline_locked_and_installs_the_wheel_without_extras(
|
||
|
|
self,
|
||
|
|
) -> None:
|
||
|
|
with tempfile.TemporaryDirectory() as directory:
|
||
|
|
root = Path(directory).resolve()
|
||
|
|
(root / "pyproject.toml").write_text("[project]\n", encoding="utf-8")
|
||
|
|
(root / "uv.lock").write_text("version = 1\n", encoding="utf-8")
|
||
|
|
commands: list[list[str]] = []
|
||
|
|
|
||
|
|
def execute(
|
||
|
|
arguments: list[str],
|
||
|
|
*,
|
||
|
|
cwd: Path,
|
||
|
|
timeout: int,
|
||
|
|
environment: dict[str, str] | None = None,
|
||
|
|
) -> subprocess.CompletedProcess[str]:
|
||
|
|
del cwd, timeout
|
||
|
|
commands.append(arguments)
|
||
|
|
self.assertIsNotNone(environment)
|
||
|
|
assert environment is not None
|
||
|
|
self.assertEqual("1", environment["UV_OFFLINE"])
|
||
|
|
self.assertNotIn("PYTHONPATH", environment)
|
||
|
|
if arguments[1] == "build":
|
||
|
|
output = Path(arguments[arguments.index("--out-dir") + 1])
|
||
|
|
output.mkdir()
|
||
|
|
(output / "docforge-1-py3-none-any.whl").write_bytes(b"wheel")
|
||
|
|
elif arguments[1] == "export":
|
||
|
|
output = Path(arguments[arguments.index("--output-file") + 1])
|
||
|
|
output.write_text("mcp==1\n", encoding="utf-8")
|
||
|
|
elif arguments[1] == "venv":
|
||
|
|
virtual_environment = Path(arguments[-1])
|
||
|
|
(virtual_environment / "bin").mkdir(parents=True)
|
||
|
|
(virtual_environment / "bin" / "python").touch()
|
||
|
|
elif arguments[0].endswith("/bin/python"):
|
||
|
|
return subprocess.CompletedProcess(
|
||
|
|
arguments,
|
||
|
|
0,
|
||
|
|
stdout=json.dumps(_evidence()),
|
||
|
|
stderr="",
|
||
|
|
)
|
||
|
|
return subprocess.CompletedProcess(arguments, 0, stdout="", stderr="")
|
||
|
|
|
||
|
|
with mock.patch(
|
||
|
|
"tools.milestone4_adoption._run_checked",
|
||
|
|
side_effect=execute,
|
||
|
|
):
|
||
|
|
result = run_adoption_proof(root, uv="uv")
|
||
|
|
|
||
|
|
self.assertEqual("offline", result["network"])
|
||
|
|
wheel = result["wheel"]
|
||
|
|
self.assertIsInstance(wheel, dict)
|
||
|
|
assert isinstance(wheel, dict)
|
||
|
|
self.assertEqual("docforge-1-py3-none-any.whl", wheel["filename"])
|
||
|
|
network_commands = (
|
||
|
|
command
|
||
|
|
for command in commands
|
||
|
|
if command[0] == "uv" and command[1] in {"build", "export", "pip"}
|
||
|
|
)
|
||
|
|
self.assertTrue(all("--offline" in command for command in network_commands))
|
||
|
|
export = next(command for command in commands if command[1] == "export")
|
||
|
|
self.assertIn("--frozen", export)
|
||
|
|
self.assertIn("--no-dev", export)
|
||
|
|
wheel_install = next(command for command in commands if command[1:3] == ["pip", "install"])
|
||
|
|
self.assertIn("--no-deps", wheel_install)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|