[AZ-178] Add real-video streaming test, update e2e tests, mark task done

- Add tests/test_az178_realvideo_streaming.py: integration test that validates
  frame decoding begins while upload is still in progress using a real video fixture
- Add conftest.py: pytest plugin for per-test duration reporting
- Update e2e tests (async_sse, performance, security, streaming_video_upload, video)
  and run-tests.sh for updated test suite
- Move AZ-178 task to done/; add data/ to .gitignore (StreamingBuffer temp files)
- Update autopilot state to step 12 (Security Audit) for new feature cycle

Made-with: Cursor
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-04-01 05:02:25 +03:00
parent be4cab4fcb
commit 07c2afb62e
11 changed files with 142 additions and 261 deletions
+13 -9
View File
@@ -1,9 +1,9 @@
"""
AZ-178: Streaming video detection with real AI inference.
Uses video_1_faststart.mp4. Stops after 10 seconds.
Uses video_1_faststart.mp4. Stops after 5 seconds.
Requires services (run via run-tests.sh) for model download.
Run: sh run-tests.sh -k test_frames_decoded
Run: sh run-tests.sh -k test_frames_decoded -s
"""
import os
import threading
@@ -65,19 +65,23 @@ def test_frames_decoded_while_upload_in_progress(faststart_video):
from constants_inf import get_annotation_name
last_det_time = [0.0]
def on_annotation(annotation, percent):
now = time.monotonic()
if not first_det_time:
first_det_time.append(now)
elapsed = now - writer_start[0]
delta = now - last_det_time[0] if last_det_time[0] else elapsed
last_det_time[0] = now
written_mb = bytes_written[0] / (1024 * 1024)
pct_file = bytes_written[0] * 100 / file_size
elapsed = now - writer_start[0]
det_strs = [
f"{get_annotation_name(d.cls)}:{d.confidence*100:.0f}% @({d.x:.3f},{d.y:.3f} {d.w:.3f}x{d.h:.3f})"
for d in annotation.detections
]
detections_log.append((now, annotation, percent))
print(f" DET | {elapsed:7.2f}s | {written_mb:8.1f} MB | {pct_file:5.1f}% file | "
print(f" DET | {elapsed:7.2f}s | +{delta:.3f}s | {written_mb:8.1f} MB | {pct_file:5.1f}% file | "
f"{percent:3d}% video | {len(annotation.detections)} dets | {det_strs}")
def on_status(media_name, count):
@@ -102,8 +106,8 @@ def test_frames_decoded_while_upload_in_progress(faststart_video):
inf_error.append(e)
print(f"\n Video: {file_size/(1024*1024):.1f} MB (faststart)")
print(f" {'':>6s} {'Time':>8s} {'Written':>10s} {'% File':>7s} {'% Vid':>5s} {'Dets':>4s} Labels")
print(f" {'-'*80}")
print(f" {'':>6s} {'Time':>8s} {'Delta':>8s} {'Written':>10s} {'% File':>7s} {'% Vid':>5s} {'Dets':>4s} Labels")
print(f" {'-'*95}")
# Act
wt = threading.Thread(target=writer, daemon=True)
@@ -112,7 +116,7 @@ def test_frames_decoded_while_upload_in_progress(faststart_video):
inf_thread = threading.Thread(target=run_inference, daemon=True)
inf_thread.start()
inf_thread.join(timeout=10.0)
inf_thread.join(timeout=5.0)
inf.stop()
stop_flag.set()
@@ -143,11 +147,11 @@ def test_frames_decoded_while_upload_in_progress(faststart_video):
else:
print(f" >>> Detections arrived after full upload")
else:
print(f" Time to first detection: (none — no detections in 10s)")
print(f" Time to first detection: (none — no detections in 5s)")
if inf_error:
print(f" Inference error: {inf_error[0]}")
print(f" {'='*60}\n")
assert not inf_error, f"Inference error: {inf_error}"
assert len(detections_log) > 0, "no detections received in 10s"
assert len(detections_log) > 0, "no detections received in 5s"