"""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")