""" Tests for the Proxmox MCP server. """ import pytest from mcp.server.mcpserver.exceptions import ToolError def test_server_initialization(server, mock_proxmox): """Test server initialization with mocked configuration.""" assert server.config.proxmox.host == "test.proxmox.com" assert server.config.auth.user == "test@pve" assert server.config.auth.token_name == "test_token" assert server.config.auth.token_value == "test_value" assert server.config.logging.level == "DEBUG" mock_proxmox.assert_called_once() @pytest.mark.asyncio async def test_list_tools(server): """Test listing available tools.""" tools = await server.mcp.list_tools() tool_names = {tool.name for tool in tools} assert {"get_nodes", "get_vms", "get_storage", "get_cluster_status", "execute_vm_command"} <= tool_names @pytest.mark.asyncio async def test_get_nodes(server, mock_proxmox): """Test get_nodes tool returns formatted node output.""" mock_proxmox.return_value.nodes.get.return_value = [ {"node": "node1", "status": "online"}, {"node": "node2", "status": "online"}, ] mock_proxmox.return_value.nodes.return_value.status.get.return_value = { "uptime": 0, "cpuinfo": {"cpus": 4}, "memory": {"used": 0, "total": 1}, } response = await server.mcp.call_tool("get_nodes", {}) text = response[0].text assert "node1" in text assert "node2" in text @pytest.mark.asyncio async def test_get_node_status_missing_parameter(server): """Test get_node_status tool with missing parameter.""" with pytest.raises(ToolError, match="Field required"): await server.mcp.call_tool("get_node_status", {}) @pytest.mark.asyncio async def test_get_node_status(server, mock_proxmox): """Test get_node_status tool with valid parameter.""" mock_proxmox.return_value.nodes.return_value.status.get.return_value = { "status": "running", "uptime": 123456, "cpu": 0.1, "cpuinfo": {"cpus": 4}, "memory": {"used": 1, "total": 2, "free": 1}, } response = await server.mcp.call_tool("get_node_status", {"node": "node1"}) assert "node1" in response[0].text assert "123456" in response[0].text or "running" in response[0].text.lower() @pytest.mark.asyncio async def test_get_vms(server, mock_proxmox): """Test get_vms tool.""" mock_proxmox.return_value.nodes.get.return_value = [{"node": "node1", "status": "online"}] mock_proxmox.return_value.nodes.return_value.qemu.get.return_value = [ {"vmid": "100", "name": "vm1", "status": "running", "mem": 0, "maxmem": 1}, {"vmid": "101", "name": "vm2", "status": "stopped", "mem": 0, "maxmem": 1}, ] mock_proxmox.return_value.nodes.return_value.qemu.return_value.config.get.return_value = { "cores": 2 } response = await server.mcp.call_tool("get_vms", {}) text = response[0].text assert "vm1" in text assert "vm2" in text @pytest.mark.asyncio async def test_get_storage(server, mock_proxmox): """Test get_storage tool.""" mock_proxmox.return_value.storage.get.return_value = [ {"storage": "local", "type": "dir", "enabled": True}, {"storage": "ceph", "type": "rbd", "enabled": True}, ] mock_proxmox.return_value.nodes.return_value.storage.return_value.status.get.return_value = { "used": 1, "total": 2, "avail": 1, } response = await server.mcp.call_tool("get_storage", {}) text = response[0].text assert "local" in text assert "ceph" in text @pytest.mark.asyncio async def test_get_cluster_status(server, mock_proxmox): """Test get_cluster_status tool.""" mock_proxmox.return_value.cluster.status.get.return_value = [ {"name": "cluster", "quorate": True, "type": "cluster"}, {"node": "node1", "type": "node"}, {"node": "node2", "type": "node"}, ] response = await server.mcp.call_tool("get_cluster_status", {}) text = response[0].text.lower() assert "cluster" in text or "quorum" in text @pytest.mark.asyncio async def test_execute_vm_command_missing_parameters(server): """Test VM command execution with missing parameters.""" with pytest.raises(ToolError): await server.mcp.call_tool("execute_vm_command", {})