mirror of
https://github.com/razzant/ouroboros.git
synced 2026-08-25 19:11:44 +00:00
Validate lock freshness, preserve the pip runtime capability and N-1 updater bridge, synchronize the uv root version during releases, and align install documentation and regression tests.
107 lines
4.3 KiB
Python
107 lines
4.3 KiB
Python
"""Regression tests for the agent interpreter handle.
|
|
|
|
The bundled app must run pytest through the same interpreter that launched
|
|
Ouroboros. Plain `pytest` or `python -m pytest` can resolve to the wrong
|
|
runtime in packaged builds.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import pathlib
|
|
import subprocess
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
|
|
def test_server_py_injects_agent_python_env_var():
|
|
repo_root = pathlib.Path(__file__).resolve().parent.parent
|
|
source = (repo_root / "server.py").read_text(encoding="utf-8")
|
|
assert 'os.environ.get("OUROBOROS_AGENT_PYTHON")' in source
|
|
assert 'os.environ["OUROBOROS_AGENT_PYTHON"]' in source
|
|
assert "sys.executable" in source
|
|
assert "isinstance" in source and "_agent_python" in source
|
|
|
|
|
|
def test_preflight_test_runner_uses_sys_executable():
|
|
repo_root = pathlib.Path(__file__).resolve().parent.parent
|
|
source = (repo_root / "ouroboros" / "preflight_runner.py").read_text(encoding="utf-8")
|
|
review_helpers = (repo_root / "ouroboros" / "tools" / "review_helpers.py").read_text(encoding="utf-8")
|
|
assert '["pytest", "tests/"' not in source
|
|
assert '"-m", "pytest"' in source
|
|
assert "sys.executable" in source
|
|
assert "run_hermetic_pytest" in review_helpers
|
|
|
|
|
|
def test_git_pre_push_tests_uses_sys_executable():
|
|
repo_root = pathlib.Path(__file__).resolve().parent.parent
|
|
source = (repo_root / "ouroboros" / "preflight_runner.py").read_text(encoding="utf-8")
|
|
git_tools = (repo_root / "ouroboros" / "tools" / "git.py").read_text(encoding="utf-8")
|
|
assert '["pytest", "tests/"' not in source
|
|
assert '"-m", "pytest"' in source
|
|
assert "sys.executable" in source
|
|
assert "OUROBOROS_AGENT_PYTHON" in source
|
|
assert "run_hermetic_pytest" in git_tools
|
|
|
|
|
|
def test_shell_no_longer_launches_pytest_at_all():
|
|
"""The shell validation runner retired WITH its only consumer (D10).
|
|
|
|
`_run_validation` was `claude_code_edit`'s own `validate=True`
|
|
implementation — one caller since the initial bundle — so it left with the
|
|
tool. The interpreter-handle invariant this pin protected (a packaged app
|
|
must run pytest through the interpreter that launched it, never bare
|
|
`python`) keeps its two FIRST-CLASS homes, each pinned by its own test
|
|
above: the preflight runner and the git pre-push tests. This pin now
|
|
asserts the new truth at the old location: shell.py launches pytest in NO
|
|
form, so an ad-hoc runner with the wrong interpreter cannot sneak back in
|
|
beside process tools — a new pytest launch belongs in
|
|
preflight_runner/run_hermetic_pytest, where the sibling pins bind it.
|
|
"""
|
|
repo_root = pathlib.Path(__file__).resolve().parent.parent
|
|
source = (repo_root / "ouroboros" / "tools" / "shell.py").read_text(encoding="utf-8")
|
|
assert '["python", "-m", "pytest"' not in source
|
|
assert '"-m", "pytest"' not in source
|
|
assert '"pytest"' not in source
|
|
|
|
|
|
def test_sys_executable_minus_m_pytest_exits_zero():
|
|
result = subprocess.run(
|
|
[sys.executable, "-m", "pytest", "--version"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=30,
|
|
)
|
|
assert result.returncode == 0, (
|
|
f"sys.executable -m pytest --version exited {result.returncode}; "
|
|
f"stdout={result.stdout!r} stderr={result.stderr!r}"
|
|
)
|
|
assert "pytest" in (result.stdout + result.stderr).lower()
|
|
|
|
|
|
def test_agent_python_env_var_points_to_usable_python():
|
|
agent_python = os.environ.get("OUROBOROS_AGENT_PYTHON")
|
|
if not agent_python:
|
|
pytest.skip("OUROBOROS_AGENT_PYTHON is not set in this unit-test run")
|
|
result = subprocess.run(
|
|
[agent_python, "-c", "print('ok')"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=10,
|
|
)
|
|
assert result.returncode == 0
|
|
assert "ok" in result.stdout
|
|
|
|
|
|
def test_pyproject_declares_pytest_as_runtime_dependency():
|
|
repo_root = pathlib.Path(__file__).resolve().parent.parent
|
|
pyproject = (repo_root / "pyproject.toml").read_text(encoding="utf-8")
|
|
assert '"pytest>=7.0"' in pyproject
|
|
|
|
|
|
def test_pyproject_declares_pip_as_runtime_dependency():
|
|
"""uv environments must preserve the runtime's ``python -m pip`` contract."""
|
|
repo_root = pathlib.Path(__file__).resolve().parent.parent
|
|
pyproject = (repo_root / "pyproject.toml").read_text(encoding="utf-8")
|
|
assert '"pip"' in pyproject
|