OmniVoice-Studio / tests /backend /services /test_ffmpeg_utils.py
LΓͺ Phi Nam
Deploy to HF Space
94004a2
Raw
History Blame Contribute Delete
3.83 kB
"""Tests for backend/services/ffmpeg_utils.py β€” Phase 1 Wave 3 (issue #76).
Covers :func:`resolve_ffprobe`'s env-first / PATH-fallback cascade and the
legacy-name alias (``FFPROBE_PATH`` still works, ``OMNIVOICE_FFPROBE_PATH``
takes precedence).
"""
import os
import pytest
@pytest.fixture(autouse=True)
def _clean_env(monkeypatch):
"""Strip both ffprobe env vars before each test so we control the cascade."""
monkeypatch.delenv("OMNIVOICE_FFPROBE_PATH", raising=False)
monkeypatch.delenv("FFPROBE_PATH", raising=False)
def test_resolve_ffprobe_prefers_omnivoice_env_var(monkeypatch, tmp_path):
"""OMNIVOICE_FFPROBE_PATH set to a real file β†’ that path wins."""
from services import ffmpeg_utils
fake = tmp_path / "ffprobe"
fake.write_text("#!/bin/sh\necho 1\n")
fake.chmod(0o755)
monkeypatch.setenv("OMNIVOICE_FFPROBE_PATH", str(fake))
assert ffmpeg_utils.resolve_ffprobe() == str(fake)
def test_resolve_ffprobe_falls_back_to_legacy_FFPROBE_PATH(monkeypatch, tmp_path):
"""OMNIVOICE_FFPROBE_PATH absent but legacy FFPROBE_PATH set β†’ legacy used."""
from services import ffmpeg_utils
fake = tmp_path / "ffprobe-legacy"
fake.write_text("#!/bin/sh\necho 1\n")
fake.chmod(0o755)
monkeypatch.setenv("FFPROBE_PATH", str(fake))
assert ffmpeg_utils.resolve_ffprobe() == str(fake)
def test_resolve_ffprobe_omnivoice_path_takes_precedence_over_legacy(
monkeypatch, tmp_path,
):
"""Both env vars set β†’ OMNIVOICE_FFPROBE_PATH wins."""
from services import ffmpeg_utils
canonical = tmp_path / "ffprobe-canonical"
legacy = tmp_path / "ffprobe-legacy"
for f in (canonical, legacy):
f.write_text("#!/bin/sh\necho 1\n")
f.chmod(0o755)
monkeypatch.setenv("OMNIVOICE_FFPROBE_PATH", str(canonical))
monkeypatch.setenv("FFPROBE_PATH", str(legacy))
assert ffmpeg_utils.resolve_ffprobe() == str(canonical)
def test_resolve_ffprobe_falls_back_to_PATH(monkeypatch, tmp_path):
"""No env var β†’ shutil.which result is returned."""
from services import ffmpeg_utils
# Stub shutil.which inside the module so we do not depend on the host PATH.
fake = "/fake/path/from/system/ffprobe"
def _fake_which(name):
if name == "ffprobe":
return fake
return None
monkeypatch.setattr(ffmpeg_utils, "shutil", _ShutilStub(_fake_which))
assert ffmpeg_utils.resolve_ffprobe() == fake
def test_resolve_ffprobe_returns_None_when_nothing_resolves(monkeypatch):
"""No env, no PATH β†’ returns None (no crash)."""
from services import ffmpeg_utils
monkeypatch.setattr(ffmpeg_utils, "shutil", _ShutilStub(lambda _name: None))
assert ffmpeg_utils.resolve_ffprobe() is None
def test_resolve_ffprobe_env_var_with_command_name_resolves_via_which(
monkeypatch, tmp_path,
):
"""Legacy shape: env var set to a bare command name (not a path) β€” resolve
via shutil.which so older Tauri shells that set FFPROBE_PATH=ffprobe still
work."""
from services import ffmpeg_utils
fake = tmp_path / "ffprobe"
fake.write_text("#!/bin/sh\necho 1\n")
fake.chmod(0o755)
def _fake_which(name):
if name == "ffprobe":
return str(fake)
return None
monkeypatch.setattr(ffmpeg_utils, "shutil", _ShutilStub(_fake_which))
monkeypatch.setenv("OMNIVOICE_FFPROBE_PATH", "ffprobe")
assert ffmpeg_utils.resolve_ffprobe() == str(fake)
class _ShutilStub:
"""A tiny shim that mimics the parts of shutil ffmpeg_utils touches.
monkeypatching the whole module avoids pulling in real PATH lookups while
keeping the existing `import shutil` call sites untouched.
"""
def __init__(self, which_impl):
self._which = which_impl
def which(self, name):
return self._which(name)