Files
SystemSimulationApp/tests/test_dependency_constraints.py

197 lines
6.0 KiB
Python

from __future__ import annotations
from importlib import metadata
import os
import platform
from pathlib import Path
import re
import sys
import unittest
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
REQUIREMENTS_PATH = REPOSITORY_ROOT / "requirements.txt"
CONSTRAINTS_PATH = (
REPOSITORY_ROOT / "constraints" / "python312-direct.txt"
)
RELEASE_LOCK_PATH = (
REPOSITORY_ROOT
/ "constraints"
/ "python312-linux-x86_64.lock"
)
PYTHON_VERSION_PATH = REPOSITORY_ROOT / ".python-version"
VERIFY_ENVIRONMENT_VARIABLE = "SYSTEM_SIMULATION_VERIFY_LOCKED_ENV"
REFERENCE_DIRECT_VERSIONS = {
"fastapi": "0.141.1",
"lxml": "6.1.1",
"pydantic": "2.13.4",
"uvicorn": "0.52.3",
}
REFERENCE_LOCKED_VERSIONS = {
"annotated-doc": "0.0.5",
"annotated-types": "0.8.0",
"anyio": "4.14.2",
"click": "8.4.2",
"fastapi": "0.141.1",
"h11": "0.16.0",
"httptools": "0.8.0",
"idna": "3.18",
"lxml": "6.1.1",
"pydantic": "2.13.4",
"pydantic-core": "2.46.4",
"python-dotenv": "1.2.3",
"pyyaml": "6.0.3",
"starlette": "1.6.0",
"typing-extensions": "4.16.0",
"typing-inspection": "0.4.4",
"uvicorn": "0.52.3",
"uvloop": "0.22.1",
"watchfiles": "1.2.0",
"websockets": "17.0.1",
}
LOCK_REQUIREMENT_PATTERN = re.compile(
r"(?P<name>[A-Za-z0-9_.-]+)"
r"(?:\[(?P<extras>[A-Za-z0-9_,.-]+)\])?"
r"==(?P<version>[^\s;]+)\s+"
r"--hash=sha256:(?P<digest>[0-9a-f]{64})\Z"
)
def _active_lines(path: Path) -> tuple[str, ...]:
return tuple(
line
for raw_line in path.read_text(encoding="utf-8").splitlines()
if (line := raw_line.strip()) and not line.startswith("#")
)
def _normalized_name(requirement: str) -> str:
match = re.match(r"[A-Za-z0-9_.-]+", requirement)
if match is None:
raise AssertionError(f"Invalid requirement line: {requirement!r}")
return match.group(0).lower().replace("_", "-")
def _constraint_versions() -> dict[str, str]:
result: dict[str, str] = {}
for line in _active_lines(CONSTRAINTS_PATH):
parts = line.split("==")
if len(parts) != 2 or not all(parts):
raise AssertionError(
f"Direct constraint must be an exact package pin: {line!r}"
)
name, version = parts
normalized = _normalized_name(name)
if normalized in result:
raise AssertionError(f"Duplicate direct constraint: {normalized}")
result[normalized] = version
return result
def _release_lock_options() -> tuple[str, ...]:
return tuple(
line
for line in _active_lines(RELEASE_LOCK_PATH)
if line.startswith("--")
)
def _release_lock_entries() -> dict[str, tuple[str, str, str | None]]:
result: dict[str, tuple[str, str, str | None]] = {}
for line in _active_lines(RELEASE_LOCK_PATH):
if line.startswith("--"):
continue
match = LOCK_REQUIREMENT_PATTERN.fullmatch(line)
if match is None:
raise AssertionError(f"Invalid release-lock entry: {line!r}")
normalized = _normalized_name(match.group("name"))
if normalized in result:
raise AssertionError(f"Duplicate release-lock entry: {normalized}")
result[normalized] = (
match.group("version"),
match.group("digest"),
match.group("extras"),
)
return result
class DependencyConstraintContractTests(unittest.TestCase):
def test_python_reference_version_is_explicit(self) -> None:
self.assertEqual(
PYTHON_VERSION_PATH.read_text(encoding="utf-8").strip(),
"3.12.3",
)
def test_requirements_remain_ranges_and_declare_every_direct_package(
self,
) -> None:
requirements = _active_lines(REQUIREMENTS_PATH)
names = {_normalized_name(line) for line in requirements}
self.assertEqual(names, set(REFERENCE_DIRECT_VERSIONS))
self.assertTrue(all("==" not in line for line in requirements))
def test_reference_constraints_pin_only_direct_cross_platform_packages(
self,
) -> None:
self.assertEqual(_constraint_versions(), REFERENCE_DIRECT_VERSIONS)
self.assertTrue(
{
"httptools",
"pyyaml",
"uvloop",
"watchfiles",
"websockets",
}.isdisjoint(_constraint_versions())
)
def test_linux_release_lock_pins_and_hashes_complete_environment(
self,
) -> None:
self.assertEqual(
_release_lock_options(),
("--only-binary=:all:", "--require-hashes"),
)
entries = _release_lock_entries()
self.assertEqual(
{name: entry[0] for name, entry in entries.items()},
REFERENCE_LOCKED_VERSIONS,
)
self.assertTrue(all(len(entry[1]) == 64 for entry in entries.values()))
self.assertEqual(entries["uvicorn"][2], "standard")
self.assertTrue(
all(
entry[2] is None
for name, entry in entries.items()
if name != "uvicorn"
)
)
self.assertEqual(
{
name: REFERENCE_LOCKED_VERSIONS[name]
for name in REFERENCE_DIRECT_VERSIONS
},
REFERENCE_DIRECT_VERSIONS,
)
@unittest.skipUnless(
os.getenv(VERIFY_ENVIRONMENT_VARIABLE, "").strip().lower()
in {"1", "true", "yes", "on"},
f"Set {VERIFY_ENVIRONMENT_VARIABLE}=1 to verify installed versions.",
)
def test_installed_environment_matches_linux_release_lock(self) -> None:
self.assertEqual(sys.version_info[:3], (3, 12, 3))
self.assertEqual(sys.platform, "linux")
self.assertEqual(platform.machine().lower(), "x86_64")
installed = {
name: metadata.version(name)
for name in REFERENCE_LOCKED_VERSIONS
}
self.assertEqual(installed, REFERENCE_LOCKED_VERSIONS)
if __name__ == "__main__":
unittest.main()