95 lines
4.1 KiB
Python
95 lines
4.1 KiB
Python
"""Launch-time CLI override tests — v4.10.0 regression guard.
|
|
|
|
The GUI entry (``launch_gui``) runs BEFORE the async environment probe
|
|
(500ms QTimer), so ``window.env`` is ``None`` at launch time. Writing
|
|
CLI overrides straight onto ``env.av1an_flags`` crashed with
|
|
``AttributeError: 'NoneType' object has no attribute 'av1an_flags'``
|
|
on every GUI launch through ``main()`` — both entries
|
|
(``python open-transcode.py`` and ``python -m opentranscode``).
|
|
|
|
The fix: overrides land in the window's pending store
|
|
(``_set_cli_flag`` / ``_clear_cli_flag``) and ``_probe_and_init``
|
|
flushes them into the live ``av1an_flags`` the moment the probe
|
|
finishes. These tests pin the pending/flush semantics hermetically (no
|
|
QApplication, no probe): the window is built via ``__new__`` and the
|
|
env is a stub.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
class _StubEnv:
|
|
def __init__(self, flags: dict | None = None):
|
|
self.av1an_flags = dict(flags or {})
|
|
|
|
|
|
def _bare_master(module):
|
|
master = module.OpenCodecMaster.__new__(module.OpenCodecMaster)
|
|
master._pending_av1an_flags = {}
|
|
return master
|
|
|
|
|
|
class TestPendingFlagStore:
|
|
def test_launch_before_probe_does_not_crash(self, opentranscode_module):
|
|
# The original failure mode: writing a flag with env unset.
|
|
# The pending store accepts it with env=None in sight.
|
|
master = _bare_master(opentranscode_module)
|
|
master.env = None
|
|
master._set_cli_flag("engine", "cpu") # raised before the fix
|
|
assert master._pending_av1an_flags["engine"] == "cpu"
|
|
|
|
def test_flush_applies_pending_into_live_flags(self, opentranscode_module):
|
|
master = _bare_master(opentranscode_module)
|
|
master.env = _StubEnv({"concat_method": "ffmpeg"})
|
|
master._set_cli_flag("engine", "cpu")
|
|
master._set_cli_flag("max_workers", 3)
|
|
master._set_cli_flag("use_av1an", False)
|
|
master._flush_cli_flags()
|
|
assert master.env.av1an_flags["engine"] == "cpu"
|
|
assert master.env.av1an_flags["max_workers"] == 3
|
|
assert master.env.av1an_flags["use_av1an"] is False
|
|
|
|
def test_falsy_values_survive_the_flush(self, opentranscode_module):
|
|
# The delete sentinel is an identity check — False, 0 and ""
|
|
# are legitimate flag values and must never be swallowed.
|
|
master = _bare_master(opentranscode_module)
|
|
master.env = _StubEnv()
|
|
master._set_cli_flag("use_av1an", False)
|
|
master._set_cli_flag("max_workers", 0)
|
|
master._set_cli_flag("some_str", "")
|
|
master._flush_cli_flags()
|
|
flags = master.env.av1an_flags
|
|
assert flags["use_av1an"] is False
|
|
assert flags["max_workers"] == 0
|
|
assert flags["some_str"] == ""
|
|
|
|
def test_clear_removes_probe_set_flag(self, opentranscode_module):
|
|
# --chunk-method auto must delete the probe's chunk_method_override
|
|
# (set when no VapourSynth source plugins are installed).
|
|
master = _bare_master(opentranscode_module)
|
|
master.env = _StubEnv({"chunk_method_override": "select",
|
|
"concat_method": "ffmpeg"})
|
|
master._clear_cli_flag("chunk_method_override")
|
|
master._flush_cli_flags()
|
|
assert "chunk_method_override" not in master.env.av1an_flags
|
|
assert master.env.av1an_flags["concat_method"] == "ffmpeg"
|
|
|
|
def test_clear_is_a_noop_when_key_absent(self, opentranscode_module):
|
|
master = _bare_master(opentranscode_module)
|
|
master.env = _StubEnv()
|
|
master._clear_cli_flag("chunk_method_override")
|
|
master._flush_cli_flags()
|
|
assert master.env.av1an_flags == {}
|
|
|
|
def test_last_write_wins_and_flush_drains(self, opentranscode_module):
|
|
master = _bare_master(opentranscode_module)
|
|
master.env = _StubEnv()
|
|
master._set_cli_flag("engine", "cpu")
|
|
master._set_cli_flag("engine", "hybrid")
|
|
master._flush_cli_flags()
|
|
assert master.env.av1an_flags["engine"] == "hybrid"
|
|
assert master._pending_av1an_flags == {}
|
|
# A second flush with no new pending writes changes nothing.
|
|
master._flush_cli_flags()
|
|
assert master.env.av1an_flags["engine"] == "hybrid"
|