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/// One of several same-named `MemorySnapshot` types in this crate: this one is the
672/// the quality-checker snapshot used for integrity validation.
673///
674/// Convert at the module boundary instead of passing it across; a global rename is
675/// deliberately avoided (see DATA_ACCURACY_DEVELOPMENT_PLAN §14.2).
676#[derive(Debug, Clone)]
677pub struct MemorySnapshot {
678    pub memory_usage: usize,
679    pub allocation_count: usize,
680    pub timestamp: Instant,
681}
682
683#[derive(Debug, Clone)]
684pub struct LeakCheckResult {
685    pub operation: String,
686    pub leak_detected: bool,
687    pub severity: LeakSeverity,
688    pub confidence: f64,
689    pub indicators: Vec<LeakIndicator>,
690    pub growth_rate: f64,
691}
692
693#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
694pub enum LeakSeverity {
695    None,
696    Low,
697    Medium,
698    High,
699    Critical,
700}
701
702#[derive(Debug, Clone)]
703pub struct LeakIndicator {
704    pub indicator_type: String,
705    pub description: String,
706    pub severity: LeakSeverity,
707}
708
709// Default implementations
710impl Default for PerformanceThresholds {
711    fn default() -> Self {
712        Self {
713            allocation_latency: Duration::from_micros(50),
714            symbol_resolution: Duration::from_millis(5),
715            stack_trace_capture: Duration::from_millis(10),
716            memory_overhead_pct: 5.0,
717            min_completeness: 0.95,
718        }
719    }
720}
721
722impl Default for CheckerConfig {
723    fn default() -> Self {
724        Self {
725            deep_analysis: true,
726            max_check_time: Duration::from_secs(5),
727            realtime_checking: false,
728            sample_rate: 0.1,
729        }
730    }
731}
732
733impl Default for LeakDetectionConfig {
734    fn default() -> Self {
735        Self {
736            measurement_interval: Duration::from_secs(60),
737            measurement_history: 100,
738            growth_threshold: 1024.0 * 1024.0, // 1MB/sec
739            track_allocations: true,
740        }
741    }
742}
743
744impl Default for SafetyConfig {
745    fn default() -> Self {
746        Self {
747            enabled_patterns: vec![
748                "memory_safety".to_string(),
749                "thread_safety".to_string(),
750                "error_handling".to_string(),
751            ],
752            min_severity: SafetySeverity::Low,
753            check_thread_safety: true,
754            check_memory_safety: true,
755        }
756    }
757}
758
759impl Default for PerformanceChecker {
760    fn default() -> Self {
761        Self::new()
762    }
763}
764
765impl Default for MemoryLeakChecker {
766    fn default() -> Self {
767        Self::new()
768    }
769}
770
771#[cfg(test)]
772mod tests {
773    use super::*;
774
775    #[test]
776    fn test_performance_checker() {
777        let mut checker = PerformanceChecker::new();
778
779        let benchmark = PerformanceBenchmark {
780            operation: "allocation_tracking".to_string(),
781            expected_duration: Duration::from_micros(10),
782            max_duration: Duration::from_micros(50),
783            expected_memory: 1024,
784            max_memory: 2048,
785            expected_throughput: 10000.0,
786            min_throughput: 5000.0,
787        };
788
789        checker.add_benchmark(benchmark);
790
791        let good_metrics = PerformanceMetrics {
792            duration: Duration::from_micros(20),
793            memory_usage: 1500,
794            throughput: 8000.0,
795            cpu_usage: 5.0,
796        };
797
798        let result = checker.check_performance("allocation_tracking", &good_metrics);
799        assert!(matches!(
800            result.status,
801            PerformanceStatus::Optimal | PerformanceStatus::Acceptable
802        ));
803
804        let bad_metrics = PerformanceMetrics {
805            duration: Duration::from_micros(100),
806            memory_usage: 3000,
807            throughput: 1000.0,
808            cpu_usage: 50.0,
809        };
810
811        let result = checker.check_performance("allocation_tracking", &bad_metrics);
812        assert!(matches!(
813            result.status,
814            PerformanceStatus::Poor | PerformanceStatus::Critical
815        ));
816        assert!(!result.violations.is_empty());
817    }
818
819    #[test]
820    fn test_memory_leak_checker() {
821        let mut checker = MemoryLeakChecker::new();
822
823        checker.set_baseline("test_operation", 1024 * 1024, 100);
824
825        let current = MemorySnapshot {
826            memory_usage: 1200 * 1024,
827            allocation_count: 120,
828            timestamp: Instant::now(),
829        };
830
831        let result = checker.check_for_leaks("test_operation", &current);
832        let _ = result;
833    }
834
835    #[test]
836    fn test_growth_patterns() {
837        assert_eq!(GrowthPattern::Constant, GrowthPattern::Constant);
838
839        let linear = GrowthPattern::Linear {
840            bytes_per_allocation: 64.0,
841        };
842        assert!(matches!(linear, GrowthPattern::Linear { .. }));
843    }
844
845    #[test]
846    fn test_performance_checker_default() {
847        let checker = PerformanceChecker::default();
848        assert!(checker.benchmarks.is_empty());
849    }
850
851    #[test]
852    fn test_memory_leak_checker_default() {
853        let checker = MemoryLeakChecker::default();
854        assert!(checker.baseline_measurements.is_empty());
855    }
856
857    #[test]
858    fn test_checker_config_default() {
859        let config = CheckerConfig::default();
860        assert!(config.deep_analysis);
861        assert_eq!(config.max_check_time, Duration::from_secs(5));
862        assert!(!config.realtime_checking);
863        assert!((config.sample_rate - 0.1).abs() < f64::EPSILON);
864    }
865
866    #[test]
867    fn test_leak_detection_config_default() {
868        let config = LeakDetectionConfig::default();
869        assert_eq!(config.measurement_interval, Duration::from_secs(60));
870        assert_eq!(config.measurement_history, 100);
871        assert!((config.growth_threshold - 1024.0 * 1024.0).abs() < f64::EPSILON);
872        assert!(config.track_allocations);
873    }
874
875    #[test]
876    fn test_safety_config_default() {
877        let config = SafetyConfig::default();
878        assert_eq!(config.enabled_patterns.len(), 3);
879        assert_eq!(config.min_severity, SafetySeverity::Low);
880        assert!(config.check_thread_safety);
881        assert!(config.check_memory_safety);
882    }
883
884    #[test]
885    fn test_performance_thresholds_default() {
886        let thresholds = PerformanceThresholds::default();
887        assert_eq!(thresholds.allocation_latency, Duration::from_micros(50));
888        assert_eq!(thresholds.symbol_resolution, Duration::from_millis(5));
889        assert_eq!(thresholds.stack_trace_capture, Duration::from_millis(10));
890        assert!((thresholds.memory_overhead_pct - 5.0).abs() < f64::EPSILON);
891        assert!((thresholds.min_completeness - 0.95).abs() < f64::EPSILON);
892    }
893
894    #[test]
895    fn test_leak_sensitivity_variants() {
896        let sensitivities = vec![
897            LeakSensitivity::Low,
898            LeakSensitivity::Medium,
899            LeakSensitivity::High,
900            LeakSensitivity::Paranoid,
901        ];
902
903        for sensitivity in sensitivities {
904            let checker = MemoryLeakChecker {
905                baseline_measurements: HashMap::new(),
906                config: LeakDetectionConfig::default(),
907                sensitivity: sensitivity.clone(),
908            };
909            assert_eq!(checker.sensitivity, sensitivity);
910        }
911    }
912
913    #[test]
914    fn test_growth_pattern_variants() {
915        let patterns = vec![
916            GrowthPattern::Constant,
917            GrowthPattern::Linear {
918                bytes_per_allocation: 64.0,
919            },
920            GrowthPattern::Logarithmic,
921            GrowthPattern::Stabilizing { max_growth: 1024 },
922            GrowthPattern::Custom {
923                description: "custom".to_string(),
924            },
925        ];
926
927        for pattern in patterns {
928            let baseline = MemoryBaseline {
929                initial_memory: 1024,
930                growth_pattern: pattern.clone(),
931                timestamp: Instant::now(),
932                allocation_count: 10,
933            };
934            assert_eq!(baseline.growth_pattern, pattern);
935        }
936    }
937
938    #[test]
939    fn test_safety_severity_ordering() {
940        assert!(SafetySeverity::Critical > SafetySeverity::High);
941        assert!(SafetySeverity::High > SafetySeverity::Medium);
942        assert!(SafetySeverity::Medium > SafetySeverity::Low);
943    }
944
945    #[test]
946    fn test_risk_level_ordering() {
947        assert!(RiskLevel::Critical > RiskLevel::High);
948        assert!(RiskLevel::High > RiskLevel::Medium);
949        assert!(RiskLevel::Medium > RiskLevel::Low);
950        assert!(RiskLevel::Low > RiskLevel::Minimal);
951    }
952
953    #[test]
954    fn test_leak_severity_ordering() {
955        assert!(LeakSeverity::Critical > LeakSeverity::High);
956        assert!(LeakSeverity::High > LeakSeverity::Medium);
957        assert!(LeakSeverity::Medium > LeakSeverity::Low);
958        assert!(LeakSeverity::Low > LeakSeverity::None);
959    }
960
961    #[test]
962    fn test_access_type_variants() {
963        let access_types = vec![
964            AccessType::Read,
965            AccessType::Write,
966            AccessType::Allocate,
967            AccessType::Deallocate,
968        ];
969
970        for access_type in access_types {
971            let access = MemoryAccess {
972                access_type: access_type.clone(),
973                address: Some(0x1000),
974                size: 64,
975                synchronized: true,
976            };
977            assert_eq!(access.access_type, access_type);
978        }
979    }
980
981    #[test]
982    fn test_interaction_type_variants() {
983        let interaction_types = vec![
984            InteractionType::SharedRead,
985            InteractionType::ExclusiveWrite,
986            InteractionType::MessagePassing,
987            InteractionType::LockAcquisition,
988        ];
989
990        for interaction_type in interaction_types {
991            let interaction = ThreadInteraction {
992                interaction_type: interaction_type.clone(),
993                resource_id: "test".to_string(),
994                synchronization: None,
995            };
996            assert_eq!(interaction.interaction_type, interaction_type);
997        }
998    }
999
1000    #[test]
1001    fn test_sync_mechanism_variants() {
1002        let mechanisms = vec![
1003            SyncMechanism::Mutex,
1004            SyncMechanism::RwLock,
1005            SyncMechanism::Atomic,
1006            SyncMechanism::LockFree,
1007            SyncMechanism::None,
1008        ];
1009
1010        for mechanism in mechanisms {
1011            let interaction = ThreadInteraction {
1012                interaction_type: InteractionType::LockAcquisition,
1013                resource_id: "test".to_string(),
1014                synchronization: Some(mechanism.clone()),
1015            };
1016            assert_eq!(interaction.synchronization, Some(mechanism));
1017        }
1018    }
1019
1020    #[test]
1021    fn test_safety_property_variants() {
1022        let properties = vec![
1023            SafetyProperty::NoMemoryLeaks,
1024            SafetyProperty::NoDataRaces,
1025            SafetyProperty::NoUseAfterFree,
1026            SafetyProperty::NoBufferOverflow,
1027            SafetyProperty::ErrorPropagation,
1028            SafetyProperty::ResourceCleanup,
1029        ];
1030
1031        for property in properties {
1032            let requirement = SafetyRequirement {
1033                properties: vec![property.clone()],
1034                thread_safe: true,
1035                error_handling: true,
1036                max_risk_level: RiskLevel::Low,
1037            };
1038            assert!(requirement.properties.contains(&property));
1039        }
1040    }
1041
1042    #[test]
1043    fn test_performance_status_variants() {
1044        let statuses = vec![
1045            PerformanceStatus::Optimal,
1046            PerformanceStatus::Acceptable,
1047            PerformanceStatus::Poor,
1048            PerformanceStatus::Critical,
1049        ];
1050
1051        for status in statuses {
1052            let result = PerformanceCheckResult {
1053                operation: "test".to_string(),
1054                status: status.clone(),
1055                violations: vec![],
1056                overall_score: 1.0,
1057            };
1058            assert_eq!(result.status, status);
1059        }
1060    }
1061
1062    #[test]
1063    fn test_performance_issue_type_variants() {
1064        let issue_types = vec![
1065            PerformanceIssueType::Minor,
1066            PerformanceIssueType::Major,
1067            PerformanceIssueType::Critical,
1068        ];
1069
1070        for issue_type in issue_types {
1071            let violation = PerformanceViolation {
1072                metric: "test".to_string(),
1073                expected: 100.0,
1074                actual: 200.0,
1075                severity: issue_type.clone(),
1076                description: "test".to_string(),
1077            };
1078            assert_eq!(violation.severity, issue_type);
1079        }
1080    }
1081
1082    #[test]
1083    fn test_performance_benchmark_creation() {
1084        let benchmark = PerformanceBenchmark {
1085            operation: "test_op".to_string(),
1086            expected_duration: Duration::from_micros(10),
1087            max_duration: Duration::from_micros(50),
1088            expected_memory: 1024,
1089            max_memory: 2048,
1090            expected_throughput: 1000.0,
1091            min_throughput: 500.0,
1092        };
1093
1094        assert_eq!(benchmark.operation, "test_op");
1095        assert_eq!(benchmark.expected_memory, 1024);
1096    }
1097
1098    #[test]
1099    fn test_memory_baseline_creation() {
1100        let baseline = MemoryBaseline {
1101            initial_memory: 1024 * 1024,
1102            growth_pattern: GrowthPattern::Constant,
1103            timestamp: Instant::now(),
1104            allocation_count: 100,
1105        };
1106
1107        assert_eq!(baseline.initial_memory, 1024 * 1024);
1108        assert_eq!(baseline.allocation_count, 100);
1109    }
1110
1111    #[test]
1112    fn test_safety_pattern_creation() {
1113        fn test_detector(_ctx: &SafetyContext) -> Vec<SafetyViolation> {
1114            vec![]
1115        }
1116
1117        let pattern = SafetyPattern {
1118            id: "test_pattern".to_string(),
1119            description: "Test pattern".to_string(),
1120            detector: test_detector,
1121            severity: SafetySeverity::Medium,
1122        };
1123
1124        assert_eq!(pattern.id, "test_pattern");
1125        assert_eq!(pattern.severity, SafetySeverity::Medium);
1126    }
1127
1128    #[test]
1129    fn test_safety_requirement_creation() {
1130        let requirement = SafetyRequirement {
1131            properties: vec![SafetyProperty::NoMemoryLeaks, SafetyProperty::NoDataRaces],
1132            thread_safe: true,
1133            error_handling: true,
1134            max_risk_level: RiskLevel::Medium,
1135        };
1136
1137        assert_eq!(requirement.properties.len(), 2);
1138        assert!(requirement.thread_safe);
1139    }
1140
1141    #[test]
1142    fn test_safety_context_creation() {
1143        let context = SafetyContext {
1144            operation: "test_op".to_string(),
1145            memory_accesses: vec![MemoryAccess {
1146                access_type: AccessType::Read,
1147                address: Some(0x1000),
1148                size: 64,
1149                synchronized: true,
1150            }],
1151            thread_interactions: vec![],
1152            error_handling: true,
1153            resource_usage: ResourceUsage {
1154                memory_bytes: 1024,
1155                file_descriptors: 2,
1156                network_connections: 1,
1157                cpu_time: Duration::from_millis(100),
1158            },
1159        };
1160
1161        assert_eq!(context.operation, "test_op");
1162        assert_eq!(context.memory_accesses.len(), 1);
1163    }
1164
1165    #[test]
1166    fn test_memory_access_creation() {
1167        let access = MemoryAccess {
1168            access_type: AccessType::Write,
1169            address: Some(0x2000),
1170            size: 128,
1171            synchronized: false,
1172        };
1173
1174        assert_eq!(access.access_type, AccessType::Write);
1175        assert_eq!(access.size, 128);
1176        assert!(!access.synchronized);
1177    }
1178
1179    #[test]
1180    fn test_thread_interaction_creation() {
1181        let interaction = ThreadInteraction {
1182            interaction_type: InteractionType::ExclusiveWrite,
1183            resource_id: "shared_data".to_string(),
1184            synchronization: Some(SyncMechanism::Mutex),
1185        };
1186
1187        assert_eq!(
1188            interaction.interaction_type,
1189            InteractionType::ExclusiveWrite
1190        );
1191        assert_eq!(interaction.resource_id, "shared_data");
1192    }
1193
1194    #[test]
1195    fn test_resource_usage_creation() {
1196        let usage = ResourceUsage {
1197            memory_bytes: 1024 * 1024,
1198            file_descriptors: 5,
1199            network_connections: 2,
1200            cpu_time: Duration::from_secs(1),
1201        };
1202
1203        assert_eq!(usage.memory_bytes, 1024 * 1024);
1204        assert_eq!(usage.file_descriptors, 5);
1205    }
1206
1207    #[test]
1208    fn test_safety_violation_creation() {
1209        let violation = SafetyViolation {
1210            violation_type: "use_after_free".to_string(),
1211            severity: SafetySeverity::Critical,
1212            description: "Memory accessed after free".to_string(),
1213            suggestion: "Check lifetime".to_string(),
1214            location: Some("test.rs:42".to_string()),
1215        };
1216
1217        assert_eq!(violation.violation_type, "use_after_free");
1218        assert_eq!(violation.severity, SafetySeverity::Critical);
1219    }
1220
1221    #[test]
1222    fn test_performance_metrics_creation() {
1223        let metrics = PerformanceMetrics {
1224            duration: Duration::from_micros(50),
1225            memory_usage: 2048,
1226            throughput: 1000.0,
1227            cpu_usage: 25.0,
1228        };
1229
1230        assert_eq!(metrics.duration, Duration::from_micros(50));
1231        assert_eq!(metrics.memory_usage, 2048);
1232    }
1233
1234    #[test]
1235    fn test_performance_check_result_creation() {
1236        let result = PerformanceCheckResult {
1237            operation: "test".to_string(),
1238            status: PerformanceStatus::Optimal,
1239            violations: vec![],
1240            overall_score: 1.0,
1241        };
1242
1243        assert_eq!(result.operation, "test");
1244        assert_eq!(result.status, PerformanceStatus::Optimal);
1245    }
1246
1247    #[test]
1248    fn test_performance_violation_creation() {
1249        let violation = PerformanceViolation {
1250            metric: "latency".to_string(),
1251            expected: 50.0,
1252            actual: 100.0,
1253            severity: PerformanceIssueType::Major,
1254            description: "Latency too high".to_string(),
1255        };
1256
1257        assert_eq!(violation.metric, "latency");
1258        assert!((violation.actual - 100.0).abs() < f64::EPSILON);
1259    }
1260
1261    #[test]
1262    fn test_memory_snapshot_creation() {
1263        let snapshot = MemorySnapshot {
1264            memory_usage: 1024 * 1024,
1265            allocation_count: 100,
1266            timestamp: Instant::now(),
1267        };
1268
1269        assert_eq!(snapshot.memory_usage, 1024 * 1024);
1270        assert_eq!(snapshot.allocation_count, 100);
1271    }
1272
1273    #[test]
1274    fn test_leak_check_result_creation() {
1275        let result = LeakCheckResult {
1276            operation: "test".to_string(),
1277            leak_detected: true,
1278            severity: LeakSeverity::High,
1279            confidence: 0.85,
1280            indicators: vec![],
1281            growth_rate: 1024.0,
1282        };
1283
1284        assert!(result.leak_detected);
1285        assert_eq!(result.severity, LeakSeverity::High);
1286    }
1287
1288    #[test]
1289    fn test_leak_indicator_creation() {
1290        let indicator = LeakIndicator {
1291            indicator_type: "excessive_growth".to_string(),
1292            description: "Memory growing too fast".to_string(),
1293            severity: LeakSeverity::Medium,
1294        };
1295
1296        assert_eq!(indicator.indicator_type, "excessive_growth");
1297    }
1298
1299    #[test]
1300    fn test_check_performance_no_benchmark() {
1301        let checker = PerformanceChecker::new();
1302        let metrics = PerformanceMetrics {
1303            duration: Duration::from_micros(50),
1304            memory_usage: 1024,
1305            throughput: 1000.0,
1306            cpu_usage: 10.0,
1307        };
1308
1309        let result = checker.check_performance("unknown_operation", &metrics);
1310        assert!(matches!(
1311            result.status,
1312            PerformanceStatus::Optimal | PerformanceStatus::Acceptable
1313        ));
1314    }
1315
1316    #[test]
1317    fn test_check_performance_allocation_latency() {
1318        let checker = PerformanceChecker::new();
1319        let metrics = PerformanceMetrics {
1320            duration: Duration::from_micros(100), // Exceeds threshold
1321            memory_usage: 1024,
1322            throughput: 1000.0,
1323            cpu_usage: 10.0,
1324        };
1325
1326        let result = checker.check_performance("allocation_tracking", &metrics);
1327        assert!(matches!(
1328            result.status,
1329            PerformanceStatus::Critical | PerformanceStatus::Poor
1330        ));
1331    }
1332
1333    #[test]
1334    fn test_check_performance_symbol_resolution() {
1335        let checker = PerformanceChecker::new();
1336        let metrics = PerformanceMetrics {
1337            duration: Duration::from_millis(10), // Exceeds threshold
1338            memory_usage: 1024,
1339            throughput: 1000.0,
1340            cpu_usage: 10.0,
1341        };
1342
1343        let result = checker.check_performance("symbol_resolution", &metrics);
1344        assert!(matches!(
1345            result.status,
1346            PerformanceStatus::Poor | PerformanceStatus::Critical
1347        ));
1348    }
1349
1350    #[test]
1351    fn test_check_for_leaks_no_baseline() {
1352        let checker = MemoryLeakChecker::new();
1353        let snapshot = MemorySnapshot {
1354            memory_usage: 1024,
1355            allocation_count: 10,
1356            timestamp: Instant::now(),
1357        };
1358
1359        let result = checker.check_for_leaks("unknown_operation", &snapshot);
1360        assert!(!result.leak_detected);
1361        assert_eq!(result.severity, LeakSeverity::None);
1362        assert!((result.confidence - 0.0).abs() < f64::EPSILON);
1363    }
1364
1365    #[test]
1366    fn test_check_for_leaks_high_growth() {
1367        let mut checker = MemoryLeakChecker::new();
1368        checker.set_baseline("test", 1024, 10);
1369
1370        let snapshot = MemorySnapshot {
1371            memory_usage: 10 * 1024 * 1024, // 10MB growth
1372            allocation_count: 20,
1373            timestamp: Instant::now(),
1374        };
1375
1376        let result = checker.check_for_leaks("test", &snapshot);
1377        // High growth should trigger leak detection
1378        let _ = result;
1379    }
1380
1381    #[test]
1382    fn test_performance_checker_config() {
1383        let checker = PerformanceChecker::new();
1384        assert!(checker.config().deep_analysis);
1385    }
1386
1387    #[test]
1388    fn test_memory_leak_checker_config() {
1389        let checker = MemoryLeakChecker::new();
1390        assert!(checker.config().track_allocations);
1391    }
1392
1393    #[test]
1394    fn test_safety_checker_violation_patterns() {
1395        let checker = SafetyChecker {
1396            violation_patterns: vec![],
1397            safety_requirements: HashMap::new(),
1398            config: SafetyConfig::default(),
1399        };
1400        assert!(checker.violation_patterns().is_empty());
1401    }
1402
1403    #[test]
1404    fn test_safety_checker_safety_requirements() {
1405        let checker = SafetyChecker {
1406            violation_patterns: vec![],
1407            safety_requirements: HashMap::new(),
1408            config: SafetyConfig::default(),
1409        };
1410        assert!(checker.safety_requirements().is_empty());
1411    }
1412
1413    #[test]
1414    fn test_safety_checker_config() {
1415        let checker = SafetyChecker {
1416            violation_patterns: vec![],
1417            safety_requirements: HashMap::new(),
1418            config: SafetyConfig::default(),
1419        };
1420        assert!(checker.config().check_thread_safety);
1421    }
1422
1423    #[test]
1424    fn test_performance_score_calculation_no_violations() {
1425        let checker = PerformanceChecker::new();
1426        let metrics = PerformanceMetrics {
1427            duration: Duration::from_micros(10),
1428            memory_usage: 512,
1429            throughput: 2000.0,
1430            cpu_usage: 5.0,
1431        };
1432
1433        let result = checker.check_performance("test", &metrics);
1434        assert!((result.overall_score - 1.0).abs() < f64::EPSILON);
1435    }
1436
1437    #[test]
1438    fn test_performance_score_with_violations() {
1439        let mut checker = PerformanceChecker::new();
1440        let benchmark = PerformanceBenchmark {
1441            operation: "test".to_string(),
1442            expected_duration: Duration::from_micros(10),
1443            max_duration: Duration::from_micros(20),
1444            expected_memory: 512,
1445            max_memory: 1024,
1446            expected_throughput: 2000.0,
1447            min_throughput: 1000.0,
1448        };
1449        checker.add_benchmark(benchmark);
1450
1451        let metrics = PerformanceMetrics {
1452            duration: Duration::from_micros(50), // Exceeds max
1453            memory_usage: 2048,                  // Exceeds max
1454            throughput: 500.0,                   // Below min
1455            cpu_usage: 50.0,
1456        };
1457
1458        let result = checker.check_performance("test", &metrics);
1459        assert!(result.overall_score < 1.0);
1460    }
1461
1462    #[test]
1463    fn test_growth_pattern_equality() {
1464        assert_eq!(GrowthPattern::Constant, GrowthPattern::Constant);
1465        assert_ne!(GrowthPattern::Constant, GrowthPattern::Logarithmic);
1466    }
1467
1468    #[test]
1469    fn test_leak_sensitivity_equality() {
1470        assert_eq!(LeakSensitivity::Low, LeakSensitivity::Low);
1471        assert_ne!(LeakSensitivity::Low, LeakSensitivity::High);
1472    }
1473
1474    #[test]
1475    fn test_access_type_equality() {
1476        assert_eq!(AccessType::Read, AccessType::Read);
1477        assert_ne!(AccessType::Read, AccessType::Write);
1478    }
1479
1480    #[test]
1481    fn test_interaction_type_equality() {
1482        assert_eq!(InteractionType::SharedRead, InteractionType::SharedRead);
1483        assert_ne!(InteractionType::SharedRead, InteractionType::ExclusiveWrite);
1484    }
1485
1486    #[test]
1487    fn test_sync_mechanism_equality() {
1488        assert_eq!(SyncMechanism::Mutex, SyncMechanism::Mutex);
1489        assert_ne!(SyncMechanism::Mutex, SyncMechanism::RwLock);
1490    }
1491
1492    #[test]
1493    fn test_safety_property_equality() {
1494        assert_eq!(SafetyProperty::NoMemoryLeaks, SafetyProperty::NoMemoryLeaks);
1495        assert_ne!(SafetyProperty::NoMemoryLeaks, SafetyProperty::NoDataRaces);
1496    }
1497
1498    #[test]
1499    fn test_performance_status_equality() {
1500        assert_eq!(PerformanceStatus::Optimal, PerformanceStatus::Optimal);
1501        assert_ne!(PerformanceStatus::Optimal, PerformanceStatus::Critical);
1502    }
1503
1504    #[test]
1505    fn test_performance_issue_type_equality() {
1506        assert_eq!(PerformanceIssueType::Minor, PerformanceIssueType::Minor);
1507        assert_ne!(PerformanceIssueType::Minor, PerformanceIssueType::Major);
1508    }
1509
1510    #[test]
1511    fn test_debug_implementations() {
1512        let benchmark = PerformanceBenchmark {
1513            operation: "test".to_string(),
1514            expected_duration: Duration::from_micros(10),
1515            max_duration: Duration::from_micros(50),
1516            expected_memory: 1024,
1517            max_memory: 2048,
1518            expected_throughput: 1000.0,
1519            min_throughput: 500.0,
1520        };
1521
1522        let debug_str = format!("{:?}", benchmark);
1523        assert!(debug_str.contains("PerformanceBenchmark"));
1524    }
1525}