216 lines
6.3 KiB
Python
216 lines
6.3 KiB
Python
import os
|
|
import time
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
import RNS
|
|
|
|
from meshchatx.src.backend.telephone_manager import TelephoneManager
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_identity():
|
|
mock_id = MagicMock(spec=RNS.Identity)
|
|
mock_id.hash = b"test_identity_hash_32_bytes_long"
|
|
return mock_id
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_config():
|
|
config = MagicMock()
|
|
config.call_recording_enabled.get.return_value = True
|
|
config.telephone_audio_profile_id.get.return_value = 2
|
|
return config
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_db():
|
|
db = MagicMock()
|
|
return db
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_storage(tmp_path):
|
|
storage_dir = tmp_path / "storage"
|
|
storage_dir.mkdir()
|
|
return str(storage_dir)
|
|
|
|
|
|
def test_telephone_manager_init(mock_identity, mock_config, temp_storage):
|
|
tm = TelephoneManager(
|
|
mock_identity,
|
|
config_manager=mock_config,
|
|
storage_dir=temp_storage,
|
|
)
|
|
assert tm.identity == mock_identity
|
|
assert tm.config_manager == mock_config
|
|
assert tm.storage_dir == temp_storage
|
|
assert os.path.exists(tm.recordings_dir)
|
|
|
|
|
|
@patch("meshchatx.src.backend.telephone_manager.Telephone")
|
|
def test_call_recording_lifecycle(
|
|
mock_telephone_class,
|
|
mock_identity,
|
|
mock_config,
|
|
mock_db,
|
|
temp_storage,
|
|
):
|
|
# Setup mocks
|
|
mock_telephone = mock_telephone_class.return_value
|
|
mock_active_call = MagicMock()
|
|
mock_remote_identity = MagicMock()
|
|
mock_remote_identity.hash = b"remote_hash_32_bytes_long_012345"
|
|
mock_active_call.get_remote_identity.return_value = mock_remote_identity
|
|
mock_telephone.active_call = mock_active_call
|
|
|
|
# Mock mixers
|
|
mock_telephone.receive_mixer = MagicMock()
|
|
mock_telephone.transmit_mixer = MagicMock()
|
|
|
|
tm = TelephoneManager(
|
|
mock_identity,
|
|
config_manager=mock_config,
|
|
storage_dir=temp_storage,
|
|
db=mock_db,
|
|
)
|
|
tm.get_name_for_identity_hash = MagicMock(return_value="Remote User")
|
|
tm.init_telephone()
|
|
|
|
# Simulate call established
|
|
tm.on_telephone_call_established(mock_remote_identity)
|
|
|
|
# Verify recording NOT started (disabled for now)
|
|
assert not tm.is_recording
|
|
# assert mock_sink.call_count == 0 # RX and TX sinks not created
|
|
# assert mock_sink.return_value.start.called # Autodigest handled by monkey patch in meshchat.py
|
|
|
|
# Simulate call ended after some time
|
|
tm.recording_start_time = time.time() - 5 # 5 seconds duration
|
|
# tm.is_recording = True # Force recording state for test (Disabled for now as property has no setter)
|
|
tm.recording_remote_identity = mock_remote_identity
|
|
tm.on_telephone_call_ended(mock_remote_identity)
|
|
|
|
# Verify recording stopped and saved to DB
|
|
assert not tm.is_recording
|
|
# assert mock_db.telephone.add_call_recording.called # Disabled for now as recording is disabled
|
|
|
|
|
|
def test_call_recording_disabled(mock_identity, mock_config, mock_db, temp_storage):
|
|
mock_config.call_recording_enabled.get.return_value = False
|
|
tm = TelephoneManager(
|
|
mock_identity,
|
|
config_manager=mock_config,
|
|
storage_dir=temp_storage,
|
|
db=mock_db,
|
|
)
|
|
|
|
# Mock telephone and active call
|
|
tm.telephone = MagicMock()
|
|
tm.telephone.active_call = MagicMock()
|
|
|
|
tm.on_telephone_call_established(MagicMock())
|
|
|
|
assert not tm.is_recording
|
|
assert not mock_db.telephone.add_call_recording.called
|
|
|
|
|
|
def test_audio_profile_persistence(mock_identity, mock_config, temp_storage):
|
|
with patch(
|
|
"meshchatx.src.backend.telephone_manager.Telephone",
|
|
) as mock_telephone_class:
|
|
mock_telephone = mock_telephone_class.return_value
|
|
mock_config.telephone_audio_profile_id.get.return_value = 4
|
|
|
|
tm = TelephoneManager(
|
|
mock_identity,
|
|
config_manager=mock_config,
|
|
storage_dir=temp_storage,
|
|
)
|
|
tm.init_telephone()
|
|
|
|
# Verify switch_profile was called with configured ID
|
|
mock_telephone.switch_profile.assert_called_with(4)
|
|
|
|
|
|
@patch("meshchatx.src.backend.telephone_manager.Telephone")
|
|
def test_call_recording_saves_after_disconnect(
|
|
mock_telephone_class,
|
|
mock_identity,
|
|
mock_config,
|
|
mock_db,
|
|
temp_storage,
|
|
):
|
|
# Setup mocks
|
|
mock_telephone = mock_telephone_class.return_value
|
|
mock_active_call = MagicMock()
|
|
mock_remote_identity = MagicMock()
|
|
mock_remote_identity.hash = b"remote_hash_32_bytes_long_012345"
|
|
mock_active_call.get_remote_identity.return_value = mock_remote_identity
|
|
mock_telephone.active_call = mock_active_call
|
|
|
|
# Mock mixers
|
|
mock_telephone.receive_mixer = MagicMock()
|
|
mock_telephone.transmit_mixer = MagicMock()
|
|
|
|
tm = TelephoneManager(
|
|
mock_identity,
|
|
config_manager=mock_config,
|
|
storage_dir=temp_storage,
|
|
db=mock_db,
|
|
)
|
|
tm.init_telephone()
|
|
|
|
# Start recording
|
|
tm.start_recording()
|
|
assert not tm.is_recording # Disabled for now
|
|
|
|
# Force recording state for test
|
|
# tm.is_recording = True (Disabled for now as property has no setter)
|
|
tm.recording_remote_identity = mock_remote_identity
|
|
|
|
# Simulate call disconnected (active_call becomes None)
|
|
mock_telephone.active_call = None
|
|
|
|
# End recording (simulate call ended callback)
|
|
tm.recording_start_time = time.time() - 5
|
|
tm.on_telephone_call_ended(mock_remote_identity)
|
|
|
|
# Verify it still saved using the captured identity
|
|
assert not tm.is_recording
|
|
# assert mock_db.telephone.add_call_recording.called # Disabled for now as recording is disabled
|
|
|
|
|
|
@patch("meshchatx.src.backend.telephone_manager.Telephone")
|
|
def test_manual_mute_overrides(
|
|
mock_telephone_class,
|
|
mock_identity,
|
|
mock_config,
|
|
temp_storage,
|
|
):
|
|
mock_telephone = mock_telephone_class.return_value
|
|
tm = TelephoneManager(
|
|
mock_identity,
|
|
config_manager=mock_config,
|
|
storage_dir=temp_storage,
|
|
)
|
|
tm.init_telephone()
|
|
|
|
# Test transmit mute
|
|
tm.mute_transmit()
|
|
assert tm.transmit_muted is True
|
|
mock_telephone.mute_transmit.assert_called_once()
|
|
|
|
tm.unmute_transmit()
|
|
assert tm.transmit_muted is False
|
|
mock_telephone.unmute_transmit.assert_called_once()
|
|
|
|
# Test receive mute
|
|
tm.mute_receive()
|
|
assert tm.receive_muted is True
|
|
mock_telephone.mute_receive.assert_called_once()
|
|
|
|
tm.unmute_receive()
|
|
assert tm.receive_muted is False
|
|
mock_telephone.unmute_receive.assert_called_once()
|