Files
detections-semantic/_docs/02_plans/components/06_output_manager/tests.md
T
Oleksandr Bezdieniezhnykh 8e2ecf50fd Initial commit
Made-with: Cursor
2026-03-26 00:20:30 +02:00

9.0 KiB

Test Specification — OutputManager

Acceptance Criteria Traceability

AC ID Acceptance Criterion Test IDs Coverage
AC-26 Total RAM ≤6GB (OutputManager must not contribute significant memory) PT-02 Covered
AC-27 Coexist with YOLO pipeline — recording must not block inference IT-01, PT-01 Covered

Note: OutputManager has no direct performance ACs from the acceptance criteria. Its tests ensure it supports the system's recording, logging, and operator delivery requirements defined in the architecture.


Integration Tests

IT-01: log_detection Writes Valid JSON-Line

Summary: Verify log_detection appends a correctly formatted JSON line to the detection log file.

Traces to: AC-27

Input data:

  • DetectionLogEntry: {frame_id: 1000, label: "footpath_winter", confidence: 0.72, tier: 2, centerX: 0.5, centerY: 0.3}
  • Output dir: temporary test directory

Expected result:

  • detections.jsonl file exists in output dir
  • Last line is valid JSON parseable to a dict with all input fields
  • Trailing newline present

Max execution time: 50ms

Dependencies: Writable filesystem


IT-02: record_frame Saves JPEG to Sequential Filename

Summary: Verify record_frame encodes and saves frame as JPEG with correct naming.

Traces to: AC-27

Input data:

  • Frame: numpy array (1080, 1920, 3), random pixel data
  • frame_id: 42, level: 1

Expected result:

  • File 42.jpg exists in output dir frames/ subdirectory
  • File is a valid JPEG (OpenCV can re-read it)
  • File size > 0 and < 500KB (reasonable JPEG of 1080p noise)

Max execution time: 100ms

Dependencies: Writable filesystem


IT-03: log_health Writes Health Entry

Summary: Verify log_health appends a JSON line with health data.

Traces to: AC-27

Input data:

  • HealthLogEntry: {timestamp: epoch, t_junction_c: 65.0, vlm_available: true, gimbal_available: true, semantic_available: true}

Expected result:

  • health.jsonl file exists
  • Last line contains all input fields as valid JSON

Max execution time: 50ms

Dependencies: Writable filesystem


IT-04: log_gimbal_command Appends to Gimbal Log

Summary: Verify gimbal command strings are appended to the gimbal log file.

Traces to: AC-27

Input data:

  • cmd_str: "SET_ANGLES pan=10.0 tilt=-20.0 zoom=5.0"

Expected result:

  • gimbal.log file exists
  • Last line matches the input command string

Max execution time: 50ms

Dependencies: Writable filesystem


IT-05: report_to_operator Formats Detection in YOLO Schema

Summary: Verify operator delivery formats detections with centerX, centerY, width, height, classNum, label, confidence.

Traces to: AC-27

Input data:

  • list of 3 Detection objects

Expected result:

  • Output matches existing YOLO output format (same field names, same coordinate normalization)
  • All 3 detections present in output

Max execution time: 50ms

Dependencies: None


IT-06: get_storage_status Returns Correct NVMe Stats

Summary: Verify storage status reports accurate free space percentage.

Traces to: AC-26

Input data:

  • Output dir on test filesystem

Expected result:

  • StorageStatus: nvme_free_pct in [0, 100], frames_recorded ≥ 0, detections_logged ≥ 0
  • should_reduce_recording matches threshold logic (true if free < 20%)

Max execution time: 50ms

Dependencies: Writable filesystem


IT-07: Circular Buffer Triggers on Low Storage

Summary: Verify should_reduce_recording becomes true when free space drops below 20%.

Traces to: AC-26

Input data:

  • Mock statvfs to report 15% free space

Expected result:

  • get_storage_status().should_reduce_recording == true
  • At 25% free → should_reduce_recording == false

Max execution time: 50ms

Dependencies: Mock filesystem stats


IT-08: Init Creates Output Directory Structure

Summary: Verify init() creates the expected directory structure.

Traces to: AC-27

Input data:

  • output_dir: temporary path that does not exist yet

Expected result:

  • Directory created with subdirectories for frames
  • No errors

Max execution time: 100ms

Dependencies: Writable filesystem


