Files
wehub-resource-sync f99010fae1
Desktop Artifacts / Desktop Build (Linux) (push) Waiting to run
Desktop Artifacts / Desktop Build (Windows) (push) Waiting to run
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Waiting to run
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:36 +08:00

416 lines
18 KiB
Python

from __future__ import annotations
import io
import os
import stat
import tarfile
import zipfile
from pathlib import Path
import pytest
from build_wheels import (
PLATFORM_MAP,
build_all_wheels,
build_wheel,
extract_binary,
parse_archive_filename,
)
# ---------------------------------------------------------------------------
# Platform mapping
# ---------------------------------------------------------------------------
class TestPlatformMap:
def test_all_required_platforms_present(self) -> None:
required = {
"linux_amd64",
"linux_arm64",
"darwin_amd64",
"darwin_arm64",
"windows_amd64",
"windows_arm64",
}
assert set(PLATFORM_MAP.keys()) == required
def test_each_entry_has_wheel_tag(self) -> None:
for key, entry in PLATFORM_MAP.items():
assert "wheel_tag" in entry, f"{key} missing wheel_tag"
assert isinstance(entry["wheel_tag"], str)
assert entry["wheel_tag"]
def test_each_entry_has_binary_name(self) -> None:
for key, entry in PLATFORM_MAP.items():
assert "binary_name" in entry, f"{key} missing binary_name"
assert isinstance(entry["binary_name"], str)
assert entry["binary_name"]
def test_windows_binary_has_exe_extension(self) -> None:
assert PLATFORM_MAP["windows_amd64"]["binary_name"] == "agentsview.exe"
assert PLATFORM_MAP["windows_arm64"]["binary_name"] == "agentsview.exe"
def test_unix_binaries_have_no_extension(self) -> None:
for key in ("linux_amd64", "linux_arm64", "darwin_amd64", "darwin_arm64"):
assert PLATFORM_MAP[key]["binary_name"] == "agentsview"
def test_manylinux_wheel_tags(self) -> None:
assert PLATFORM_MAP["linux_amd64"]["wheel_tag"] == "manylinux_2_28_x86_64"
assert PLATFORM_MAP["linux_arm64"]["wheel_tag"] == "manylinux_2_28_aarch64"
def test_macos_wheel_tags(self) -> None:
assert PLATFORM_MAP["darwin_amd64"]["wheel_tag"] == "macosx_11_0_x86_64"
assert PLATFORM_MAP["darwin_arm64"]["wheel_tag"] == "macosx_11_0_arm64"
def test_windows_wheel_tag(self) -> None:
assert PLATFORM_MAP["windows_amd64"]["wheel_tag"] == "win_amd64"
assert PLATFORM_MAP["windows_arm64"]["wheel_tag"] == "win_arm64"
# ---------------------------------------------------------------------------
# Archive filename parsing
# ---------------------------------------------------------------------------
class TestParseArchiveFilename:
def test_parse_linux_amd64_tar_gz(self) -> None:
result = parse_archive_filename("agentsview_0.15.0_linux_amd64.tar.gz")
assert result == ("linux_amd64", "0.15.0")
def test_parse_darwin_arm64_tar_gz(self) -> None:
result = parse_archive_filename("agentsview_1.2.3_darwin_arm64.tar.gz")
assert result == ("darwin_arm64", "1.2.3")
def test_parse_windows_amd64_zip(self) -> None:
result = parse_archive_filename("agentsview_0.15.0_windows_amd64.zip")
assert result == ("windows_amd64", "0.15.0")
def test_parse_windows_arm64_zip(self) -> None:
result = parse_archive_filename("agentsview_0.15.0_windows_arm64.zip")
assert result == ("windows_arm64", "0.15.0")
def test_parse_darwin_amd64_tar_gz(self) -> None:
result = parse_archive_filename("agentsview_2.0.0_darwin_amd64.tar.gz")
assert result == ("darwin_amd64", "2.0.0")
def test_unrecognized_filename_returns_none(self) -> None:
assert parse_archive_filename("somethingelse_0.1.0_linux_amd64.tar.gz") is None
def test_unknown_platform_returns_none(self) -> None:
assert parse_archive_filename("agentsview_0.1.0_freebsd_amd64.tar.gz") is None
def test_no_extension_returns_none(self) -> None:
assert parse_archive_filename("agentsview_0.1.0_linux_amd64") is None
def test_sha256sums_returns_none(self) -> None:
assert parse_archive_filename("agentsview_0.15.0_SHA256SUMS") is None
def test_path_with_directory_uses_basename(self) -> None:
result = parse_archive_filename(
"releases/agentsview_0.15.0_linux_arm64.tar.gz"
)
# parse_archive_filename only accepts basenames, so paths return None
assert result is None
# The caller is responsible for passing just the filename
result = parse_archive_filename("agentsview_0.15.0_linux_arm64.tar.gz")
assert result == ("linux_arm64", "0.15.0")
# ---------------------------------------------------------------------------
# Archive extraction
# ---------------------------------------------------------------------------
def _make_targz(binary_name: str, content: bytes) -> bytes:
"""Create an in-memory .tar.gz with a single binary file."""
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w:gz") as tf:
info = tarfile.TarInfo(name=binary_name)
info.size = len(content)
tf.addfile(info, io.BytesIO(content))
return buf.getvalue()
def _make_zip(binary_name: str, content: bytes) -> bytes:
"""Create an in-memory .zip with a single binary file."""
buf = io.BytesIO()
with zipfile.ZipFile(buf, "w") as zf:
zf.writestr(binary_name, content)
return buf.getvalue()
class TestExtractBinary:
def test_extract_from_tar_gz(self, tmp_path: Path) -> None:
content = b"fake-binary-content"
archive = tmp_path / "agentsview_0.15.0_linux_amd64.tar.gz"
archive.write_bytes(_make_targz("agentsview", content))
result = extract_binary(archive, "agentsview")
assert result == content
def test_extract_from_zip(self, tmp_path: Path) -> None:
content = b"fake-binary-exe"
archive = tmp_path / "agentsview_0.15.0_windows_amd64.zip"
archive.write_bytes(_make_zip("agentsview.exe", content))
result = extract_binary(archive, "agentsview.exe")
assert result == content
def test_missing_binary_raises_file_not_found(self, tmp_path: Path) -> None:
archive = tmp_path / "agentsview_0.15.0_linux_amd64.tar.gz"
archive.write_bytes(_make_targz("wrong_name", b"data"))
with pytest.raises(FileNotFoundError, match="agentsview"):
extract_binary(archive, "agentsview")
def test_missing_binary_in_zip_raises_file_not_found(self, tmp_path: Path) -> None:
archive = tmp_path / "agentsview_0.15.0_windows_amd64.zip"
archive.write_bytes(_make_zip("wrong.exe", b"data"))
with pytest.raises(FileNotFoundError, match="agentsview.exe"):
extract_binary(archive, "agentsview.exe")
def test_nested_path_in_tar_gz(self, tmp_path: Path) -> None:
"""Binary may be inside a subdirectory in the archive."""
content = b"nested-binary"
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w:gz") as tf:
info = tarfile.TarInfo(name="agentsview_0.15.0_linux_amd64/agentsview")
info.size = len(content)
tf.addfile(info, io.BytesIO(content))
archive = tmp_path / "agentsview_0.15.0_linux_amd64.tar.gz"
archive.write_bytes(buf.getvalue())
result = extract_binary(archive, "agentsview")
assert result == content
# ---------------------------------------------------------------------------
# Wheel assembly
# ---------------------------------------------------------------------------
class TestBuildWheel:
def test_wheel_filename_matches_convention(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
assert whl.name == "agentsview-0.15.0-py3-none-manylinux_2_28_x86_64.whl"
def test_wheel_is_valid_zip(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
assert zipfile.is_zipfile(whl)
def test_wheel_contains_expected_files(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
names = set(zf.namelist())
assert "agentsview/__init__.py" in names
assert "agentsview/__main__.py" in names
assert "agentsview/bin/agentsview" in names
assert "agentsview-0.15.0.dist-info/METADATA" in names
assert "agentsview-0.15.0.dist-info/WHEEL" in names
assert "agentsview-0.15.0.dist-info/entry_points.txt" in names
assert "agentsview-0.15.0.dist-info/RECORD" in names
def test_binary_has_executable_permissions(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
info = zf.getinfo("agentsview/bin/agentsview")
unix_mode = (info.external_attr >> 16) & 0xFFFF
assert oct(unix_mode & 0o777) == oct(0o755)
def test_wheel_files_are_compressed(self, tmp_path: Path) -> None:
whl = build_wheel(b"x" * 10000, tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
for info in zf.infolist():
assert info.compress_type == zipfile.ZIP_DEFLATED, (
f"{info.filename} uses {info.compress_type}, expected DEFLATED"
)
def test_binary_has_regular_file_type_bit(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
info = zf.getinfo("agentsview/bin/agentsview")
# S_IFREG (0o100000) must be set so pip applies permissions
unix_mode = (info.external_attr >> 16) & 0xFFFF
assert unix_mode & stat.S_IFREG, "S_IFREG must be set"
def test_windows_wheel_uses_exe_binary(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "windows_amd64")
with zipfile.ZipFile(whl) as zf:
names = set(zf.namelist())
assert "agentsview/bin/agentsview.exe" in names
assert "agentsview/bin/agentsview" not in names
def test_metadata_required_fields(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
metadata = zf.read("agentsview-0.15.0.dist-info/METADATA").decode()
assert "Metadata-Version: 2.1" in metadata
assert "Name: agentsview" in metadata
assert "Version: 0.15.0" in metadata
assert "Requires-Python: >=3.9" in metadata
assert "License: MIT" in metadata
assert "Author: Kenn Software LLC" in metadata
def test_wheel_file_has_root_is_purelib_false(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
wheel_meta = zf.read("agentsview-0.15.0.dist-info/WHEEL").decode()
assert "Root-Is-Purelib: false" in wheel_meta
assert "Generator: agentsview-build-wheels" in wheel_meta
def test_entry_points_correct(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
ep = zf.read("agentsview-0.15.0.dist-info/entry_points.txt").decode()
assert "[console_scripts]" in ep
assert "agentsview = agentsview:main" in ep
def test_record_contains_hashes(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
record = zf.read("agentsview-0.15.0.dist-info/RECORD").decode()
# Each non-RECORD entry should have a sha256 hash
lines = [ln for ln in record.splitlines() if ln.strip()]
record_line = None
for line in lines:
if "RECORD" in line:
record_line = line
else:
assert "sha256=" in line, f"Missing hash in RECORD line: {line}"
# RECORD itself listed as empty
assert record_line is not None
assert record_line.endswith(",,")
def test_readme_included_in_metadata(self, tmp_path: Path) -> None:
readme = "# agentsview\nA great tool."
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64", readme=readme)
with zipfile.ZipFile(whl) as zf:
metadata = zf.read("agentsview-0.15.0.dist-info/METADATA").decode()
assert "A great tool." in metadata
def test_init_py_uses_execvp_on_unix(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "linux_amd64")
with zipfile.ZipFile(whl) as zf:
init = zf.read("agentsview/__init__.py").decode()
assert "os.execvp" in init
def test_init_py_uses_subprocess_on_windows(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "0.15.0", "windows_amd64")
with zipfile.ZipFile(whl) as zf:
init = zf.read("agentsview/__init__.py").decode()
assert "subprocess.call" in init
def test_wheel_filename_darwin_arm64(self, tmp_path: Path) -> None:
whl = build_wheel(b"fake", tmp_path, "1.0.0", "darwin_arm64")
assert whl.name == "agentsview-1.0.0-py3-none-macosx_11_0_arm64.whl"
# ---------------------------------------------------------------------------
# End-to-end: build_all_wheels
# ---------------------------------------------------------------------------
class TestBuildAllWheels:
def _make_fake_archives(self, input_dir: Path, version: str) -> None:
"""Create fake release archives for every supported platform."""
platforms = [
("linux_amd64", "agentsview", ".tar.gz"),
("linux_arm64", "agentsview", ".tar.gz"),
("darwin_amd64", "agentsview", ".tar.gz"),
("darwin_arm64", "agentsview", ".tar.gz"),
("windows_amd64", "agentsview.exe", ".zip"),
("windows_arm64", "agentsview.exe", ".zip"),
]
for platform_key, binary_name, ext in platforms:
content = f"binary-for-{platform_key}".encode()
filename = f"agentsview_{version}_{platform_key}{ext}"
archive_path = input_dir / filename
if ext == ".tar.gz":
archive_path.write_bytes(_make_targz(binary_name, content))
else:
archive_path.write_bytes(_make_zip(binary_name, content))
# Also add a SHA256SUMS file that should be skipped
(input_dir / f"agentsview_{version}_SHA256SUMS").write_text("checksums here")
def test_produces_a_wheel_per_platform(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
self._make_fake_archives(input_dir, "0.15.0")
wheels = build_all_wheels(input_dir, output_dir, "0.15.0")
assert len(wheels) == len(PLATFORM_MAP)
def test_correct_wheel_names(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
self._make_fake_archives(input_dir, "0.15.0")
wheels = build_all_wheels(input_dir, output_dir, "0.15.0")
names = {w.name for w in wheels}
expected = {
"agentsview-0.15.0-py3-none-manylinux_2_28_x86_64.whl",
"agentsview-0.15.0-py3-none-manylinux_2_28_aarch64.whl",
"agentsview-0.15.0-py3-none-macosx_11_0_x86_64.whl",
"agentsview-0.15.0-py3-none-macosx_11_0_arm64.whl",
"agentsview-0.15.0-py3-none-win_amd64.whl",
"agentsview-0.15.0-py3-none-win_arm64.whl",
}
assert names == expected
def test_unknown_platforms_skipped(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
self._make_fake_archives(input_dir, "0.15.0")
# Add an unknown platform archive
unknown = input_dir / "agentsview_0.15.0_freebsd_amd64.tar.gz"
unknown.write_bytes(_make_targz("agentsview", b"fake"))
wheels = build_all_wheels(input_dir, output_dir, "0.15.0")
assert len(wheels) == len(PLATFORM_MAP) # unknown skipped
def test_output_dir_created_if_missing(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output" / "nested"
input_dir.mkdir()
self._make_fake_archives(input_dir, "0.15.0")
build_all_wheels(input_dir, output_dir, "0.15.0")
assert output_dir.exists()
def test_version_mismatch_raises(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
self._make_fake_archives(input_dir, "0.15.0")
with pytest.raises(RuntimeError, match="does not match"):
build_all_wheels(input_dir, output_dir, "0.16.0")
def test_all_wheels_are_valid_zips(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
self._make_fake_archives(input_dir, "0.15.0")
wheels = build_all_wheels(input_dir, output_dir, "0.15.0")
for whl in wheels:
assert zipfile.is_zipfile(whl), f"{whl.name} is not a valid zip"
def test_require_all_fails_on_missing_platform(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
# Only create linux_amd64
(input_dir / "agentsview_1.0.0_linux_amd64.tar.gz").write_bytes(
_make_targz("agentsview", b"fake")
)
with pytest.raises(RuntimeError, match="Missing archives"):
build_all_wheels(
input_dir, output_dir, "1.0.0", require_all=True
)
def test_require_all_passes_with_all_platforms(self, tmp_path: Path) -> None:
input_dir = tmp_path / "input"
output_dir = tmp_path / "output"
input_dir.mkdir()
self._make_fake_archives(input_dir, "1.0.0")
wheels = build_all_wheels(
input_dir, output_dir, "1.0.0", require_all=True
)
assert len(wheels) == len(PLATFORM_MAP)