Skip to main content

memscope_rs/analysis/quality/
checker.rs

1use std::collections::HashMap;
2use std::time::{Duration, Instant};
3
4/// Performance checker for memory analysis operations
5pub struct PerformanceChecker {
6    benchmarks: HashMap<String, PerformanceBenchmark>,
7    thresholds: PerformanceThresholds,
8    config: CheckerConfig,
9}
10
11impl PerformanceChecker {
12    pub fn config(&self) -> &CheckerConfig {
13        &self.config
14    }
15}
16
17/// Memory leak detection checker
18pub struct MemoryLeakChecker {
19    baseline_measurements: HashMap<String, MemoryBaseline>,
20    config: LeakDetectionConfig,
21    sensitivity: LeakSensitivity,
22}
23
24impl MemoryLeakChecker {
25    pub fn config(&self) -> &LeakDetectionConfig {
26        &self.config
27    }
28}
29
30/// Safety checker for memory operations
31pub struct SafetyChecker {
32    violation_patterns: Vec<SafetyPattern>,
33    safety_requirements: HashMap<String, SafetyRequirement>,
34    config: SafetyConfig,
35}
36
37impl SafetyChecker {
38    pub fn violation_patterns(&self) -> &[SafetyPattern] {
39        &self.violation_patterns
40    }
41    pub fn safety_requirements(&self) -> &HashMap<String, SafetyRequirement> {
42        &self.safety_requirements
43    }
44    pub fn config(&self) -> &SafetyConfig {
45        &self.config
46    }
47}
48
49/// Performance benchmark for specific operation
50#[derive(Debug, Clone)]
51pub struct PerformanceBenchmark {
52    /// Operation identifier
53    pub operation: String,
54    /// Expected average duration
55    pub expected_duration: Duration,
56    /// Maximum acceptable duration
57    pub max_duration: Duration,
58    /// Expected memory usage
59    pub expected_memory: usize,
60    /// Maximum acceptable memory
61    pub max_memory: usize,
62    /// Expected throughput (operations per second)
63    pub expected_throughput: f64,
64    /// Minimum acceptable throughput
65    pub min_throughput: f64,
66}
67
68/// Performance thresholds for different operations
69#[derive(Debug, Clone)]
70pub struct PerformanceThresholds {
71    /// Allocation tracking latency threshold
72    pub allocation_latency: Duration,
73    /// Symbol resolution time threshold
74    pub symbol_resolution: Duration,
75    /// Stack trace capture time threshold
76    pub stack_trace_capture: Duration,
77    /// Memory overhead percentage threshold
78    pub memory_overhead_pct: f64,
79    /// Minimum tracking completeness
80    pub min_completeness: f64,
81}
82
83/// Memory baseline for leak detection
84#[derive(Debug, Clone)]
85pub struct MemoryBaseline {
86    /// Initial memory usage
87    pub initial_memory: usize,
88    /// Expected memory growth pattern
89    pub growth_pattern: GrowthPattern,
90    /// Measurement timestamp
91    pub timestamp: Instant,
92    /// Number of allocations at baseline
93    pub allocation_count: usize,
94}
95
96/// Expected memory growth patterns
97#[derive(Debug, Clone, PartialEq)]
98pub enum GrowthPattern {
99    /// Memory usage should remain constant
100    Constant,
101    /// Memory should grow linearly with allocations
102    Linear { bytes_per_allocation: f64 },
103    /// Memory should grow logarithmically
104    Logarithmic,
105    /// Memory should stabilize after initial growth
106    Stabilizing { max_growth: usize },
107    /// Custom growth pattern
108    Custom { description: String },
109}
110
111/// Leak detection sensitivity levels
112#[derive(Debug, Clone, PartialEq)]
113pub enum LeakSensitivity {
114    /// Only detect obvious leaks
115    Low,
116    /// Detect moderate leaks
117    Medium,
118    /// Detect subtle leaks
119    High,
120    /// Detect any unusual growth
121    Paranoid,
122}
123
124/// Safety violation patterns
125#[derive(Debug, Clone)]
126pub struct SafetyPattern {
127    /// Pattern identifier
128    pub id: String,
129    /// Pattern description
130    pub description: String,
131    /// Detection function
132    pub detector: SafetyDetector,
133    /// Severity of violation
134    pub severity: SafetySeverity,
135}
136
137/// Safety detection function type
138pub type SafetyDetector = fn(&SafetyContext) -> Vec<SafetyViolation>;
139
140/// Safety requirement for operations
141#[derive(Debug, Clone)]
142pub struct SafetyRequirement {
143    /// Required safety properties
144    pub properties: Vec<SafetyProperty>,
145    /// Whether operation must be thread-safe
146    pub thread_safe: bool,
147    /// Whether operation must handle errors
148    pub error_handling: bool,
149    /// Maximum acceptable risk level
150    pub max_risk_level: RiskLevel,
151}
152
153/// Safety properties that operations should have
154#[derive(Debug, Clone, PartialEq)]
155pub enum SafetyProperty {
156    /// No memory leaks
157    NoMemoryLeaks,
158    /// No data races
159    NoDataRaces,
160    /// No use after free
161    NoUseAfterFree,
162    /// No buffer overflows
163    NoBufferOverflow,
164    /// Proper error propagation
165    ErrorPropagation,
166    /// Resource cleanup
167    ResourceCleanup,
168}
169
170/// Safety violation severity
171#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
172pub enum SafetySeverity {
173    /// Minor safety concern
174    Low,
175    /// Moderate safety issue
176    Medium,
177    /// Serious safety problem
178    High,
179    /// Critical safety violation
180    Critical,
181}
182
183/// Risk assessment levels
184#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
185pub enum RiskLevel {
186    /// Minimal risk
187    Minimal,
188    /// Low risk
189    Low,
190    /// Medium risk
191    Medium,
192    /// High risk
193    High,
194    /// Critical risk
195    Critical,
196}
197
198/// Context for safety checking
199#[derive(Debug)]
200pub struct SafetyContext {
201    /// Operation being checked
202    pub operation: String,
203    /// Memory access patterns
204    pub memory_accesses: Vec<MemoryAccess>,
205    /// Thread interactions
206    pub thread_interactions: Vec<ThreadInteraction>,
207    /// Error handling status
208    pub error_handling: bool,
209    /// Resource usage
210    pub resource_usage: ResourceUsage,
211}
212
213/// Memory access information
214#[derive(Debug, Clone)]
215pub struct MemoryAccess {
216    /// Type of access
217    pub access_type: AccessType,
218    /// Memory address (if known)
219    pub address: Option<usize>,
220    /// Size of access
221    pub size: usize,
222    /// Whether access is synchronized
223    pub synchronized: bool,
224}
225
226/// Types of memory access
227#[derive(Debug, Clone, PartialEq)]
228pub enum AccessType {
229    /// Reading memory
230    Read,
231    /// Writing memory
232    Write,
233    /// Allocating memory
234    Allocate,
235    /// Deallocating memory
236    Deallocate,
237}
238
239/// Thread interaction information
240#[derive(Debug, Clone)]
241pub struct ThreadInteraction {
242    /// Type of interaction
243    pub interaction_type: InteractionType,
244    /// Shared resource identifier
245    pub resource_id: String,
246    /// Synchronization mechanism used
247    pub synchronization: Option<SyncMechanism>,
248}
249
250/// Types of thread interactions
251#[derive(Debug, Clone, PartialEq)]
252pub enum InteractionType {
253    /// Shared read access
254    SharedRead,
255    /// Exclusive write access
256    ExclusiveWrite,
257    /// Message passing
258    MessagePassing,
259    /// Lock acquisition
260    LockAcquisition,
261}
262
263/// Synchronization mechanisms
264#[derive(Debug, Clone, PartialEq)]
265pub enum SyncMechanism {
266    /// Mutex lock
267    Mutex,
268    /// Read-write lock
269    RwLock,
270    /// Atomic operations
271    Atomic,
272    /// Lock-free data structure
273    LockFree,
274    /// None (unsafe)
275    None,
276}
277
278/// Resource usage information
279#[derive(Debug, Clone)]
280pub struct ResourceUsage {
281    /// Memory usage in bytes
282    pub memory_bytes: usize,
283    /// File descriptors used
284    pub file_descriptors: usize,
285    /// Network connections
286    pub network_connections: usize,
287    /// CPU time used
288    pub cpu_time: Duration,
289}
290
291/// Safety violation detected
292#[derive(Debug, Clone)]
293pub struct SafetyViolation {
294    /// Violation type
295    pub violation_type: String,
296    /// Severity level
297    pub severity: SafetySeverity,
298    /// Description of the issue
299    pub description: String,
300    /// Suggested fix
301    pub suggestion: String,
302    /// Location where violation was detected
303    pub location: Option<String>,
304}
305
306/// Configuration for checkers
307#[derive(Debug, Clone)]
308pub struct CheckerConfig {
309    /// Whether to enable deep analysis
310    pub deep_analysis: bool,
311    /// Maximum time to spend checking
312    pub max_check_time: Duration,
313    /// Whether to check during operation
314    pub realtime_checking: bool,
315    /// Sampling rate for performance monitoring
316    pub sample_rate: f64,
317}
318
319/// Leak detection configuration
320#[derive(Debug, Clone)]
321pub struct LeakDetectionConfig {
322    /// Minimum time between measurements
323    pub measurement_interval: Duration,
324    /// Number of measurements to keep
325    pub measurement_history: usize,
326    /// Growth threshold for leak detection
327    pub growth_threshold: f64,
328    /// Whether to track individual allocations
329    pub track_allocations: bool,
330}
331
332/// Safety checking configuration
333#[derive(Debug, Clone)]
334pub struct SafetyConfig {
335    /// Safety patterns to check
336    pub enabled_patterns: Vec<String>,
337    /// Minimum severity to report
338    pub min_severity: SafetySeverity,
339    /// Whether to check thread safety
340    pub check_thread_safety: bool,
341    /// Whether to check memory safety
342    pub check_memory_safety: bool,
343}
344
345impl PerformanceChecker {
346    /// Create performance checker with default thresholds
347    pub fn new() -> Self {
348        Self {
349            benchmarks: HashMap::new(),
350            thresholds: PerformanceThresholds::default(),
351            config: CheckerConfig::default(),
352        }
353    }
354
355    /// Add performance benchmark for operation
356    pub fn add_benchmark(&mut self, benchmark: PerformanceBenchmark) {
357        self.benchmarks
358            .insert(benchmark.operation.clone(), benchmark);
359    }
360
361    /// Check operation performance against benchmarks
362    pub fn check_performance(
363        &self,
364        operation: &str,
365        actual: &PerformanceMetrics,
366    ) -> PerformanceCheckResult {
367        let mut violations = Vec::new();
368
369        // Check against specific benchmark if available
370        if let Some(benchmark) = self.benchmarks.get(operation) {
371            violations.extend(self.check_against_benchmark(benchmark, actual));
372        }
373
374        // Check against general thresholds
375        violations.extend(self.check_against_thresholds(operation, actual));
376
377        let status = if violations
378            .iter()
379            .any(|v| v.severity == PerformanceIssueType::Critical)
380        {
381            PerformanceStatus::Critical
382        } else if violations
383            .iter()
384            .any(|v| v.severity == PerformanceIssueType::Major)
385        {
386            PerformanceStatus::Poor
387        } else if violations
388            .iter()
389            .any(|v| v.severity == PerformanceIssueType::Minor)
390        {
391            PerformanceStatus::Acceptable
392        } else {
393            PerformanceStatus::Optimal
394        };
395
396        let overall_score = self.calculate_performance_score(&violations);
397
398        PerformanceCheckResult {
399            operation: operation.to_string(),
400            status,
401            violations,
402            overall_score,
403        }
404    }
405
406    fn check_against_benchmark(
407        &self,
408        benchmark: &PerformanceBenchmark,
409        actual: &PerformanceMetrics,
410    ) -> Vec<PerformanceViolation> {
411        let mut violations = Vec::new();
412
413        // Check duration
414        if actual.duration > benchmark.max_duration {
415            violations.push(PerformanceViolation {
416                metric: "duration".to_string(),
417                expected: benchmark.expected_duration.as_micros() as f64,
418                actual: actual.duration.as_micros() as f64,
419                severity: PerformanceIssueType::Major,
420                description: format!(
421                    "Duration {:.2}ms exceeds maximum {:.2}ms",
422                    actual.duration.as_millis(),
423                    benchmark.max_duration.as_millis()
424                ),
425            });
426        }
427
428        // Check memory usage
429        if actual.memory_usage > benchmark.max_memory {
430            violations.push(PerformanceViolation {
431                metric: "memory".to_string(),
432                expected: benchmark.expected_memory as f64,
433                actual: actual.memory_usage as f64,
434                severity: PerformanceIssueType::Major,
435                description: format!(
436                    "Memory usage {:.2}MB exceeds maximum {:.2}MB",
437                    actual.memory_usage as f64 / (1024.0 * 1024.0),
438                    benchmark.max_memory as f64 / (1024.0 * 1024.0)
439                ),
440            });
441        }
442
443        // Check throughput
444        if actual.throughput < benchmark.min_throughput {
445            violations.push(PerformanceViolation {
446                metric: "throughput".to_string(),
447                expected: benchmark.expected_throughput,
448                actual: actual.throughput,
449                severity: PerformanceIssueType::Minor,
450                description: format!(
451                    "Throughput {:.0}/sec below minimum {:.0}/sec",
452                    actual.throughput, benchmark.min_throughput
453                ),
454            });
455        }
456
457        violations
458    }
459
460    fn check_against_thresholds(
461        &self,
462        operation: &str,
463        actual: &PerformanceMetrics,
464    ) -> Vec<PerformanceViolation> {
465        let mut violations = Vec::new();
466
467        // Check allocation latency for tracking operations
468        if operation.contains("allocation") && actual.duration > self.thresholds.allocation_latency
469        {
470            violations.push(PerformanceViolation {
471                metric: "allocation_latency".to_string(),
472                expected: self.thresholds.allocation_latency.as_micros() as f64,
473                actual: actual.duration.as_micros() as f64,
474                severity: PerformanceIssueType::Critical,
475                description: "Allocation tracking latency exceeds threshold".to_string(),
476            });
477        }
478
479        // Check symbol resolution time
480        if operation.contains("symbol") && actual.duration > self.thresholds.symbol_resolution {
481            violations.push(PerformanceViolation {
482                metric: "symbol_resolution".to_string(),
483                expected: self.thresholds.symbol_resolution.as_millis() as f64,
484                actual: actual.duration.as_millis() as f64,
485                severity: PerformanceIssueType::Major,
486                description: "Symbol resolution time exceeds threshold".to_string(),
487            });
488        }
489
490        violations
491    }
492
493    fn calculate_performance_score(&self, violations: &[PerformanceViolation]) -> f64 {
494        if violations.is_empty() {
495            return 1.0;
496        }
497
498        let penalty: f64 = violations
499            .iter()
500            .map(|v| match v.severity {
501                PerformanceIssueType::Critical => 0.5,
502                PerformanceIssueType::Major => 0.3,
503                PerformanceIssueType::Minor => 0.1,
504            })
505            .sum();
506
507        (1.0 - penalty).max(0.0)
508    }
509}
510
511impl MemoryLeakChecker {
512    /// Create memory leak checker
513    pub fn new() -> Self {
514        Self {
515            baseline_measurements: HashMap::new(),
516            config: LeakDetectionConfig::default(),
517            sensitivity: LeakSensitivity::Medium,
518        }
519    }
520
521    /// Set baseline memory measurement for operation
522    pub fn set_baseline(&mut self, operation: &str, memory: usize, allocations: usize) {
523        let baseline = MemoryBaseline {
524            initial_memory: memory,
525            growth_pattern: GrowthPattern::Constant,
526            timestamp: Instant::now(),
527            allocation_count: allocations,
528        };
529        self.baseline_measurements
530            .insert(operation.to_string(), baseline);
531    }
532
533    /// Check for memory leaks
534    pub fn check_for_leaks(&self, operation: &str, current: &MemorySnapshot) -> LeakCheckResult {
535        if let Some(baseline) = self.baseline_measurements.get(operation) {
536            let growth_rate = self.calculate_growth_rate(baseline, current);
537            let leak_indicators = self.detect_leak_indicators(baseline, current, growth_rate);
538
539            let severity = self.assess_leak_severity(&leak_indicators);
540            let confidence = self.calculate_confidence(&leak_indicators);
541
542            LeakCheckResult {
543                operation: operation.to_string(),
544                leak_detected: !leak_indicators.is_empty(),
545                severity,
546                confidence,
547                indicators: leak_indicators,
548                growth_rate,
549            }
550        } else {
551            LeakCheckResult {
552                operation: operation.to_string(),
553                leak_detected: false,
554                severity: LeakSeverity::None,
555                confidence: 0.0,
556                indicators: Vec::new(),
557                growth_rate: 0.0,
558            }
559        }
560    }
561
562    fn calculate_growth_rate(&self, baseline: &MemoryBaseline, current: &MemorySnapshot) -> f64 {
563        let time_elapsed = baseline.timestamp.elapsed().as_secs_f64();
564        if time_elapsed > 0.0 {
565            (current.memory_usage as f64 - baseline.initial_memory as f64) / time_elapsed
566        } else {
567            0.0
568        }
569    }
570
571    fn detect_leak_indicators(
572        &self,
573        baseline: &MemoryBaseline,
574        current: &MemorySnapshot,
575        growth_rate: f64,
576    ) -> Vec<LeakIndicator> {
577        let mut indicators = Vec::new();
578
579        // Check for unexpected growth
580        if growth_rate > self.config.growth_threshold {
581            indicators.push(LeakIndicator {
582                indicator_type: "excessive_growth".to_string(),
583                description: format!(
584                    "Memory growing at {:.2}MB/sec",
585                    growth_rate / (1024.0 * 1024.0)
586                ),
587                severity: LeakSeverity::High,
588            });
589        }
590
591        // Check allocation/deallocation imbalance
592        let alloc_growth = current.allocation_count as f64 - baseline.allocation_count as f64;
593        let memory_growth = current.memory_usage as f64 - baseline.initial_memory as f64;
594
595        if alloc_growth > 0.0 && memory_growth / alloc_growth > 1024.0 {
596            // More than 1KB per allocation
597            indicators.push(LeakIndicator {
598                indicator_type: "allocation_imbalance".to_string(),
599                description: "High memory per allocation ratio".to_string(),
600                severity: LeakSeverity::Medium,
601            });
602        }
603
604        indicators
605    }
606
607    fn assess_leak_severity(&self, indicators: &[LeakIndicator]) -> LeakSeverity {
608        indicators
609            .iter()
610            .map(|i| &i.severity)
611            .max()
612            .cloned()
613            .unwrap_or(LeakSeverity::None)
614    }
615
616    fn calculate_confidence(&self, indicators: &[LeakIndicator]) -> f64 {
617        if indicators.is_empty() {
618            0.0
619        } else {
620            match self.sensitivity {
621                LeakSensitivity::Low => 0.5,
622                LeakSensitivity::Medium => 0.7,
623                LeakSensitivity::High => 0.85,
624                LeakSensitivity::Paranoid => 0.95,
625            }
626        }
627    }
628}
629
630// Additional types for results and metrics
631#[derive(Debug, Clone)]
632pub struct PerformanceMetrics {
633    pub duration: Duration,
634    pub memory_usage: usize,
635    pub throughput: f64,
636    pub cpu_usage: f64,
637}
638
639#[derive(Debug, Clone)]
640pub struct PerformanceCheckResult {
641    pub operation: String,
642    pub status: PerformanceStatus,
643    pub violations: Vec<PerformanceViolation>,
644    pub overall_score: f64,
645}
646
647#[derive(Debug, Clone, PartialEq)]
648pub enum PerformanceStatus {
649    Optimal,
650    Acceptable,
651    Poor,
652    Critical,
653}
654
655#[derive(Debug, Clone)]
656pub struct PerformanceViolation {
657    pub metric: String,
658    pub expected: f64,
659    pub actual: f64,
660    pub severity: PerformanceIssueType,
661    pub description: String,
662}
663
664#[derive(Debug, Clone, PartialEq)]
665pub enum PerformanceIssueType {
666    Minor,
667    Major,
668    Critical,
669}
670
671#[derive(Debug, Clone)]
672pub struct MemorySnapshot {
673    pub memory_usage: usize,
674    pub allocation_count: usize,
675    pub timestamp: Instant,
676}
677
678#[derive(Debug, Clone)]
679pub struct LeakCheckResult {
680    pub operation: String,
681    pub leak_detected: bool,
682    pub severity: LeakSeverity,
683    pub confidence: f64,
684    pub indicators: Vec<LeakIndicator>,
685    pub growth_rate: f64,
686}
687
688#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
689pub enum LeakSeverity {
690    None,
691    Low,
692    Medium,
693    High,
694    Critical,
695}
696
697#[derive(Debug, Clone)]
698pub struct LeakIndicator {
699    pub indicator_type: String,
700    pub description: String,
701    pub severity: LeakSeverity,
702}
703
704// Default implementations
705impl Default for PerformanceThresholds {
706    fn default() -> Self {
707        Self {
708            allocation_latency: Duration::from_micros(50),
709            symbol_resolution: Duration::from_millis(5),
710            stack_trace_capture: Duration::from_millis(10),
711            memory_overhead_pct: 5.0,
712            min_completeness: 0.95,
713        }
714    }
715}
716
717impl Default for CheckerConfig {
718    fn default() -> Self {
719        Self {
720            deep_analysis: true,
721            max_check_time: Duration::from_secs(5),
722            realtime_checking: false,
723            sample_rate: 0.1,
724        }
725    }
726}
727
728impl Default for LeakDetectionConfig {
729    fn default() -> Self {
730        Self {
731            measurement_interval: Duration::from_secs(60),
732            measurement_history: 100,
733            growth_threshold: 1024.0 * 1024.0, // 1MB/sec
734            track_allocations: true,
735        }
736    }
737}
738
739impl Default for SafetyConfig {
740    fn default() -> Self {
741        Self {
742            enabled_patterns: vec![
743                "memory_safety".to_string(),
744                "thread_safety".to_string(),
745                "error_handling".to_string(),
746            ],
747            min_severity: SafetySeverity::Low,
748            check_thread_safety: true,
749            check_memory_safety: true,
750        }
751    }
752}
753
754impl Default for PerformanceChecker {
755    fn default() -> Self {
756        Self::new()
757    }
758}
759
760impl Default for MemoryLeakChecker {
761    fn default() -> Self {
762        Self::new()
763    }
764}
765
766#[cfg(test)]
767mod tests {
768    use super::*;
769
770    #[test]
771    fn test_performance_checker() {
772        let mut checker = PerformanceChecker::new();
773
774        let benchmark = PerformanceBenchmark {
775            operation: "allocation_tracking".to_string(),
776            expected_duration: Duration::from_micros(10),
777            max_duration: Duration::from_micros(50),
778            expected_memory: 1024,
779            max_memory: 2048,
780            expected_throughput: 10000.0,
781            min_throughput: 5000.0,
782        };
783
784        checker.add_benchmark(benchmark);
785
786        let good_metrics = PerformanceMetrics {
787            duration: Duration::from_micros(20),
788            memory_usage: 1500,
789            throughput: 8000.0,
790            cpu_usage: 5.0,
791        };
792
793        let result = checker.check_performance("allocation_tracking", &good_metrics);
794        assert!(matches!(
795            result.status,
796            PerformanceStatus::Optimal | PerformanceStatus::Acceptable
797        ));
798
799        let bad_metrics = PerformanceMetrics {
800            duration: Duration::from_micros(100),
801            memory_usage: 3000,
802            throughput: 1000.0,
803            cpu_usage: 50.0,
804        };
805
806        let result = checker.check_performance("allocation_tracking", &bad_metrics);
807        assert!(matches!(
808            result.status,
809            PerformanceStatus::Poor | PerformanceStatus::Critical
810        ));
811        assert!(!result.violations.is_empty());
812    }
813
814    #[test]
815    fn test_memory_leak_checker() {
816        let mut checker = MemoryLeakChecker::new();
817
818        checker.set_baseline("test_operation", 1024 * 1024, 100);
819
820        let current = MemorySnapshot {
821            memory_usage: 1200 * 1024,
822            allocation_count: 120,
823            timestamp: Instant::now(),
824        };
825
826        let result = checker.check_for_leaks("test_operation", &current);
827        let _ = result;
828    }
829
830    #[test]
831    fn test_growth_patterns() {
832        assert_eq!(GrowthPattern::Constant, GrowthPattern::Constant);
833
834        let linear = GrowthPattern::Linear {
835            bytes_per_allocation: 64.0,
836        };
837        assert!(matches!(linear, GrowthPattern::Linear { .. }));
838    }
839
840    #[test]
841    fn test_performance_checker_default() {
842        let checker = PerformanceChecker::default();
843        assert!(checker.benchmarks.is_empty());
844    }
845
846    #[test]
847    fn test_memory_leak_checker_default() {
848        let checker = MemoryLeakChecker::default();
849        assert!(checker.baseline_measurements.is_empty());
850    }
851
852    #[test]
853    fn test_checker_config_default() {
854        let config = CheckerConfig::default();
855        assert!(config.deep_analysis);
856        assert_eq!(config.max_check_time, Duration::from_secs(5));
857        assert!(!config.realtime_checking);
858        assert!((config.sample_rate - 0.1).abs() < f64::EPSILON);
859    }
860
861    #[test]
862    fn test_leak_detection_config_default() {
863        let config = LeakDetectionConfig::default();
864        assert_eq!(config.measurement_interval, Duration::from_secs(60));
865        assert_eq!(config.measurement_history, 100);
866        assert!((config.growth_threshold - 1024.0 * 1024.0).abs() < f64::EPSILON);
867        assert!(config.track_allocations);
868    }
869
870    #[test]
871    fn test_safety_config_default() {
872        let config = SafetyConfig::default();
873        assert_eq!(config.enabled_patterns.len(), 3);
874        assert_eq!(config.min_severity, SafetySeverity::Low);
875        assert!(config.check_thread_safety);
876        assert!(config.check_memory_safety);
877    }
878
879    #[test]
880    fn test_performance_thresholds_default() {
881        let thresholds = PerformanceThresholds::default();
882        assert_eq!(thresholds.allocation_latency, Duration::from_micros(50));
883        assert_eq!(thresholds.symbol_resolution, Duration::from_millis(5));
884        assert_eq!(thresholds.stack_trace_capture, Duration::from_millis(10));
885        assert!((thresholds.memory_overhead_pct - 5.0).abs() < f64::EPSILON);
886        assert!((thresholds.min_completeness - 0.95).abs() < f64::EPSILON);
887    }
888
889    #[test]
890    fn test_leak_sensitivity_variants() {
891        let sensitivities = vec![
892            LeakSensitivity::Low,
893            LeakSensitivity::Medium,
894            LeakSensitivity::High,
895            LeakSensitivity::Paranoid,
896        ];
897
898        for sensitivity in sensitivities {
899            let checker = MemoryLeakChecker {
900                baseline_measurements: HashMap::new(),
901                config: LeakDetectionConfig::default(),
902                sensitivity: sensitivity.clone(),
903            };
904            assert_eq!(checker.sensitivity, sensitivity);
905        }
906    }
907
908    #[test]
909    fn test_growth_pattern_variants() {
910        let patterns = vec![
911            GrowthPattern::Constant,
912            GrowthPattern::Linear {
913                bytes_per_allocation: 64.0,
914            },
915            GrowthPattern::Logarithmic,
916            GrowthPattern::Stabilizing { max_growth: 1024 },
917            GrowthPattern::Custom {
918                description: "custom".to_string(),
919            },
920        ];
921
922        for pattern in patterns {
923            let baseline = MemoryBaseline {
924                initial_memory: 1024,
925                growth_pattern: pattern.clone(),
926                timestamp: Instant::now(),
927                allocation_count: 10,
928            };
929            assert_eq!(baseline.growth_pattern, pattern);
930        }
931    }
932
933    #[test]
934    fn test_safety_severity_ordering() {
935        assert!(SafetySeverity::Critical > SafetySeverity::High);
936        assert!(SafetySeverity::High > SafetySeverity::Medium);
937        assert!(SafetySeverity::Medium > SafetySeverity::Low);
938    }
939
940    #[test]
941    fn test_risk_level_ordering() {
942        assert!(RiskLevel::Critical > RiskLevel::High);
943        assert!(RiskLevel::High > RiskLevel::Medium);
944        assert!(RiskLevel::Medium > RiskLevel::Low);
945        assert!(RiskLevel::Low > RiskLevel::Minimal);
946    }
947
948    #[test]
949    fn test_leak_severity_ordering() {
950        assert!(LeakSeverity::Critical > LeakSeverity::High);
951        assert!(LeakSeverity::High > LeakSeverity::Medium);
952        assert!(LeakSeverity::Medium > LeakSeverity::Low);
953        assert!(LeakSeverity::Low > LeakSeverity::None);
954    }
955
956    #[test]
957    fn test_access_type_variants() {
958        let access_types = vec![
959            AccessType::Read,
960            AccessType::Write,
961            AccessType::Allocate,
962            AccessType::Deallocate,
963        ];
964
965        for access_type in access_types {
966            let access = MemoryAccess {
967                access_type: access_type.clone(),
968                address: Some(0x1000),
969                size: 64,
970                synchronized: true,
971            };
972            assert_eq!(access.access_type, access_type);
973        }
974    }
975
976    #[test]
977    fn test_interaction_type_variants() {
978        let interaction_types = vec![
979            InteractionType::SharedRead,
980            InteractionType::ExclusiveWrite,
981            InteractionType::MessagePassing,
982            InteractionType::LockAcquisition,
983        ];
984
985        for interaction_type in interaction_types {
986            let interaction = ThreadInteraction {
987                interaction_type: interaction_type.clone(),
988                resource_id: "test".to_string(),
989                synchronization: None,
990            };
991            assert_eq!(interaction.interaction_type, interaction_type);
992        }
993    }
994
995    #[test]
996    fn test_sync_mechanism_variants() {
997        let mechanisms = vec![
998            SyncMechanism::Mutex,
999            SyncMechanism::RwLock,
1000            SyncMechanism::Atomic,
1001            SyncMechanism::LockFree,
1002            SyncMechanism::None,
1003        ];
1004
1005        for mechanism in mechanisms {
1006            let interaction = ThreadInteraction {
1007                interaction_type: InteractionType::LockAcquisition,
1008                resource_id: "test".to_string(),
1009                synchronization: Some(mechanism.clone()),
1010            };
1011            assert_eq!(interaction.synchronization, Some(mechanism));
1012        }
1013    }
1014
1015    #[test]
1016    fn test_safety_property_variants() {
1017        let properties = vec![
1018            SafetyProperty::NoMemoryLeaks,
1019            SafetyProperty::NoDataRaces,
1020            SafetyProperty::NoUseAfterFree,
1021            SafetyProperty::NoBufferOverflow,
1022            SafetyProperty::ErrorPropagation,
1023            SafetyProperty::ResourceCleanup,
1024        ];
1025
1026        for property in properties {
1027            let requirement = SafetyRequirement {
1028                properties: vec![property.clone()],
1029                thread_safe: true,
1030                error_handling: true,
1031                max_risk_level: RiskLevel::Low,
1032            };
1033            assert!(requirement.properties.contains(&property));
1034        }
1035    }
1036
1037    #[test]
1038    fn test_performance_status_variants() {
1039        let statuses = vec![
1040            PerformanceStatus::Optimal,
1041            PerformanceStatus::Acceptable,
1042            PerformanceStatus::Poor,
1043            PerformanceStatus::Critical,
1044        ];
1045
1046        for status in statuses {
1047            let result = PerformanceCheckResult {
1048                operation: "test".to_string(),
1049                status: status.clone(),
1050                violations: vec![],
1051                overall_score: 1.0,
1052            };
1053            assert_eq!(result.status, status);
1054        }
1055    }
1056
1057    #[test]
1058    fn test_performance_issue_type_variants() {
1059        let issue_types = vec![
1060            PerformanceIssueType::Minor,
1061            PerformanceIssueType::Major,
1062            PerformanceIssueType::Critical,
1063        ];
1064
1065        for issue_type in issue_types {
1066            let violation = PerformanceViolation {
1067                metric: "test".to_string(),
1068                expected: 100.0,
1069                actual: 200.0,
1070                severity: issue_type.clone(),
1071                description: "test".to_string(),
1072            };
1073            assert_eq!(violation.severity, issue_type);
1074        }
1075    }
1076
1077    #[test]
1078    fn test_performance_benchmark_creation() {
1079        let benchmark = PerformanceBenchmark {
1080            operation: "test_op".to_string(),
1081            expected_duration: Duration::from_micros(10),
1082            max_duration: Duration::from_micros(50),
1083            expected_memory: 1024,
1084            max_memory: 2048,
1085            expected_throughput: 1000.0,
1086            min_throughput: 500.0,
1087        };
1088
1089        assert_eq!(benchmark.operation, "test_op");
1090        assert_eq!(benchmark.expected_memory, 1024);
1091    }
1092
1093    #[test]
1094    fn test_memory_baseline_creation() {
1095        let baseline = MemoryBaseline {
1096            initial_memory: 1024 * 1024,
1097            growth_pattern: GrowthPattern::Constant,
1098            timestamp: Instant::now(),
1099            allocation_count: 100,
1100        };
1101
1102        assert_eq!(baseline.initial_memory, 1024 * 1024);
1103        assert_eq!(baseline.allocation_count, 100);
1104    }
1105
1106    #[test]
1107    fn test_safety_pattern_creation() {
1108        fn test_detector(_ctx: &SafetyContext) -> Vec<SafetyViolation> {
1109            vec![]
1110        }
1111
1112        let pattern = SafetyPattern {
1113            id: "test_pattern".to_string(),
1114            description: "Test pattern".to_string(),
1115            detector: test_detector,
1116            severity: SafetySeverity::Medium,
1117        };
1118
1119        assert_eq!(pattern.id, "test_pattern");
1120        assert_eq!(pattern.severity, SafetySeverity::Medium);
1121    }
1122
1123    #[test]
1124    fn test_safety_requirement_creation() {
1125        let requirement = SafetyRequirement {
1126            properties: vec![SafetyProperty::NoMemoryLeaks, SafetyProperty::NoDataRaces],
1127            thread_safe: true,
1128            error_handling: true,
1129            max_risk_level: RiskLevel::Medium,
1130        };
1131
1132        assert_eq!(requirement.properties.len(), 2);
1133        assert!(requirement.thread_safe);
1134    }
1135
1136    #[test]
1137    fn test_safety_context_creation() {
1138        let context = SafetyContext {
1139            operation: "test_op".to_string(),
1140            memory_accesses: vec![MemoryAccess {
1141                access_type: AccessType::Read,
1142                address: Some(0x1000),
1143                size: 64,
1144                synchronized: true,
1145            }],
1146            thread_interactions: vec![],
1147            error_handling: true,
1148            resource_usage: ResourceUsage {
1149                memory_bytes: 1024,
1150                file_descriptors: 2,
1151                network_connections: 1,
1152                cpu_time: Duration::from_millis(100),
1153            },
1154        };
1155
1156        assert_eq!(context.operation, "test_op");
1157        assert_eq!(context.memory_accesses.len(), 1);
1158    }
1159
1160    #[test]
1161    fn test_memory_access_creation() {
1162        let access = MemoryAccess {
1163            access_type: AccessType::Write,
1164            address: Some(0x2000),
1165            size: 128,
1166            synchronized: false,
1167        };
1168
1169        assert_eq!(access.access_type, AccessType::Write);
1170        assert_eq!(access.size, 128);
1171        assert!(!access.synchronized);
1172    }
1173
1174    #[test]
1175    fn test_thread_interaction_creation() {
1176        let interaction = ThreadInteraction {
1177            interaction_type: InteractionType::ExclusiveWrite,
1178            resource_id: "shared_data".to_string(),
1179            synchronization: Some(SyncMechanism::Mutex),
1180        };
1181
1182        assert_eq!(
1183            interaction.interaction_type,
1184            InteractionType::ExclusiveWrite
1185        );
1186        assert_eq!(interaction.resource_id, "shared_data");
1187    }
1188
1189    #[test]
1190    fn test_resource_usage_creation() {
1191        let usage = ResourceUsage {
1192            memory_bytes: 1024 * 1024,
1193            file_descriptors: 5,
1194            network_connections: 2,
1195            cpu_time: Duration::from_secs(1),
1196        };
1197
1198        assert_eq!(usage.memory_bytes, 1024 * 1024);
1199        assert_eq!(usage.file_descriptors, 5);
1200    }
1201
1202    #[test]
1203    fn test_safety_violation_creation() {
1204        let violation = SafetyViolation {
1205            violation_type: "use_after_free".to_string(),
1206            severity: SafetySeverity::Critical,
1207            description: "Memory accessed after free".to_string(),
1208            suggestion: "Check lifetime".to_string(),
1209            location: Some("test.rs:42".to_string()),
1210        };
1211
1212        assert_eq!(violation.violation_type, "use_after_free");
1213        assert_eq!(violation.severity, SafetySeverity::Critical);
1214    }
1215
1216    #[test]
1217    fn test_performance_metrics_creation() {
1218        let metrics = PerformanceMetrics {
1219            duration: Duration::from_micros(50),
1220            memory_usage: 2048,
1221            throughput: 1000.0,
1222            cpu_usage: 25.0,
1223        };
1224
1225        assert_eq!(metrics.duration, Duration::from_micros(50));
1226        assert_eq!(metrics.memory_usage, 2048);
1227    }
1228
1229    #[test]
1230    fn test_performance_check_result_creation() {
1231        let result = PerformanceCheckResult {
1232            operation: "test".to_string(),
1233            status: PerformanceStatus::Optimal,
1234            violations: vec![],
1235            overall_score: 1.0,
1236        };
1237
1238        assert_eq!(result.operation, "test");
1239        assert_eq!(result.status, PerformanceStatus::Optimal);
1240    }
1241
1242    #[test]
1243    fn test_performance_violation_creation() {
1244        let violation = PerformanceViolation {
1245            metric: "latency".to_string(),
1246            expected: 50.0,
1247            actual: 100.0,
1248            severity: PerformanceIssueType::Major,
1249            description: "Latency too high".to_string(),
1250        };
1251
1252        assert_eq!(violation.metric, "latency");
1253        assert!((violation.actual - 100.0).abs() < f64::EPSILON);
1254    }
1255
1256    #[test]
1257    fn test_memory_snapshot_creation() {
1258        let snapshot = MemorySnapshot {
1259            memory_usage: 1024 * 1024,
1260            allocation_count: 100,
1261            timestamp: Instant::now(),
1262        };
1263
1264        assert_eq!(snapshot.memory_usage, 1024 * 1024);
1265        assert_eq!(snapshot.allocation_count, 100);
1266    }
1267
1268    #[test]
1269    fn test_leak_check_result_creation() {
1270        let result = LeakCheckResult {
1271            operation: "test".to_string(),
1272            leak_detected: true,
1273            severity: LeakSeverity::High,
1274            confidence: 0.85,
1275            indicators: vec![],
1276            growth_rate: 1024.0,
1277        };
1278
1279        assert!(result.leak_detected);
1280        assert_eq!(result.severity, LeakSeverity::High);
1281    }
1282
1283    #[test]
1284    fn test_leak_indicator_creation() {
1285        let indicator = LeakIndicator {
1286            indicator_type: "excessive_growth".to_string(),
1287            description: "Memory growing too fast".to_string(),
1288            severity: LeakSeverity::Medium,
1289        };
1290
1291        assert_eq!(indicator.indicator_type, "excessive_growth");
1292    }
1293
1294    #[test]
1295    fn test_check_performance_no_benchmark() {
1296        let checker = PerformanceChecker::new();
1297        let metrics = PerformanceMetrics {
1298            duration: Duration::from_micros(50),
1299            memory_usage: 1024,
1300            throughput: 1000.0,
1301            cpu_usage: 10.0,
1302        };
1303
1304        let result = checker.check_performance("unknown_operation", &metrics);
1305        assert!(matches!(
1306            result.status,
1307            PerformanceStatus::Optimal | PerformanceStatus::Acceptable
1308        ));
1309    }
1310
1311    #[test]
1312    fn test_check_performance_allocation_latency() {
1313        let checker = PerformanceChecker::new();
1314        let metrics = PerformanceMetrics {
1315            duration: Duration::from_micros(100), // Exceeds threshold
1316            memory_usage: 1024,
1317            throughput: 1000.0,
1318            cpu_usage: 10.0,
1319        };
1320
1321        let result = checker.check_performance("allocation_tracking", &metrics);
1322        assert!(matches!(
1323            result.status,
1324            PerformanceStatus::Critical | PerformanceStatus::Poor
1325        ));
1326    }
1327
1328    #[test]
1329    fn test_check_performance_symbol_resolution() {
1330        let checker = PerformanceChecker::new();
1331        let metrics = PerformanceMetrics {
1332            duration: Duration::from_millis(10), // Exceeds threshold
1333            memory_usage: 1024,
1334            throughput: 1000.0,
1335            cpu_usage: 10.0,
1336        };
1337
1338        let result = checker.check_performance("symbol_resolution", &metrics);
1339        assert!(matches!(
1340            result.status,
1341            PerformanceStatus::Poor | PerformanceStatus::Critical
1342        ));
1343    }
1344
1345    #[test]
1346    fn test_check_for_leaks_no_baseline() {
1347        let checker = MemoryLeakChecker::new();
1348        let snapshot = MemorySnapshot {
1349            memory_usage: 1024,
1350            allocation_count: 10,
1351            timestamp: Instant::now(),
1352        };
1353
1354        let result = checker.check_for_leaks("unknown_operation", &snapshot);
1355        assert!(!result.leak_detected);
1356        assert_eq!(result.severity, LeakSeverity::None);
1357        assert!((result.confidence - 0.0).abs() < f64::EPSILON);
1358    }
1359
1360    #[test]
1361    fn test_check_for_leaks_high_growth() {
1362        let mut checker = MemoryLeakChecker::new();
1363        checker.set_baseline("test", 1024, 10);
1364
1365        let snapshot = MemorySnapshot {
1366            memory_usage: 10 * 1024 * 1024, // 10MB growth
1367            allocation_count: 20,
1368            timestamp: Instant::now(),
1369        };
1370
1371        let result = checker.check_for_leaks("test", &snapshot);
1372        // High growth should trigger leak detection
1373        let _ = result;
1374    }
1375
1376    #[test]
1377    fn test_performance_checker_config() {
1378        let checker = PerformanceChecker::new();
1379        assert!(checker.config().deep_analysis);
1380    }
1381
1382    #[test]
1383    fn test_memory_leak_checker_config() {
1384        let checker = MemoryLeakChecker::new();
1385        assert!(checker.config().track_allocations);
1386    }
1387
1388    #[test]
1389    fn test_safety_checker_violation_patterns() {
1390        let checker = SafetyChecker {
1391            violation_patterns: vec![],
1392            safety_requirements: HashMap::new(),
1393            config: SafetyConfig::default(),
1394        };
1395        assert!(checker.violation_patterns().is_empty());
1396    }
1397
1398    #[test]
1399    fn test_safety_checker_safety_requirements() {
1400        let checker = SafetyChecker {
1401            violation_patterns: vec![],
1402            safety_requirements: HashMap::new(),
1403            config: SafetyConfig::default(),
1404        };
1405        assert!(checker.safety_requirements().is_empty());
1406    }
1407
1408    #[test]
1409    fn test_safety_checker_config() {
1410        let checker = SafetyChecker {
1411            violation_patterns: vec![],
1412            safety_requirements: HashMap::new(),
1413            config: SafetyConfig::default(),
1414        };
1415        assert!(checker.config().check_thread_safety);
1416    }
1417
1418    #[test]
1419    fn test_performance_score_calculation_no_violations() {
1420        let checker = PerformanceChecker::new();
1421        let metrics = PerformanceMetrics {
1422            duration: Duration::from_micros(10),
1423            memory_usage: 512,
1424            throughput: 2000.0,
1425            cpu_usage: 5.0,
1426        };
1427
1428        let result = checker.check_performance("test", &metrics);
1429        assert!((result.overall_score - 1.0).abs() < f64::EPSILON);
1430    }
1431
1432    #[test]
1433    fn test_performance_score_with_violations() {
1434        let mut checker = PerformanceChecker::new();
1435        let benchmark = PerformanceBenchmark {
1436            operation: "test".to_string(),
1437            expected_duration: Duration::from_micros(10),
1438            max_duration: Duration::from_micros(20),
1439            expected_memory: 512,
1440            max_memory: 1024,
1441            expected_throughput: 2000.0,
1442            min_throughput: 1000.0,
1443        };
1444        checker.add_benchmark(benchmark);
1445
1446        let metrics = PerformanceMetrics {
1447            duration: Duration::from_micros(50), // Exceeds max
1448            memory_usage: 2048,                  // Exceeds max
1449            throughput: 500.0,                   // Below min
1450            cpu_usage: 50.0,
1451        };
1452
1453        let result = checker.check_performance("test", &metrics);
1454        assert!(result.overall_score < 1.0);
1455    }
1456
1457    #[test]
1458    fn test_growth_pattern_equality() {
1459        assert_eq!(GrowthPattern::Constant, GrowthPattern::Constant);
1460        assert_ne!(GrowthPattern::Constant, GrowthPattern::Logarithmic);
1461    }
1462
1463    #[test]
1464    fn test_leak_sensitivity_equality() {
1465        assert_eq!(LeakSensitivity::Low, LeakSensitivity::Low);
1466        assert_ne!(LeakSensitivity::Low, LeakSensitivity::High);
1467    }
1468
1469    #[test]
1470    fn test_access_type_equality() {
1471        assert_eq!(AccessType::Read, AccessType::Read);
1472        assert_ne!(AccessType::Read, AccessType::Write);
1473    }
1474
1475    #[test]
1476    fn test_interaction_type_equality() {
1477        assert_eq!(InteractionType::SharedRead, InteractionType::SharedRead);
1478        assert_ne!(InteractionType::SharedRead, InteractionType::ExclusiveWrite);
1479    }
1480
1481    #[test]
1482    fn test_sync_mechanism_equality() {
1483        assert_eq!(SyncMechanism::Mutex, SyncMechanism::Mutex);
1484        assert_ne!(SyncMechanism::Mutex, SyncMechanism::RwLock);
1485    }
1486
1487    #[test]
1488    fn test_safety_property_equality() {
1489        assert_eq!(SafetyProperty::NoMemoryLeaks, SafetyProperty::NoMemoryLeaks);
1490        assert_ne!(SafetyProperty::NoMemoryLeaks, SafetyProperty::NoDataRaces);
1491    }
1492
1493    #[test]
1494    fn test_performance_status_equality() {
1495        assert_eq!(PerformanceStatus::Optimal, PerformanceStatus::Optimal);
1496        assert_ne!(PerformanceStatus::Optimal, PerformanceStatus::Critical);
1497    }
1498
1499    #[test]
1500    fn test_performance_issue_type_equality() {
1501        assert_eq!(PerformanceIssueType::Minor, PerformanceIssueType::Minor);
1502        assert_ne!(PerformanceIssueType::Minor, PerformanceIssueType::Major);
1503    }
1504
1505    #[test]
1506    fn test_debug_implementations() {
1507        let benchmark = PerformanceBenchmark {
1508            operation: "test".to_string(),
1509            expected_duration: Duration::from_micros(10),
1510            max_duration: Duration::from_micros(50),
1511            expected_memory: 1024,
1512            max_memory: 2048,
1513            expected_throughput: 1000.0,
1514            min_throughput: 500.0,
1515        };
1516
1517        let debug_str = format!("{:?}", benchmark);
1518        assert!(debug_str.contains("PerformanceBenchmark"));
1519    }
1520}