Files
michaelschiemer/tests/debug/test-mcp-system.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

535 lines
21 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
/**
* MCP System Test Suite
*
* Comprehensive testing of the MCP framework including:
* - Cache Manager Performance
* - Concurrent Execution
* - Result Optimization
* - Performance Monitoring
*/
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\Cache\SmartCache;
use App\Framework\Mcp\Core\Services\IntelligentMcpCacheManager;
use App\Framework\Mcp\Core\Services\McpPerformanceMonitor;
use App\Framework\Mcp\Core\Services\ResultOptimizer;
use App\Framework\Mcp\Core\ValueObjects\CacheStrategy;
use App\Framework\Mcp\Core\ValueObjects\ConcurrencyStrategy;
use App\Framework\Mcp\Core\ValueObjects\ExecutionTask;
use App\Framework\Mcp\Core\ValueObjects\OptimizationStrategy;
use App\Framework\Mcp\Core\ValueObjects\OutputFormat;
class McpSystemTester
{
private array $testResults = [];
private float $startTime;
public function __construct()
{
$this->startTime = microtime(true);
echo "🧪 MCP System Test Suite Starting...\n\n";
}
public function runAllTests(): void
{
echo "📋 Running comprehensive MCP system tests...\n\n";
// Test Cache Manager
$this->testCacheManager();
// Test Result Optimizer
$this->testResultOptimizer();
// Test Performance Monitor
$this->testPerformanceMonitor();
// Test Concurrent Execution (simulated)
$this->testConcurrentExecution();
// Performance Integration Test
$this->testIntegratedPerformance();
// Generate final report
$this->generateReport();
}
private function testCacheManager(): void
{
echo "🗄️ Testing Cache Manager...\n";
try {
// Create mock cache for testing
$cache = new SmartCache();
$cacheManager = new IntelligentMcpCacheManager($cache);
// Test 1: Basic caching functionality
echo " ⚡ Test 1: Basic Caching\n";
$testData = ['test' => 'data', 'timestamp' => time()];
// Test set/get
$cacheManager->set('test_tool', 'test_method', [], $testData, CacheStrategy::MEDIUM);
$retrieved = $cacheManager->get('test_tool', 'test_method', [], CacheStrategy::MEDIUM);
$this->assert($retrieved === $testData, "Cache set/get should work");
echo " ✅ Basic caching works\n";
// Test 2: Cache strategy selection
echo " ⚡ Test 2: Cache Strategy Selection\n";
$healthStrategy = CacheStrategy::recommendFor('health_checker', 'status');
$routeStrategy = CacheStrategy::recommendFor('route_analyzer', 'analyze');
$this->assert($healthStrategy === CacheStrategy::SHORT, "Health tools should use SHORT strategy");
$this->assert($routeStrategy === CacheStrategy::LONG, "Route tools should use LONG strategy");
echo " ✅ Strategy selection works\n";
// Test 3: Remember pattern
echo " ⚡ Test 3: Remember Pattern\n";
$callCount = 0;
$result = $cacheManager->remember(
'test_tool',
'expensive_operation',
['param' => 'value'],
function () use (&$callCount) {
$callCount++;
return ['expensive' => 'result', 'call_count' => $callCount];
},
CacheStrategy::MEDIUM
);
// Should be called once
$this->assert($callCount === 1, "Callback should be called once");
// Second call should use cache
$result2 = $cacheManager->remember(
'test_tool',
'expensive_operation',
['param' => 'value'],
function () use (&$callCount) {
$callCount++;
return ['expensive' => 'result', 'call_count' => $callCount];
},
CacheStrategy::MEDIUM
);
$this->assert($callCount === 1, "Callback should not be called again (cache hit)");
$this->assert($result === $result2, "Results should be identical");
echo " ✅ Remember pattern works\n";
// Test 4: Cache metrics
echo " ⚡ Test 4: Cache Metrics\n";
$metrics = $cacheManager->getMetrics();
$this->assert(is_array($metrics->toArray()), "Metrics should be returned");
echo " ✅ Cache metrics available\n";
$this->testResults['cache_manager'] = [
'status' => 'passed',
'tests' => 4,
'details' => 'All cache manager tests passed',
];
} catch (\Throwable $e) {
$this->testResults['cache_manager'] = [
'status' => 'failed',
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
];
echo " ❌ Cache Manager test failed: " . $e->getMessage() . "\n";
}
echo "\n";
}
private function testResultOptimizer(): void
{
echo "🔧 Testing Result Optimizer...\n";
try {
$optimizer = new ResultOptimizer();
// Test 1: Basic optimization
echo " ⚡ Test 1: Basic Optimization\n";
$largeData = array_fill(0, 1000, 'test data item');
$result = $optimizer->optimize($largeData, OutputFormat::JSON, OptimizationStrategy::SIZE);
$this->assert($result->compressionRatio < 1.0, "Should achieve compression");
$this->assert($result->optimizedSize < $result->originalSize, "Optimized size should be smaller");
echo " ✅ Basic optimization works\n";
// Test 2: Strategy comparison
echo " ⚡ Test 2: Strategy Comparison\n";
$testData = ['large_array' => array_fill(0, 500, 'data'), 'metadata' => 'test'];
$sizeResult = $optimizer->optimize($testData, OutputFormat::JSON, OptimizationStrategy::SIZE);
$speedResult = $optimizer->optimize($testData, OutputFormat::JSON, OptimizationStrategy::SPEED);
$noneResult = $optimizer->optimize($testData, OutputFormat::JSON, OptimizationStrategy::NONE);
$this->assert($sizeResult->compressionRatio <= $speedResult->compressionRatio, "Size strategy should compress more");
$this->assert($noneResult->compressionRatio === 1.0, "None strategy should not compress");
echo " ✅ Strategy comparison works\n";
// Test 3: Format-specific optimization
echo " ⚡ Test 3: Format-Specific Optimization\n";
$complexData = [
'nodes' => ['A' => ['connections' => ['B', 'C']], 'B' => ['connections' => ['A']]],
'metadata' => ['type' => 'graph', 'version' => '1.0'],
];
$jsonResult = $optimizer->optimize($complexData, OutputFormat::JSON, OptimizationStrategy::BALANCED);
$tableResult = $optimizer->optimize($complexData, OutputFormat::TABLE, OptimizationStrategy::BALANCED);
$this->assert(is_array($jsonResult->optimizedData), "JSON optimization should return array");
echo " ✅ Format-specific optimization works\n";
// Test 4: Compression and decompression
echo " ⚡ Test 4: Compression and Decompression\n";
$originalData = array_fill(0, 100, 'This is a test string that should compress well when repeated many times');
$compressed = $optimizer->compress($originalData, 6);
if (is_array($compressed) && isset($compressed['_compressed'])) {
$decompressed = $optimizer->decompress($compressed);
$this->assert($decompressed === $originalData, "Decompression should restore original data");
echo " ✅ Compression/decompression works\n";
} else {
echo " Data too small for compression\n";
}
$this->testResults['result_optimizer'] = [
'status' => 'passed',
'tests' => 4,
'details' => 'All result optimizer tests passed',
];
} catch (\Throwable $e) {
$this->testResults['result_optimizer'] = [
'status' => 'failed',
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
];
echo " ❌ Result Optimizer test failed: " . $e->getMessage() . "\n";
}
echo "\n";
}
private function testPerformanceMonitor(): void
{
echo "📊 Testing Performance Monitor...\n";
try {
$cache = new SmartCache();
$monitor = new McpPerformanceMonitor($cache);
// Test 1: Basic execution monitoring
echo " ⚡ Test 1: Basic Execution Monitoring\n";
$executionId = $monitor->startExecution('test_tool', 'test_method', ['param' => 'value']);
$this->assert(! empty($executionId), "Execution ID should be generated");
// Simulate some work
usleep(100000); // 0.1 seconds
$metrics = $monitor->endExecution($executionId, ['result' => 'data']);
$this->assert($metrics->success, "Execution should be successful");
$this->assert($metrics->executionTime > 0.09, "Execution time should be recorded");
echo " ✅ Basic monitoring works\n";
// Test 2: Error handling
echo " ⚡ Test 2: Error Handling\n";
$errorId = $monitor->startExecution('test_tool', 'failing_method');
$errorMetrics = $monitor->endExecution($errorId, null, 'Test error');
$this->assert(! $errorMetrics->success, "Failed execution should be marked as unsuccessful");
$this->assert($errorMetrics->error === 'Test error', "Error message should be preserved");
echo " ✅ Error handling works\n";
// Test 3: Monitor wrapper
echo " ⚡ Test 3: Monitor Wrapper\n";
$result = $monitor->monitor(
'test_tool',
'wrapper_test',
function () {
usleep(50000); // 0.05 seconds
return ['wrapped' => 'result'];
},
['wrapper' => 'param']
);
$this->assert($result === ['wrapped' => 'result'], "Monitor wrapper should return result");
echo " ✅ Monitor wrapper works\n";
// Test 4: Performance thresholds
echo " ⚡ Test 4: Performance Thresholds\n";
$threshold = $monitor->getThresholds('test_tool');
$this->assert($threshold->maxExecutionTime > 0, "Threshold should have execution time limit");
echo " ✅ Performance thresholds work\n";
$this->testResults['performance_monitor'] = [
'status' => 'passed',
'tests' => 4,
'details' => 'All performance monitor tests passed',
];
} catch (\Throwable $e) {
$this->testResults['performance_monitor'] = [
'status' => 'failed',
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
];
echo " ❌ Performance Monitor test failed: " . $e->getMessage() . "\n";
}
echo "\n";
}
private function testConcurrentExecution(): void
{
echo "🔄 Testing Concurrent Execution (Simulated)...\n";
try {
// Note: This is a simplified test since we can't easily test real concurrency in this context
// Test 1: Task creation
echo " ⚡ Test 1: Task Creation\n";
$task1 = ExecutionTask::create('test_tool', 'method1', ['param1' => 'value1']);
$task2 = ExecutionTask::highPriority('test_tool', 'method2', ['param2' => 'value2']);
$task3 = ExecutionTask::lowResource('test_tool', 'method3', ['param3' => 'value3']);
$this->assert(! empty($task1->getId()), "Task should have ID");
$this->assert($task2->getPriority() > $task1->getPriority(), "High priority task should have higher priority");
$this->assert($task3->getEstimatedMemory() < $task1->getEstimatedMemory(), "Low resource task should estimate less memory");
echo " ✅ Task creation works\n";
// Test 2: Concurrency strategy
echo " ⚡ Test 2: Concurrency Strategy\n";
$conservative = ConcurrencyStrategy::conservative();
$balanced = ConcurrencyStrategy::balanced();
$aggressive = ConcurrencyStrategy::aggressive();
$this->assert($conservative->getMaxConcurrency() < $balanced->getMaxConcurrency(), "Conservative should have lower concurrency");
$this->assert($balanced->getMaxConcurrency() < $aggressive->getMaxConcurrency(), "Aggressive should have higher concurrency");
echo " ✅ Concurrency strategy works\n";
// Test 3: Task array conversion
echo " ⚡ Test 3: Task Serialization\n";
$taskArray = $task1->toArray();
$this->assert(isset($taskArray['id']), "Task array should contain ID");
$this->assert(isset($taskArray['tool_name']), "Task array should contain tool name");
echo " ✅ Task serialization works\n";
$this->testResults['concurrent_execution'] = [
'status' => 'passed',
'tests' => 3,
'details' => 'Concurrent execution structure tests passed (simulated)',
];
} catch (\Throwable $e) {
$this->testResults['concurrent_execution'] = [
'status' => 'failed',
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
];
echo " ❌ Concurrent Execution test failed: " . $e->getMessage() . "\n";
}
echo "\n";
}
private function testIntegratedPerformance(): void
{
echo "🎯 Testing Integrated Performance...\n";
try {
$cache = new SmartCache();
$cacheManager = new IntelligentMcpCacheManager($cache);
$optimizer = new ResultOptimizer();
$monitor = new McpPerformanceMonitor($cache);
// Test 1: Full pipeline performance
echo " ⚡ Test 1: Full Pipeline Performance\n";
$startTime = microtime(true);
// Simulate complex operation
$complexData = $this->generateComplexTestData();
// Optimize the data
$optimized = $optimizer->optimize($complexData, OutputFormat::JSON, OptimizationStrategy::BALANCED);
// Cache the result
$cacheManager->set('integration_test', 'complex_operation', ['test' => 'param'], $optimized->optimizedData);
// Retrieve from cache
$cached = $cacheManager->get('integration_test', 'complex_operation', ['test' => 'param']);
$endTime = microtime(true);
$totalTime = $endTime - $startTime;
$this->assert($cached !== null, "Should retrieve from cache");
$this->assert($totalTime < 1.0, "Full pipeline should complete in under 1 second");
echo " ✅ Full pipeline performance acceptable ({$totalTime}s)\n";
// Test 2: Memory efficiency
echo " ⚡ Test 2: Memory Efficiency\n";
$memoryBefore = memory_get_usage(true);
// Process multiple datasets
for ($i = 0; $i < 10; $i++) {
$data = array_fill(0, 100, "test data item {$i}");
$optimized = $optimizer->optimize($data, OutputFormat::JSON, OptimizationStrategy::SIZE);
$cacheManager->set('memory_test', "operation_{$i}", [], $optimized->optimizedData);
}
$memoryAfter = memory_get_usage(true);
$memoryIncrease = $memoryAfter - $memoryBefore;
$this->assert($memoryIncrease < 50 * 1024 * 1024, "Memory increase should be under 50MB"); // 50MB
echo " ✅ Memory efficiency acceptable (" . $this->formatBytes($memoryIncrease) . " increase)\n";
// Test 3: Cache hit performance
echo " ⚡ Test 3: Cache Hit Performance\n";
$hitTimes = [];
// Prime the cache
$cacheManager->set('performance_test', 'hit_test', [], $complexData);
// Measure cache hit times
for ($i = 0; $i < 5; $i++) {
$hitStart = microtime(true);
$result = $cacheManager->get('performance_test', 'hit_test', []);
$hitEnd = microtime(true);
$hitTimes[] = $hitEnd - $hitStart;
}
$averageHitTime = array_sum($hitTimes) / count($hitTimes);
$this->assert($averageHitTime < 0.01, "Cache hits should be under 10ms"); // 10ms
echo " ✅ Cache hit performance excellent ({$averageHitTime}s average)\n";
$this->testResults['integrated_performance'] = [
'status' => 'passed',
'tests' => 3,
'details' => "Full pipeline: {$totalTime}s, Memory: " . $this->formatBytes($memoryIncrease) . ", Cache hits: {$averageHitTime}s",
];
} catch (\Throwable $e) {
$this->testResults['integrated_performance'] = [
'status' => 'failed',
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
];
echo " ❌ Integrated Performance test failed: " . $e->getMessage() . "\n";
}
echo "\n";
}
private function generateComplexTestData(): array
{
return [
'routes' => array_fill(0, 50, [
'path' => '/api/test/' . uniqid(),
'method' => 'GET',
'controller' => 'TestController',
'middleware' => ['auth', 'throttle'],
'parameters' => ['id' => 'integer'],
]),
'containers' => array_fill(0, 30, [
'service' => 'Service' . rand(1, 100),
'binding' => 'Interface' . rand(1, 50),
'singleton' => rand(0, 1) === 1,
'dependencies' => array_fill(0, rand(1, 5), 'Dependency' . rand(1, 20)),
]),
'metadata' => [
'generated_at' => time(),
'version' => '1.0.0',
'environment' => 'test',
'memory_usage' => memory_get_usage(true),
'peak_memory' => memory_get_peak_usage(true),
],
];
}
private function generateReport(): void
{
$totalTime = microtime(true) - $this->startTime;
echo "📊 TEST REPORT\n";
echo "═══════════════════════════════════════════════════════\n\n";
$passed = 0;
$failed = 0;
foreach ($this->testResults as $testName => $result) {
$status = $result['status'] === 'passed' ? '✅' : '❌';
$statusText = strtoupper($result['status']);
echo "{$status} {$testName}: {$statusText}\n";
if ($result['status'] === 'passed') {
$passed++;
if (isset($result['tests'])) {
echo " 📋 {$result['tests']} sub-tests passed\n";
}
if (isset($result['details'])) {
echo " 📝 {$result['details']}\n";
}
} else {
$failed++;
echo " ❌ Error: {$result['error']}\n";
}
echo "\n";
}
echo "═══════════════════════════════════════════════════════\n";
echo "📈 SUMMARY:\n";
echo " ✅ Passed: {$passed}\n";
echo " ❌ Failed: {$failed}\n";
echo " ⏱️ Total time: " . round($totalTime, 3) . "s\n";
echo " 🧠 Memory usage: " . $this->formatBytes(memory_get_usage(true)) . "\n";
echo " 📊 Peak memory: " . $this->formatBytes(memory_get_peak_usage(true)) . "\n";
if ($failed === 0) {
echo "\n🎉 ALL TESTS PASSED! MCP System is working correctly.\n";
} else {
echo "\n⚠️ Some tests failed. Please check the errors above.\n";
}
echo "\n";
}
private function assert(bool $condition, string $message): void
{
if (! $condition) {
throw new \AssertionError("Assertion failed: {$message}");
}
}
private function formatBytes(int $bytes): string
{
if ($bytes === 0) {
return '0 B';
}
$units = ['B', 'KB', 'MB', 'GB'];
$unitIndex = 0;
$value = $bytes;
while ($value >= 1024 && $unitIndex < count($units) - 1) {
$value /= 1024;
$unitIndex++;
}
return round($value, 2) . ' ' . $units[$unitIndex];
}
}
// Run the tests
$tester = new McpSystemTester();
$tester->runAllTests();