Files
modelcontextprotocol--pytho…/tests/examples/test_stories.py
T
wehub-resource-sync 49b9bb6724
Deploy Docs / deploy-docs (push) Failing after 1s
Conformance Tests / client-conformance (push) Failing after 3s
Conformance Tests / server-conformance (push) Failing after 1s
GitHub Actions Security Analysis / zizmor (push) Failing after 1s
CI / checks (push) Failing after 59m20s
CI / all-green (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:10:27 +08:00

75 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Run every story's ``main`` over the in-process (transport × era × variant) matrix."""
from __future__ import annotations
import importlib
import inspect
from typing import Any
import anyio
import pytest
from tests.examples.conftest import MANIFEST, STORIES, STORIES_DIR, Hosted, Leg, story_cfg
pytestmark = pytest.mark.anyio
async def test_story(leg: Leg, cfg: dict[str, Any], hosted: Hosted, client_module: Any) -> None:
kwargs: dict[str, Any] = {"mode": leg.mode}
if cfg["needs_http"]:
kwargs["http"] = hosted.http
with anyio.fail_after(cfg["timeout_s"]):
if cfg["multi_connection"]:
await client_module.main(hosted.targets, **kwargs)
else:
await client_module.main(hosted.targets(), **kwargs)
def test_manifest_matches_filesystem() -> None:
"""Manifest [story.*] / [deferred] keys and on-disk story directories agree exactly."""
dirs = {d.name for d in STORIES_DIR.iterdir() if d.is_dir() and not d.name.startswith(("_", "."))}
runnable = {d for d in dirs if (STORIES_DIR / d / "client.py").exists()}
in_manifest = set(STORIES)
assert runnable == in_manifest, {"only_on_disk": runnable - in_manifest, "only_in_manifest": in_manifest - runnable}
# README-only stub dirs must be exactly the [deferred] table.
deferred_manifest = set(MANIFEST.get("deferred", {}))
assert dirs - runnable == deferred_manifest, {
"stub_dirs_missing_from_manifest": (dirs - runnable) - deferred_manifest,
"deferred_entries_missing_dir": deferred_manifest - (dirs - runnable),
}
assert runnable.isdisjoint(deferred_manifest), "deferred stories must not have a client.py"
_ERAS = {"dual", "modern", "legacy", "dual-in-body"}
_TRANSPORTS = {"in-memory", "http-asgi"}
_SERVER_EXPORTS = {"factory", "app"}
def test_manifest_schema_valid() -> None:
"""Declared manifest values are mutually consistent with the story files."""
for name in STORIES:
cfg = story_cfg(name)
assert "-" not in name, f"{name!r}: story directories must be underscored"
assert cfg["era"] in _ERAS, f"{name!r}: era={cfg['era']!r} not in {_ERAS}"
assert cfg["server_export"] in _SERVER_EXPORTS, f"{name!r}: server_export={cfg['server_export']!r}"
assert set(cfg["transports"]) <= _TRANSPORTS, f"{name!r}: transports={cfg['transports']!r}"
assert (STORIES_DIR / name / "__init__.py").exists(), f"{name!r}: missing __init__.py"
if cfg["server_export"] == "factory":
assert (STORIES_DIR / name / "server.py").exists(), f"{name!r}: missing server.py"
else:
assert "in-memory" not in cfg["transports"], f"{name!r}: server_export='app' cannot run in-memory"
if cfg["needs_http"]:
assert cfg["transports"] == ["http-asgi"], f"{name!r}: needs_http requires transports=['http-asgi']"
ll = STORIES_DIR / name / "server_lowlevel.py"
assert cfg["lowlevel"] == ll.exists(), f"{name!r}: lowlevel={cfg['lowlevel']} vs server_lowlevel.py on disk"
@pytest.mark.parametrize("name", sorted(STORIES))
def test_main_signature_matches_manifest(name: str) -> None:
"""``main``'s first parameter is ``target``/``targets`` per ``multi_connection``; ``http`` iff ``needs_http``."""
cfg = story_cfg(name)
params = list(inspect.signature(importlib.import_module(f"stories.{name}.client").main).parameters)
first = "targets" if cfg["multi_connection"] else "target"
assert params[0] == first, f"{name}: first param is {params[0]!r}, expected {first!r}"
assert ("http" in params) == cfg["needs_http"], f"{name}: 'http' param vs needs_http={cfg['needs_http']}"