"""Tests for validation tools."""
import pytest
import sys
from pathlib import Path
# Add tests directory to path for helper import
sys.path.insert(0, str(Path(__file__).parent.parent))
from helpers import get_tool_fn
class TestValidateAzureResourceName:
"""Tests for validate_azure_resource_name tool."""
@pytest.mark.asyncio
async def test_valid_resource_group_name(self, mock_context):
"""Valid resource group name should pass validation."""
from standards_mcp_server.tools.validation import validate_azure_resource_name
result = await get_tool_fn(validate_azure_resource_name)(
resource_name="rg-myapp-eus-dev",
resource_type="resource_group",
ctx=mock_context
)
assert result["valid"] is True
assert result["errors"] == 0
@pytest.mark.asyncio
async def test_invalid_resource_group_name(self, mock_context):
"""Invalid resource group name should fail validation."""
from standards_mcp_server.tools.validation import validate_azure_resource_name
result = await get_tool_fn(validate_azure_resource_name)(
resource_name="MyResourceGroup", # Invalid: uppercase
resource_type="resource_group",
ctx=mock_context
)
assert result["valid"] is False
assert result["errors"] > 0
assert any("naming-convention" in i["rule"] or "valid-characters" in i["rule"]
for i in result["issues"])
@pytest.mark.asyncio
async def test_valid_storage_account_name(self, mock_context):
"""Valid storage account name should pass."""
from standards_mcp_server.tools.validation import validate_azure_resource_name
result = await get_tool_fn(validate_azure_resource_name)(
resource_name="stmyappdata001",
resource_type="storage_account",
ctx=mock_context
)
assert result["valid"] is True
@pytest.mark.asyncio
async def test_name_too_long(self, mock_context):
"""Name exceeding max length should fail."""
from standards_mcp_server.tools.validation import validate_azure_resource_name
result = await get_tool_fn(validate_azure_resource_name)(
resource_name="rg-" + "a" * 100 + "-eus-dev",
resource_type="resource_group",
ctx=mock_context
)
assert result["valid"] is False
assert any(i["rule"] == "max-length" for i in result["issues"])
@pytest.mark.asyncio
async def test_unknown_resource_type_warns(self, mock_context):
"""Unknown resource type should produce warning."""
from standards_mcp_server.tools.validation import validate_azure_resource_name
result = await get_tool_fn(validate_azure_resource_name)(
resource_name="myresource",
resource_type="unknown_type",
ctx=mock_context
)
assert result["warnings"] > 0
assert any(i["rule"] == "known-resource-type" for i in result["issues"])
class TestValidateMcpToolDefinition:
"""Tests for validate_mcp_tool_definition tool."""
@pytest.mark.asyncio
async def test_valid_tool_definition(self, mock_context):
"""Valid tool definition should pass."""
from standards_mcp_server.tools.validation import validate_mcp_tool_definition
result = await get_tool_fn(validate_mcp_tool_definition)(
tool_name="terraform_plan",
tool_description="""Generate Terraform execution plan.
Args:
config_path: Path to configuration
Returns:
Plan result with changes summary
""",
parameters={
"type": "object",
"properties": {
"config_path": {
"type": "string",
"description": "Path to Terraform configuration"
}
}
},
ctx=mock_context
)
assert result["valid"] is True
@pytest.mark.asyncio
async def test_invalid_tool_name_format(self, mock_context):
"""Tool name with wrong format should fail."""
from standards_mcp_server.tools.validation import validate_mcp_tool_definition
result = await get_tool_fn(validate_mcp_tool_definition)(
tool_name="TerraformPlan", # Should be snake_case
tool_description="Generate plan",
parameters={},
ctx=mock_context
)
assert result["valid"] is False
assert any(i["rule"] == "tool-name-format" for i in result["issues"])
@pytest.mark.asyncio
async def test_missing_description(self, mock_context):
"""Missing description should fail."""
from standards_mcp_server.tools.validation import validate_mcp_tool_definition
result = await get_tool_fn(validate_mcp_tool_definition)(
tool_name="my_tool",
tool_description="",
parameters={},
ctx=mock_context
)
assert result["valid"] is False
assert any(i["rule"] == "description-required" for i in result["issues"])
@pytest.mark.asyncio
async def test_warns_missing_docstring_sections(self, mock_context):
"""Missing Args/Returns sections should warn."""
from standards_mcp_server.tools.validation import validate_mcp_tool_definition
result = await get_tool_fn(validate_mcp_tool_definition)(
tool_name="my_tool",
tool_description="This is a tool that does something useful.",
parameters={},
ctx=mock_context
)
# Should have warnings for missing Args and Returns
assert result["warnings"] >= 2
assert any(i["rule"] == "docstring-args" for i in result["issues"])
assert any(i["rule"] == "docstring-returns" for i in result["issues"])
class TestValidateAgentCard:
"""Tests for validate_agent_card tool."""
@pytest.mark.asyncio
async def test_valid_agent_card(self, mock_context):
"""Valid agent card should pass."""
from standards_mcp_server.tools.validation import validate_agent_card
result = await get_tool_fn(validate_agent_card)(
agent_card={
"name": "infrastructure-agent",
"description": "Agent for managing Azure infrastructure",
"url": "https://agents.darwin.example.com/infrastructure",
"version": "1.0.0",
"capabilities": {
"streaming": False,
"pushNotifications": False
},
"skills": [
{"id": "deploy", "name": "Deploy Infrastructure"}
]
},
ctx=mock_context
)
assert result["valid"] is True
assert result["errors"] == 0
@pytest.mark.asyncio
async def test_missing_required_fields(self, mock_context):
"""Missing required fields should fail."""
from standards_mcp_server.tools.validation import validate_agent_card
result = await get_tool_fn(validate_agent_card)(
agent_card={
"name": "my-agent"
# Missing: description, url, version, capabilities
},
ctx=mock_context
)
assert result["valid"] is False
assert result["errors"] >= 4 # At least 4 missing fields
@pytest.mark.asyncio
async def test_invalid_version_format(self, mock_context):
"""Non-semver version should fail."""
from standards_mcp_server.tools.validation import validate_agent_card
result = await get_tool_fn(validate_agent_card)(
agent_card={
"name": "my-agent",
"description": "Test agent",
"url": "https://example.com",
"version": "v1.0", # Invalid: should be X.Y.Z
"capabilities": {}
},
ctx=mock_context
)
assert result["valid"] is False
assert any(i["rule"] == "version-format" for i in result["issues"])
@pytest.mark.asyncio
async def test_invalid_agent_name_format(self, mock_context):
"""Invalid agent name format should fail."""
from standards_mcp_server.tools.validation import validate_agent_card
result = await get_tool_fn(validate_agent_card)(
agent_card={
"name": "MyAgent", # Should be kebab-case
"description": "Test agent",
"url": "https://example.com",
"version": "1.0.0",
"capabilities": {}
},
ctx=mock_context
)
assert result["valid"] is False
assert any(i["rule"] == "agent-name-format" for i in result["issues"])