mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-01-31 16:25:26 +03:00
Compare commits
1 Commits
38101eb3e1
...
f66b460dee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f66b460dee |
@ -97,7 +97,6 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
self.object_recordings_info: dict[str, list] = defaultdict(list)
|
self.object_recordings_info: dict[str, list] = defaultdict(list)
|
||||||
self.audio_recordings_info: dict[str, list] = defaultdict(list)
|
self.audio_recordings_info: dict[str, list] = defaultdict(list)
|
||||||
self.end_time_cache: dict[str, Tuple[datetime.datetime, float]] = {}
|
self.end_time_cache: dict[str, Tuple[datetime.datetime, float]] = {}
|
||||||
self.unexpected_cache_files_logged: bool = False
|
|
||||||
|
|
||||||
async def move_files(self) -> None:
|
async def move_files(self) -> None:
|
||||||
cache_files = [
|
cache_files = [
|
||||||
@ -113,14 +112,7 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
for cache in cache_files:
|
for cache in cache_files:
|
||||||
cache_path = os.path.join(CACHE_DIR, cache)
|
cache_path = os.path.join(CACHE_DIR, cache)
|
||||||
basename = os.path.splitext(cache)[0]
|
basename = os.path.splitext(cache)[0]
|
||||||
try:
|
camera, date = basename.rsplit("@", maxsplit=1)
|
||||||
camera, date = basename.rsplit("@", maxsplit=1)
|
|
||||||
except ValueError:
|
|
||||||
if not self.unexpected_cache_files_logged:
|
|
||||||
logger.warning("Skipping unexpected files in cache")
|
|
||||||
self.unexpected_cache_files_logged = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
start_time = datetime.datetime.strptime(
|
start_time = datetime.datetime.strptime(
|
||||||
date, CACHE_SEGMENT_FORMAT
|
date, CACHE_SEGMENT_FORMAT
|
||||||
).astimezone(datetime.timezone.utc)
|
).astimezone(datetime.timezone.utc)
|
||||||
@ -172,13 +164,7 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
|
|
||||||
cache_path = os.path.join(CACHE_DIR, cache)
|
cache_path = os.path.join(CACHE_DIR, cache)
|
||||||
basename = os.path.splitext(cache)[0]
|
basename = os.path.splitext(cache)[0]
|
||||||
try:
|
camera, date = basename.rsplit("@", maxsplit=1)
|
||||||
camera, date = basename.rsplit("@", maxsplit=1)
|
|
||||||
except ValueError:
|
|
||||||
if not self.unexpected_cache_files_logged:
|
|
||||||
logger.warning("Skipping unexpected files in cache")
|
|
||||||
self.unexpected_cache_files_logged = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
# important that start_time is utc because recordings are stored and compared in utc
|
# important that start_time is utc because recordings are stored and compared in utc
|
||||||
start_time = datetime.datetime.strptime(
|
start_time = datetime.datetime.strptime(
|
||||||
|
|||||||
@ -1,66 +0,0 @@
|
|||||||
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()
|
|
||||||
Loading…
Reference in New Issue
Block a user