test_camera_stderr_summary.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. """Tests for _summarize_ffmpeg_stderr (#925).
  2. The ffmpeg banner (version / build / configuration / lib*) dumps ~20 lines
  3. before any actual error. Before this fix, every failed camera retry logged
  4. the full banner, producing hundreds of lines per failure — see #925 where a
  5. single click produced 555 lines across 30 retries. The helper strips the
  6. banner so logs stay focused on the real error.
  7. """
  8. from backend.app.api.routes.camera import _summarize_ffmpeg_stderr
  9. _FAKE_BANNER = """ffmpeg version 7.1.3-0+deb13u1 Copyright (c) 2000-2025 the FFmpeg developers
  10. built with gcc 14 (Debian 14.2.0-19)
  11. configuration: --prefix=/usr --extra-version=0+deb13u1 --toolchain=hardened --enable-gpl --enable-gnutls
  12. libavutil 59. 39.100 / 59. 39.100
  13. libavcodec 61. 19.101 / 61. 19.101
  14. libavformat 61. 7.100 / 61. 7.100
  15. libavdevice 61. 3.100 / 61. 3.100
  16. libavfilter 10. 4.100 / 10. 4.100
  17. libswscale 8. 3.100 / 8. 3.100
  18. libswresample 5. 3.100 / 5. 3.100
  19. libpostproc 58. 3.100 / 58. 3.100
  20. """
  21. def test_empty_input():
  22. assert _summarize_ffmpeg_stderr("") == ""
  23. assert _summarize_ffmpeg_stderr(None) == ""
  24. def test_keeps_error_lines_drops_banner():
  25. stderr = _FAKE_BANNER + (
  26. "[in#0 @ 0x64a7cd6350c0] Error opening input: Invalid data found when processing input\n"
  27. "Error opening input file rtsp://[CREDENTIALS]@192.0.2.1:322/streaming/live/1.\n"
  28. "Error opening input files: Invalid data found when processing input\n"
  29. )
  30. result = _summarize_ffmpeg_stderr(stderr)
  31. # Banner gone
  32. assert "ffmpeg version" not in result
  33. assert "configuration:" not in result
  34. assert "libavcodec" not in result
  35. # Real errors preserved
  36. assert "Error opening input: Invalid data found when processing input" in result
  37. assert "Error opening input file rtsp" in result
  38. def test_caps_at_10_lines():
  39. stderr = _FAKE_BANNER + "\n".join(f"error line {i}" for i in range(25))
  40. result = _summarize_ffmpeg_stderr(stderr)
  41. lines = result.splitlines()
  42. assert len(lines) == 10
  43. # Keeps the *last* 10 lines (most recent errors closest to failure)
  44. assert lines[-1] == "error line 24"
  45. assert lines[0] == "error line 15"
  46. def test_drops_blank_lines():
  47. stderr = "real error\n\n\n \nsecond error\n"
  48. result = _summarize_ffmpeg_stderr(stderr)
  49. assert result == "real error\nsecond error"
  50. def test_banner_only_returns_empty():
  51. """If ffmpeg prints only the banner (no errors), the summary should be empty."""
  52. assert _summarize_ffmpeg_stderr(_FAKE_BANNER) == ""