feat: add governed nationwide AOI orchestration and CUDA enforcement
This commit is contained in:
@@ -2,13 +2,15 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from app.core.config import Settings
|
||||
from app.core.errors import AppError
|
||||
from app.models import AnalysisRun, Dataset, Detection, Job, Project
|
||||
from app.models import AnalysisRun, Area, Dataset, Detection, Job, Project
|
||||
from app.services.detection_georeferencing import pixel_bbox_to_epsg4326_polygon
|
||||
from app.services.detection_service import DetectionService
|
||||
from app.services.model_registry_service import ModelRegistryService
|
||||
@@ -235,6 +237,7 @@ def test_yolo_configured_model_reports_configured_with_local_model_and_dependenc
|
||||
assert model.nationally_validated is False
|
||||
assert model.operator_review_required is True
|
||||
assert model.validated_regions == ["flanders_mol_kempen"]
|
||||
assert model.supported_classes == ["building"]
|
||||
assert "Mol and the Kempen" in (model.validation_scope or "")
|
||||
|
||||
|
||||
@@ -246,6 +249,45 @@ def test_yolo_dependency_check_uses_real_imports_not_find_spec() -> None:
|
||||
assert "import torch" in source
|
||||
|
||||
|
||||
def test_yolo_runtime_fails_closed_when_cuda_is_required_but_unavailable(tmp_path: Path, monkeypatch) -> None:
|
||||
settings = _settings(tmp_path, yolo_device="cuda:0", yolo_require_cuda=True)
|
||||
monkeypatch.setitem(sys.modules, "torch", SimpleNamespace(cuda=SimpleNamespace(is_available=lambda: False)))
|
||||
|
||||
with pytest.raises(AppError) as exc_info:
|
||||
YoloDetectionAdapter(settings).validate_runtime()
|
||||
|
||||
assert exc_info.value.code == "DETECTION_ACCELERATOR_UNAVAILABLE"
|
||||
|
||||
|
||||
def test_yolo_runtime_rejects_cpu_device_when_cuda_is_required(tmp_path: Path, monkeypatch) -> None:
|
||||
settings = _settings(tmp_path, yolo_device="cpu", yolo_require_cuda=True)
|
||||
monkeypatch.setitem(sys.modules, "torch", SimpleNamespace(cuda=SimpleNamespace(is_available=lambda: True)))
|
||||
|
||||
with pytest.raises(AppError) as exc_info:
|
||||
YoloDetectionAdapter(settings).validate_runtime()
|
||||
|
||||
assert exc_info.value.code == "DETECTION_ACCELERATOR_MISCONFIGURED"
|
||||
|
||||
|
||||
def test_yolo_validation_scope_requires_persisted_validated_area(tmp_path: Path) -> None:
|
||||
dataset = Dataset(id=uuid4(), project_id=uuid4(), name="image.tif", dataset_type="raster", source="test", area_id=uuid4())
|
||||
wrong_area = Area(id=dataset.area_id, project_id=dataset.project_id, name="Brussels", geometry="MULTIPOLYGON EMPTY")
|
||||
db = FakeSession(objects={(Area, dataset.area_id): wrong_area})
|
||||
|
||||
with pytest.raises(AppError) as exc_info:
|
||||
DetectionService._validate_model_area_scope(db, dataset, _settings(tmp_path, yolo_validated_area_names="Mol,Kempen"))
|
||||
|
||||
assert exc_info.value.code == "DETECTION_VALIDATION_SCOPE_UNAVAILABLE"
|
||||
|
||||
|
||||
def test_yolo_validation_scope_accepts_bound_mol_area(tmp_path: Path) -> None:
|
||||
dataset = Dataset(id=uuid4(), project_id=uuid4(), name="image.tif", dataset_type="raster", source="test", area_id=uuid4())
|
||||
area = Area(id=dataset.area_id, project_id=dataset.project_id, name="Gemeente Mol", geometry="MULTIPOLYGON EMPTY")
|
||||
db = FakeSession(objects={(Area, dataset.area_id): area})
|
||||
|
||||
DetectionService._validate_model_area_scope(db, dataset, _settings(tmp_path, yolo_validated_area_names="Mol,Kempen"))
|
||||
|
||||
|
||||
def test_yolo_run_requires_tile_manifest_path(tmp_path: Path) -> None:
|
||||
db, project_id, dataset_id = _project_and_dataset()
|
||||
settings = _settings(tmp_path)
|
||||
|
||||
Reference in New Issue
Block a user