import os import sys from pathlib import Path import pytest REPO_ROOT = Path(__file__).resolve().parents[1] SRC_ROOT = REPO_ROOT / "src" if str(SRC_ROOT) not in sys.path: sys.path.insert(0, str(SRC_ROOT)) from orisys import Sensor from orisys import configs as orisys_configs from orisys.backend_availability import check_cupy_available, check_opencl_available def _resolve_test_video() -> Path: env_video = os.getenv("ORISYS_TEST_VIDEO") if env_video: raw = Path(env_video) candidates = [ raw, # as provided (absolute or cwd-relative) REPO_ROOT / raw, # repo-relative ] # Common typo fallback: "test/..." -> "tests/..." if env_video.startswith("test/") or env_video.startswith("test\\"): fixed = Path("tests", *Path(env_video).parts[1:]) candidates.append(REPO_ROOT / fixed) for candidate in candidates: if candidate.exists(): return candidate return raw # Prefer tests/ fixture clip; fallback kept by caller exists check. return REPO_ROOT / "tests" / "idle_1min.mp4" @pytest.fixture(scope="session") def test_video_path() -> Path: path = _resolve_test_video() if not path.exists(): pytest.skip( "Test video not found. Set ORISYS_TEST_VIDEO to a valid video path." ) return path @pytest.fixture(scope="session") def test_config_name() -> str: requested = os.getenv("ORISYS_TEST_CONFIG") def _is_usable_config(name: str) -> bool: cfg = orisys_configs.load_config(name) return "box_size" in cfg.get("stitcher", {}) if requested: if not _is_usable_config(requested): raise RuntimeError( f"ORISYS_TEST_CONFIG='{requested}' is missing required key " "'stitcher.box_size'. Use a config like 'ddjx01' or provide a full path." ) return requested # Auto-pick a stable config for tests (avoid prototype variants missing keys). for name in orisys_configs.list_config(): try: if _is_usable_config(name): return name except Exception: continue raise RuntimeError( "No usable config found for tests (missing 'stitcher.box_size'). " "Set ORISYS_TEST_CONFIG to a valid config JSON/path." ) @pytest.fixture(scope="session") def available_backends() -> list[str]: backends = ["cpu"] if check_cupy_available(): backends.append("cupy") if check_opencl_available(): backends.append("opencl") return backends def make_sensor( video_path: Path, config_name: str = "prototype", backend: str = "cpu", verbose: bool = False, ) -> Sensor: use_cuda = backend in ("cupy", "opencl") return Sensor( vid_src=str(video_path), cuda=use_cuda, isstitch=True, verbose=verbose, config_name=config_name, backend=backend, ) @pytest.fixture def sensor_factory(test_video_path, test_config_name): def _factory(backend: str = "cpu", verbose: bool = False): return make_sensor( test_video_path, config_name=test_config_name, backend=backend, verbose=verbose, ) return _factory