| """Smoke tests for backend/kpis_scheduler.py. |
| |
| Exercise the pure / fast paths only: |
| * token resolution order |
| * build_kpis import path |
| * start()/shutdown() lifecycle without APScheduler actually running a job |
| * backfill() passes the right hour values through to _run_hour |
| """ |
|
|
| from __future__ import annotations |
|
|
| import asyncio |
| import importlib.util |
| import sys |
| from datetime import datetime, timezone |
| from pathlib import Path |
|
|
|
|
| def _load(): |
| path = Path(__file__).parent.parent.parent / "backend" / "kpis_scheduler.py" |
| spec = importlib.util.spec_from_file_location("kpis_scheduler", path) |
| mod = importlib.util.module_from_spec(spec) |
| sys.modules["kpis_scheduler"] = mod |
| assert spec.loader is not None |
| spec.loader.exec_module(mod) |
| return mod |
|
|
|
|
| def test_token_resolution_order(monkeypatch): |
| mod = _load() |
| for var in ( |
| "HF_KPI_WRITE_TOKEN", |
| "HF_SESSION_UPLOAD_TOKEN", |
| "HF_TOKEN", |
| "HF_ADMIN_TOKEN", |
| ): |
| monkeypatch.delenv(var, raising=False) |
| assert mod._resolve_token() is None |
|
|
| monkeypatch.setenv("HF_ADMIN_TOKEN", "admin") |
| assert mod._resolve_token() == "admin" |
|
|
| monkeypatch.setenv("HF_TOKEN", "generic") |
| assert mod._resolve_token() == "generic" |
|
|
| monkeypatch.setenv("HF_SESSION_UPLOAD_TOKEN", "sessions") |
| assert mod._resolve_token() == "sessions" |
|
|
| monkeypatch.setenv("HF_KPI_WRITE_TOKEN", "kpis") |
| assert mod._resolve_token() == "kpis" |
|
|
|
|
| def test_load_build_kpis_exposes_run_for_hour(): |
| mod = _load() |
| bk = mod._load_build_kpis() |
| assert hasattr(bk, "run_for_hour") |
| assert callable(bk.run_for_hour) |
|
|
|
|
| def test_backfill_calls_run_hour_for_each_hour(monkeypatch): |
| mod = _load() |
| monkeypatch.setenv("HF_KPI_WRITE_TOKEN", "x") |
| calls: list[datetime] = [] |
|
|
| async def fake_run_hour(hour_dt): |
| calls.append(hour_dt) |
|
|
| monkeypatch.setattr(mod, "_run_hour", fake_run_hour) |
| asyncio.run(mod.backfill(hours=3)) |
| assert len(calls) == 3 |
| |
| assert calls[0] > calls[1] > calls[2] |
| |
| for c in calls: |
| assert c.minute == 0 and c.second == 0 and c.microsecond == 0 |
| assert c.tzinfo == timezone.utc |
|
|
|
|
| def test_start_is_no_op_when_disabled(monkeypatch): |
| mod = _load() |
| |
| mod._scheduler = None |
| monkeypatch.setenv("ML_INTERN_KPIS_DISABLED", "1") |
| mod.start() |
| assert mod._scheduler is None |
|
|
|
|
| def test_start_skips_cleanly_without_apscheduler(monkeypatch): |
| mod = _load() |
| mod._scheduler = None |
| monkeypatch.delenv("ML_INTERN_KPIS_DISABLED", raising=False) |
|
|
| |
| real_import = ( |
| __builtins__["__import__"] |
| if isinstance(__builtins__, dict) |
| else __builtins__.__import__ |
| ) |
|
|
| def fake_import(name, *args, **kwargs): |
| if name.startswith("apscheduler"): |
| raise ImportError("apscheduler unavailable in test") |
| return real_import(name, *args, **kwargs) |
|
|
| monkeypatch.setattr( |
| "builtins.__import__", |
| fake_import, |
| ) |
| mod.start() |
| assert mod._scheduler is None |
|
|
|
|
| def test_shutdown_is_no_op_when_not_started(): |
| mod = _load() |
| mod._scheduler = None |
| asyncio.run(mod.shutdown()) |
|
|