"""Integration tests for remote-to-remote beam transfers."""
from unittest.mock import AsyncMock, patch
import pytest
from scout_mcp.tools.scout import scout
@pytest.mark.asyncio
async def test_remote_to_remote_full_flow(tmp_path):
"""Test complete remote-to-remote transfer flow."""
with patch("scout_mcp.tools.scout.get_config") as mock_config, \
patch("scout_mcp.tools.scout.get_pool"), \
patch("scout_mcp.services.get_connection_with_retry") as mock_conn, \
patch("scout_mcp.utils.hostname.get_server_hostname") as mock_hostname:
# Setup mocks
config = AsyncMock()
source_host = AsyncMock(name="remote1")
target_host = AsyncMock(name="remote2")
def get_host(name):
return source_host if name == "remote1" else target_host
config.get_host.side_effect = get_host
mock_config.return_value = config
mock_hostname.return_value = "localhost"
# Mock SSH connections
source_conn = AsyncMock()
target_conn = AsyncMock()
mock_conn.side_effect = [source_conn, target_conn]
# Mock SFTP
source_sftp = AsyncMock()
target_sftp = AsyncMock()
source_conn.start_sftp_client.return_value.__aenter__.return_value = source_sftp
target_conn.start_sftp_client.return_value.__aenter__.return_value = target_sftp
# Mock SFTP file handles for streaming
source_file = AsyncMock()
target_file = AsyncMock()
# Mock file attributes
mock_attrs = AsyncMock()
mock_attrs.size = 1024
source_sftp.stat.return_value = mock_attrs
# Simulate streaming
chunk_data = b"test file contents"
source_file.read.side_effect = [chunk_data, b""]
source_sftp.open.return_value.__aenter__.return_value = source_file
target_sftp.open.return_value.__aenter__.return_value = target_file
# Execute transfer
result = await scout(
beam_source="remote1:/src/file.txt",
beam_target="remote2:/dst/file.txt",
)
# Verify success
assert "✓" in result or "Streamed" in result
# Verify streaming operations
source_sftp.stat.assert_called_once()
source_sftp.open.assert_called_once_with("/src/file.txt", 'rb')
target_sftp.open.assert_called_once_with("/dst/file.txt", 'wb')
target_file.write.assert_called_with(chunk_data)
@pytest.mark.asyncio
async def test_optimization_when_server_is_source(tmp_path):
"""Test optimization when MCP server is the source host."""
with patch("scout_mcp.tools.scout.get_config") as mock_config, \
patch("scout_mcp.services.get_connection_with_retry") as mock_conn, \
patch("scout_mcp.utils.hostname.get_server_hostname") as mock_hostname:
# Setup: MCP server is "tootie"
config = AsyncMock()
target_host = AsyncMock(name="remote1")
config.get_host.return_value = target_host
mock_config.return_value = config
mock_hostname.return_value = "tootie"
# Mock connection (only to target)
target_conn = AsyncMock()
mock_conn.return_value = target_conn
# Mock SFTP
target_sftp = AsyncMock()
target_conn.start_sftp_client.return_value.__aenter__.return_value = target_sftp
# Create local source file
source_file = tmp_path / "source.txt"
source_file.write_text("test content")
# Execute transfer
with patch("scout_mcp.tools.handlers.Path") as mock_path:
mock_path.return_value.exists.return_value = True
mock_path.return_value.stat.return_value.st_size = 12
result = await scout(
beam_source=f"tootie:{source_file}",
beam_target="remote1:/dst/file.txt",
)
# Should be optimized to direct upload (no download)
assert "✓" in result or "Uploaded" in result
target_sftp.put.assert_called_once()