- 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.
348 lines
14 KiB
PHP
348 lines
14 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Enhanced Discovery System Test
|
|
*
|
|
* Tests the enhanced auto-discovery system with MCP integration.
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\ComponentType;
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\DependencyEdge;
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\DependencyGraph;
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\DependencyNode;
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\DiscoveryMetrics;
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\DiscoveryPlan;
|
|
use App\Framework\Discovery\Enhanced\ValueObjects\PlanStrategy;
|
|
|
|
class EnhancedDiscoveryTester
|
|
{
|
|
private array $results = [];
|
|
|
|
private float $startTime;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->startTime = microtime(true);
|
|
echo "🔍 Enhanced Discovery System Test Starting...\n\n";
|
|
}
|
|
|
|
public function runAllTests(): void
|
|
{
|
|
echo "📋 Running enhanced discovery system tests...\n\n";
|
|
|
|
// Test Value Objects
|
|
$this->testDiscoveryPlan();
|
|
$this->testPlanStrategy();
|
|
$this->testDiscoveryMetrics();
|
|
$this->testComponentType();
|
|
$this->testDependencyGraph();
|
|
|
|
// Generate final report
|
|
$this->generateReport();
|
|
}
|
|
|
|
private function testDiscoveryPlan(): void
|
|
{
|
|
echo "📋 Testing Discovery Plan...\n";
|
|
|
|
try {
|
|
// Test optimized plan creation
|
|
$optimizedPlan = DiscoveryPlan::optimized(
|
|
['/src/Framework', '/src/Application'],
|
|
['Route', 'Command']
|
|
);
|
|
|
|
$this->assert($optimizedPlan->getStrategy() === PlanStrategy::PERFORMANCE_OPTIMIZED, 'Should use performance optimized strategy');
|
|
$this->assert($optimizedPlan->hasOptimization('memory_efficient'), 'Should have memory efficient optimization');
|
|
$this->assert(count($optimizedPlan->getPaths()) === 2, 'Should have correct path count');
|
|
|
|
// Test comprehensive plan
|
|
$comprehensivePlan = DiscoveryPlan::comprehensive(
|
|
['/src'],
|
|
['Route', 'Command', 'Event']
|
|
);
|
|
|
|
$this->assert($comprehensivePlan->getStrategy() === PlanStrategy::COMPREHENSIVE, 'Should use comprehensive strategy');
|
|
$this->assert($comprehensivePlan->hasOptimization('deep_analysis'), 'Should have deep analysis');
|
|
|
|
// Test minimal plan
|
|
$minimalPlan = DiscoveryPlan::minimal(['/src/small']);
|
|
$this->assert($minimalPlan->getStrategy() === PlanStrategy::MINIMAL, 'Should use minimal strategy');
|
|
$this->assert($minimalPlan->hasOptimization('cache_only'), 'Should be cache only');
|
|
|
|
// Test plan modifications
|
|
$modifiedPlan = $optimizedPlan->withOptimizations(['custom_optimization' => true]);
|
|
$this->assert($modifiedPlan->hasOptimization('custom_optimization'), 'Should have custom optimization');
|
|
|
|
echo " ✅ Discovery Plan tests passed\n";
|
|
$this->results['discovery_plan'] = ['status' => 'PASSED', 'details' => 'All plan creation and modification tests passed'];
|
|
|
|
} catch (\Throwable $e) {
|
|
$this->results['discovery_plan'] = ['status' => 'FAILED', 'error' => $e->getMessage()];
|
|
echo " ❌ Discovery Plan test failed: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
|
|
private function testPlanStrategy(): void
|
|
{
|
|
echo "🎯 Testing Plan Strategy...\n";
|
|
|
|
try {
|
|
// Test strategy descriptions
|
|
$performance = PlanStrategy::PERFORMANCE_OPTIMIZED;
|
|
$this->assert(! empty($performance->getDescription()), 'Should have description');
|
|
$this->assert(! empty($performance->getDefaultOptimizations()), 'Should have default optimizations');
|
|
|
|
// Test strategy features
|
|
$this->assert($performance->supports('caching'), 'Performance strategy should support caching');
|
|
$this->assert($performance->supports('parallel_processing'), 'Performance strategy should support parallel processing');
|
|
|
|
// Test strategy recommendation
|
|
$context = ['path_count' => 100, 'accuracy' => 'high', 'time_limit' => 10];
|
|
$recommended = PlanStrategy::recommendFor($context);
|
|
$this->assert($recommended !== null, 'Should recommend a strategy');
|
|
|
|
// Test memory efficient strategy
|
|
$memoryContext = ['path_count' => 2000, 'memory_limit' => 32 * 1024 * 1024];
|
|
$memoryStrategy = PlanStrategy::recommendFor($memoryContext);
|
|
$this->assert($memoryStrategy === PlanStrategy::MEMORY_EFFICIENT, 'Should recommend memory efficient for large projects');
|
|
|
|
echo " ✅ Plan Strategy tests passed\n";
|
|
$this->results['plan_strategy'] = ['status' => 'PASSED', 'details' => 'All strategy tests passed'];
|
|
|
|
} catch (\Throwable $e) {
|
|
$this->results['plan_strategy'] = ['status' => 'FAILED', 'error' => $e->getMessage()];
|
|
echo " ❌ Plan Strategy test failed: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
|
|
private function testDiscoveryMetrics(): void
|
|
{
|
|
echo "📊 Testing Discovery Metrics...\n";
|
|
|
|
try {
|
|
// Test metrics creation
|
|
$metrics = new DiscoveryMetrics(
|
|
cacheHitRate: 0.85,
|
|
averageDiscoveryTime: 2.5,
|
|
componentsDiscovered: 150,
|
|
patternMatchRate: 0.75,
|
|
predictionAccuracy: 0.8,
|
|
memoryEfficiency: 0.9,
|
|
optimizationImpact: 0.6
|
|
);
|
|
|
|
// Test efficiency score calculation
|
|
$score = $metrics->getEfficiencyScore();
|
|
$this->assert($score > 0.7, 'Efficiency score should be above 0.7');
|
|
|
|
// Test performance rating
|
|
$rating = $metrics->getPerformanceRating();
|
|
$this->assert(in_array($rating, ['excellent', 'very_good', 'good', 'average', 'below_average', 'poor']), 'Should have valid rating');
|
|
|
|
// Test components per second
|
|
$cps = $metrics->getComponentsPerSecond();
|
|
$this->assert($cps > 0, 'Components per second should be positive');
|
|
|
|
// Test improvement suggestions
|
|
$suggestions = $metrics->getImprovementSuggestions();
|
|
$this->assert(is_array($suggestions), 'Should return suggestions array');
|
|
|
|
// Test array conversion
|
|
$array = $metrics->toArray();
|
|
$this->assert(isset($array['efficiency_score']), 'Array should contain efficiency score');
|
|
$this->assert(isset($array['performance_rating']), 'Array should contain performance rating');
|
|
|
|
// Test empty metrics
|
|
$emptyMetrics = DiscoveryMetrics::empty();
|
|
$this->assert($emptyMetrics->getEfficiencyScore() === 0.0, 'Empty metrics should have zero efficiency');
|
|
|
|
echo " ✅ Discovery Metrics tests passed\n";
|
|
$this->results['discovery_metrics'] = ['status' => 'PASSED', 'details' => 'All metrics tests passed'];
|
|
|
|
} catch (\Throwable $e) {
|
|
$this->results['discovery_metrics'] = ['status' => 'FAILED', 'error' => $e->getMessage()];
|
|
echo " ❌ Discovery Metrics test failed: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
|
|
private function testComponentType(): void
|
|
{
|
|
echo "🧩 Testing Component Type...\n";
|
|
|
|
try {
|
|
// Test component type properties
|
|
$controller = ComponentType::CONTROLLER;
|
|
$this->assert($controller->getDescription() !== '', 'Should have description');
|
|
$this->assert($controller->getWeight() > 1.0, 'Controller should have high weight');
|
|
$this->assert($controller->hasDependencies(), 'Controller should typically have dependencies');
|
|
$this->assert($controller->getPerformanceImpact() === 'high', 'Controller should have high performance impact');
|
|
|
|
// Test service type
|
|
$service = ComponentType::SERVICE;
|
|
$this->assert($service->getWeight() > 1.0, 'Service should have above-average weight');
|
|
$this->assert($service->hasDependencies(), 'Service should typically have dependencies');
|
|
|
|
// Test value object type
|
|
$valueObject = ComponentType::VALUE_OBJECT;
|
|
$this->assert($valueObject->getWeight() < 1.0, 'Value object should have low weight');
|
|
$this->assert(! $valueObject->hasDependencies(), 'Value object should not typically have dependencies');
|
|
|
|
// Test typical dependencies
|
|
$controllerDeps = $controller->getTypicalDependencies();
|
|
$this->assert(in_array('service', $controllerDeps), 'Controller should typically depend on services');
|
|
|
|
echo " ✅ Component Type tests passed\n";
|
|
$this->results['component_type'] = ['status' => 'PASSED', 'details' => 'All component type tests passed'];
|
|
|
|
} catch (\Throwable $e) {
|
|
$this->results['component_type'] = ['status' => 'FAILED', 'error' => $e->getMessage()];
|
|
echo " ❌ Component Type test failed: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
|
|
private function testDependencyGraph(): void
|
|
{
|
|
echo "🕸️ Testing Dependency Graph...\n";
|
|
|
|
try {
|
|
// Create test nodes
|
|
$nodeA = DependencyNode::simple('A', 'ComponentA', ComponentType::CONTROLLER);
|
|
$nodeB = DependencyNode::simple('B', 'ComponentB', ComponentType::SERVICE);
|
|
$nodeC = DependencyNode::simple('C', 'ComponentC', ComponentType::REPOSITORY);
|
|
|
|
// Create test edges
|
|
$edgeAB = DependencyEdge::constructor('A', 'B');
|
|
$edgeBC = DependencyEdge::method('B', 'C', 0.8);
|
|
|
|
// Create graph
|
|
$graph = new DependencyGraph([$nodeA, $nodeB, $nodeC], [$edgeAB, $edgeBC]);
|
|
|
|
// Test basic operations
|
|
$this->assert(count($graph->getNodes()) === 3, 'Should have 3 nodes');
|
|
$this->assert(count($graph->getEdges()) === 2, 'Should have 2 edges');
|
|
|
|
// Test node retrieval
|
|
$retrievedNode = $graph->getNode('A');
|
|
$this->assert($retrievedNode !== null, 'Should find node A');
|
|
$this->assert($retrievedNode->name === 'ComponentA', 'Should have correct name');
|
|
|
|
// Test edge operations
|
|
$edgesFromA = $graph->getEdgesFrom('A');
|
|
$this->assert(count($edgesFromA) === 1, 'A should have 1 outgoing edge');
|
|
$this->assert($edgesFromA[0]->to === 'B', 'A should connect to B');
|
|
|
|
$edgesToB = $graph->getEdgesTo('B');
|
|
$this->assert(count($edgesToB) === 1, 'B should have 1 incoming edge');
|
|
|
|
// Test dependencies
|
|
$depsA = $graph->getDependencies('A');
|
|
$this->assert(in_array('B', $depsA), 'A should depend on B');
|
|
|
|
$dependentsB = $graph->getDependents('B');
|
|
$this->assert(in_array('A', $dependentsB), 'A should be dependent on B');
|
|
|
|
// Test path finding
|
|
$hasPath = $graph->hasPath('A', 'C');
|
|
$this->assert($hasPath, 'Should have path from A to C');
|
|
|
|
$shortestPath = $graph->getShortestPath('A', 'C');
|
|
$this->assert($shortestPath === ['A', 'B', 'C'], 'Should find correct shortest path');
|
|
|
|
// Test statistics
|
|
$stats = $graph->getStatistics();
|
|
$this->assert($stats['node_count'] === 3, 'Stats should show 3 nodes');
|
|
$this->assert($stats['edge_count'] === 2, 'Stats should show 2 edges');
|
|
|
|
// Test array conversion
|
|
$graphArray = $graph->toArray();
|
|
$this->assert(isset($graphArray['nodes']), 'Should have nodes in array');
|
|
$this->assert(isset($graphArray['edges']), 'Should have edges in array');
|
|
$this->assert(isset($graphArray['statistics']), 'Should have statistics in array');
|
|
|
|
echo " ✅ Dependency Graph tests passed\n";
|
|
$this->results['dependency_graph'] = ['status' => 'PASSED', 'details' => 'All dependency graph tests passed'];
|
|
|
|
} catch (\Throwable $e) {
|
|
$this->results['dependency_graph'] = ['status' => 'FAILED', 'error' => $e->getMessage()];
|
|
echo " ❌ Dependency Graph test failed: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
|
|
private function generateReport(): void
|
|
{
|
|
$totalTime = microtime(true) - $this->startTime;
|
|
|
|
echo "\n📊 ENHANCED DISCOVERY TEST REPORT\n";
|
|
echo "═══════════════════════════════════════════════════════\n\n";
|
|
|
|
$passed = 0;
|
|
$failed = 0;
|
|
|
|
foreach ($this->results as $testName => $result) {
|
|
$status = $result['status'] === 'PASSED' ? '✅' : '❌';
|
|
$statusText = $result['status'];
|
|
|
|
echo "{$status} {$testName}: {$statusText}\n";
|
|
|
|
if ($result['status'] === 'PASSED') {
|
|
$passed++;
|
|
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";
|
|
|
|
if ($failed === 0) {
|
|
echo "\n🎉 ALL ENHANCED DISCOVERY TESTS PASSED!\n";
|
|
echo "✨ Phase 4: Enhanced Auto-Discovery System is complete!\n";
|
|
} else {
|
|
echo "\n⚠️ Some tests failed. Please check the errors above.\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 EnhancedDiscoveryTester();
|
|
$tester->runAllTests();
|