half an attempt to asyncify tests + deprecate old temp path creation

This commit is contained in:
lda
2026-06-11 05:01:33 +07:00 Verified
parent d695fd7533
commit 9dae4a8445
32 changed files with 782 additions and 753 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import sys
from pathlib import Path
from typing import Any
from wf_mcp.models import BrokerConfig, ConnectionConfig
@@ -14,9 +15,9 @@ def structured(result: Any) -> dict[str, Any]:
return content
def proxy_config() -> BrokerConfig:
def proxy_config(tmp_path: Path = local_temp_root()) -> BrokerConfig:
return BrokerConfig(
store_root=local_temp_root() / "proxy_store",
store_root=tmp_path / "proxy_store",
connections=[
ConnectionConfig(
id="fixture.personal",
+10 -9
View File
@@ -3,18 +3,19 @@ from __future__ import annotations
import asyncio
import json
import sys
from pathlib import Path
import mcp.types as mcp_types
from wf_mcp.broker import load_broker_config
from wf_mcp.proxy import create_proxy_client
from ..test_support import fixture_server_path, local_temp_root
from ..test_support import fixture_server_path
from .conftest import structured
def test_proxy_admin_tools_mutate_config_file() -> None:
tmp_path = local_temp_root() / "proxy_admin_store"
def test_proxy_admin_tools_mutate_config_file(tmp_path: Path) -> None:
tmp_path = tmp_path / "proxy_admin_store"
tmp_path.mkdir(parents=True, exist_ok=True)
config_path = tmp_path / "wf_mcp.config.json"
config_path.write_text(
@@ -89,8 +90,8 @@ def test_proxy_admin_tools_mutate_config_file() -> None:
]
def test_proxy_admin_reload_remounts_connections() -> None:
tmp_path = local_temp_root() / "proxy_reload_store"
def test_proxy_admin_reload_remounts_connections(tmp_path: Path) -> None:
tmp_path = tmp_path / "proxy_reload_store"
tmp_path.mkdir(parents=True, exist_ok=True)
config_path = tmp_path / "wf_mcp.config.json"
config_path.write_text(
@@ -130,8 +131,8 @@ def test_proxy_admin_reload_remounts_connections() -> None:
asyncio.run(run_proxy())
def test_proxy_admin_reload_sends_list_changed_notifications() -> None:
tmp_path = local_temp_root() / "proxy_reload_notification_store"
def test_proxy_admin_reload_sends_list_changed_notifications(tmp_path: Path) -> None:
tmp_path = tmp_path / "proxy_reload_notification_store"
tmp_path.mkdir(parents=True, exist_ok=True)
config_path = tmp_path / "wf_mcp.config.json"
config_path.write_text(
@@ -164,8 +165,8 @@ def test_proxy_admin_reload_sends_list_changed_notifications() -> None:
assert "notifications/prompts/list_changed" in methods
def test_proxy_config_mutation_does_not_notify_before_reload() -> None:
tmp_path = local_temp_root() / "proxy_staged_notification_store"
def test_proxy_config_mutation_does_not_notify_before_reload(tmp_path: Path) -> None:
tmp_path = tmp_path / "proxy_staged_notification_store"
tmp_path.mkdir(parents=True, exist_ok=True)
config_path = tmp_path / "wf_mcp.config.json"
config_path.write_text(
+172 -197
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import asyncio
import sys
from pathlib import Path
from typing import Any
import anyio
@@ -14,72 +15,69 @@ from wf_mcp.models import BrokerConfig, ConnectionConfig
from wf_mcp.proxy import create_proxy_client
from wf_mcp.proxy.mounts import _bounded_proxy_list
from ..test_support import fixture_server_path, local_temp_root
from ..test_support import fixture_server_path
from .conftest import proxy_config, structured
def test_proxy_lists_and_calls_upstream_tools() -> None:
config = proxy_config()
async def test_proxy_lists_and_calls_upstream_tools(tmp_path: Path) -> None:
config = proxy_config(tmp_path)
async def run_proxy() -> None:
client = create_proxy_client(config)
async with client:
tools = await client.list_tools()
names = [tool.name for tool in tools]
assert "wf.admin.list_connections" in names
assert "wf.admin.get_connection_statuses" in names
assert "wf.admin.list_proxy_tools" in names
assert "wf.admin.get_proxy_tool" in names
assert "fixture.personal.echo_tool" in names
client = create_proxy_client(config)
async with client:
tools = await client.list_tools()
names = [tool.name for tool in tools]
assert "wf.admin.list_connections" in names
assert "wf.admin.get_connection_statuses" in names
assert "wf.admin.list_proxy_tools" in names
assert "wf.admin.get_proxy_tool" in names
assert "fixture.personal.echo_tool" in names
connections_result = await client.call_tool("wf.admin.list_connections")
connections = structured(connections_result)["result"]
assert len(connections) == 1
connection = connections[0]
assert connection["id"] == "fixture.personal"
assert connection["server"] == "fixture"
assert connection["account"] == "personal"
assert connection["enabled"] is True
assert connection["source_config_ownership"] == "locked"
assert connection["metadata"] == {
"transport": "stdio",
"command": sys.executable,
"args": [fixture_server_path()],
}
connections_result = await client.call_tool("wf.admin.list_connections")
connections = structured(connections_result)["result"]
assert len(connections) == 1
connection = connections[0]
assert connection["id"] == "fixture.personal"
assert connection["server"] == "fixture"
assert connection["account"] == "personal"
assert connection["enabled"] is True
assert connection["source_config_ownership"] == "locked"
assert connection["metadata"] == {
"transport": "stdio",
"command": sys.executable,
"args": [fixture_server_path()],
}
result = await client.call_tool(
"fixture.personal.echo_tool",
{"text": "hello"},
)
assert structured(result) == {"echoed": "hello"}
result = await client.call_tool(
"fixture.personal.echo_tool",
{"text": "hello"},
)
assert structured(result) == {"echoed": "hello"}
proxy_tools_result = await client.call_tool("wf.admin.list_proxy_tools")
proxy_tools_payload = structured(proxy_tools_result)
proxy_tools = proxy_tools_payload["tools"]
assert proxy_tools_payload["nextCursor"] is None
assert proxy_tools_payload["total"] == 5
assert len(proxy_tools) == 5
assert proxy_tools[0]["proxy_name"] == "fixture.personal.echo_tool"
assert proxy_tools[0]["connection_id"] == "fixture.personal"
assert proxy_tools[0]["local_name"] == "echo_tool"
assert proxy_tools[0]["enabled"] is True
proxy_names = [tool["proxy_name"] for tool in proxy_tools]
assert "fixture.personal.emit_notifications_tool" in proxy_names
assert "fixture.personal.remember_value_tool" in proxy_names
assert "fixture.personal.recall_value_tool" in proxy_names
assert "fixture.personal.resource_link_tool" in proxy_names
proxy_tools_result = await client.call_tool("wf.admin.list_proxy_tools")
proxy_tools_payload = structured(proxy_tools_result)
proxy_tools = proxy_tools_payload["tools"]
assert proxy_tools_payload["nextCursor"] is None
assert proxy_tools_payload["total"] == 5
assert len(proxy_tools) == 5
assert proxy_tools[0]["proxy_name"] == "fixture.personal.echo_tool"
assert proxy_tools[0]["connection_id"] == "fixture.personal"
assert proxy_tools[0]["local_name"] == "echo_tool"
assert proxy_tools[0]["enabled"] is True
proxy_names = [tool["proxy_name"] for tool in proxy_tools]
assert "fixture.personal.emit_notifications_tool" in proxy_names
assert "fixture.personal.remember_value_tool" in proxy_names
assert "fixture.personal.recall_value_tool" in proxy_names
assert "fixture.personal.resource_link_tool" in proxy_names
proxy_tool_result = await client.call_tool(
"wf.admin.get_proxy_tool",
{"proxy_name": "fixture.personal.echo_tool"},
)
proxy_tool = structured(proxy_tool_result)
assert proxy_tool["proxy_name"] == "fixture.personal.echo_tool"
assert proxy_tool["connection_id"] == "fixture.personal"
assert proxy_tool["local_name"] == "echo_tool"
assert proxy_tool["input_schema"]["properties"]["text"]["type"] == "string"
asyncio.run(run_proxy())
proxy_tool_result = await client.call_tool(
"wf.admin.get_proxy_tool",
{"proxy_name": "fixture.personal.echo_tool"},
)
proxy_tool = structured(proxy_tool_result)
assert proxy_tool["proxy_name"] == "fixture.personal.echo_tool"
assert proxy_tool["connection_id"] == "fixture.personal"
assert proxy_tool["local_name"] == "echo_tool"
assert proxy_tool["input_schema"]["properties"]["text"]["type"] == "string"
def test_proxy_listing_degrades_when_one_source_hangs() -> None:
@@ -183,60 +181,49 @@ def test_proxy_listing_degrades_when_session_transport_closes(
assert "remote.default" in caplog.text
def test_proxy_registers_admin_tools_on_local_provider() -> None:
config = proxy_config()
async def test_proxy_registers_admin_tools_on_local_provider(tmp_path) -> None:
config = proxy_config(tmp_path)
async def run_proxy() -> None:
client = create_proxy_client(config)
async with client:
tools = await client.list_tools()
admin_names = [
tool.name for tool in tools if tool.name.startswith("wf.admin.")
]
assert "wf.admin.list_connections" in admin_names
assert "wf.admin.get_connection_statuses" in admin_names
assert "wf.admin.list_proxy_tools" in admin_names
assert "wf.admin.get_proxy_tool" in admin_names
asyncio.run(run_proxy())
client = create_proxy_client(config)
async with client:
tools = await client.list_tools()
admin_names = [tool.name for tool in tools if tool.name.startswith("wf.admin.")]
assert "wf.admin.list_connections" in admin_names
assert "wf.admin.get_connection_statuses" in admin_names
assert "wf.admin.list_proxy_tools" in admin_names
assert "wf.admin.get_proxy_tool" in admin_names
def test_proxy_rewrites_resource_links_returned_by_tools() -> None:
config = proxy_config()
async def test_proxy_rewrites_resource_links_returned_by_tools(tmp_path) -> None:
config = proxy_config(tmp_path)
async def run_proxy() -> None:
client = create_proxy_client(config)
async with client:
result = await client.call_tool("fixture.personal.resource_link_tool")
link = result.content[0]
assert link.type == "resource_link"
assert str(link.uri) == "fixture://fixture/personal/docs/welcome"
asyncio.run(run_proxy())
client = create_proxy_client(config)
async with client:
result = await client.call_tool("fixture.personal.resource_link_tool")
link = result.content[0]
assert link.type == "resource_link"
assert str(link.uri) == "fixture://fixture/personal/docs/welcome"
def test_proxy_reuses_one_upstream_session_for_stateful_tools() -> None:
async def test_proxy_reuses_one_upstream_session_for_stateful_tools(tmp_path) -> None:
"""Visible proxy tools must share server-local state for one MCP client."""
config = proxy_config()
config = proxy_config(tmp_path)
async def run_proxy() -> None:
client = create_proxy_client(config)
async with client:
written = await client.call_tool(
"fixture.personal.remember_value_tool",
{"value": "held"},
)
recalled = await client.call_tool("fixture.personal.recall_value_tool")
client = create_proxy_client(config)
async with client:
written = await client.call_tool(
"fixture.personal.remember_value_tool",
{"value": "held"},
)
recalled = await client.call_tool("fixture.personal.recall_value_tool")
assert structured(written)["remembered"] == "held"
assert structured(recalled)["remembered"] == "held"
asyncio.run(run_proxy())
assert structured(written)["remembered"] == "held"
assert structured(recalled)["remembered"] == "held"
def test_proxy_rejects_invalid_connection_config() -> None:
def test_proxy_rejects_invalid_connection_config(tmp_path) -> None:
config = BrokerConfig(
store_root=local_temp_root() / "proxy_invalid_store",
store_root=tmp_path / "proxy_invalid_store",
connections=[
ConnectionConfig(
id="fixture.personal",
@@ -291,103 +278,91 @@ def test_proxy_rejects_invalid_connection_config() -> None:
assert "connection id 'wf.admin' is reserved by wf-mcp" in message
def test_proxy_can_expose_resources_and_prompts_as_tools() -> None:
config = proxy_config()
async def test_proxy_can_expose_resources_and_prompts_as_tools(tmp_path) -> None:
config = proxy_config(tmp_path)
async def run_proxy() -> None:
client = create_proxy_client(
config,
resources_as_tools=True,
prompts_as_tools=True,
client = create_proxy_client(
config,
resources_as_tools=True,
prompts_as_tools=True,
)
async with client:
tools = await client.list_tools()
names = [tool.name for tool in tools]
assert "list_resources" in names
assert "read_resource" in names
assert "list_prompts" in names
assert "get_prompt" in names
async def test_proxy_can_collapse_upstream_tools_behind_search(tmp_path) -> None:
config = BrokerConfig(
store_root=tmp_path / "search_proxy_store",
connections=[
ConnectionConfig(
id="fixture.personal",
server="fixture",
account="personal",
metadata={
"transport": "stdio",
"command": sys.executable,
"args": [fixture_server_path()],
},
)
],
)
client = create_proxy_client(config, search_tools=True)
async with client:
tools = await client.list_tools()
names = [tool.name for tool in tools]
assert "search_tools" in names
assert "wf.admin.list_connections" in names
assert "wf.admin.get_connection_statuses" in names
assert "wf.admin.list_proxy_tools" in names
assert "fixture.personal.echo_tool" not in names
async def test_proxy_admin_inventory_ignores_search_visibility(tmp_path) -> None:
config = BrokerConfig(
store_root=tmp_path / "search_admin_store",
connections=[
ConnectionConfig(
id="fixture.personal",
server="fixture",
account="personal",
metadata={
"transport": "stdio",
"command": sys.executable,
"args": [fixture_server_path()],
},
)
],
)
client = create_proxy_client(config, search_tools=True)
async with client:
result = await client.call_tool("wf.admin.list_proxy_tools")
payload = structured(result)
assert payload["total"] > 0
async def test_proxy_proxy_tool_listing_supports_filters_and_cursor(tmp_path) -> None:
config = proxy_config(tmp_path)
client = create_proxy_client(config)
async with client:
result = await client.call_tool(
"wf.admin.list_proxy_tools",
{"limit": 2},
)
async with client:
tools = await client.list_tools()
names = [tool.name for tool in tools]
assert "list_resources" in names
assert "read_resource" in names
assert "list_prompts" in names
assert "get_prompt" in names
payload = structured(result)
assert len(payload["tools"]) == 2
assert payload["nextCursor"] is not None
asyncio.run(run_proxy())
def test_proxy_can_collapse_upstream_tools_behind_search() -> None:
config = BrokerConfig(
store_root=local_temp_root() / "search_proxy_store",
connections=[
ConnectionConfig(
id="fixture.personal",
server="fixture",
account="personal",
metadata={
"transport": "stdio",
"command": sys.executable,
"args": [fixture_server_path()],
},
)
],
)
async def run_proxy() -> None:
client = create_proxy_client(config, search_tools=True)
async with client:
tools = await client.list_tools()
names = [tool.name for tool in tools]
assert "search_tools" in names
assert "wf.admin.list_connections" in names
assert "wf.admin.get_connection_statuses" in names
assert "wf.admin.list_proxy_tools" in names
assert "fixture.personal.echo_tool" not in names
asyncio.run(run_proxy())
def test_proxy_admin_inventory_ignores_search_visibility() -> None:
config = BrokerConfig(
store_root=local_temp_root() / "search_admin_store",
connections=[
ConnectionConfig(
id="fixture.personal",
server="fixture",
account="personal",
metadata={
"transport": "stdio",
"command": sys.executable,
"args": [fixture_server_path()],
},
)
],
)
async def run_proxy() -> None:
client = create_proxy_client(config, search_tools=True)
async with client:
result = await client.call_tool("wf.admin.list_proxy_tools")
payload = structured(result)
assert payload["total"] > 0
asyncio.run(run_proxy())
def test_proxy_proxy_tool_listing_supports_filters_and_cursor() -> None:
config = proxy_config()
async def run_proxy() -> None:
client = create_proxy_client(config)
async with client:
result = await client.call_tool(
"wf.admin.list_proxy_tools",
{"limit": 2},
)
payload = structured(result)
assert len(payload["tools"]) == 2
assert payload["nextCursor"] is not None
result2 = await client.call_tool(
"wf.admin.list_proxy_tools",
{"limit": 2, "cursor": payload["nextCursor"]},
)
payload2 = structured(result2)
assert len(payload2["tools"]) > 0
asyncio.run(run_proxy())
result2 = await client.call_tool(
"wf.admin.list_proxy_tools",
{"limit": 2, "cursor": payload["nextCursor"]},
)
payload2 = structured(result2)
assert len(payload2["tools"]) > 0