NODEDC_MISSION_CORE/tests/test_dataset_gateway.py

108 lines
3.8 KiB
Python

from __future__ import annotations
from pathlib import Path
import numpy as np
import pytest
from fastapi import APIRouter
from fastapi.routing import APIRoute
from k1link.datasets import (
DatasetFrameError,
dataset_gateway_catalog,
read_semantic_kitti_frame,
)
from k1link.web.lidar_api import build_lidar_router
def _endpoint(router: APIRouter, path: str) -> object:
for route in router.routes:
if isinstance(route, APIRoute) and route.path == path and "GET" in route.methods:
return route.endpoint
raise AssertionError(f"GET {path} route is missing")
def test_goose_semantickitti_frame_retains_xyzi_and_packed_labels(
tmp_path: Path,
) -> None:
points_path = tmp_path / "frame_vls128.bin"
labels_path = tmp_path / "frame_goose.label"
np.asarray(
[
[1.0, 2.0, 3.0, 0.25],
[-4.0, 5.0, 0.5, 0.75],
],
dtype="<f4",
).tofile(points_path)
np.asarray(
[
(12 << 16) | 3,
(99 << 16) | 42,
],
dtype="<u4",
).tofile(labels_path)
frame = read_semantic_kitti_frame(points_path, labels_path)
assert frame.representation == "native-scan"
assert frame.point_count == 2
assert frame.points_xyz_m.tolist() == [[1.0, 2.0, 3.0], [-4.0, 5.0, 0.5]]
assert frame.remission.tolist() == [0.25, 0.75]
assert frame.semantic_labels.tolist() == [3, 42]
assert frame.instance_labels.tolist() == [12, 99]
assert frame.points_xyz_m.flags.writeable is False
def test_dataset_frame_fails_closed_on_misaligned_or_nonfinite_input(
tmp_path: Path,
) -> None:
points_path = tmp_path / "frame.bin"
labels_path = tmp_path / "frame.label"
np.asarray([[1.0, 2.0, 3.0, 0.25]], dtype="<f4").tofile(points_path)
np.asarray([1, 2], dtype="<u4").tofile(labels_path)
with pytest.raises(DatasetFrameError, match="counts do not match"):
read_semantic_kitti_frame(points_path, labels_path)
np.asarray([[np.nan, 2.0, 3.0, 0.25]], dtype="<f4").tofile(points_path)
np.asarray([1], dtype="<u4").tofile(labels_path)
with pytest.raises(DatasetFrameError, match="non-finite"):
read_semantic_kitti_frame(points_path, labels_path)
def test_dataset_gateway_enforces_d_storage_and_representation_boundaries(
tmp_path: Path,
) -> None:
blocked = dataset_gateway_catalog(tmp_path / "datasets")
admitted = dataset_gateway_catalog(Path("/mnt/d/NDC_MISSIONCORE/datasets"))
assert blocked["storage"]["status"] == "blocked-storage-policy" # type: ignore[index]
assert admitted["storage"]["status"] == "ready" # type: ignore[index]
assert admitted["next_action"] == "download-goose-validation-to-d"
representations = admitted["representations"]
assert isinstance(representations, list)
assert [item["id"] for item in representations] == [ # type: ignore[index]
"native-scan",
"normalized-scan",
"rolling-local-map",
]
inputs = admitted["known_inputs"]
assert isinstance(inputs, list)
assert inputs[0]["admitted_for_patchworkpp"] is False # type: ignore[index]
def test_dataset_gateway_api_is_read_only_and_path_free(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("MISSIONCORE_DATASET_ROOT", "/mnt/d/NDC_MISSIONCORE/datasets")
route = _endpoint(build_lidar_router(), "/api/v1/lidar/dataset-gateway")
response = route() # type: ignore[operator]
assert response["schema_version"] == "missioncore.dataset-gateway-catalog/v1"
assert response["access"] == "read-only"
assert response["storage"]["admitted"] is True
assert response["storage"]["path_exposed"] is False
assert "/mnt/d/NDC_MISSIONCORE/datasets" not in repr(response).replace(
response["storage"]["required_wsl_root"], # type: ignore[index]
"",
)