1pub mod detectors;
16
17pub mod circular_reference;
18pub mod heap_scanner;
19pub mod relation_inference;
20pub mod unsafe_ffi_tracker;
21pub mod unsafe_inference;
22pub mod variable_relationships;
23
24pub mod closure;
26pub mod generic;
27pub mod safety;
28pub mod security;
29pub mod unknown;
30
31pub mod async_analysis;
33pub mod borrow_analysis;
34
35pub mod ffi_function_resolver;
36pub mod lifecycle;
37pub mod lifecycle_analysis;
38pub mod memory_passport_tracker;
39
40pub mod classification;
42pub mod estimation;
43pub mod metrics;
44pub mod quality;
45
46pub use circular_reference::{CircularReference, CircularReferenceAnalysis, CircularReferenceNode};
48pub use unsafe_ffi_tracker::UnsafeFFITracker;
49pub use variable_relationships::{
50 build_variable_relationship_graph, GraphStatistics, RelationshipType as VarRelationshipType,
51 SmartPointerInfo as VarSmartPointerInfo, VariableCategory, VariableCluster, VariableNode,
52 VariableRelationship, VariableRelationshipGraph,
53};
54
55pub mod relationship_cycle_detector;
57pub use relationship_cycle_detector::{detect_cycles_in_relationships, CycleDetectionResult};
58
59pub mod ownership_graph;
61pub use ownership_graph::{Edge, EdgeKind, Node, ObjectId, OwnershipGraph, OwnershipOp};
62
63pub use detectors::{
65 Detector, LeakDetector, LeakDetectorConfig, LifecycleDetector, LifecycleDetectorConfig,
66 OverflowDetector, OverflowDetectorConfig, SafetyDetector, SafetyDetectorConfig, UafDetector,
67 UafDetectorConfig,
68};
69
70pub use async_analysis::{
71 get_global_async_analyzer, AsyncAnalyzer, AsyncPatternAnalysis, AsyncStatistics,
72};
73pub use borrow_analysis::{get_global_borrow_analyzer, BorrowAnalyzer, BorrowPatternAnalysis};
74pub use closure::{get_global_closure_analyzer, ClosureAnalysisReport, ClosureAnalyzer};
75pub use ffi_function_resolver::{
76 get_global_ffi_resolver, initialize_global_ffi_resolver, FfiFunctionCategory,
77 FfiFunctionResolver, FfiRiskLevel, ResolutionStats, ResolvedFfiFunction, ResolverConfig,
78};
79pub use generic::{get_global_generic_analyzer, GenericAnalyzer, GenericStatistics};
80pub use lifecycle::{
81 lifecycle_summary::{
82 AllocationLifecycleSummary, ExportMetadata, LifecycleEvent, LifecycleEventSummary,
83 LifecycleExportData, LifecyclePattern, LifecycleSummaryGenerator, SummaryConfig,
84 VariableGroup,
85 },
86 ownership_history::{
87 BorrowInfo, CloneInfo, OwnershipEvent, OwnershipEventType, OwnershipHistoryRecorder,
88 OwnershipStatistics, OwnershipSummary, RefCountInfo,
89 },
90};
91pub use lifecycle_analysis::{
92 get_global_lifecycle_analyzer, LifecycleAnalysisReport, LifecycleAnalyzer,
93};
94pub use memory_passport_tracker::{
95 get_global_passport_tracker, initialize_global_passport_tracker, LeakDetail,
96 LeakDetectionResult, MemoryPassport, MemoryPassportTracker, PassportEvent, PassportEventType,
97 PassportStatus, PassportTrackerConfig, PassportTrackerStats,
98};
99pub use safety::{
100 DynamicViolation, RiskAssessment, RiskFactor, RiskFactorType, SafetyAnalysisConfig,
101 SafetyAnalysisStats, SafetyAnalyzer, UnsafeReport, UnsafeSource,
102};
103pub use unsafe_ffi_tracker::ComprehensiveSafetyReport;
104pub use unsafe_inference::{
105 count_valid_pointers, get_valid_regions, is_valid_ptr, is_valid_ptr_static, InferenceMethod,
106 InferenceRecord, MemoryRegion, MemoryView, TypeGuess, TypeKind, UnsafeInferenceEngine,
107 ValidRegions,
108};
109
110pub use heap_scanner::{HeapScanner, ScanResult};
112
113pub use relation_inference::{
115 detect_clones, detect_owner, detect_slice, CloneConfig, GraphBuilderConfig, RangeMap, Relation,
116 RelationEdge, RelationGraph, RelationGraphBuilder,
117};
118
119pub use classification::{
121 pattern_matcher::PatternMatcher,
122 rule_engine::{Rule as ClassificationRule, RuleEngine},
123 type_classifier::{TypeCategory, TypeClassifier},
124};
125pub use estimation::{
126 size_estimator::SizeEstimator, type_classifier::TypeClassifier as EstimationTypeClassifier,
127};
128pub use metrics::{
129 analyzer::{Benchmark, PerformanceAnalyzer, PerformanceReport},
130 collector::{Metric, MetricType, MetricValue, MetricsCollector},
131 reporter::{AlertThreshold, MetricsReporter, ReportFormat},
132};
133pub use quality::{
134 analyzer::{AnalysisReport, CodeAnalyzer, QualityMetric},
135 checker::{MemoryLeakChecker, PerformanceChecker, SafetyChecker},
136 validator::{QualityValidator, ValidationResult, ValidationRule},
137};
138
139use crate::capture::types::stats::FragmentationAnalysis;
140use crate::capture::types::*;
141use std::sync::Arc;
142
143pub struct AnalysisManager {
145 }
147
148impl AnalysisManager {
149 pub fn new() -> Self {
151 Self {}
152 }
153
154 pub fn analyze_fragmentation(&self, allocations: &[AllocationInfo]) -> FragmentationAnalysis {
156 if allocations.is_empty() {
157 return FragmentationAnalysis::default();
158 }
159
160 let active_allocations: Vec<_> = allocations
161 .iter()
162 .filter(|a| a.timestamp_dealloc.is_none())
163 .collect();
164
165 if active_allocations.is_empty() {
166 return FragmentationAnalysis::default();
167 }
168
169 let mut sorted_ptrs: Vec<usize> = active_allocations.iter().map(|a| a.ptr).collect();
170 sorted_ptrs.sort();
171
172 let mut gaps: Vec<usize> = Vec::new();
173 for i in 1..sorted_ptrs.len() {
174 let prev = sorted_ptrs[i - 1];
175 let curr = sorted_ptrs[i];
176 if curr > prev {
177 let prev_alloc = active_allocations
178 .iter()
179 .find(|a| a.ptr == prev)
180 .map(|a| a.size)
181 .unwrap_or(0);
182 let gap = curr.saturating_sub(prev + prev_alloc);
183 if gap > 0 {
184 gaps.push(gap);
185 }
186 }
187 }
188
189 let total_memory: usize = active_allocations.iter().map(|a| a.size).sum();
190 let total_gap: usize = gaps.iter().sum();
191
192 let fragmentation_ratio = if total_memory > 0 {
193 total_gap as f64 / (total_memory + total_gap) as f64
194 } else {
195 0.0
196 };
197
198 let largest_free_block = gaps.iter().max().copied().unwrap_or(0);
199 let smallest_free_block = gaps.iter().min().copied().unwrap_or(0);
200 let free_block_count = gaps.len();
201 let total_free_memory = total_gap;
202
203 let external_fragmentation = if !gaps.is_empty() {
204 let avg_gap = total_gap as f64 / gaps.len() as f64;
205 let max_gap = largest_free_block as f64;
206 if max_gap > 0.0 {
207 1.0 - (avg_gap / max_gap)
208 } else {
209 0.0
210 }
211 } else {
212 0.0
213 };
214
215 let total_requested: usize = active_allocations.iter().map(|a| a.size).sum();
216 let total_allocated = total_requested + total_gap;
217 let internal_fragmentation = if total_allocated > 0 {
218 (total_gap as f64 / total_allocated as f64) * 100.0
219 } else {
220 0.0
221 };
222
223 FragmentationAnalysis {
224 fragmentation_ratio,
225 largest_free_block,
226 smallest_free_block,
227 free_block_count,
228 total_free_memory,
229 external_fragmentation,
230 internal_fragmentation,
231 }
232 }
233
234 pub fn analyze_system_libraries(&self, allocations: &[AllocationInfo]) -> SystemLibraryStats {
236 let mut stats = SystemLibraryStats::default();
237
238 for alloc in allocations {
239 let type_name = alloc.type_name.as_deref().unwrap_or("");
240 let stack = alloc.stack_trace.as_deref().unwrap_or(&[]);
241
242 if type_name.contains("Vec<")
243 || type_name.contains("HashMap")
244 || type_name.contains("HashSet")
245 || type_name.contains("BTreeMap")
246 || type_name.contains("BTreeSet")
247 {
248 stats.std_collections.allocation_count += 1;
249 stats.std_collections.total_bytes += alloc.size;
250 }
251
252 if type_name.contains("Future")
253 || type_name.contains("async")
254 || type_name.contains("tokio")
255 || type_name.contains("async_std")
256 {
257 stats.async_runtime.allocation_count += 1;
258 stats.async_runtime.total_bytes += alloc.size;
259 }
260
261 if type_name.contains("TcpStream")
262 || type_name.contains("UdpSocket")
263 || type_name.contains("Http")
264 || stack.iter().any(|s| s.contains("net::"))
265 {
266 stats.network_io.allocation_count += 1;
267 stats.network_io.total_bytes += alloc.size;
268 }
269
270 if type_name.contains("File")
271 || type_name.contains("Path")
272 || stack.iter().any(|s| s.contains("fs::"))
273 {
274 stats.file_system.allocation_count += 1;
275 stats.file_system.total_bytes += alloc.size;
276 }
277
278 if type_name.contains("serde")
279 || type_name.contains("Json")
280 || type_name.contains("Deserialize")
281 {
282 stats.serialization.allocation_count += 1;
283 stats.serialization.total_bytes += alloc.size;
284 }
285
286 if type_name.contains("Regex") || type_name.contains("regex") {
287 stats.regex_engine.allocation_count += 1;
288 stats.regex_engine.total_bytes += alloc.size;
289 }
290
291 if type_name.contains("Crypto")
292 || type_name.contains("Hash")
293 || type_name.contains("Signature")
294 {
295 stats.crypto_security.allocation_count += 1;
296 stats.crypto_security.total_bytes += alloc.size;
297 }
298
299 if type_name.contains("Database")
300 || type_name.contains("Connection")
301 || type_name.contains("Query")
302 {
303 stats.database.allocation_count += 1;
304 stats.database.total_bytes += alloc.size;
305 }
306
307 if type_name.contains("Window")
308 || type_name.contains("Canvas")
309 || type_name.contains("Surface")
310 || type_name.contains("wgpu")
311 {
312 stats.graphics_ui.allocation_count += 1;
313 stats.graphics_ui.total_bytes += alloc.size;
314 }
315
316 if type_name.contains("Request")
317 || type_name.contains("Response")
318 || type_name.contains("hyper")
319 || type_name.contains("reqwest")
320 {
321 stats.http_stack.allocation_count += 1;
322 stats.http_stack.total_bytes += alloc.size;
323 }
324 }
325
326 stats
327 }
328
329 pub fn analyze_concurrency_safety(
331 &self,
332 allocations: &[AllocationInfo],
333 ) -> ConcurrencyAnalysis {
334 let mut analysis = ConcurrencyAnalysis::default();
335
336 let mut thread_alloc_counts: std::collections::HashMap<std::thread::ThreadId, usize> =
337 std::collections::HashMap::new();
338
339 for alloc in allocations {
340 let type_name = alloc.type_name.as_deref().unwrap_or("");
341
342 if type_name.contains("Arc<")
343 || type_name.contains("Mutex<")
344 || type_name.contains("RwLock<")
345 {
346 analysis.thread_safety_allocations += 1;
347 analysis.shared_memory_bytes += alloc.size;
348 }
349
350 if type_name.contains("Arc<") {
351 analysis.arc_shared += 1;
352 }
353
354 if type_name.contains("mpsc")
355 || type_name.contains("channel")
356 || type_name.contains("Sender")
357 || type_name.contains("Receiver")
358 {
359 analysis.channel_buffers += 1;
360 }
361
362 if type_name.contains("thread_local") || type_name.contains("LocalKey") {
363 analysis.thread_local_storage += 1;
364 }
365
366 if type_name.contains("Atomic") {
367 analysis.atomic_operations += 1;
368 }
369
370 *thread_alloc_counts.entry(alloc.thread_id).or_insert(0) += 1;
371 }
372
373 let max_thread_allocs = thread_alloc_counts.values().max().copied().unwrap_or(0);
374 let min_thread_allocs = thread_alloc_counts.values().min().copied().unwrap_or(0);
375 let thread_count = thread_alloc_counts.len();
376
377 if thread_count <= 1 {
378 analysis.lock_contention_risk = "None".to_string();
379 } else {
380 let imbalance_ratio = if min_thread_allocs > 0 {
381 max_thread_allocs as f64 / min_thread_allocs as f64
382 } else {
383 f64::MAX
384 };
385
386 if imbalance_ratio > 10.0 {
387 analysis.lock_contention_risk = "High".to_string();
388 } else if imbalance_ratio > 3.0 {
389 analysis.lock_contention_risk = "Medium".to_string();
390 } else {
391 analysis.lock_contention_risk = "Low".to_string();
392 }
393 }
394
395 analysis
396 }
397
398 pub fn get_unsafe_ffi_tracker(&self) -> Arc<crate::unsafe_ffi_tracker::UnsafeFFITracker> {
400 crate::unsafe_ffi_tracker::get_global_unsafe_ffi_tracker()
402 }
403
404 pub fn get_unsafe_ffi_stats(&self) -> crate::unsafe_ffi_tracker::UnsafeFFIStats {
406 self.get_unsafe_ffi_tracker().get_stats()
408 }
409
410 pub fn analyze_circular_references(
412 &self,
413 allocations: &[AllocationInfo],
414 ) -> crate::circular_reference::CircularReferenceAnalysis {
415 crate::circular_reference::detect_circular_references(allocations)
416 }
417
418 pub fn analyze_borrow_patterns(
420 &self,
421 _allocations: &[AllocationInfo],
422 ) -> BorrowPatternAnalysis {
423 let analyzer = get_global_borrow_analyzer();
424 analyzer.analyze_borrow_patterns()
425 }
426
427 pub fn analyze_generic_types(&self, _allocations: &[AllocationInfo]) -> GenericStatistics {
429 let analyzer = GenericAnalyzer::new();
431 analyzer.get_generic_statistics()
432 }
433
434 pub fn analyze_async_patterns(&self, _allocations: &[AllocationInfo]) -> AsyncPatternAnalysis {
436 let analyzer = get_global_async_analyzer();
437 analyzer.analyze_async_patterns()
438 }
439
440 pub fn analyze_closure_patterns(
442 &self,
443 allocations: &[AllocationInfo],
444 ) -> ClosureAnalysisReport {
445 let analyzer = get_global_closure_analyzer();
446 analyzer.analyze_closure_patterns(allocations)
447 }
448
449 pub fn analyze_lifecycle_patterns(
451 &self,
452 _allocations: &[AllocationInfo],
453 ) -> LifecycleAnalysisReport {
454 let analyzer = get_global_lifecycle_analyzer();
455 analyzer.get_lifecycle_report()
456 }
457
458 pub fn analyze_memory_leaks(
460 &self,
461 allocations: &[AllocationInfo],
462 ) -> crate::analysis::detectors::DetectionResult {
463 let detector = crate::analysis::detectors::LeakDetector::new(
464 crate::analysis::detectors::LeakDetectorConfig::default(),
465 );
466 detector.detect(allocations)
467 }
468
469 pub fn analyze_use_after_free(
471 &self,
472 allocations: &[AllocationInfo],
473 ) -> crate::analysis::detectors::DetectionResult {
474 let detector = crate::analysis::detectors::UafDetector::new(
475 crate::analysis::detectors::UafDetectorConfig::default(),
476 );
477 detector.detect(allocations)
478 }
479
480 pub fn analyze_buffer_overflow(
482 &self,
483 allocations: &[AllocationInfo],
484 ) -> crate::analysis::detectors::DetectionResult {
485 let detector = crate::analysis::detectors::OverflowDetector::new(
486 crate::analysis::detectors::OverflowDetectorConfig::default(),
487 );
488 detector.detect(allocations)
489 }
490
491 pub fn analyze_safety_violations(
493 &self,
494 allocations: &[AllocationInfo],
495 ) -> crate::analysis::detectors::DetectionResult {
496 let detector = crate::analysis::detectors::SafetyDetector::new(
497 crate::analysis::detectors::SafetyDetectorConfig::default(),
498 );
499 detector.detect(allocations)
500 }
501
502 pub fn analyze_lifecycle_issues(
504 &self,
505 allocations: &[AllocationInfo],
506 ) -> crate::analysis::detectors::DetectionResult {
507 let detector = crate::analysis::detectors::LifecycleDetector::new(
508 crate::analysis::detectors::LifecycleDetectorConfig::default(),
509 );
510 detector.detect(allocations)
511 }
512
513 pub fn perform_comprehensive_analysis(
515 &self,
516 allocations: &[AllocationInfo],
517 stats: &MemoryStats,
518 ) -> ComprehensiveAnalysisReport {
519 let fragmentation = self.analyze_fragmentation(allocations);
520 let system_libs = self.analyze_system_libraries(allocations);
521 let concurrency = self.analyze_concurrency_safety(allocations);
522 let unsafe_stats = self.get_unsafe_ffi_stats();
523 let circular_refs = self.analyze_circular_references(allocations);
524
525 let borrow_analysis = self.analyze_borrow_patterns(allocations);
527 let generic_analysis = self.analyze_generic_types(allocations);
528 let async_analysis = self.analyze_async_patterns(allocations);
529 let closure_analysis = self.analyze_closure_patterns(allocations);
530 let lifecycle_analysis = self.analyze_lifecycle_patterns(allocations);
531
532 ComprehensiveAnalysisReport {
533 fragmentation_analysis: fragmentation,
534 system_library_stats: system_libs,
535 concurrency_analysis: concurrency,
536 unsafe_ffi_stats: unsafe_stats,
537 circular_reference_analysis: circular_refs,
538 borrow_analysis,
539 generic_analysis,
540 async_analysis,
541 closure_analysis,
542 lifecycle_analysis,
543 memory_stats: stats.clone(),
544 analysis_timestamp: std::time::SystemTime::now()
545 .duration_since(std::time::UNIX_EPOCH)
546 .unwrap_or_default()
547 .as_secs(),
548 }
549 }
550}
551
552impl Default for AnalysisManager {
553 fn default() -> Self {
554 Self::new()
555 }
556}
557
558#[derive(Debug, Clone)]
560pub struct ComprehensiveAnalysisReport {
561 pub fragmentation_analysis: FragmentationAnalysis,
563 pub system_library_stats: SystemLibraryStats,
565 pub concurrency_analysis: ConcurrencyAnalysis,
567 pub unsafe_ffi_stats: crate::unsafe_ffi_tracker::UnsafeFFIStats,
569 pub circular_reference_analysis: crate::circular_reference::CircularReferenceAnalysis,
571 pub borrow_analysis: BorrowPatternAnalysis,
573 pub generic_analysis: GenericStatistics,
575 pub async_analysis: AsyncPatternAnalysis,
577 pub closure_analysis: ClosureAnalysisReport,
579 pub lifecycle_analysis: LifecycleAnalysisReport,
581 pub memory_stats: MemoryStats,
583 pub analysis_timestamp: u64,
585}
586
587pub fn analyze_fragmentation(allocations: &[AllocationInfo]) -> FragmentationAnalysis {
592 let manager = AnalysisManager::new();
593 manager.analyze_fragmentation(allocations)
594}
595
596pub fn analyze_system_libraries(allocations: &[AllocationInfo]) -> SystemLibraryStats {
598 let manager = AnalysisManager::new();
599 manager.analyze_system_libraries(allocations)
600}
601
602pub fn analyze_concurrency_safety(allocations: &[AllocationInfo]) -> ConcurrencyAnalysis {
604 let manager = AnalysisManager::new();
605 manager.analyze_concurrency_safety(allocations)
606}
607
608pub fn get_global_unsafe_ffi_tracker() -> Arc<crate::unsafe_ffi_tracker::UnsafeFFITracker> {
610 crate::unsafe_ffi_tracker::get_global_unsafe_ffi_tracker()
611}
612
613pub fn get_unsafe_ffi_stats() -> crate::unsafe_ffi_tracker::UnsafeFFIStats {
615 let manager = AnalysisManager::new();
616 manager.get_unsafe_ffi_stats()
617}
618
619pub fn perform_comprehensive_analysis(
621 allocations: &[AllocationInfo],
622 stats: &MemoryStats,
623) -> ComprehensiveAnalysisReport {
624 let manager = AnalysisManager::new();
625 manager.perform_comprehensive_analysis(allocations, stats)
626}
627
628#[cfg(test)]
632mod tests {
633 use super::*;
634 use crate::capture::types::AllocationInfo;
635
636 #[test]
637 fn test_analyze_fragmentation() {
638 let manager = AnalysisManager::new();
639 let allocations = vec![
644 AllocationInfo::new(0x1000, 1024),
645 AllocationInfo::new(0x2000, 512),
646 ];
647
648 let result = manager.analyze_fragmentation(&allocations);
649
650 assert!(
653 result.fragmentation_ratio > 0.5,
654 "fragmentation_ratio should be > 0.5, got {}",
655 result.fragmentation_ratio
656 );
657 assert_eq!(result.free_block_count, 1, "should have exactly 1 gap");
658 assert_eq!(
659 result.largest_free_block, 3072,
660 "largest gap should be 3072"
661 );
662 assert_eq!(
663 result.smallest_free_block, 3072,
664 "smallest gap should be 3072"
665 );
666 }
667
668 #[test]
669 fn test_analyze_fragmentation_no_gaps() {
670 let manager = AnalysisManager::new();
671 let allocations = vec![
673 AllocationInfo::new(0x1000, 256),
674 AllocationInfo::new(0x1100, 256),
675 ];
676
677 let result = manager.analyze_fragmentation(&allocations);
678 assert_eq!(
679 result.fragmentation_ratio, 0.0,
680 "no gaps means zero fragmentation"
681 );
682 assert_eq!(result.free_block_count, 0);
683 }
684
685 #[test]
686 fn test_analyze_system_libraries() {
687 let manager = AnalysisManager::new();
688
689 let mut alloc_vec = AllocationInfo::new(0x1000, 256);
691 alloc_vec.type_name = Some("Vec<String>".to_string());
692
693 let mut alloc_hashmap = AllocationInfo::new(0x2000, 512);
694 alloc_hashmap.type_name = Some("HashMap<K, V>".to_string());
695
696 let mut alloc_file = AllocationInfo::new(0x3000, 128);
697 alloc_file.type_name = Some("File".to_string());
698
699 let mut alloc_regex = AllocationInfo::new(0x4000, 64);
700 alloc_regex.type_name = Some("Regex".to_string());
701
702 let allocations = vec![alloc_vec, alloc_hashmap, alloc_file, alloc_regex];
703
704 let result = manager.analyze_system_libraries(&allocations);
705
706 assert_eq!(
707 result.std_collections.allocation_count, 2,
708 "Vec and HashMap"
709 );
710 assert_eq!(result.std_collections.total_bytes, 256 + 512);
711 assert_eq!(result.file_system.allocation_count, 1, "File");
712 assert_eq!(result.file_system.total_bytes, 128);
713 assert_eq!(result.regex_engine.allocation_count, 1, "Regex");
714 assert_eq!(result.regex_engine.total_bytes, 64);
715 assert_eq!(result.async_runtime.allocation_count, 0, "no async types");
716 }
717
718 #[test]
719 fn test_analyze_concurrency_safety() {
720 let manager = AnalysisManager::new();
721
722 let mut alloc_arc = AllocationInfo::new(0x1000, 64);
723 alloc_arc.type_name = Some("Arc<Mutex<i32>>".to_string());
724
725 let mut alloc_mutex = AllocationInfo::new(0x2000, 128);
726 alloc_mutex.type_name = Some("Mutex<String>".to_string());
727
728 let mut alloc_atomic = AllocationInfo::new(0x3000, 8);
729 alloc_atomic.type_name = Some("AtomicUsize".to_string());
730
731 let allocations = vec![alloc_arc, alloc_mutex, alloc_atomic];
732
733 let result = manager.analyze_concurrency_safety(&allocations);
734
735 assert_eq!(result.thread_safety_allocations, 2, "Arc and Mutex");
736 assert_eq!(result.arc_shared, 1, "Arc");
737 assert_eq!(result.atomic_operations, 1, "AtomicUsize");
738 assert_eq!(result.shared_memory_bytes, 64 + 128);
739 assert_eq!(result.lock_contention_risk, "None", "single thread");
740 }
741
742 #[test]
743 fn test_analyze_concurrency_safety_multi_thread() {
744 let manager = AnalysisManager::new();
745
746 let mut alloc_arc = AllocationInfo::new(0x1000, 64);
749 alloc_arc.type_name = Some("Arc<i32>".to_string());
750
751 let allocations = vec![alloc_arc];
752
753 let result = manager.analyze_concurrency_safety(&allocations);
754 assert_eq!(result.arc_shared, 1);
755 }
756
757 #[test]
758 fn test_get_unsafe_ffi_tracker() {
759 let manager = AnalysisManager::new();
760
761 let _tracker = manager.get_unsafe_ffi_tracker();
762
763 }
765
766 #[test]
767 fn test_get_unsafe_ffi_stats() {
768 let manager = AnalysisManager::new();
769
770 let stats = manager.get_unsafe_ffi_stats();
771
772 assert_eq!(stats.total_operations, 0);
774 assert_eq!(stats.ffi_calls, 0);
775 assert_eq!(stats.raw_pointer_operations, 0);
776 assert_eq!(stats.memory_violations, 0);
777 assert!(stats.operations.is_empty());
778 }
779
780 #[test]
781 fn test_analyze_circular_references() {
782 let manager = AnalysisManager::new();
783 let allocations = vec![
786 AllocationInfo::new(0x4000, 128),
787 AllocationInfo::new(0x5000, 256),
788 ];
789
790 let result = manager.analyze_circular_references(&allocations);
791 assert_eq!(result.total_smart_pointers, 0, "no smart pointer info");
792 assert_eq!(result.circular_references.len(), 0);
793 assert_eq!(result.pointers_in_cycles, 0);
794 assert_eq!(result.total_leaked_memory, 0);
795 }
796
797 #[test]
798 fn test_analyze_borrow_patterns() {
799 let manager = AnalysisManager::new();
800 let allocations = vec![AllocationInfo::new(0x7000, 1024)];
801
802 let result = manager.analyze_borrow_patterns(&allocations);
803
804 assert!(result.patterns.is_empty());
806 assert_eq!(result.total_events, 0);
807 assert!(result.analysis_timestamp > 0);
808 }
809
810 #[test]
811 fn test_analyze_generic_types() {
812 let manager = AnalysisManager::new();
813 let allocations = vec![AllocationInfo::new(0x8000, 256)];
814
815 let result = manager.analyze_generic_types(&allocations);
816
817 assert_eq!(result.total_instances, 0);
819 assert_eq!(result.unique_base_types, 0);
820 assert_eq!(result.total_instantiations, 0);
821 assert_eq!(result.constraint_violations, 0);
822 assert!(result.most_used_types.is_empty());
823 }
824
825 #[test]
826 fn test_analyze_async_patterns() {
827 let manager = AnalysisManager::new();
828 let allocations = vec![AllocationInfo::new(0x9000, 2048)];
829
830 let result = manager.analyze_async_patterns(&allocations);
831
832 assert!(result.patterns.is_empty());
834 assert_eq!(result.total_futures_analyzed, 0);
835 assert!(result.analysis_timestamp > 0);
836 }
837
838 #[test]
839 fn test_analyze_closure_patterns() {
840 let manager = AnalysisManager::new();
841 let allocations = vec![AllocationInfo::new(0xa000, 128)];
842
843 let result = manager.analyze_closure_patterns(&allocations);
844
845 assert!(result.detected_closures.is_empty());
847 assert_eq!(result.capture_statistics.total_closures, 0);
848 assert!(result.optimization_suggestions.is_empty());
849 assert!(result.lifetime_analysis.lifetime_patterns.is_empty());
850 assert!(result.analysis_timestamp > 0);
851 }
852
853 #[test]
854 fn test_analyze_lifecycle_patterns() {
855 let manager = AnalysisManager::new();
856 let allocations = vec![AllocationInfo::new(0xb000, 512)];
857
858 let result = manager.analyze_lifecycle_patterns(&allocations);
859
860 assert!(result.drop_events.is_empty());
862 assert!(result.raii_patterns.is_empty());
863 assert!(result.borrow_analysis.borrow_patterns.is_empty());
864 assert!(result.closure_captures.is_empty());
865 assert!(result.analysis_timestamp > 0);
866 }
867
868 #[test]
869 fn test_perform_comprehensive_analysis() {
870 let manager = AnalysisManager::new();
871 let allocations = vec![
872 AllocationInfo::new(0x1000, 1024),
873 AllocationInfo::new(0x2000, 512),
874 AllocationInfo::new(0x3000, 256),
875 ];
876 let stats = MemoryStats::new();
877
878 let result = manager.perform_comprehensive_analysis(&allocations, &stats);
879
880 assert!(
881 result.fragmentation_analysis.fragmentation_ratio >= 0.0
882 && result.fragmentation_analysis.fragmentation_ratio <= 1.0
883 );
884 assert_eq!(
885 result.system_library_stats.std_collections.allocation_count,
886 0
887 );
888 assert_eq!(result.concurrency_analysis.thread_safety_allocations, 0);
889 assert_eq!(result.unsafe_ffi_stats.total_operations, 0);
890 assert_eq!(result.circular_reference_analysis.total_smart_pointers, 0);
891 assert!(result.borrow_analysis.patterns.is_empty());
892 assert_eq!(result.generic_analysis.total_instances, 0);
893 assert!(result.async_analysis.patterns.is_empty());
894 assert!(result.closure_analysis.detected_closures.is_empty());
895 assert!(result.lifecycle_analysis.drop_events.is_empty());
896 assert_eq!(result.memory_stats.total_allocations, 0);
897 assert!(result.analysis_timestamp > 0);
898 }
899
900 #[test]
901 fn test_backward_compatibility_functions() {
902 let allocations = vec![AllocationInfo::new(0x1000, 1024)];
903
904 let frag_result = analyze_fragmentation(&allocations);
906 assert_eq!(frag_result.fragmentation_ratio, 0.0);
907
908 let lib_result = analyze_system_libraries(&allocations);
909 assert_eq!(lib_result.std_collections.allocation_count, 0);
910
911 let conc_result = analyze_concurrency_safety(&allocations);
912 assert_eq!(conc_result.thread_safety_allocations, 0);
913
914 let _tracker = get_global_unsafe_ffi_tracker();
915
916 let stats = get_unsafe_ffi_stats();
917 assert_eq!(stats.total_operations, 0);
918
919 let memory_stats = MemoryStats::new();
920 let comp_result = perform_comprehensive_analysis(&allocations, &memory_stats);
921 assert!(comp_result.analysis_timestamp > 0);
922 }
923
924 #[test]
925 fn test_empty_allocations_analysis() {
926 let manager = AnalysisManager::new();
927 let empty_allocations: Vec<AllocationInfo> = vec![];
928
929 let frag_result = manager.analyze_fragmentation(&empty_allocations);
931 assert_eq!(frag_result.fragmentation_ratio, 0.0);
932
933 let lib_result = manager.analyze_system_libraries(&empty_allocations);
934 assert_eq!(lib_result.std_collections.allocation_count, 0);
935
936 let conc_result = manager.analyze_concurrency_safety(&empty_allocations);
937 assert_eq!(conc_result.thread_safety_allocations, 0);
938
939 let circ_result = manager.analyze_circular_references(&empty_allocations);
940 assert_eq!(circ_result.total_smart_pointers, 0);
941 }
942
943 #[test]
944 fn test_large_allocation_list_analysis() {
945 let manager = AnalysisManager::new();
946 let mut allocations = Vec::new();
947
948 for i in 0..100 {
950 allocations.push(AllocationInfo::new(0x1000 + i * 0x1000, 1024 + i));
951 }
952
953 let stats = MemoryStats::new();
954 let result = manager.perform_comprehensive_analysis(&allocations, &stats);
955
956 assert!(result.analysis_timestamp > 0);
958 assert_eq!(result.memory_stats.total_allocations, 0); }
960}