Skip to content

Commit d190cfb

Browse files
committed
test: harden MCP container smoke validation
1 parent b304c14 commit d190cfb

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

examples/mcp_server/smoke_test.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@
2020

2121

2222
def validate_responses(responses):
23-
by_id = {response.get("id"): response for response in responses}
24-
if set(by_id) != {1, 2}:
25-
raise ValueError(f"expected response IDs 1 and 2, got {sorted(by_id)}")
23+
if not all(isinstance(response, dict) for response in responses):
24+
raise ValueError("expected each stdout payload to be a JSON object")
25+
26+
response_ids = [response.get("id") for response in responses]
27+
if len(responses) != 2 or set(response_ids) != {1, 2}:
28+
raise ValueError(f"expected response IDs 1 and 2 only, got {response_ids}")
29+
by_id = {response["id"]: response for response in responses}
2630

2731
server_info = by_id[1].get("result", {}).get("serverInfo", {})
2832
if server_info.get("name") != "funasr":
@@ -34,6 +38,21 @@ def validate_responses(responses):
3438
raise ValueError(f"transcribe_audio missing from tools/list: {tool_names}")
3539

3640

41+
def parse_responses(stdout):
42+
responses = []
43+
for line_number, raw_line in enumerate(stdout.splitlines(), start=1):
44+
line = raw_line.strip()
45+
if not line:
46+
continue
47+
try:
48+
responses.append(json.loads(line))
49+
except json.JSONDecodeError as error:
50+
raise ValueError(
51+
f"non-JSON stdout on line {line_number}: {line[:120]}"
52+
) from error
53+
return responses
54+
55+
3756
def run_smoke_test(image, timeout):
3857
payload = "".join(f"{json.dumps(request)}\n" for request in REQUESTS)
3958
completed = subprocess.run(
@@ -49,9 +68,7 @@ def run_smoke_test(image, timeout):
4968
f"container exited with {completed.returncode}: {completed.stderr.strip()}"
5069
)
5170

52-
responses = [
53-
json.loads(line) for line in completed.stdout.splitlines() if line.strip()
54-
]
71+
responses = parse_responses(completed.stdout)
5572
validate_responses(responses)
5673

5774

examples/mcp_server/test_registry_metadata.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
def load_smoke_test_module():
1717
spec = importlib.util.spec_from_file_location("funasr_mcp_smoke_test", SMOKE_TEST)
18+
if spec is None or spec.loader is None:
19+
raise ImportError(f"Could not load smoke test module from {SMOKE_TEST}")
1820
module = importlib.util.module_from_spec(spec)
1921
spec.loader.exec_module(module)
2022
return module
@@ -135,6 +137,26 @@ def test_validate_responses_rejects_missing_tool(self):
135137
with self.assertRaisesRegex(ValueError, "transcribe_audio"):
136138
self.smoke_test.validate_responses(responses)
137139

140+
def test_validate_responses_rejects_non_object_payload(self):
141+
with self.assertRaisesRegex(ValueError, "JSON object"):
142+
self.smoke_test.validate_responses([{"id": 1}, ["unexpected"]])
143+
144+
def test_validate_responses_reports_unexpected_ids_without_sorting(self):
145+
responses = [
146+
{"jsonrpc": "2.0", "id": 1, "result": {}},
147+
{"jsonrpc": "2.0", "id": 2, "result": {"tools": []}},
148+
{"jsonrpc": "2.0", "method": "notifications/progress"},
149+
]
150+
151+
with self.assertRaisesRegex(ValueError, "expected response IDs 1 and 2"):
152+
self.smoke_test.validate_responses(responses)
153+
154+
def test_parse_responses_rejects_non_json_stdout(self):
155+
stdout = 'library log on stdout\n{"jsonrpc":"2.0","id":1,"result":{}}\n'
156+
157+
with self.assertRaisesRegex(ValueError, "non-JSON stdout"):
158+
self.smoke_test.parse_responses(stdout)
159+
138160

139161
if __name__ == "__main__":
140162
unittest.main()

0 commit comments

Comments
 (0)