139 lines
4.6 KiB
Python
139 lines
4.6 KiB
Python
from __future__ import annotations
|
|
|
|
import sys
|
|
|
|
from wf_mcp.events import EventBus, InMemoryEventSink
|
|
from wf_mcp.models import BrokerConfig, ConnectionConfig
|
|
from wf_mcp.proxy import ProxyRuntime
|
|
from wf_mcp.proxy.reload_events import (
|
|
ProxyReloadResult,
|
|
reload_change_events,
|
|
)
|
|
from wf_mcp.proxy.tools import ProxyToolPayload, ProxyToolsPage
|
|
|
|
from ..test_support import fixture_server_path, local_temp_root
|
|
|
|
|
|
def test_proxy_runtime_reload_publishes_local_change_events() -> None:
|
|
sink = InMemoryEventSink()
|
|
event_bus = EventBus(sink)
|
|
config = BrokerConfig(
|
|
store_root=local_temp_root() / "proxy_reload_events_store",
|
|
connections=[
|
|
ConnectionConfig(
|
|
id="fixture.personal",
|
|
server="fixture",
|
|
account="personal",
|
|
metadata={
|
|
"transport": "stdio",
|
|
"command": sys.executable,
|
|
"args": [fixture_server_path()],
|
|
},
|
|
)
|
|
],
|
|
)
|
|
runtime = ProxyRuntime(config, event_bus=event_bus)
|
|
initial_event_count = len(sink.list_events())
|
|
|
|
result = runtime.reload()
|
|
|
|
events = sink.list_events()[initial_event_count:]
|
|
event_kinds = [event.kind for event in events]
|
|
catalog_changed = [event for event in events if event.kind == "catalog_changed"]
|
|
assert result["reloaded"] is True
|
|
assert "tools_changed" in event_kinds
|
|
assert "resources_changed" in event_kinds
|
|
assert "prompts_changed" in event_kinds
|
|
assert catalog_changed[0].payload["reason"] == "transparent_reload"
|
|
|
|
|
|
def test_proxy_runtime_reload_reuses_unchanged_mounts() -> None:
|
|
config = BrokerConfig(
|
|
store_root=local_temp_root() / "proxy_reuse_store",
|
|
connections=[
|
|
ConnectionConfig(
|
|
id="fixture.personal",
|
|
server="fixture",
|
|
account="personal",
|
|
metadata={
|
|
"transport": "stdio",
|
|
"command": sys.executable,
|
|
"args": [fixture_server_path()],
|
|
},
|
|
)
|
|
],
|
|
)
|
|
runtime = ProxyRuntime(config)
|
|
first_mount = runtime.mounts.active_mounts_for(config)[0]
|
|
|
|
result = runtime.reload()
|
|
second_mount = runtime.mounts.active_mounts_for(config)[0]
|
|
|
|
assert result["mounted_connections"] == ["fixture.personal"]
|
|
assert result["connection_count"] == 1
|
|
assert result["enabled_connection_count"] == 1
|
|
assert first_mount is second_mount
|
|
|
|
|
|
def test_proxy_reload_result_serializes_and_drives_reload_events() -> None:
|
|
result = ProxyReloadResult(
|
|
mounted_connections=["fixture.personal"],
|
|
connection_count=2,
|
|
enabled_connection_count=1,
|
|
)
|
|
|
|
payload = result.to_payload()
|
|
rehydrated = ProxyReloadResult.from_payload(payload)
|
|
events = reload_change_events(result)
|
|
|
|
assert payload["ok"] is True
|
|
assert payload["reloaded"] is True
|
|
assert payload["mounted_connections"] == ["fixture.personal"]
|
|
assert payload["connection_count"] == 2
|
|
assert payload["enabled_connection_count"] == 1
|
|
assert rehydrated == result
|
|
assert events[0].payload["mounted_connections"] == ["fixture.personal"]
|
|
assert events[0].payload["enabled_connection_count"] == 1
|
|
|
|
|
|
def test_proxy_tool_payload_serializes_admin_tool_metadata() -> None:
|
|
payload = ProxyToolPayload(
|
|
proxy_name="fixture.personal.echo_tool",
|
|
connection_id="fixture.personal",
|
|
local_name="echo_tool",
|
|
title="Echo Tool",
|
|
description="Echo text back",
|
|
input_schema={"type": "object"},
|
|
output_schema={"type": "object"},
|
|
)
|
|
|
|
minimal = payload.to_payload(include_schema=False)
|
|
with_schema = payload.to_payload(include_schema=True)
|
|
|
|
assert minimal["proxy_name"] == "fixture.personal.echo_tool"
|
|
assert minimal["connection_id"] == "fixture.personal"
|
|
assert minimal["local_name"] == "echo_tool"
|
|
assert minimal["enabled"] is True
|
|
assert "input_schema" not in minimal
|
|
assert with_schema["input_schema"] == {"type": "object"}
|
|
assert with_schema["output_schema"] == {"type": "object"}
|
|
|
|
|
|
def test_proxy_tools_page_serializes_paginated_payload() -> None:
|
|
tool = ProxyToolPayload(
|
|
proxy_name="fixture.personal.echo_tool",
|
|
connection_id="fixture.personal",
|
|
local_name="echo_tool",
|
|
)
|
|
page = ProxyToolsPage(
|
|
tools=[tool],
|
|
next_cursor="cursor-1",
|
|
total=3,
|
|
)
|
|
|
|
payload = page.to_payload(include_schema=False)
|
|
|
|
assert payload["nextCursor"] == "cursor-1"
|
|
assert payload["total"] == 3
|
|
assert payload["tools"][0]["proxy_name"] == "fixture.personal.echo_tool"
|