Files
MeshChatX/tests/backend/test_rncp_handler_extended.py

156 lines
5.4 KiB
Python

import os
import shutil
import tempfile
from unittest.mock import MagicMock, patch
import pytest
import RNS
from meshchatx.src.backend.rncp_handler import RNCPHandler
@pytest.fixture
def temp_dir():
dir_path = tempfile.mkdtemp()
yield dir_path
shutil.rmtree(dir_path)
@pytest.fixture
def mock_rns():
# Save real Identity class to use as base for our mock class
real_identity_class = RNS.Identity
class MockIdentityClass(real_identity_class):
def __init__(self, *args, **kwargs):
self.hash = b"test_hash_32_bytes_long_01234567"
self.hexhash = self.hash.hex()
with (
patch("RNS.Reticulum") as mock_reticulum,
patch("RNS.Transport") as mock_transport,
patch("RNS.Identity", MockIdentityClass),
patch("RNS.Destination") as mock_destination,
patch("RNS.Resource") as mock_resource,
patch("RNS.Link") as mock_link_class,
):
mock_id_instance = MockIdentityClass()
mock_id_instance.get_private_key = MagicMock(return_value=b"test_private_key")
with (
patch.object(MockIdentityClass, "from_file", return_value=mock_id_instance),
patch.object(MockIdentityClass, "recall", return_value=mock_id_instance),
patch.object(
MockIdentityClass, "from_bytes", return_value=mock_id_instance
),
):
mock_dest_instance = MagicMock()
mock_destination.return_value = mock_dest_instance
mock_link_instance = MagicMock()
mock_link_class.return_value = mock_link_instance
mock_link_instance.status = RNS.Link.ACTIVE
mock_resource_instance = MagicMock()
mock_resource_instance.status = 2 # COMPLETE
mock_resource_instance.hash = b"res_hash"
mock_resource.return_value = mock_resource_instance
mock_resource.COMPLETE = 2
mock_resource.FAILED = 3
mock_transport.active_links = []
mock_transport.has_path.return_value = True
yield {
"Reticulum": mock_reticulum,
"Transport": mock_transport,
"Identity": MockIdentityClass,
"Destination": mock_destination,
"Resource": mock_resource,
"Link": mock_link_class,
"link_instance": mock_link_instance,
"id_instance": mock_id_instance,
"dest_instance": mock_dest_instance,
}
def test_rncp_handler_init(mock_rns, temp_dir):
handler = RNCPHandler(mock_rns["Reticulum"], mock_rns["id_instance"], temp_dir)
assert handler.reticulum == mock_rns["Reticulum"]
assert handler.identity == mock_rns["id_instance"]
assert handler.storage_dir == temp_dir
def test_setup_receive_destination(mock_rns, temp_dir):
handler = RNCPHandler(mock_rns["Reticulum"], mock_rns["id_instance"], temp_dir)
mock_rns["Reticulum"].identitypath = temp_dir
dest_hash = handler.setup_receive_destination(
allowed_hashes=["abc123def456"], fetch_allowed=True, fetch_jail=temp_dir
)
assert handler.receive_destination is not None
mock_rns["Destination"].assert_called()
assert handler.allowed_identity_hashes == [bytes.fromhex("abc123def456")]
assert handler.fetch_jail == temp_dir
def test_receive_resource_callback(mock_rns, temp_dir):
handler = RNCPHandler(mock_rns["Reticulum"], mock_rns["id_instance"], temp_dir)
handler.allowed_identity_hashes = [b"allowed_hash"]
mock_resource = MagicMock()
mock_link = MagicMock()
mock_remote_id = MagicMock()
mock_remote_id.hash = b"allowed_hash"
mock_link.get_remote_identity.return_value = mock_remote_id
mock_resource.link = mock_link
# Allowed
assert handler._receive_resource_callback(mock_resource) is True
# Not allowed
mock_remote_id.hash = b"other_hash"
assert handler._receive_resource_callback(mock_resource) is False
def test_receive_resource_concluded_success(mock_rns, temp_dir):
handler = RNCPHandler(mock_rns["Reticulum"], mock_rns["id_instance"], temp_dir)
mock_resource = MagicMock()
mock_resource.status = RNS.Resource.COMPLETE
mock_resource.hash = b"resource_hash"
mock_resource.metadata = {"name": b"test_file.txt"}
# Create dummy source file
source_file = os.path.join(temp_dir, "temp_resource_data")
with open(source_file, "w") as f:
f.write("test data")
mock_resource.data.name = source_file
handler.active_transfers["7265736f757263655f68617368"] = {"status": "receiving"}
handler._receive_resource_concluded(mock_resource)
# Check if file was moved to rncp_received
received_dir = os.path.join(temp_dir, "rncp_received")
assert os.path.exists(os.path.join(received_dir, "test_file.txt"))
assert (
handler.active_transfers["7265736f757263655f68617368"]["status"] == "completed"
)
@pytest.mark.asyncio
async def test_send_file_success(mock_rns, temp_dir):
handler = RNCPHandler(mock_rns["Reticulum"], mock_rns["id_instance"], temp_dir)
test_file = os.path.join(temp_dir, "send_me.txt")
with open(test_file, "w") as f:
f.write("payload")
# Mocking the async behavior
result = await handler.send_file(b"dest_hash", test_file, timeout=10)
assert result["status"] == "completed"
mock_rns["Link"].assert_called()
mock_rns["Resource"].assert_called()