import sys import unittest from unittest.mock import MagicMock, patch # Mock complex imports before importing maintainer sys.modules["frigate.comms.inter_process"] = MagicMock() sys.modules["frigate.comms.detections_updater"] = MagicMock() sys.modules["frigate.comms.recordings_updater"] = MagicMock() sys.modules["frigate.config.camera.updater"] = MagicMock() # Now import the class under test from frigate.config import FrigateConfig # noqa: E402 from frigate.record.maintainer import RecordingMaintainer # noqa: E402 class TestMaintainer(unittest.IsolatedAsyncioTestCase): async def test_move_files_survives_bad_filename(self): config = MagicMock(spec=FrigateConfig) config.cameras = {} stop_event = MagicMock() maintainer = RecordingMaintainer(config, stop_event) # We need to mock end_time_cache to avoid key errors if logic proceeds maintainer.end_time_cache = {} # Mock filesystem # One bad file, one good file files = ["bad_filename.mp4", "camera@20210101000000+0000.mp4"] with patch("os.listdir", return_value=files): with patch("os.path.isfile", return_value=True): with patch( "frigate.record.maintainer.psutil.process_iter", return_value=[] ): with patch("frigate.record.maintainer.logger.warning") as warn: # Mock validate_and_move_segment to avoid further logic maintainer.validate_and_move_segment = MagicMock() try: await maintainer.move_files() except ValueError as e: if "not enough values to unpack" in str(e): self.fail("move_files() crashed on bad filename!") raise e except Exception: # Ignore other errors (like DB connection) as we only care about the unpack crash pass # The bad filename is encountered in multiple loops, but should only warn once. matching = [ c for c in warn.call_args_list if c.args and isinstance(c.args[0], str) and "Skipping unexpected files in cache" in c.args[0] ] self.assertEqual( 1, len(matching), f"Expected a single warning for unexpected files, got {len(matching)}", ) if __name__ == "__main__": unittest.main()