88 lines
2.4 KiB
Python
88 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from k1link.compute.realtime_tracking_qualification import (
|
|
FRAME_SCHEMA,
|
|
TELEMETRY_SCHEMA,
|
|
_validate_realtime_frames,
|
|
_validate_realtime_telemetry,
|
|
)
|
|
from k1link.sessions import SessionIntegrityError
|
|
|
|
|
|
def _frame(index: int) -> dict[str, object]:
|
|
return {
|
|
"schema_version": FRAME_SCHEMA,
|
|
"frame_index": index,
|
|
"sequence": index + 1,
|
|
"source_frame_index": 1000 + index,
|
|
"source_sequence": 1001 + index,
|
|
"session_seconds": 135.0 + index * 0.1,
|
|
"detections": [],
|
|
"tracks": [],
|
|
"delivery": {"health": "healthy", "result_age_ms": 50.0},
|
|
}
|
|
|
|
|
|
def _telemetry(index: int) -> dict[str, object]:
|
|
return {
|
|
"schema_version": TELEMETRY_SCHEMA,
|
|
"frame_index": index,
|
|
"session_seconds": 135.0 + index * 0.1,
|
|
"health": "healthy",
|
|
"result_age_ms": 50.0,
|
|
"processing_ms": 20.0,
|
|
"queue_depth_after_take": 0,
|
|
"queue_dropped_overflow": 0,
|
|
}
|
|
|
|
|
|
def test_realtime_rows_allow_explicit_latest_wins_gaps(tmp_path: Path) -> None:
|
|
indices = (0, 2, 3)
|
|
frames = tmp_path / "frames.jsonl"
|
|
telemetry = tmp_path / "telemetry.jsonl"
|
|
frames.write_text(
|
|
"".join(json.dumps(_frame(index)) + "\n" for index in indices),
|
|
encoding="utf-8",
|
|
)
|
|
telemetry.write_text(
|
|
"".join(json.dumps(_telemetry(index)) + "\n" for index in indices),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
observed = _validate_realtime_frames(
|
|
frames,
|
|
tmp_path,
|
|
expected_count=3,
|
|
selection_count=4,
|
|
source_start=1000,
|
|
timeline_start=135.0,
|
|
timeline_end=135.3,
|
|
)
|
|
_validate_realtime_telemetry(telemetry, tmp_path, expected_indices=observed)
|
|
|
|
assert observed == indices
|
|
|
|
|
|
def test_realtime_rows_reject_out_of_order_results(tmp_path: Path) -> None:
|
|
frames = tmp_path / "frames.jsonl"
|
|
frames.write_text(
|
|
json.dumps(_frame(1)) + "\n" + json.dumps(_frame(0)) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(SessionIntegrityError, match="frame metadata"):
|
|
_validate_realtime_frames(
|
|
frames,
|
|
tmp_path,
|
|
expected_count=2,
|
|
selection_count=4,
|
|
source_start=1000,
|
|
timeline_start=135.0,
|
|
timeline_end=135.3,
|
|
)
|