Skip to main content
Glama

MockLoop MCP Server

Official
by MockLoop
test_mcp_resources.pyโ€ข21 kB
""" Unit tests for MCP Resources module. Tests the built-in scenario pack resources, resource discovery functionality, content validation, and audit logging integration. """ import pytest import json import asyncio from unittest.mock import Mock, patch, AsyncMock from typing import Any # Handle imports for different execution contexts try: from src.mockloop_mcp.mcp_resources import ( get_4xx_client_errors_pack, get_5xx_server_errors_pack, get_network_timeouts_pack, get_rate_limiting_pack, get_load_testing_pack, get_stress_testing_pack, get_spike_testing_pack, get_endurance_testing_pack, get_auth_bypass_pack, get_injection_attacks_pack, get_xss_attacks_pack, get_csrf_attacks_pack, get_edge_cases_pack, get_data_validation_pack, get_workflow_testing_pack, list_scenario_packs, get_scenario_pack_by_uri, validate_scenario_pack_content, get_resource_integrity_info, _validate_resource_uri, _calculate_content_hash, SCENARIO_PACK_CATEGORIES, ) from src.mockloop_mcp.community_scenarios import ( list_community_scenarios, get_community_scenario, refresh_community_cache, search_community_scenarios, validate_community_scenario, get_community_stats, get_community_architecture_info, CommunityScenarioManager, COMMUNITY_CATEGORIES, ) except ImportError: # Fallback for direct execution import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src")) from mockloop_mcp.mcp_resources import ( get_4xx_client_errors_pack, get_5xx_server_errors_pack, get_network_timeouts_pack, get_rate_limiting_pack, get_load_testing_pack, get_stress_testing_pack, get_spike_testing_pack, get_endurance_testing_pack, get_auth_bypass_pack, get_injection_attacks_pack, get_xss_attacks_pack, get_csrf_attacks_pack, get_edge_cases_pack, get_data_validation_pack, get_workflow_testing_pack, list_scenario_packs, get_scenario_pack_by_uri, validate_scenario_pack_content, get_resource_integrity_info, _validate_resource_uri, _calculate_content_hash, SCENARIO_PACK_CATEGORIES, ) from mockloop_mcp.community_scenarios import ( list_community_scenarios, get_community_scenario, refresh_community_cache, search_community_scenarios, validate_community_scenario, get_community_stats, get_community_architecture_info, CommunityScenarioManager, COMMUNITY_CATEGORIES, ) class TestMCPResources: """Test suite for MCP Resources functionality.""" @pytest.mark.asyncio async def test_4xx_client_errors_pack(self): """Test 4xx client errors scenario pack.""" pack = await get_4xx_client_errors_pack() # Validate structure assert "metadata" in pack assert "scenarios" in pack assert "documentation" in pack # Validate metadata metadata = pack["metadata"] assert metadata["name"] == "4xx Client Errors" assert metadata["category"] == "errors" assert metadata["pack_id"] == "4xx-client-errors" assert "4xx" in metadata["tags"] # Validate scenarios scenarios = pack["scenarios"] assert len(scenarios) > 0 for scenario in scenarios: assert "scenario_name" in scenario assert "description" in scenario assert "scenario_type" in scenario assert "endpoints" in scenario assert "test_parameters" in scenario assert "validation_rules" in scenario @pytest.mark.asyncio async def test_5xx_server_errors_pack(self): """Test 5xx server errors scenario pack.""" pack = await get_5xx_server_errors_pack() assert pack["metadata"]["name"] == "5xx Server Errors" assert pack["metadata"]["category"] == "errors" assert "5xx" in pack["metadata"]["tags"] assert "resilience" in pack["metadata"]["tags"] @pytest.mark.asyncio async def test_load_testing_pack(self): """Test load testing scenario pack.""" pack = await get_load_testing_pack() assert pack["metadata"]["name"] == "Load Testing" assert pack["metadata"]["category"] == "performance" assert "load-testing" in pack["metadata"]["tags"] assert pack["metadata"]["complexity"] == "high" @pytest.mark.asyncio async def test_auth_bypass_pack(self): """Test authentication bypass scenario pack.""" pack = await get_auth_bypass_pack() assert pack["metadata"]["name"] == "Authentication Bypass" assert pack["metadata"]["category"] == "security" assert "authentication" in pack["metadata"]["tags"] assert "bypass" in pack["metadata"]["tags"] @pytest.mark.asyncio async def test_edge_cases_pack(self): """Test edge cases scenario pack.""" pack = await get_edge_cases_pack() assert pack["metadata"]["name"] == "Edge Cases" assert pack["metadata"]["category"] == "business" assert "edge-cases" in pack["metadata"]["tags"] assert "boundaries" in pack["metadata"]["tags"] @pytest.mark.asyncio async def test_list_scenario_packs_no_filters(self): """Test listing all scenario packs without filters.""" result = await list_scenario_packs() assert "total_packs" in result assert "packs" in result assert "categories" in result assert "available_filters" in result # Should have all 15 built-in packs assert result["total_packs"] == 15 assert len(result["packs"]) == 15 # Check categories expected_categories = ["errors", "performance", "security", "business"] assert set(result["categories"]) == set(expected_categories) @pytest.mark.asyncio async def test_list_scenario_packs_with_category_filter(self): """Test listing scenario packs with category filter.""" result = await list_scenario_packs(category="errors") assert result["total_packs"] == 4 # 4 error scenario packs for pack in result["packs"]: assert pack["category"] == "errors" @pytest.mark.asyncio async def test_list_scenario_packs_with_complexity_filter(self): """Test listing scenario packs with complexity filter.""" result = await list_scenario_packs(complexity="high") for pack in result["packs"]: assert pack["complexity"] == "high" @pytest.mark.asyncio async def test_list_scenario_packs_with_tags_filter(self): """Test listing scenario packs with tags filter.""" result = await list_scenario_packs(tags=["performance"]) for pack in result["packs"]: assert any("performance" in tag for tag in pack["tags"]) @pytest.mark.asyncio async def test_get_scenario_pack_by_uri_valid(self): """Test getting scenario pack by valid URI.""" uri = "scenario-pack://errors/4xx-client-errors" pack = await get_scenario_pack_by_uri(uri) assert "error" not in pack assert pack["metadata"]["pack_id"] == "4xx-client-errors" @pytest.mark.asyncio async def test_get_scenario_pack_by_uri_invalid(self): """Test getting scenario pack by invalid URI.""" uri = "invalid://uri/format" result = await get_scenario_pack_by_uri(uri) assert "error" in result assert result["error"] == "Invalid URI" @pytest.mark.asyncio async def test_get_scenario_pack_by_uri_not_found(self): """Test getting scenario pack by non-existent URI.""" uri = "scenario-pack://errors/non-existent-pack" result = await get_scenario_pack_by_uri(uri) assert "error" in result assert "Unknown pack" in result["message"] def test_validate_resource_uri_valid(self): """Test URI validation with valid URIs.""" valid_uris = [ "scenario-pack://errors/4xx-client-errors", "scenario-pack://performance/load-testing", "scenario-pack://security/auth-bypass", "scenario-pack://business/edge-cases", ] for uri in valid_uris: is_valid, category, pack_name, error = _validate_resource_uri(uri) assert is_valid assert category in SCENARIO_PACK_CATEGORIES assert pack_name in SCENARIO_PACK_CATEGORIES[category] assert error == "" def test_validate_resource_uri_invalid(self): """Test URI validation with invalid URIs.""" invalid_uris = [ "http://invalid/scheme", "scenario-pack://invalid-category/pack", "scenario-pack://errors/invalid-pack", "scenario-pack://errors", "scenario-pack://errors/pack/extra", ] for uri in invalid_uris: is_valid, category, pack_name, error = _validate_resource_uri(uri) assert not is_valid assert error != "" def test_calculate_content_hash(self): """Test content hash calculation.""" content1 = {"test": "data", "number": 123} content2 = {"number": 123, "test": "data"} # Same content, different order content3 = {"test": "different", "number": 123} hash1 = _calculate_content_hash(content1) hash2 = _calculate_content_hash(content2) hash3 = _calculate_content_hash(content3) # Same content should produce same hash regardless of order assert hash1 == hash2 # Different content should produce different hash assert hash1 != hash3 # Hash should be a valid SHA-256 hex string assert len(hash1) == 64 assert all(c in "0123456789abcdef" for c in hash1) @pytest.mark.asyncio async def test_validate_scenario_pack_content_valid(self): """Test scenario pack content validation with valid content.""" pack = await get_4xx_client_errors_pack() is_valid, errors = validate_scenario_pack_content(pack) assert is_valid assert len(errors) == 0 def test_validate_scenario_pack_content_invalid(self): """Test scenario pack content validation with invalid content.""" invalid_pack = { "metadata": { "name": "Test Pack" # Missing required fields }, "scenarios": "not_a_list", # Should be a list # Missing documentation } is_valid, errors = validate_scenario_pack_content(invalid_pack) assert not is_valid assert len(errors) > 0 assert any("Missing required field" in error for error in errors) @pytest.mark.asyncio async def test_get_resource_integrity_info(self): """Test resource integrity information generation.""" pack = await get_4xx_client_errors_pack() integrity_info = get_resource_integrity_info(pack) assert "content_hash" in integrity_info assert "is_valid" in integrity_info assert "validation_errors" in integrity_info assert "content_size" in integrity_info assert "last_validated" in integrity_info assert integrity_info["is_valid"] is True assert len(integrity_info["validation_errors"]) == 0 assert integrity_info["content_size"] > 0 @pytest.mark.asyncio async def test_all_scenario_pack_functions(self): """Test that all scenario pack functions return valid content.""" pack_functions = [ get_4xx_client_errors_pack, get_5xx_server_errors_pack, get_network_timeouts_pack, get_rate_limiting_pack, get_load_testing_pack, get_stress_testing_pack, get_spike_testing_pack, get_endurance_testing_pack, get_auth_bypass_pack, get_injection_attacks_pack, get_xss_attacks_pack, get_csrf_attacks_pack, get_edge_cases_pack, get_data_validation_pack, get_workflow_testing_pack, ] for func in pack_functions: pack = await func() # Validate basic structure assert "metadata" in pack assert "scenarios" in pack assert "documentation" in pack # Validate content is_valid, errors = validate_scenario_pack_content(pack) assert is_valid, f"Pack {func.__name__} failed validation: {errors}" class TestCommunityScenarios: """Test suite for Community Scenarios placeholder functionality.""" @pytest.mark.asyncio async def test_list_community_scenarios(self): """Test listing community scenarios (placeholder).""" result = await list_community_scenarios() assert result["status"] == "placeholder" assert result["total_scenarios"] == 0 assert "phase_2_features" in result assert "placeholder_note" in result @pytest.mark.asyncio async def test_list_community_scenarios_with_filters(self): """Test listing community scenarios with filters (placeholder).""" result = await list_community_scenarios( category="technology", technology="graphql", tags=["api", "testing"], min_rating=4.0, max_age_days=30, ) assert result["status"] == "placeholder" assert "categories" in result assert "technologies" in result @pytest.mark.asyncio async def test_get_community_scenario(self): """Test getting community scenario (placeholder).""" result = await get_community_scenario("test-scenario-id") assert result["status"] == "placeholder" assert result["scenario_id"] == "test-scenario-id" assert "phase_2_features" in result @pytest.mark.asyncio async def test_get_community_scenario_with_version(self): """Test getting community scenario with version (placeholder).""" result = await get_community_scenario( "test-scenario-id", version="1.2.0", include_metadata=True, validate_integrity=True, ) assert result["status"] == "placeholder" assert result["requested_version"] == "1.2.0" @pytest.mark.asyncio async def test_refresh_community_cache(self): """Test refreshing community cache (placeholder).""" result = await refresh_community_cache() assert result["status"] == "placeholder" assert result["cache_status"] == "not_implemented" assert result["scenarios_cached"] == 0 @pytest.mark.asyncio async def test_refresh_community_cache_with_options(self): """Test refreshing community cache with options (placeholder).""" result = await refresh_community_cache( force_refresh=True, categories=["technology", "industry"], max_age_hours=48 ) assert result["status"] == "placeholder" assert "phase_2_features" in result @pytest.mark.asyncio async def test_search_community_scenarios(self): """Test searching community scenarios (placeholder).""" result = await search_community_scenarios("graphql testing") assert result["status"] == "placeholder" assert result["query"] == "graphql testing" assert result["total_results"] == 0 @pytest.mark.asyncio async def test_search_community_scenarios_with_options(self): """Test searching community scenarios with options (placeholder).""" result = await search_community_scenarios( "api testing", search_fields=["title", "description", "tags"], filters={"category": "technology", "min_rating": 4.0}, sort_by="rating", limit=50, offset=10, ) assert result["status"] == "placeholder" assert "phase_2_features" in result @pytest.mark.asyncio async def test_validate_community_scenario(self): """Test validating community scenario (placeholder).""" test_scenario = { "scenario_name": "test_scenario", "description": "Test scenario", "scenario_type": "functional_testing", } result = await validate_community_scenario(test_scenario) assert result["status"] == "placeholder" assert result["is_valid"] is False assert "phase_2_features" in result @pytest.mark.asyncio async def test_validate_community_scenario_with_options(self): """Test validating community scenario with options (placeholder).""" test_scenario = {"test": "data"} result = await validate_community_scenario( test_scenario, security_scan=True, schema_validation=True, content_analysis=True, ) assert result["status"] == "placeholder" assert "security_score" in result assert "quality_score" in result @pytest.mark.asyncio async def test_get_community_stats(self): """Test getting community statistics (placeholder).""" result = await get_community_stats() assert result["status"] == "placeholder" assert result["total_scenarios"] == 0 assert result["total_contributors"] == 0 assert "categories" in result assert "quality_metrics" in result def test_get_community_architecture_info(self): """Test getting community architecture information.""" result = get_community_architecture_info() assert "architecture" in result assert "current_status" in result assert "implementation_timeline" in result assert "technical_requirements" in result assert result["current_status"] == "placeholder_implementation" def test_community_scenario_manager_init(self): """Test CommunityScenarioManager initialization.""" manager = CommunityScenarioManager() assert manager.config is not None assert "repository_url" in manager.config assert "cache_directory" in manager.config def test_community_scenario_manager_with_config(self): """Test CommunityScenarioManager with custom config.""" custom_config = { "repository_url": "https://github.com/custom/repo", "cache_directory": "/custom/cache", "cache_ttl_hours": 48, } manager = CommunityScenarioManager(custom_config) assert manager.config["repository_url"] == custom_config["repository_url"] assert manager.config["cache_directory"] == custom_config["cache_directory"] assert manager.config["cache_ttl_hours"] == custom_config["cache_ttl_hours"] def test_community_categories_structure(self): """Test community categories structure.""" assert "industry" in COMMUNITY_CATEGORIES assert "technology" in COMMUNITY_CATEGORIES assert "compliance" in COMMUNITY_CATEGORIES assert "advanced" in COMMUNITY_CATEGORIES # Check some specific categories assert "fintech" in COMMUNITY_CATEGORIES["industry"] assert "graphql" in COMMUNITY_CATEGORIES["technology"] assert "gdpr" in COMMUNITY_CATEGORIES["compliance"] assert "chaos-engineering" in COMMUNITY_CATEGORIES["advanced"] class TestResourceAuditLogging: """Test suite for resource audit logging functionality.""" @patch("src.mockloop_mcp.mcp_resources.create_audit_logger") @pytest.mark.asyncio async def test_resource_audit_logging(self, mock_create_audit_logger): """Test that resource access is properly audited.""" mock_logger = Mock() mock_create_audit_logger.return_value = mock_logger # Test resource access await get_4xx_client_errors_pack() # Verify audit logger was created and used mock_create_audit_logger.assert_called() mock_logger.log_resource_access.assert_called() @patch("src.mockloop_mcp.community_scenarios.create_audit_logger") @pytest.mark.asyncio async def test_community_audit_logging(self, mock_create_audit_logger): """Test that community scenario access is properly audited.""" mock_logger = Mock() mock_create_audit_logger.return_value = mock_logger # Test community scenario access await list_community_scenarios() # Verify audit logging was attempted mock_create_audit_logger.assert_called() if __name__ == "__main__": # Run tests directly pytest.main([__file__, "-v"])

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/MockLoop/mockloop-mcp'

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