IT-09: WriteError Does Not Block Caller

Summary: Verify that a disk write failure (e.g., permission denied) is caught and does not propagate as an unhandled exception.

Traces to: AC-27

Input data:

  • Output dir set to a read-only path

Expected result:

  • log_detection raises no unhandled exception (catches WriteError internally)
  • Error counter incremented
  • Function returns normally

Max execution time: 50ms

Dependencies: Read-only filesystem path


Performance Tests

PT-01: Frame Recording Throughput at L2 Rate

Summary: Verify OutputManager can sustain 30 FPS frame recording without becoming a bottleneck.

Traces to: AC-27

Load scenario:

  • 30 frames/second, 1080p JPEG encoding + write
  • Duration: 10 seconds (300 frames)
  • Ramp-up: immediate

Expected results:

Metric Target Failure Threshold
Sustained write rate ≥30 FPS <25 FPS
Encoding latency (p95) ≤20ms >33ms
Dropped frames 0 >5
Write throughput ≥3 MB/s <2 MB/s

Resource limits:

  • CPU: ≤20% (JPEG encoding)
  • Memory: ≤100MB (buffer)

PT-02: Memory Usage Under Sustained Load

Summary: Verify no memory leak during continuous logging and recording.

Traces to: AC-26

Load scenario:

  • 1000 log_detection calls + 300 record_frame calls
  • Duration: 60 seconds
  • Measure RSS before and after

Expected results:

Metric Target Failure Threshold
Memory growth ≤10MB >50MB
Memory leak rate 0 MB/min >5 MB/min

Resource limits:

  • Memory: ≤100MB total for OutputManager

Security Tests

ST-01: Detection Log Does Not Contain Raw Image Data

Summary: Verify detection JSON lines contain metadata only, not embedded image data.

Traces to: AC-27

Attack vector: Information leakage through oversized log entries

Test procedure:

  1. Log 10 detections
  2. Read detections.jsonl
  3. Verify no field contains base64, raw bytes, or binary data

Expected behavior: Each JSON line is < 1KB; only text/numeric fields.

Pass criteria: All lines < 1KB, no binary data patterns.

Fail criteria: Any line contains embedded image data or exceeds 10KB.


ST-02: Path Traversal Prevention in Output Directory

Summary: Verify frame_id or other inputs cannot cause writes outside the output directory.

Traces to: AC-27

Attack vector: Path traversal via crafted frame_id

Test procedure:

  1. Call record_frame with frame_id containing "../" characters (e.g., as uint64 this shouldn't be possible, but verify string conversion)
  2. Verify file is written inside output_dir only

Expected behavior: File written within output_dir; no file created outside.

Pass criteria: All files within output_dir subtree.

Fail criteria: File created outside output_dir.


Acceptance Tests

AT-01: Full Flight Recording Session

Summary: Verify OutputManager correctly handles a simulated 5-minute flight with mixed L1 and L2 recording.

Traces to: AC-27

Preconditions:

  • Temporary output directory with sufficient space
  • Config: recording_l1_fps=2, recording_l2_fps=30

Steps:

Step Action Expected Result
1 init(output_dir) Directory structure created
2 Simulate 3 min L1: record_frame at 2 FPS 360 frames written
3 Simulate 1 min L2: record_frame at 30 FPS 1800 frames written
4 Log 50 detections during L2 detections.jsonl has 50 lines
5 get_storage_status() frames_recorded=2160, detections_logged=50

AT-02: Storage Reduction Under Pressure

Summary: Verify the storage management signals reduce recording at the right thresholds.

Traces to: AC-26

Preconditions:

  • Mock filesystem with configurable free space

Steps:

Step Action Expected Result
1 Set free space to 25% should_reduce_recording = false
2 Set free space to 15% should_reduce_recording = true
3 Set free space to 8% should_reduce_recording = true (critical)

Test Data Management

Required test data:

Data Set Description Source Size
sample_frames 10 sample 1080p frames for recording tests Generated (random or real) ~10 MB
sample_detections 50 DetectionLogEntry dicts Generated fixtures ~5 KB
sample_health 10 HealthLogEntry dicts Generated fixtures ~2 KB

Setup procedure:

  1. Create temporary output directory
  2. Call init(output_dir)

Teardown procedure:

  1. Delete temporary output directory and all contents

Data isolation strategy: Each test uses its own temporary directory. No shared output paths between tests.