from __future__ import annotations import json import zipfile from pathlib import Path import numpy as np import pytest from fastapi import APIRouter from fastapi.routing import APIRoute from k1link.datasets import ( DatasetAdmissionError, DatasetFrameError, dataset_gateway_catalog, goose_admission, goose_benchmark, read_dataset_admission_manifest, read_dataset_ground_preview, read_dataset_native_scan_preview, read_semantic_kitti_frame, ) from k1link.datasets.goose_admission import admit_goose_validation from k1link.datasets.goose_benchmark import benchmark_goose_current_ground 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=" None: points_path = tmp_path / "frame.bin" labels_path = tmp_path / "frame.label" np.asarray([[1.0, 2.0, 3.0, 0.25]], dtype=" 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/v2" 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] "", ) def _downloading_manifest() -> dict[str, object]: return { "schema_version": "missioncore.dataset-admission/v1", "source_id": "goose-3d/v2025-08-22", "observed_at_utc": "2026-07-25T10:00:00Z", "status": "downloading", "storage": { "policy": "worker-d-only", "admitted": True, "canonical_root": True, "path_exposed": False, }, "archive": { "filename": "goose_3d_val.zip", "source_url": "https://goose-dataset.de/storage/goose_3d_val.zip", "bytes_transferred": 512, "total_bytes": 1024, "size_bytes": None, "sha256": None, "integrity": "pending", "vendor_checksum_available": False, }, "license": { "spdx": "CC-BY-SA-4.0", "artifact_present": False, }, "frame": None, "next_action": "complete-download-and-admit", } def test_dataset_gateway_uses_worker_manifest_instead_of_static_download_state( tmp_path: Path, ) -> None: manifest_path = tmp_path / "admission.json" manifest_path.write_text(json.dumps(_downloading_manifest()), encoding="utf-8") catalog = dataset_gateway_catalog( tmp_path / "not-worker-d", admission_manifest_path=manifest_path, ) assert catalog["storage"]["admitted"] is True # type: ignore[index] assert catalog["storage"]["attestation"] == "worker-manifest" # type: ignore[index] source = catalog["sources"][0] # type: ignore[index] assert source["admission"]["status"] == "downloading" # type: ignore[index] assert source["admission"]["archive"]["bytes_transferred"] == 512 # type: ignore[index] assert catalog["next_action"] == "complete-download-and-admit" def test_dataset_admission_manifest_fails_closed_on_forged_storage( tmp_path: Path, ) -> None: manifest = _downloading_manifest() manifest["storage"]["path_exposed"] = True # type: ignore[index] path = tmp_path / "admission.json" path.write_text(json.dumps(manifest), encoding="utf-8") with pytest.raises(DatasetAdmissionError, match="storage admission"): read_dataset_admission_manifest(path) def test_goose_admission_extracts_one_aligned_frame_and_bounded_preview( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: root = tmp_path / "datasets" archive = root / "goose-3d/v2025-08-22/archives/goose_3d_val.zip" archive.parent.mkdir(parents=True) points = np.asarray( [ [1.0, 2.0, 3.0, 0.25], [-4.0, 5.0, 0.5, 0.75], [2.0, 1.0, -0.2, 0.5], ], dtype=" None: preview_path = tmp_path / "preview.json" preview_path.write_text( json.dumps( { "schema_version": "missioncore.dataset-native-scan-preview/v1", "source_id": "goose-3d/v2025-08-22", "frame_id": "frame-1", "representation": "native-scan", "sampling": "deterministic-even-index", "source_point_count": 1, "point_count": 1, "points_xyz_m": [[1.0, 2.0, 3.0]], "remission_0_to_255": [128], "semantic_label_ids": [23], "semantic_rgb_0_to_255": [255, 47, 128], "ground_truth_ground": [1], "classes": [ { "label_id": 23, "class_name": "asphalt", "hex": "#ff2f80", "challenge_category_id": 2, "challenge_category_name": "artificial_ground", } ], "safety": { "visualization_only": True, "navigation_or_safety_accepted": False, }, } ), encoding="utf-8", ) router = build_lidar_router( dataset_admission_provider=lambda: None, dataset_preview_provider=lambda: preview_path, ) route = _endpoint(router, "/api/v1/lidar/dataset-gateway/preview") response = route() # type: ignore[operator] assert response["frame_id"] == "frame-1" def test_goose_current_ground_is_scored_against_independent_labels( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: root = tmp_path / "datasets" digest = "a" * 64 frame_id = "frame-1" install = root / f"goose-3d/v2025-08-22/installs/{digest}" frame_root = install / f"frames/{frame_id}" frame_root.mkdir(parents=True) np.asarray( [ [-1.0, 0.0, 0.00, 0.1], [0.0, 0.0, 0.02, 0.2], [1.0, 0.0, 0.01, 0.3], [0.0, 0.2, 1.50, 0.4], ], dtype="