73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
"""Integration: boots a real (diskless) QEMU VM through the MCP tools.
|
|
|
|
Run with: uv run pytest -m integration
|
|
"""
|
|
|
|
import base64
|
|
import shutil
|
|
|
|
import pytest
|
|
from fastmcp import Client
|
|
|
|
from conftest import result_data
|
|
from mcqemu.registry import pid_alive
|
|
from mcqemu.server import mcp
|
|
|
|
pytestmark = [
|
|
pytest.mark.integration,
|
|
pytest.mark.skipif(
|
|
shutil.which("qemu-system-x86_64") is None, reason="qemu-system-x86_64 not installed"
|
|
),
|
|
]
|
|
|
|
|
|
async def test_real_vm_lifecycle(dirs):
|
|
async with Client(mcp) as client:
|
|
data = result_data(
|
|
await client.call_tool(
|
|
"launch_vm",
|
|
{"name": "itest", "memory_mb": 128, "cpus": 1, "no_net": True},
|
|
)
|
|
)
|
|
pid = data["pid"]
|
|
try:
|
|
assert data["status"] == "running"
|
|
assert pid_alive(pid)
|
|
|
|
vms = result_data(await client.call_tool("list_vms", {}))
|
|
assert [(v["name"], v["status"]) for v in vms] == [("itest", "running")]
|
|
|
|
info = result_data(await client.call_tool("vm_info", {"name": "itest"}))
|
|
assert info["vcpus"] == 1
|
|
|
|
data = result_data(await client.call_tool("pause_vm", {"name": "itest"}))
|
|
assert data["status"] == "paused"
|
|
vms = result_data(await client.call_tool("list_vms", {}))
|
|
assert vms[0]["status"] == "paused"
|
|
|
|
await client.call_tool("resume_vm", {"name": "itest"})
|
|
|
|
# See & drive against the live SeaBIOS display.
|
|
result = await client.call_tool("vm_screenshot", {"name": "itest"})
|
|
block = result.content[0]
|
|
assert block.type == "image"
|
|
png = base64.b64decode(block.data)
|
|
assert png[:8] == b"\x89PNG\r\n\x1a\n"
|
|
|
|
await client.call_tool(
|
|
"vm_send_keys", {"name": "itest", "keys": ["f2", "enter"], "delay_ms": 0}
|
|
)
|
|
await client.call_tool("vm_click", {"name": "itest", "x": 10, "y": 10})
|
|
data = result_data(await client.call_tool("vm_serial_read", {"name": "itest"}))
|
|
assert "tail" in data
|
|
|
|
data = result_data(await client.call_tool("stop_vm", {"name": "itest", "force": True}))
|
|
assert data["status"] == "stopped"
|
|
assert not pid_alive(pid)
|
|
finally:
|
|
if pid_alive(pid):
|
|
import os
|
|
import signal
|
|
|
|
os.kill(pid, signal.SIGKILL)
|