config = new DDoSConfig( criticalThreatThreshold: 0.9, highThreatThreshold: 0.7, mediumThreatThreshold: 0.3 ); // Create a simple logger for testing $this->logger = new DefaultLogger( minLevel: LogLevel::ERROR, handlers: [new ConsoleHandler(LogLevel::ERROR)] ); $this->calculator = new ThreatLevelCalculator($this->logger); }); describe('ThreatLevelCalculator', function () { it('calculates LOW threat for normal scores', function () { $analyses = [ 'traffic_patterns' => ['threat_score' => 0.1], 'geo_anomalies' => ['threat_score' => 0.05], ]; $threatLevel = $this->calculator->calculateThreatLevel($analyses); expect($threatLevel)->toBe(ThreatLevel::LOW); }); it('calculates MEDIUM threat for moderate scores', function () { $analyses = [ 'traffic_patterns' => ['threat_score' => 0.6], // 0.3 * 0.6 = 0.18 'geo_anomalies' => ['threat_score' => 0.7], // 0.2 * 0.7 = 0.14 'waf_analysis' => ['threat_score' => 0.4], // 0.25 * 0.4 = 0.1 ]; // Total: 0.18 + 0.14 + 0.1 = 0.42 (above 0.3 threshold) $threatLevel = $this->calculator->calculateThreatLevel($analyses); expect($threatLevel)->toBe(ThreatLevel::MEDIUM); }); it('calculates HIGH threat for elevated scores', function () { $analyses = [ 'traffic_patterns' => ['threat_score' => 1.0], // 0.3 * 1.0 = 0.3 'geo_anomalies' => ['threat_score' => 1.0], // 0.2 * 1.0 = 0.2 'waf_analysis' => ['threat_score' => 0.8], // 0.25 * 0.8 = 0.2 'service_health' => ['threat_score' => 0.0], // 0.15 * 0.0 = 0.0 ]; // Total: 0.3 + 0.2 + 0.2 + 0.0 = 0.7 (exactly HIGH threshold) $threatLevel = $this->calculator->calculateThreatLevel($analyses); expect($threatLevel)->toBe(ThreatLevel::HIGH); }); it('calculates CRITICAL threat for maximum scores', function () { $analyses = [ 'traffic_patterns' => ['threat_score' => 0.95], 'geo_anomalies' => ['threat_score' => 0.9], 'waf_analysis' => ['threat_score' => 0.95], 'service_health' => ['threat_score' => 0.9], 'request_signature' => ['threat_score' => 0.9], ]; $threatLevel = $this->calculator->calculateThreatLevel($analyses); expect($threatLevel)->toBe(ThreatLevel::CRITICAL); }); it('handles edge cases at thresholds', function () { // Test MEDIUM threshold (0.3) $mediumAnalyses = [ 'traffic_patterns' => ['threat_score' => 1.0], // Will be weighted to exactly 0.3 ]; expect($this->calculator->calculateThreatLevel($mediumAnalyses))->toBe(ThreatLevel::MEDIUM); // Test HIGH threshold (0.7) $highAnalyses = [ 'traffic_patterns' => ['threat_score' => 1.0], // 0.3 weight 'geo_anomalies' => ['threat_score' => 1.0], // 0.2 weight 'waf_analysis' => ['threat_score' => 0.8], // 0.25 weight * 0.8 = 0.2 ]; // Total: 0.3 + 0.2 + 0.2 = 0.7 expect($this->calculator->calculateThreatLevel($highAnalyses))->toBe(ThreatLevel::HIGH); }); it('handles empty analysis results', function () { $threatLevel = $this->calculator->calculateThreatLevel([]); expect($threatLevel)->toBe(ThreatLevel::LOW); }); it('calculates confidence from multiple analyses', function () { $analyses = [ 'traffic_patterns' => ['threat_score' => 0.6, 'confidence' => 0.8], 'geo_anomalies' => ['threat_score' => 0.4, 'confidence' => 0.9], 'waf_analysis' => ['threat_score' => 0.7, 'confidence' => 0.7], ]; $confidence = $this->calculator->calculateConfidence($analyses); expect($confidence)->toBeBetween(0.0, 1.0); expect($confidence)->toBeGreaterThan(0.7); // Average should be around 0.8 }); it('handles missing confidence values', function () { $analyses = [ 'traffic_patterns' => ['threat_score' => 0.6], // No confidence 'geo_anomalies' => ['threat_score' => 0.4, 'confidence' => 0.8], ]; $confidence = $this->calculator->calculateConfidence($analyses); expect($confidence)->toBe(0.8); // Only one confidence value available }); }); describe('Threat Level Recommendations', function () { it('provides appropriate action recommendations', function () { expect($this->calculator->getRecommendedAction(ThreatLevel::LOW))->toBe('ALLOW'); expect($this->calculator->getRecommendedAction(ThreatLevel::MEDIUM))->toBe('RATE_LIMIT'); expect($this->calculator->getRecommendedAction(ThreatLevel::HIGH))->toBe('ENHANCED_MONITORING'); expect($this->calculator->getRecommendedAction(ThreatLevel::CRITICAL))->toBe('BLOCK_IMMEDIATELY'); }); it('suggests rate limiting for medium threats', function () { $recommendation = $this->calculator->getRecommendedAction(ThreatLevel::MEDIUM); expect($recommendation)->toBe('RATE_LIMIT'); }); it('suggests enhanced monitoring for high threats', function () { $recommendation = $this->calculator->getRecommendedAction(ThreatLevel::HIGH); expect($recommendation)->toBe('ENHANCED_MONITORING'); }); it('suggests immediate blocking for critical threats', function () { $recommendation = $this->calculator->getRecommendedAction(ThreatLevel::CRITICAL); expect($recommendation)->toBe('BLOCK_IMMEDIATELY'); }); });