This commit is contained in:
Joakim Hellsén 2026-04-27 20:43:26 +02:00
commit a7a5b5c8ea
Signed by: Joakim Hellsén
SSH key fingerprint: SHA256:/9h/CsExpFp+PRhsfA0xznFx2CGfTT5R/kpuFfUgEQk
43 changed files with 5531 additions and 9 deletions

View file

@ -0,0 +1,115 @@
from __future__ import annotations
import socket
import subprocess # noqa: S404
import sys
import time
from pathlib import Path
from urllib.error import URLError
from urllib.request import urlopen
import pytest
from control_plane.host_commands import build_host_command_env
from control_plane.runtime_plans import DjangoApplicationLaunchConfig
from control_plane.runtime_plans import build_django_server_command
def _find_free_port() -> int:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as probe:
probe.bind(("127.0.0.1", 0))
probe.listen(1)
return int(probe.getsockname()[1])
def _wait_for_http_ready(url: str, *, timeout_seconds: float = 15.0) -> str:
deadline = time.monotonic() + timeout_seconds
while time.monotonic() < deadline:
try:
with urlopen(url, timeout=1) as response: # noqa: S310
return response.read().decode("utf-8")
except URLError:
time.sleep(0.25)
msg = f"Timed out waiting for {url}"
raise TimeoutError(msg)
def _write_sentinel_urls(project_dir: Path, project_name: str) -> None:
urls_file = project_dir / project_name / "urls.py"
urls_file.write_text(
"from django.http import HttpResponse\n"
"from django.urls import path\n\n"
"def sentinel_view(request):\n"
" return HttpResponse('sentinel-ok')\n\n"
"urlpatterns = [\n"
" path('sentinel/', sentinel_view),\n"
"]\n",
encoding="utf-8",
)
@pytest.mark.host_smoke
def test_temp_django_project_serves_content(
host_smoke_enabled: bool,
tmp_path: Path,
) -> None:
"""Opt-in smoke test should create a temp Django project and serve a sentinel view."""
if not host_smoke_enabled:
pytest.skip("Set TUSSILAGO_RUN_HOST_SMOKE=1 to run host smoke coverage.")
workspace_root = Path(__file__).resolve().parents[1]
project_name = "guestsite"
project_dir = tmp_path / project_name
child_process_env = build_host_command_env()
startproject_command = [
sys.executable,
"-m",
"django",
"startproject",
project_name,
str(project_dir),
]
subprocess.run( # noqa: S603
startproject_command,
check=True,
capture_output=True,
text=True,
cwd=workspace_root,
env=child_process_env,
timeout=30,
)
_write_sentinel_urls(project_dir, project_name)
port = _find_free_port()
command = build_django_server_command(
DjangoApplicationLaunchConfig(
wsgi_module=f"{project_name}.wsgi:application",
bind_host="127.0.0.1",
port=port,
workers=1,
python_executable=Path(sys.executable),
),
)
process = subprocess.Popen( # noqa: S603
command,
cwd=project_dir,
env=child_process_env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
try:
response_body = _wait_for_http_ready(f"http://127.0.0.1:{port}/sentinel/")
except TimeoutError as error:
process.terminate()
stdout, stderr = process.communicate(timeout=10)
pytest.fail(f"{error}\nstdout:\n{stdout}\nstderr:\n{stderr}")
finally:
if process.poll() is None:
process.terminate()
process.wait(timeout=10)
assert response_body == "sentinel-ok"