1use std::collections::HashMap;
2use std::time::{Duration, Instant};
3
4pub 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
17pub 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
30pub 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#[derive(Debug, Clone)]
51pub struct PerformanceBenchmark {
52 pub operation: String,
54 pub expected_duration: Duration,
56 pub max_duration: Duration,
58 pub expected_memory: usize,
60 pub max_memory: usize,
62 pub expected_throughput: f64,
64 pub min_throughput: f64,
66}
67
68#[derive(Debug, Clone)]
70pub struct PerformanceThresholds {
71 pub allocation_latency: Duration,
73 pub symbol_resolution: Duration,
75 pub stack_trace_capture: Duration,
77 pub memory_overhead_pct: f64,
79 pub min_completeness: f64,
81}
82
83#[derive(Debug, Clone)]
85pub struct MemoryBaseline {
86 pub initial_memory: usize,
88 pub growth_pattern: GrowthPattern,
90 pub timestamp: Instant,
92 pub allocation_count: usize,
94}
95
96#[derive(Debug, Clone, PartialEq)]
98pub enum GrowthPattern {
99 Constant,
101 Linear { bytes_per_allocation: f64 },
103 Logarithmic,
105 Stabilizing { max_growth: usize },
107 Custom { description: String },
109}
110
111#[derive(Debug, Clone, PartialEq)]
113pub enum LeakSensitivity {
114 Low,
116 Medium,
118 High,
120 Paranoid,
122}
123
124#[derive(Debug, Clone)]
126pub struct SafetyPattern {
127 pub id: String,
129 pub description: String,
131 pub detector: SafetyDetector,
133 pub severity: SafetySeverity,
135}
136
137pub type SafetyDetector = fn(&SafetyContext) -> Vec<SafetyViolation>;
139
140#[derive(Debug, Clone)]
142pub struct SafetyRequirement {
143 pub properties: Vec<SafetyProperty>,
145 pub thread_safe: bool,
147 pub error_handling: bool,
149 pub max_risk_level: RiskLevel,
151}
152
153#[derive(Debug, Clone, PartialEq)]
155pub enum SafetyProperty {
156 NoMemoryLeaks,
158 NoDataRaces,
160 NoUseAfterFree,
162 NoBufferOverflow,
164 ErrorPropagation,
166 ResourceCleanup,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
172pub enum SafetySeverity {
173 Low,
175 Medium,
177 High,
179 Critical,
181}
182
183#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
185pub enum RiskLevel {
186 Minimal,
188 Low,
190 Medium,
192 High,
194 Critical,
196}
197
198#[derive(Debug)]
200pub struct SafetyContext {
201 pub operation: String,
203 pub memory_accesses: Vec<MemoryAccess>,
205 pub thread_interactions: Vec<ThreadInteraction>,
207 pub error_handling: bool,
209 pub resource_usage: ResourceUsage,
211}
212
213#[derive(Debug, Clone)]
215pub struct MemoryAccess {
216 pub access_type: AccessType,
218 pub address: Option<usize>,
220 pub size: usize,
222 pub synchronized: bool,
224}
225
226#[derive(Debug, Clone, PartialEq)]
228pub enum AccessType {
229 Read,
231 Write,
233 Allocate,
235 Deallocate,
237}
238
239#[derive(Debug, Clone)]
241pub struct ThreadInteraction {
242 pub interaction_type: InteractionType,
244 pub resource_id: String,
246 pub synchronization: Option<SyncMechanism>,
248}
249
250#[derive(Debug, Clone, PartialEq)]
252pub enum InteractionType {
253 SharedRead,
255 ExclusiveWrite,
257 MessagePassing,
259 LockAcquisition,
261}
262
263#[derive(Debug, Clone, PartialEq)]
265pub enum SyncMechanism {
266 Mutex,
268 RwLock,
270 Atomic,
272 LockFree,
274 None,
276}
277
278#[derive(Debug, Clone)]
280pub struct ResourceUsage {
281 pub memory_bytes: usize,
283 pub file_descriptors: usize,
285 pub network_connections: usize,
287 pub cpu_time: Duration,
289}
290
291#[derive(Debug, Clone)]
293pub struct SafetyViolation {
294 pub violation_type: String,
296 pub severity: SafetySeverity,
298 pub description: String,
300 pub suggestion: String,
302 pub location: Option<String>,
304}
305
306#[derive(Debug, Clone)]
308pub struct CheckerConfig {
309 pub deep_analysis: bool,
311 pub max_check_time: Duration,
313 pub realtime_checking: bool,
315 pub sample_rate: f64,
317}
318
319#[derive(Debug, Clone)]
321pub struct LeakDetectionConfig {
322 pub measurement_interval: Duration,
324 pub measurement_history: usize,
326 pub growth_threshold: f64,
328 pub track_allocations: bool,
330}
331
332#[derive(Debug, Clone)]
334pub struct SafetyConfig {
335 pub enabled_patterns: Vec<String>,
337 pub min_severity: SafetySeverity,
339 pub check_thread_safety: bool,
341 pub check_memory_safety: bool,
343}
344
345impl PerformanceChecker {
346 pub fn new() -> Self {
348 Self {
349 benchmarks: HashMap::new(),
350 thresholds: PerformanceThresholds::default(),
351 config: CheckerConfig::default(),
352 }
353 }
354
355 pub fn add_benchmark(&mut self, benchmark: PerformanceBenchmark) {
357 self.benchmarks
358 .insert(benchmark.operation.clone(), benchmark);
359 }
360
361 pub fn check_performance(
363 &self,
364 operation: &str,
365 actual: &PerformanceMetrics,
366 ) -> PerformanceCheckResult {
367 let mut violations = Vec::new();
368
369 if let Some(benchmark) = self.benchmarks.get(operation) {
371 violations.extend(self.check_against_benchmark(benchmark, actual));
372 }
373
374 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 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 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 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 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 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 pub fn new() -> Self {
514 Self {
515 baseline_measurements: HashMap::new(),
516 config: LeakDetectionConfig::default(),
517 sensitivity: LeakSensitivity::Medium,
518 }
519 }
520
521 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 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 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 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 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#[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
704impl 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, 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", ¤t);
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), 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), 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, allocation_count: 20,
1368 timestamp: Instant::now(),
1369 };
1370
1371 let result = checker.check_for_leaks("test", &snapshot);
1372 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), memory_usage: 2048, throughput: 500.0, 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}