Files
operating-room-monitor-server/backend/tests/test_voice_terminal_binding.py
Kevin 30e6acea70 Replace chain 1 with RTSP slice batch pipeline and add 24h segment TTL.
Route live recording through ffmpeg MP4 segments and the 5.15 batch subprocess, remove simulated RTSP chain 2, purge expired slices on startup and hourly, and expose TTL settings to the demo client.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-25 10:24:25 +08:00

117 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""术间绑定与站点配置OR_SITE_CONFIG_JSON解析。"""
from __future__ import annotations
from pathlib import Path
import pytest
from app.config import Settings
from app.or_site_config import (
load_or_site_config_from_path,
parse_or_site_config_object,
)
from app.services.voice_terminal_binding import VoiceTerminalBindingIndex
def test_parse_and_resolve() -> None:
idx = VoiceTerminalBindingIndex.from_binding_list(
[
{
"or_room_id": "OR-05",
"camera_ids": ["or-cam-01", "or-cam-02"],
"voice_terminal_id": "T-05",
}
]
)
assert idx is not None
assert idx.resolve_terminal(["or-cam-02", "or-cam-01"]) == "T-05"
assert idx.resolve_terminal(["or-cam-01"]) == "T-05"
def test_resolve_subset_uses_smallest_superset_when_ambiguous() -> None:
idx = VoiceTerminalBindingIndex.from_binding_list(
[
{
"or_room_id": "A",
"camera_ids": ["c1", "c2"],
"voice_terminal_id": "T-AB",
},
{
"or_room_id": "B",
"camera_ids": ["c1", "c2", "c3"],
"voice_terminal_id": "T-ABC",
},
]
)
assert idx is not None
assert idx.resolve_terminal(["c1"]) == "T-AB"
def test_duplicate_terminal_rejected() -> None:
assert (
VoiceTerminalBindingIndex.from_binding_list(
[
{"or_room_id": "A", "camera_ids": ["c1"], "voice_terminal_id": "T"},
{"or_room_id": "B", "camera_ids": ["c2"], "voice_terminal_id": "T"},
]
)
is None
)
def test_duplicate_camera_set_rejected() -> None:
assert (
VoiceTerminalBindingIndex.from_binding_list(
[
{"or_room_id": "A", "camera_ids": ["c1"], "voice_terminal_id": "T1"},
{"or_room_id": "B", "camera_ids": ["c1"], "voice_terminal_id": "T2"},
]
)
is None
)
def test_from_binding_list_empty() -> None:
idx = VoiceTerminalBindingIndex.from_binding_list([])
assert idx is not None
assert idx.resolve_terminal(["x"]) is None
def test_parse_site_config_rejects_unknown_keys() -> None:
with pytest.raises(ValueError, match="unknown top-level"):
parse_or_site_config_object(
{
"video_rtsp_urls": {},
"voice_or_room_bindings": [],
"extra": 1,
}
)
def test_parse_site_config_requires_both_sections() -> None:
with pytest.raises(ValueError, match="must include"):
parse_or_site_config_object({"video_rtsp_urls": {}})
def test_load_from_path_roundtrip(tmp_path: Path) -> None:
p = tmp_path / "site.json"
p.write_text(
'{"video_rtsp_urls":{"c1":"rtsp://h"},"voice_or_room_bindings":['
'{"or_room_id":"R","camera_ids":["a"],"voice_terminal_id":"T"}]}',
encoding="utf-8",
)
cfg = load_or_site_config_from_path(p)
assert cfg.video_rtsp_urls == {"c1": "rtsp://h"}
assert cfg.voice_bindings.resolve_terminal(["a"]) == "T"
def test_settings_video_map(tmp_path: Path) -> None:
p = tmp_path / "site.json"
p.write_text(
'{"video_rtsp_urls":{"c1":"rtsp://x"},"voice_or_room_bindings":[]}',
encoding="utf-8",
)
s = Settings(or_site_config_json_file=str(p))
assert s.video_rtsp_url_map() == {"c1": "rtsp://x"}