mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-07-13 12:38:02 +00:00
178 lines
4.0 KiB
Python
178 lines
4.0 KiB
Python
import asyncio
|
|
import json
|
|
import time
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
|
|
class FakeQuery:
|
|
def __init__(self, servers):
|
|
self._servers = servers
|
|
|
|
def filter(self, *_args, **_kwargs):
|
|
return self
|
|
|
|
def all(self):
|
|
return self._servers
|
|
|
|
|
|
class FakeDB:
|
|
def __init__(self, servers):
|
|
self._servers = servers
|
|
|
|
def query(self, *_args, **_kwargs):
|
|
return FakeQuery(self._servers)
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_connect_all_enabled_runs_concurrently(monkeypatch):
|
|
from src.mcp_manager import McpManager
|
|
|
|
manager = McpManager()
|
|
|
|
servers = [
|
|
SimpleNamespace(
|
|
id=1,
|
|
name="server1",
|
|
transport="stdio",
|
|
command="cmd1",
|
|
args=json.dumps([]),
|
|
env=json.dumps({}),
|
|
url=None,
|
|
),
|
|
SimpleNamespace(
|
|
id=2,
|
|
name="server2",
|
|
transport="stdio",
|
|
command="cmd2",
|
|
args=json.dumps([]),
|
|
env=json.dumps({}),
|
|
url=None,
|
|
),
|
|
SimpleNamespace(
|
|
id=3,
|
|
name="server3",
|
|
transport="stdio",
|
|
command="cmd3",
|
|
args=json.dumps([]),
|
|
env=json.dumps({}),
|
|
url=None,
|
|
),
|
|
]
|
|
|
|
# Patch the SessionLocal used by connect_all_enabled().
|
|
import src.mcp_manager as mcp_manager
|
|
|
|
monkeypatch.setattr(
|
|
mcp_manager,
|
|
"SessionLocal",
|
|
lambda: FakeDB(servers),
|
|
)
|
|
|
|
async def fake_connect_with_timeout(_server):
|
|
await asyncio.sleep(1)
|
|
|
|
# We're testing that connect_all_enabled launches these concurrently,
|
|
# not the implementation of connect_server().
|
|
monkeypatch.setattr(
|
|
manager,
|
|
"_connect_with_timeout",
|
|
fake_connect_with_timeout,
|
|
)
|
|
|
|
start = time.perf_counter()
|
|
|
|
await manager.connect_all_enabled()
|
|
|
|
elapsed = time.perf_counter() - start
|
|
|
|
# Sequential would take ~3 seconds.
|
|
# Concurrent should take about 1 second.
|
|
assert 0.9 <= elapsed < 2.0
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_connect_all_enabled_timeout_does_not_block_other_servers(monkeypatch):
|
|
import src.mcp_manager as mcp_manager
|
|
from src.mcp_manager import McpManager
|
|
|
|
manager = McpManager()
|
|
|
|
servers = [
|
|
SimpleNamespace(
|
|
id=1,
|
|
name="fast1",
|
|
transport="stdio",
|
|
command="cmd1",
|
|
args=json.dumps([]),
|
|
env=json.dumps({}),
|
|
url=None,
|
|
),
|
|
SimpleNamespace(
|
|
id=2,
|
|
name="slow",
|
|
transport="stdio",
|
|
command="cmd2",
|
|
args=json.dumps([]),
|
|
env=json.dumps({}),
|
|
url=None,
|
|
),
|
|
SimpleNamespace(
|
|
id=3,
|
|
name="fast2",
|
|
transport="stdio",
|
|
command="cmd3",
|
|
args=json.dumps([]),
|
|
env=json.dumps({}),
|
|
url=None,
|
|
),
|
|
]
|
|
|
|
monkeypatch.setattr(
|
|
mcp_manager,
|
|
"SessionLocal",
|
|
lambda: FakeDB(servers),
|
|
)
|
|
|
|
completed = []
|
|
|
|
async def fake_connect_server(server_id, **kwargs):
|
|
if server_id == 2:
|
|
# Simulate a hung connection.
|
|
await asyncio.sleep(30)
|
|
else:
|
|
await asyncio.sleep(0.1)
|
|
completed.append(server_id)
|
|
|
|
monkeypatch.setattr(
|
|
manager,
|
|
"connect_server",
|
|
fake_connect_server,
|
|
)
|
|
|
|
#
|
|
# Don't actually wait 20 seconds during the test.
|
|
# Replace asyncio.wait_for used by mcp_manager with a much shorter timeout.
|
|
#
|
|
real_wait_for = asyncio.wait_for
|
|
|
|
async def short_wait_for(awaitable, timeout):
|
|
return await real_wait_for(awaitable, timeout=0.2)
|
|
|
|
monkeypatch.setattr(
|
|
mcp_manager.asyncio,
|
|
"wait_for",
|
|
short_wait_for,
|
|
)
|
|
|
|
start = time.perf_counter()
|
|
|
|
await manager.connect_all_enabled()
|
|
|
|
elapsed = time.perf_counter() - start
|
|
|
|
assert set(completed) == {1, 3}
|
|
assert elapsed < 1 |