personal memory agent
0

Configure Feed

Select the types of activity you want to include in your feed.

solstone / tests / test_release_candidate_driver_uv_contract.py
4.6 kB 136 lines
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3"""Real uv parser contract for release-driver build argv. 4 5This is intentionally in the unit lane despite AGENTS.md/CLAUDE.md §6's normal 6mock-process-boundary rule: it runs only `uv --version`, `uv build --help`, 7driver argv plus `--help`, and one instantly parse-failing invalid invocation. 8It performs no build, network access, package resolution, or journal I/O, and uv 9is guaranteed for `make test` by the Makefile's install path check. 10 11Unlike tests/integration/test_release_tool_uv_boundary.py, this test is not 12version-guarded. That integration test checks pin comparison; this one checks 13the argv the driver actually constructs against whatever uv is installed. 14 15Limitation: `--help` short-circuits workspace resolution, so this validates flags 16only. Package-name drift is covered by the WORKSPACE_SOURCES drift test and the 17release driver's exact local-dist inventory validation. 18""" 19 20from __future__ import annotations 21 22import re 23import shutil 24import subprocess 25from collections.abc import Iterable 26from pathlib import Path 27 28import pytest 29 30import scripts.release_candidate_driver as driver 31 32OPTION_DEFINITION_RE = re.compile( 33 r"^(?: {6}| {2}-[A-Za-z], )(?P<flag>--[A-Za-z0-9][A-Za-z0-9-]*)\b" 34) 35 36 37def _uv_or_skip() -> str: 38 uv = shutil.which("uv") 39 if uv is None: 40 pytest.skip( 41 "uv is not installed; release-driver uv argv contract needs real uv" 42 ) 43 return uv 44 45 46def _combined_output(result: subprocess.CompletedProcess[str]) -> str: 47 return "\n".join(part for part in (result.stdout, result.stderr) if part) 48 49 50def _uv_banner(uv: str) -> str: 51 result = subprocess.run( 52 [uv, "--version"], 53 capture_output=True, 54 text=True, 55 check=False, 56 ) 57 return result.stdout.strip() or result.stderr.strip() or f"exit {result.returncode}" 58 59 60def _driver_uv_argvs() -> Iterable[tuple[str, ...]]: 61 for include_models in (True, False): 62 for argv, _maturin_args in driver._expected_local_build_commands( 63 include_models=include_models, 64 version=driver._project_version(Path.cwd()), 65 ): 66 if argv[:2] == ("uv", "build"): 67 yield argv 68 69 70def test_release_driver_uv_build_argv_matches_real_uv_parser() -> None: 71 uv = _uv_or_skip() 72 banner = _uv_banner(uv) 73 help_result = subprocess.run( 74 [uv, "build", "--help"], 75 capture_output=True, 76 text=True, 77 check=False, 78 ) 79 assert help_result.returncode == 0, ( 80 f"ambient uv {banner!r} did not provide build help: " 81 f"{_combined_output(help_result)}" 82 ) 83 flags = { 84 match.group("flag") 85 for line in help_result.stdout.splitlines() 86 if (match := OPTION_DEFINITION_RE.match(line)) 87 } 88 89 assert {"--package", "--all-packages", "--wheel"} <= flags, ( 90 f"ambient uv {banner!r} produced an unusable build-help flag parse: " 91 f"{sorted(flags)}" 92 ) 93 assert "--exclude" not in flags, ( 94 f"ambient uv {banner!r} unexpectedly exposes unsupported --exclude" 95 ) 96 97 for argv in _driver_uv_argvs(): 98 parse_result = subprocess.run( 99 [uv, *argv[1:], "--help"], 100 capture_output=True, 101 text=True, 102 check=False, 103 ) 104 assert parse_result.returncode == 0, ( 105 f"ambient uv {banner!r} rejected release driver argv {argv!r}: " 106 f"{_combined_output(parse_result)}" 107 ) 108 for token in argv: 109 if token.startswith("--"): 110 assert token in flags, ( 111 f"release driver argv {argv!r} uses uv flag {token!r} " 112 f"missing from ambient uv {banner!r}; parsed flags={sorted(flags)}" 113 ) 114 115 # Keep this negative control help-only so a future uv that accepts --exclude 116 # fails safely with help output instead of starting a real workspace build. 117 invalid = subprocess.run( 118 [ 119 uv, 120 "build", 121 "--all-packages", 122 "--exclude", 123 driver.MODELS_WORKSPACE_PACKAGE, 124 "--help", 125 ], 126 capture_output=True, 127 text=True, 128 check=False, 129 ) 130 invalid_output = _combined_output(invalid) 131 assert invalid.returncode != 0, ( 132 f"ambient uv {banner!r} accepted unsupported --exclude in negative control" 133 ) 134 assert "unexpected argument '--exclude' found" in invalid_output, ( 135 f"ambient uv {banner!r} rejected --exclude differently: {invalid_output}" 136 )