from __future__ import annotations import json import re from pathlib import Path from fastapi.testclient import TestClient from app.models import OPTIONAL_BACKENDS, Registry, default_backends from .conftest import AUTH, make_settings CONTRACT = json.loads((Path(__file__).parent / "fixtures" / "media-capabilities.json").read_text()) def _assert_shape(body: dict) -> None: assert sorted(body) == sorted(CONTRACT["keys"]) assert body["configured"] is True assert body["accelerator"] in CONTRACT["accelerators"] assert isinstance(body["hardwareEncoders"], list) assert all(isinstance(name, str) for name in body["hardwareEncoders"]) assert sorted(body["operations"]) == sorted(CONTRACT["operations"]) for entry in body["operations"].values(): assert sorted(entry) == sorted(CONTRACT["operationKeys"]) assert isinstance(entry["available"], bool) assert isinstance(entry["experimental"], bool) assert entry["model"] is None or isinstance(entry["model"], str) assert entry["license"] is None or isinstance(entry["license"], str) assert entry["commercialUse"] in (True, False, None) def test_capabilities_match_the_contract(make_client) -> None: # Real registry, no fakes, downloads off: whatever is installed here. body = make_client(fakes=False).get("/v1/capabilities", headers=AUTH).json() _assert_shape(body) ops = body["operations"] # Operations that need no model weights work offline with the core requirements. for name in ("detectScenes", "redact", "audioFeatures", "saliency"): assert ops[name]["available"] is True, name assert ops["synthesizeIdentity"] == { "available": False, "experimental": True, "model": None, "license": None, "commercialUse": None, } # Weights are not installed and downloads are off. for name in ("transcribe", "detectFaces", "embedFrames", "inpaintVideo", "segmentPrompted"): assert ops[name]["available"] is False, name def test_with_fake_backends_everything_but_synthesis_is_available(client: TestClient) -> None: body = client.get("/v1/capabilities", headers=AUTH).json() _assert_shape(body) unavailable = [name for name, entry in body["operations"].items() if not entry["available"]] assert unavailable == ["synthesizeIdentity"] def test_default_backends_are_commercially_usable_and_pinned() -> None: for operation, backend in default_backends().items(): spec = backend.spec if spec.unavailable_reason: continue assert spec.commercialUse is True, operation assert spec.license, operation for model_file in spec.files: assert re.fullmatch(r"[0-9a-f]{64}", model_file.sha256), model_file.name assert model_file.sizeBytes > 0 assert model_file.url.startswith("https://") assert "/resolve/main/" not in model_file.url, "pin a revision, not a branch" for backend in OPTIONAL_BACKENDS.values(): assert backend.spec.commercialUse is not True def test_optional_backend_needs_opt_in(media_root: Path, tmp_path: Path) -> None: registry = Registry(make_settings(media_root, tmp_path)) assert not registry.optional_enabled("faceIdentity") reason = registry.unavailable_reason(OPTIONAL_BACKENDS["faceIdentity"], "faceIdentity") assert reason is not None and "MEDIA_OPTIONAL_BACKENDS" in reason opted = Registry(make_settings(media_root, tmp_path, optional_backends=frozenset({"faceIdentity"}))) reason = opted.unavailable_reason(OPTIONAL_BACKENDS["faceIdentity"], "faceIdentity") assert reason is None or "MEDIA_OPTIONAL_BACKENDS" not in reason