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)]
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
709impl 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, 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", ¤t);
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), 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), 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, allocation_count: 20,
1373 timestamp: Instant::now(),
1374 };
1375
1376 let result = checker.check_for_leaks("test", &snapshot);
1377 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), memory_usage: 2048, throughput: 500.0, 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}