"""Release verification must cover each staged architecture and Python ABI.""" import json import subprocess from pathlib import Path from types import SimpleNamespace import pytest from release import preflight, runtime def test_all_wheel_pythons_selects_all_nine_wheels(tmp_path, monkeypatch): check = preflight.Preflight( preflight.PreflightOptions(version="1.2.3", all_wheel_pythons=True), repo_root=tmp_path, ) check.wheels = [ tmp_path / f"orisys-1.2.3-{abi}-{abi}-{platform}.whl" for abi in ("cp310", "cp311", "cp312") for platform in ("win_amd64", "manylinux_2_28_x86_64", "manylinux_2_28_aarch64") ] monkeypatch.setattr(preflight.sys, "platform", "win32") monkeypatch.setattr( preflight.version_mod, "python_for_tag", lambda tag: Path(f"{tag}/python.exe") ) assert {wheel for _, wheel, _ in check._runtime_targets()} == set(check.wheels) @pytest.mark.parametrize( "architecture,platform,image", [ ("x86_64", "linux/amd64", "orisys-manylinux"), ("aarch64", "linux/arm64", "orisys-manylinux-aarch64"), ], ) def test_manylinux_verifier_uses_matching_container( tmp_path, monkeypatch, architecture, platform, image ): wheel = tmp_path / f"orisys-1.2.3-cp311-cp311-manylinux_2_28_{architecture}.whl" wheel.touch() video = tmp_path / "sample.mp4" video.touch() record = { "wheel": wheel.name, "assets": "OK", "imports": "OK", "frames": 40, "flow_shape": [1, 2], } calls = [] def run(argv, **kwargs): calls.append(argv) return subprocess.CompletedProcess( argv, 0, "progress\nORISYS_RUNTIME_RESULT=" + json.dumps(record), "" ) monkeypatch.setattr(runtime.subprocess, "run", run) assert ( runtime.verify_manylinux_wheel( wheel, repo_root=tmp_path, video=video, config_name="box", frames=40 ) == record ) argv = calls[0] assert argv[argv.index("--platform") + 1] == platform assert image in argv assert "/opt/python/cp311-cp311/bin/python" in argv assert any( str(tmp_path.resolve()) in arg and arg.endswith(":/src:ro") for arg in argv ) def test_manylinux_verifier_propagates_container_failure(tmp_path, monkeypatch): monkeypatch.setattr( runtime.subprocess, "run", lambda argv, **kwargs: subprocess.CompletedProcess( argv, 1, "", "ARM import failed" ), ) with pytest.raises(RuntimeError, match="ARM import failed"): runtime.verify_manylinux_wheel( tmp_path / "orisys-1.2.3-cp312-cp312-manylinux_2_28_aarch64.whl", repo_root=tmp_path, video=tmp_path / "sample.mp4", config_name="box", frames=40, ) def test_runtime_step_records_hashes_for_windows_and_arm(tmp_path, monkeypatch): video = tmp_path / "sample.mp4" video.touch() check = preflight.Preflight( preflight.PreflightOptions( version="1.2.3", all_wheel_pythons=True, video=video ), repo_root=tmp_path, ) check.wheels = [ tmp_path / f"orisys-1.2.3-cp311-cp311-{target}.whl" for target in ("win_amd64", "manylinux_2_28_aarch64") ] for wheel in check.wheels: wheel.write_bytes(b"wheel") monkeypatch.setattr(preflight.sys, "platform", "win32") monkeypatch.setattr( preflight.version_mod, "python_for_tag", lambda tag: Path("python.exe") ) seen = [] def verify(wheel, **kwargs): seen.append(wheel) return {"wheel": wheel.name, "assets": "OK", "frames": 40, "flow_shape": [1, 2]} monkeypatch.setattr(preflight, "verify_wheel", verify) monkeypatch.setattr(preflight, "verify_manylinux_wheel", verify) step = check._wheel_runtime() assert step.ok, step.detail assert set(seen) == set(check.wheels) assert all( record["sha256"] == preflight._sha256_file(check.wheels[0]) for record in step.data["records"] ) @pytest.mark.parametrize( "name", [ "orisys-1.2.3-cp311-cp311-manylinux_2_28_aarch64.whl", "orisys-1.2.3-cp311-cp311-manylinux_2_28_x86_64.whl", ], ) def test_native_linux_selection_matches_machine(tmp_path, monkeypatch, name): check = preflight.Preflight( preflight.PreflightOptions(version="1.2.3"), repo_root=tmp_path ) check.wheels = [tmp_path / name] monkeypatch.setattr(preflight.sys, "platform", "linux") monkeypatch.setattr(preflight.sys, "version_info", SimpleNamespace(major=3, minor=11)) monkeypatch.setattr(preflight.platform, "machine", lambda: "aarch64") if "aarch64" in name: assert check._runtime_targets()[0][1].name == name else: with pytest.raises(RuntimeError, match="no cp311 aarch64 wheel"): check._runtime_targets()