Source: tests/test_geometry_supplier.py · Plain text

tests/test_geometry_supplier.py

import json
from dataclasses import replace
from pathlib import Path

import numpy as np
import pytest
import torch

from mcss.geometry_supplier import (
    CodeDependency,
    GeometrySupplierRequest,
    GeometrySupplierResult,
    SupplierIdentity,
    SupplierRunConfig,
    read_supplier_cache,
    write_supplier_cache,
)
from mcss.types import Cameras


def _request(frame_ids: tuple[int, ...] = (20, 10)) -> GeometrySupplierRequest:
    rgb = torch.stack(
        [torch.full((3, 4, 5), float(frame_id) / 100.0) for frame_id in frame_ids]
    )
    intrinsics = torch.tensor(
        [[[4.0, 0.0, 2.0], [0.0, 4.0, 1.5], [0.0, 0.0, 1.0]]] * len(frame_ids)
    )
    c2w = torch.eye(4).repeat(len(frame_ids), 1, 1)
    c2w[:, 0, 3] = torch.tensor(frame_ids, dtype=torch.float32) / 10.0
    return GeometrySupplierRequest(frame_ids, rgb, Cameras(intrinsics, c2w, (4, 5)))


def _result(request: GeometrySupplierRequest) -> GeometrySupplierResult:
    canonical = request.canonical()
    view_count = len(canonical.frame_ids)
    depth = np.stack(
        [np.full((4, 5), float(frame_id), dtype=np.float32) for frame_id in canonical.frame_ids]
    )
    return GeometrySupplierResult(
        frame_ids=canonical.frame_ids,
        depth_along_ray=depth,
        confidence=np.ones((view_count, 4, 5), dtype=np.float32),
        valid_mask=np.ones((view_count, 4, 5), dtype=np.bool_),
        intrinsics=canonical.cameras.intrinsics.numpy(),
        c2w=canonical.cameras.c2w.numpy(),
    )


def test_request_canonicalizes_by_frame_id_and_hashes_content() -> None:
    request = _request()
    canonical = request.canonical()

    assert canonical.frame_ids == (10, 20)
    assert torch.allclose(canonical.rgb[:, 0, 0, 0], torch.tensor([0.1, 0.2]))
    assert canonical.input_sha256 == _request((10, 20)).input_sha256
    changed = _request()
    changed.rgb[0, 0, 0, 0] += 0.01
    assert changed.input_sha256 != request.input_sha256


def test_request_rejects_duplicate_frames_and_mismatched_views() -> None:
    with pytest.raises(ValueError, match="unique"):
        _request((10, 10))

    request = _request()
    with pytest.raises(ValueError, match="view"):
        GeometrySupplierRequest(request.frame_ids, request.rgb[:1], request.cameras)


def test_atomic_supplier_cache_round_trip_refuses_overwrite_and_detects_tamper(
    tmp_path: Path,
) -> None:
    request = _request().canonical()
    result = _result(request)
    identity = SupplierIdentity(
        model_id="facebook/map-anything",
        model_revision="model-revision",
        code_repository="facebookresearch/map-anything",
        code_revision="code-revision",
        dependencies=(
            CodeDependency(
                name="dinov2",
                repository="facebookresearch/dinov2",
                revision="dinov2-revision",
                source_sha256="a" * 64,
            ),
        ),
    )
    config = SupplierRunConfig()
    destination = tmp_path / "supplier"

    write_supplier_cache(destination, result, identity, request.input_sha256, config)
    loaded, metadata = read_supplier_cache(destination)

    assert loaded.frame_ids == (10, 20)
    assert np.array_equal(loaded.depth_along_ray, result.depth_along_ray)
    assert metadata["input_sha256"] == request.input_sha256
    assert metadata["identity"]["model_revision"] == "model-revision"
    assert metadata["identity"]["dependencies"] == [
        {
            "name": "dinov2",
            "repository": "facebookresearch/dinov2",
            "revision": "dinov2-revision",
            "source_sha256": "a" * 64,
        }
    ]
    assert not list(tmp_path.glob(".supplier.tmp-*"))
    with pytest.raises(FileExistsError):
        write_supplier_cache(destination, result, identity, request.input_sha256, config)

    arrays = destination / "arrays.npz"
    arrays.write_bytes(arrays.read_bytes() + b"tamper")
    with pytest.raises(ValueError, match="hash"):
        read_supplier_cache(destination)


def test_cache_metadata_cannot_claim_different_frames(tmp_path: Path) -> None:
    request = _request().canonical()
    destination = tmp_path / "supplier"
    write_supplier_cache(
        destination,
        _result(request),
        SupplierIdentity("model", "revision", "repo", "code"),
        request.input_sha256,
        SupplierRunConfig(),
    )
    metadata_path = destination / "metadata.json"
    metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
    metadata["frame_ids"] = [999, 1000]
    metadata_path.write_text(json.dumps(metadata), encoding="utf-8")

    with pytest.raises(ValueError, match="metadata"):
        read_supplier_cache(destination)


def test_result_rejects_nonfinite_depth_and_shape_mismatch() -> None:
    request = _request().canonical()
    result = _result(request)
    bad_depth = result.depth_along_ray.copy()
    bad_depth[0, 0, 0] = np.nan
    with pytest.raises(ValueError, match="finite"):
        replace(result, depth_along_ray=bad_depth)
    with pytest.raises(ValueError, match="shape"):
        replace(result, confidence=result.confidence[:, :-1])