mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 14:41:15 +00:00
[AZ-594] Implement core-three harness stubs (fdr_reader, frame_source_replay, imu_replay)
Replaces the NotImplementedError stubs AZ-406 reserved on three runner-
side helpers; these were stranded from any tracker ticket since
AZ-407/408 never came back to fill them. Concrete bodies:
* fdr_reader.iter_records: JSONL parser + wire-envelope validator;
recursive *.jsonl walk; projects {schema_version, ts, producer_id,
kind, payload} to runner-side FdrRecord with record_type/monotonic_ms
renames; yields oldest-first.
* frame_source_replay.replay_video: OpenCV VideoCapture decode + JPEG
re-encode; auto-detects file vs directory; injectable sleep_fn for
unit-test pacing.
* imu_replay.ImuReplayer.replay: csv.DictReader parse; degrees->radians
attitude conversion; tolerates scientific notation; same sleep_fn
injection pattern.
Adds 34 unit tests (14 + 10 + 10). Full e2e unit suite: 558 passed (+31).
Existing scenario _harness_helpers_implemented probes still return False
because they also depend on sitl_observer / fc_proxy_runtime stubs that
remain pending; scenario probe cleanup is out of AZ-594 scope.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# Harness stubs — core three (fdr_reader, frame_source_replay, imu_replay)
|
||||
|
||||
**Task**: AZ-594_harness_stubs_core_three
|
||||
**Name**: Implement the three foundational e2e/runner/helpers/ stubs that AZ-406 reserved
|
||||
**Description**: Replace `NotImplementedError` stubs in `fdr_reader.iter_records`, `frame_source_replay.replay_video`, and `imu_replay.ImuReplayer.replay` with concrete bodies. Together they unblock the skip-gated scenarios from batches 71-73 once `sitl_observer` lands.
|
||||
**Complexity**: 4 points
|
||||
**Dependencies**: AZ-406, AZ-407, AZ-408
|
||||
**Component**: Blackbox Tests / Test Infrastructure (epic AZ-262)
|
||||
**Tracker**: AZ-594
|
||||
**Epic**: AZ-262 (E-BBT)
|
||||
|
||||
## Problem
|
||||
|
||||
AZ-406 committed to the public surface of the runner-side helpers and
|
||||
reserved each method body as `NotImplementedError`. AZ-407/408 filled
|
||||
the fixture-builder side; the runtime replay/read surfaces were
|
||||
deferred without a dedicated ticket. The skip-gated scenarios in
|
||||
batches 71-73 (`test_ft_p_07/08/10/11`, `test_ft_n_01..04`) reference
|
||||
these stubs in their `_harness_helpers_implemented` probe and skip
|
||||
cleanly until the bodies land.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `fdr_reader.iter_records` reads `*.jsonl` files under an archive
|
||||
root and yields `FdrRecord` envelopes ordered by `monotonic_ms`.
|
||||
- `frame_source_replay.replay_video` decodes `.mp4` files or
|
||||
directories of `.jpg`/`.png` frames via OpenCV and emits to the
|
||||
injected `FrameSink` at the requested cadence.
|
||||
- `imu_replay.ImuReplayer.replay` parses `data_imu.csv` and drives a
|
||||
`FcInboundEmitter` at the configured rate.
|
||||
- Each body has ≥5 unit tests (happy path + ≥2 error paths + ≥1
|
||||
boundary case).
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- The three method bodies + their unit tests.
|
||||
- Layout-test entries (already present for the helper files).
|
||||
|
||||
### Excluded
|
||||
- `sitl_observer.get_observer` + `read_*` surfaces — separate ticket.
|
||||
- `fc_proxy` runtime driver — separate ticket.
|
||||
- Removing the skip-gates in existing scenarios — happens once
|
||||
`sitl_observer` lands.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1**: `fdr_reader.iter_records` opens every `*.jsonl` file under
|
||||
the archive root, parses each line as JSON, and yields `FdrRecord`
|
||||
envelopes sorted by `monotonic_ms`. Raises `FileNotFoundError` on
|
||||
missing root.
|
||||
|
||||
**AC-2**: `frame_source_replay.replay_video` accepts an `.mp4` file
|
||||
OR a directory of `.jpg`/`.png` frames; decodes via OpenCV; emits to
|
||||
the sink at the cadence (encoded FPS if `realtime`, configured FPS
|
||||
otherwise). Returns the count emitted. Raises `FileNotFoundError` on
|
||||
missing input.
|
||||
|
||||
**AC-3**: `imu_replay.ImuReplayer.replay` parses the CSV at
|
||||
`csv_path`, constructs `ImuSample`s with accel/gyro/attitude/baro,
|
||||
and calls `emitter.emit(sample)` for each row. Returns the count
|
||||
emitted. Tolerates scientific-notation floats.
|
||||
|
||||
**AC-4**: Each new body has ≥5 unit tests in
|
||||
`e2e/_unit_tests/helpers/` covering the happy path + 2 error paths +
|
||||
1 boundary case.
|
||||
|
||||
**AC-5**: Full e2e unit-test suite passes (regression gate).
|
||||
|
||||
## System Under Test Boundary
|
||||
|
||||
None — these are runner-side helpers that synthesize the SUT's
|
||||
inputs and parse the SUT's FDR output. They do NOT import any
|
||||
`src/gps_denied_onboard` symbol.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Use `opencv-python-headless` (already pinned in
|
||||
`e2e/runner/requirements.txt`).
|
||||
- `imu_replay.replay` must not block on wall-clock at the requested
|
||||
rate when called in tests; a `time.sleep`-based pacing path is
|
||||
acceptable for production use but the test must inject a fake
|
||||
clock / cadence=0 to keep unit tests fast.
|
||||
- `fdr_reader.iter_records` uses stdlib `json` (orjson is fine but
|
||||
not required at this stage — keep dependencies minimal).
|
||||
|
||||
## Document Dependencies
|
||||
|
||||
- `_docs/02_document/tests/blackbox-tests.md` § Test infrastructure
|
||||
- `_docs/02_tasks/done/AZ-406_test_infrastructure.md`
|
||||
- `_docs/02_tasks/done/AZ-407_fixture_builders_static.md`
|
||||
Reference in New Issue
Block a user