Files
Oleksandr Bezdieniezhnykh f49d803252 [AZ-597] Batch 77: replay_mode helpers + 13 scenario stub rewires
Add `runner/helpers/replay_mode.py` (NullFrameSink, NullFcInboundEmitter,
default_frame_period_ms, load_replay_json, resolve_replay_subdir,
imu_replay_noop) and rewire all 13 scenarios off their local
`_resolve_*` / `_drive_*` / `_push_*` NotImplementedError stubs.

Closes the offline FDR-replay execution path. `grep raise
NotImplementedError` under `e2e/tests/` now returns zero matches. +17
unit tests (626 total, up from 608). Unit-test behaviour unchanged
(scenarios still skip via b75 sitl_replay_ready gate when
E2E_SITL_REPLAY_DIR is unset).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 09:52:05 +03:00

185 lines
4.3 KiB
Python

"""Unit tests for `e2e/runner/helpers/replay_mode.py` (AZ-597)."""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from e2e.runner.helpers import replay_mode as rm
@pytest.fixture
def replay_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
monkeypatch.setenv("E2E_SITL_REPLAY_DIR", str(tmp_path))
return tmp_path
@pytest.fixture
def unset_replay_dir(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.delenv("E2E_SITL_REPLAY_DIR", raising=False)
# NullFrameSink
def test_null_frame_sink_counts_writes():
# Arrange
sink = rm.NullFrameSink()
# Act
sink.write_frame(b"jpeg-bytes-1", timestamp_ms=100)
sink.write_frame(b"jpeg-bytes-2", timestamp_ms=200)
sink.write_frame(b"jpeg-bytes-3", timestamp_ms=300)
# Assert
assert sink.frames_written == 3
def test_null_frame_sink_starts_at_zero():
# Assert
assert rm.NullFrameSink().frames_written == 0
# NullFcInboundEmitter
def test_null_emitter_counts_emits():
# Arrange
emitter = rm.NullFcInboundEmitter()
# Act
emitter.emit(object())
emitter.emit(object())
# Assert
assert emitter.samples_emitted == 2
def test_null_emitter_starts_at_zero():
# Assert
assert rm.NullFcInboundEmitter().samples_emitted == 0
# default_frame_period_ms
def test_default_frame_period_ms_is_30_fps():
# Assert
assert rm.default_frame_period_ms() == 33
assert rm.DEFAULT_FRAME_PERIOD_MS == 33
# imu_replay_noop
def test_imu_replay_noop_returns_none(tmp_path: Path):
# Assert
assert rm.imu_replay_noop(tmp_path / "any.csv") is None
def test_imu_replay_noop_does_not_touch_disk(tmp_path: Path):
# Arrange
csv = tmp_path / "does-not-exist.csv"
# Act
rm.imu_replay_noop(csv)
# Assert
assert not csv.exists()
# load_replay_json
def test_load_replay_json_raises_when_env_unset(unset_replay_dir):
# Assert
with pytest.raises(FileNotFoundError, match="E2E_SITL_REPLAY_DIR.*not set"):
rm.load_replay_json("any.json")
def test_load_replay_json_raises_when_env_empty(monkeypatch: pytest.MonkeyPatch):
# Arrange
monkeypatch.setenv("E2E_SITL_REPLAY_DIR", " ")
# Assert
with pytest.raises(FileNotFoundError, match="not set or empty"):
rm.load_replay_json("any.json")
def test_load_replay_json_raises_when_file_missing(replay_dir: Path):
# Assert
with pytest.raises(FileNotFoundError, match="replay fixture 'gone.json' not found"):
rm.load_replay_json("gone.json")
def test_load_replay_json_raises_on_malformed_json(replay_dir: Path):
# Arrange
(replay_dir / "bad.json").write_text("{not valid")
# Assert
with pytest.raises(ValueError, match="malformed replay fixture JSON"):
rm.load_replay_json("bad.json")
def test_load_replay_json_round_trips_dict(replay_dir: Path):
# Arrange
payload = {"key": "value", "nested": {"a": 1}}
(replay_dir / "ok.json").write_text(json.dumps(payload))
# Act
result = rm.load_replay_json("ok.json")
# Assert
assert result == payload
def test_load_replay_json_round_trips_list(replay_dir: Path):
# Arrange
payload = [{"frame_idx": i} for i in range(3)]
(replay_dir / "list.json").write_text(json.dumps(payload))
# Act
result = rm.load_replay_json("list.json")
# Assert
assert result == payload
# resolve_replay_subdir
def test_resolve_replay_subdir_raises_when_env_unset(unset_replay_dir):
# Assert
with pytest.raises(FileNotFoundError, match="E2E_SITL_REPLAY_DIR.*not set"):
rm.resolve_replay_subdir("frames")
def test_resolve_replay_subdir_raises_when_subdir_missing(replay_dir: Path):
# Assert
with pytest.raises(FileNotFoundError, match="replay fixture subdir 'frames' not found"):
rm.resolve_replay_subdir("frames")
def test_resolve_replay_subdir_returns_path_when_exists(replay_dir: Path):
# Arrange
target = replay_dir / "frames"
target.mkdir()
# Act
result = rm.resolve_replay_subdir("frames")
# Assert
assert result == target
assert result.is_dir()
def test_resolve_replay_subdir_rejects_file_at_path(replay_dir: Path):
# Arrange
(replay_dir / "actually-a-file").write_text("oops")
# Assert
with pytest.raises(FileNotFoundError, match="subdir 'actually-a-file' not found"):
rm.resolve_replay_subdir("actually-a-file")