Skip to main content
Glama
test_complete_commands.py28.6 kB
""" Exhaustive functional tests for EVERY command system function. Tests all command functionality with real Claude Code execution. """ import pytest import asyncio import json import tempfile import shutil from pathlib import Path from datetime import datetime from typing import Dict, List, Any, Optional from shannon_mcp.commands.parser import CommandParser from shannon_mcp.commands.executor import CommandExecutor from shannon_mcp.commands.registry import CommandRegistry from shannon_mcp.commands.validator import CommandValidator from shannon_mcp.managers.session import SessionManager from shannon_mcp.managers.binary import BinaryManager from shannon_mcp.storage.database import Database class TestCompleteCommandSystem: """Test every single command system function comprehensively.""" @pytest.fixture async def command_setup(self): """Set up command testing environment.""" temp_dir = tempfile.mkdtemp() db_path = Path(temp_dir) / "commands.db" db = Database(db_path) await db.initialize() binary_manager = BinaryManager() session_manager = SessionManager(binary_manager=binary_manager) parser = CommandParser() validator = CommandValidator() registry = CommandRegistry(db=db) executor = CommandExecutor( parser=parser, validator=validator, registry=registry, session_manager=session_manager ) await registry.initialize() await executor.initialize() yield { "executor": executor, "parser": parser, "validator": validator, "registry": registry, "session_manager": session_manager, "db": db, "temp_dir": temp_dir } # Cleanup await executor.cleanup() await session_manager.cleanup() await db.close() shutil.rmtree(temp_dir) async def test_command_parser_complete(self, command_setup): """Test command parser with all syntax variations.""" parser = command_setup["parser"] # Test basic command result1 = parser.parse("/help") assert result1["command"] == "help" assert result1["args"] == [] assert result1["options"] == {} # Test command with arguments result2 = parser.parse("/session create test-session") assert result2["command"] == "session" assert result2["args"] == ["create", "test-session"] # Test command with options result3 = parser.parse("/session create --model claude-3 --temperature 0.7") assert result3["command"] == "session" assert result3["args"] == ["create"] assert result3["options"]["model"] == "claude-3" assert result3["options"]["temperature"] == "0.7" # Test command with quoted arguments result4 = parser.parse('/prompt "Hello world" --session test') assert result4["args"] == ["Hello world"] assert result4["options"]["session"] == "test" # Test complex command result5 = parser.parse( '/agent create "Research Agent" --type research ' '--capabilities "web_search,analysis" --priority 5' ) assert result5["args"] == ["create", "Research Agent"] assert result5["options"]["type"] == "research" assert result5["options"]["capabilities"] == "web_search,analysis" assert result5["options"]["priority"] == "5" # Test command with flags result6 = parser.parse("/checkpoint create --incremental --compress") assert result6["options"]["incremental"] is True assert result6["options"]["compress"] is True # Test command with JSON option result7 = parser.parse('/config set --data \'{"key": "value", "num": 123}\'') assert result7["options"]["data"] == '{"key": "value", "num": 123}' # Test multiline command result8 = parser.parse(""" /pipeline create \\ --name "DataPipeline" \\ --stages "extract,transform,load" \\ --parallel """) assert result8["args"] == ["create"] assert result8["options"]["name"] == "DataPipeline" assert result8["options"]["parallel"] is True # Test special characters result9 = parser.parse('/echo "Special chars: $@#%^&*()"') assert "Special chars: $@#%^&*()" in result9["args"][0] # Test escape sequences result10 = parser.parse('/prompt "Line 1\\nLine 2\\tTabbed"') assert result10["args"][0] == "Line 1\\nLine 2\\tTabbed" async def test_command_validation_complete(self, command_setup): """Test command validation with all rules.""" validator = command_setup["validator"] registry = command_setup["registry"] # Register test commands with validation rules await registry.register_command({ "name": "session", "description": "Manage sessions", "subcommands": { "create": { "args": [ { "name": "session_id", "type": "string", "required": False, "pattern": "^[a-zA-Z0-9-_]+$" } ], "options": { "model": { "type": "string", "choices": ["claude-3-opus-20240229", "claude-3-sonnet-20240229"], "default": "claude-3-opus-20240229" }, "temperature": { "type": "float", "min": 0.0, "max": 1.0, "default": 0.7 }, "max_tokens": { "type": "int", "min": 1, "max": 100000 } } } } }) # Test valid command valid1 = await validator.validate({ "command": "session", "args": ["create", "test-123"], "options": {"temperature": "0.5"} }) assert valid1["valid"] is True # Test invalid session ID pattern invalid1 = await validator.validate({ "command": "session", "args": ["create", "test session"], # Space not allowed "options": {} }) assert invalid1["valid"] is False assert "pattern" in invalid1["errors"][0] # Test invalid option type invalid2 = await validator.validate({ "command": "session", "args": ["create"], "options": {"temperature": "high"} # Should be float }) assert invalid2["valid"] is False assert "type" in invalid2["errors"][0] # Test out of range value invalid3 = await validator.validate({ "command": "session", "args": ["create"], "options": {"temperature": "1.5"} # Max is 1.0 }) assert invalid3["valid"] is False assert "max" in invalid3["errors"][0] # Test invalid choice invalid4 = await validator.validate({ "command": "session", "args": ["create"], "options": {"model": "gpt-4"} # Not in choices }) assert invalid4["valid"] is False assert "choices" in invalid4["errors"][0] # Test custom validation function await registry.register_command({ "name": "custom", "validator": lambda cmd: cmd["options"].get("key") == "secret" }) custom_valid = await validator.validate({ "command": "custom", "args": [], "options": {"key": "secret"} }) assert custom_valid["valid"] is True async def test_command_registry_complete(self, command_setup): """Test command registry with all features.""" registry = command_setup["registry"] # Register various command types commands = [ { "name": "help", "description": "Show help information", "aliases": ["h", "?"], "category": "general", "handler": "help_handler" }, { "name": "session", "description": "Session management", "category": "core", "subcommands": { "create": {"description": "Create new session"}, "list": {"description": "List sessions"}, "delete": {"description": "Delete session"}, "info": {"description": "Show session info"} } }, { "name": "agent", "description": "Agent management", "category": "advanced", "requires_session": True, "permissions": ["agent.manage"], "subcommands": { "register": {"description": "Register agent"}, "assign": {"description": "Assign task"}, "status": {"description": "Check status"} } }, { "name": "debug", "description": "Debug commands", "category": "development", "hidden": True, "admin_only": True } ] for cmd in commands: await registry.register_command(cmd) # Test command lookup help_cmd = await registry.get_command("help") assert help_cmd["name"] == "help" assert "h" in help_cmd["aliases"] # Test alias resolution h_cmd = await registry.resolve_alias("h") assert h_cmd == "help" # Test category listing categories = await registry.list_categories() assert "general" in categories assert "core" in categories assert "advanced" in categories # Test commands by category general_cmds = await registry.list_commands(category="general") assert any(cmd["name"] == "help" for cmd in general_cmds) # Test hidden commands all_cmds = await registry.list_commands(include_hidden=False) assert not any(cmd["name"] == "debug" for cmd in all_cmds) hidden_cmds = await registry.list_commands(include_hidden=True) assert any(cmd["name"] == "debug" for cmd in hidden_cmds) # Test command search search_results = await registry.search_commands("session") assert len(search_results) > 0 assert search_results[0]["name"] == "session" # Test subcommand resolution subcommands = await registry.get_subcommands("session") assert "create" in subcommands assert "list" in subcommands # Test command updates await registry.update_command("help", { "description": "Updated help description", "aliases": ["h", "?", "help"] }) updated = await registry.get_command("help") assert updated["description"] == "Updated help description" assert len(updated["aliases"]) == 3 # Test command deletion await registry.unregister_command("debug") deleted = await registry.get_command("debug") assert deleted is None async def test_command_execution_complete(self, command_setup): """Test command execution with all scenarios.""" executor = command_setup["executor"] registry = command_setup["registry"] session_manager = command_setup["session_manager"] # Register executable commands async def help_handler(context): return { "success": True, "output": "Available commands: help, session, echo", "data": {"commands": ["help", "session", "echo"]} } async def echo_handler(context): message = " ".join(context["args"]) return { "success": True, "output": message, "data": {"echoed": message} } async def session_create_handler(context): session_id = context["args"][1] if len(context["args"]) > 1 else None options = context["options"] session = await session_manager.create_session( session_id=session_id, model=options.get("model", "claude-3-opus-20240229") ) return { "success": True, "output": f"Created session: {session.id}", "data": {"session_id": session.id} } # Register handlers await registry.register_handler("help", help_handler) await registry.register_handler("echo", echo_handler) await registry.register_handler("session.create", session_create_handler) # Test basic command execution result1 = await executor.execute("/help") assert result1["success"] is True assert "Available commands" in result1["output"] # Test command with arguments result2 = await executor.execute("/echo Hello World!") assert result2["output"] == "Hello World!" # Test subcommand execution result3 = await executor.execute("/session create test-session") assert result3["success"] is True assert "test-session" in result3["output"] # Test command with options result4 = await executor.execute( "/session create --model claude-3-sonnet-20240229" ) assert result4["success"] is True # Test command context async def context_handler(context): return { "success": True, "output": f"User: {context.get('user', 'unknown')}", "data": context } await registry.register_handler("whoami", context_handler) result5 = await executor.execute( "/whoami", context={"user": "test_user", "session": "test_session"} ) assert "User: test_user" in result5["output"] # Test command pipeline pipeline_result = await executor.execute_pipeline([ "/session create pipeline-test", "/echo Session created", "/session info pipeline-test" ]) assert len(pipeline_result) == 3 assert all(r["success"] for r in pipeline_result) # Test command with error handling async def error_handler(context): raise ValueError("Test error") await registry.register_handler("error", error_handler) result6 = await executor.execute("/error") assert result6["success"] is False assert "error" in result6["output"].lower() async def test_command_permissions_security(self, command_setup): """Test command permissions and security.""" executor = command_setup["executor"] registry = command_setup["registry"] # Register commands with permissions await registry.register_command({ "name": "admin", "description": "Admin command", "permissions": ["admin.execute"], "handler": lambda ctx: {"success": True, "output": "Admin command executed"} }) await registry.register_command({ "name": "restricted", "description": "Restricted command", "permissions": ["user.advanced", "feature.experimental"], "handler": lambda ctx: {"success": True, "output": "Restricted command executed"} }) # Test without permissions result1 = await executor.execute( "/admin", context={"permissions": []} ) assert result1["success"] is False assert "permission" in result1["output"].lower() # Test with correct permissions result2 = await executor.execute( "/admin", context={"permissions": ["admin.execute"]} ) assert result2["success"] is True # Test with partial permissions result3 = await executor.execute( "/restricted", context={"permissions": ["user.advanced"]} ) assert result3["success"] is False # Test with all permissions result4 = await executor.execute( "/restricted", context={"permissions": ["user.advanced", "feature.experimental"]} ) assert result4["success"] is True # Test command sanitization dangerous_commands = [ "/exec rm -rf /", "/eval __import__('os').system('ls')", "/shell && cat /etc/passwd" ] for cmd in dangerous_commands: result = await executor.execute(cmd) assert result["success"] is False assert "not found" in result["output"].lower() or "invalid" in result["output"].lower() async def test_command_autocomplete(self, command_setup): """Test command autocomplete functionality.""" executor = command_setup["executor"] registry = command_setup["registry"] # Register commands for autocomplete commands = ["help", "session", "agent", "checkpoint", "analytics"] for cmd in commands: await registry.register_command({ "name": cmd, "description": f"{cmd} command" }) # Register subcommands await registry.register_command({ "name": "session", "subcommands": { "create": {}, "list": {}, "delete": {}, "info": {} } }) # Test command prefix autocomplete suggestions1 = await executor.autocomplete("/he") assert "help" in suggestions1 suggestions2 = await executor.autocomplete("/sess") assert "session" in suggestions2 # Test subcommand autocomplete suggestions3 = await executor.autocomplete("/session cr") assert "create" in suggestions3 # Test option autocomplete await registry.register_command({ "name": "test", "options": { "model": {"choices": ["claude-3-opus", "claude-3-sonnet"]}, "temperature": {"type": "float"}, "verbose": {"type": "bool"} } }) suggestions4 = await executor.autocomplete("/test --mo") assert "--model" in suggestions4 suggestions5 = await executor.autocomplete("/test --model ") assert "claude-3-opus" in suggestions5 assert "claude-3-sonnet" in suggestions5 # Test context-aware autocomplete async def dynamic_autocomplete(partial, context): if "sessions" in context: return [s for s in context["sessions"] if s.startswith(partial)] return [] await registry.register_autocomplete("session", "delete", dynamic_autocomplete) suggestions6 = await executor.autocomplete( "/session delete test", context={"sessions": ["test-1", "test-2", "prod-1"]} ) assert "test-1" in suggestions6 assert "test-2" in suggestions6 assert "prod-1" not in suggestions6 async def test_command_history_replay(self, command_setup): """Test command history and replay functionality.""" executor = command_setup["executor"] registry = command_setup["registry"] # Enable history tracking await executor.enable_history(max_size=100) # Execute commands commands = [ "/help", "/echo First command", "/echo Second command", "/session create history-test" ] for cmd in commands: await executor.execute(cmd) # Test history retrieval history = await executor.get_history() assert len(history) == 4 assert history[0]["command"] == "/help" assert history[-1]["command"] == "/session create history-test" # Test history search echo_history = await executor.search_history("echo") assert len(echo_history) == 2 # Test replay last command replay_result = await executor.replay_last() assert replay_result["success"] is True assert "history-test" in replay_result["output"] # Test replay by index replay_result2 = await executor.replay(1) # "echo First command" assert replay_result2["output"] == "First command" # Test replay with modifications replay_result3 = await executor.replay( 2, # "echo Second command" modifications={"args": ["Modified command"]} ) assert replay_result3["output"] == "Modified command" # Test history export exported = await executor.export_history() assert len(exported) > 0 assert "timestamp" in exported[0] assert "command" in exported[0] assert "result" in exported[0] # Test history import await executor.clear_history() await executor.import_history(exported) imported_history = await executor.get_history() assert len(imported_history) == len(exported) async def test_command_macros_aliases(self, command_setup): """Test command macros and custom aliases.""" executor = command_setup["executor"] registry = command_setup["registry"] # Register base commands await registry.register_handler( "echo", lambda ctx: {"success": True, "output": " ".join(ctx["args"])} ) await registry.register_handler( "session.create", lambda ctx: {"success": True, "output": f"Session created: {ctx['args'][1]}"} ) # Create macros await executor.create_macro({ "name": "setup", "description": "Setup development environment", "commands": [ "/session create dev-{timestamp}", "/echo Development session created", "/agent register --name DevAgent --type developer" ], "parameters": { "timestamp": { "type": "string", "default": "{{datetime.now().strftime('%Y%m%d-%H%M%S')}}" } } }) # Execute macro macro_result = await executor.execute("/macro setup") assert len(macro_result) == 3 assert all(r["success"] for r in macro_result) # Create parameterized macro await executor.create_macro({ "name": "deploy", "description": "Deploy to environment", "commands": [ "/echo Deploying to {env}", "/session create deploy-{env}-{version}", "/echo Deployment complete" ], "parameters": { "env": {"type": "string", "required": True}, "version": {"type": "string", "default": "latest"} } }) # Execute with parameters deploy_result = await executor.execute( "/macro deploy --env production --version 1.2.3" ) assert "Deploying to production" in deploy_result[0]["output"] assert "deploy-production-1.2.3" in deploy_result[1]["output"] # Create command alias await executor.create_alias("ll", "/session list --detailed") await executor.create_alias("new", "/session create") # Test aliases alias_result1 = await executor.execute("/new test-alias") assert "Session created: test-alias" in alias_result1["output"] # Test macro management macros = await executor.list_macros() assert len(macros) >= 2 assert any(m["name"] == "setup" for m in macros) # Test macro deletion await executor.delete_macro("setup") macros_after = await executor.list_macros() assert len(macros_after) == len(macros) - 1 async def test_command_error_handling_recovery(self, command_setup): """Test command error handling and recovery.""" executor = command_setup["executor"] registry = command_setup["registry"] # Register commands with different error scenarios async def timeout_handler(context): await asyncio.sleep(10) # Longer than timeout return {"success": True} async def retry_handler(context): if not hasattr(retry_handler, "attempts"): retry_handler.attempts = 0 retry_handler.attempts += 1 if retry_handler.attempts < 3: raise ConnectionError("Temporary failure") return {"success": True, "output": "Success after retries"} async def validation_handler(context): if not context["args"]: raise ValueError("Arguments required") return {"success": True, "output": "Valid"} await registry.register_handler("timeout", timeout_handler) await registry.register_handler("retry", retry_handler) await registry.register_handler("validate", validation_handler) # Test timeout handling timeout_result = await executor.execute( "/timeout", timeout=1 # 1 second timeout ) assert timeout_result["success"] is False assert "timeout" in timeout_result["output"].lower() # Test retry mechanism retry_result = await executor.execute( "/retry", retry_config={ "max_retries": 3, "delay": 0.1, "backoff": 1.5 } ) assert retry_result["success"] is True assert "Success after retries" in retry_result["output"] # Test validation error validation_result = await executor.execute("/validate") assert validation_result["success"] is False assert "Arguments required" in validation_result["output"] # Test error recovery suggestions async def recoverable_handler(context): raise FileNotFoundError("Config file not found: config.json") await registry.register_handler("recoverable", recoverable_handler) await registry.register_recovery_suggestions( "FileNotFoundError", [ "Create default config with: /config init", "Specify custom config with: --config path/to/config.json", "Run in no-config mode with: --no-config" ] ) recovery_result = await executor.execute("/recoverable") assert recovery_result["success"] is False assert "suggestions" in recovery_result assert len(recovery_result["suggestions"]) == 3 # Test fallback commands await executor.register_fallback( "timeout", "/echo Command timed out, using cached result" ) fallback_result = await executor.execute( "/timeout", timeout=1, use_fallback=True ) assert "using cached result" in fallback_result["output"]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/krzemienski/shannon-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server