Skip to main content

memscope_rs/capture/types/
tracking.rs

1//! Function call tracking types.
2//!
3//! This module contains types for tracking function calls,
4//! call stacks, and performance characteristics.
5
6use serde::{Deserialize, Serialize};
7
8use super::allocation::{BottleneckType, ImpactLevel, PerformanceBottleneck};
9use super::generic::MemoryAccessPattern;
10
11/// Function call tracking information.
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub struct FunctionCallTrackingInfo {
14    /// Function name.
15    pub function_name: String,
16    /// Module path.
17    pub module_path: String,
18    /// Total call count.
19    pub total_call_count: u64,
20    /// Call frequency per second.
21    pub call_frequency_per_sec: f64,
22    /// Average execution time per call.
23    pub avg_execution_time_ns: f64,
24    /// Total execution time.
25    pub total_execution_time_ns: u64,
26    /// Call stack information.
27    pub call_stack_info: CallStackInfo,
28    /// Memory allocations per call.
29    pub memory_allocations_per_call: f64,
30    /// Performance characteristics.
31    pub performance_characteristics: FunctionPerformanceCharacteristics,
32    /// Call patterns.
33    pub call_patterns: Vec<CallPattern>,
34}
35
36/// Call stack information.
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub struct CallStackInfo {
39    /// Maximum call stack depth.
40    pub max_stack_depth: u32,
41    /// Average call stack depth.
42    pub avg_stack_depth: f64,
43    /// Most common call sequences.
44    pub common_call_sequences: Vec<CallSequence>,
45    /// Recursive call detection.
46    pub recursive_calls: Vec<RecursiveCallInfo>,
47    /// Stack overflow risk assessment.
48    pub stack_overflow_risk: StackOverflowRisk,
49}
50
51/// Call sequence information.
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct CallSequence {
54    /// Sequence of function names.
55    pub function_sequence: Vec<String>,
56    /// Frequency of this sequence.
57    pub frequency: u32,
58    /// Average execution time for this sequence.
59    pub avg_execution_time_ns: f64,
60    /// Memory usage pattern for this sequence.
61    pub memory_usage_pattern: MemoryUsagePattern,
62}
63
64/// Memory usage pattern.
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66pub struct MemoryUsagePattern {
67    /// Peak memory usage in sequence.
68    pub peak_memory_usage: usize,
69    /// Average memory usage.
70    pub avg_memory_usage: usize,
71    /// Memory allocation frequency.
72    pub allocation_frequency: f64,
73    /// Memory deallocation frequency.
74    pub deallocation_frequency: f64,
75    /// Memory leak potential.
76    pub leak_potential: LeakPotential,
77}
78
79/// Memory leak potential assessment.
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81pub enum LeakPotential {
82    /// Low memory leak potential.
83    Low,
84    /// Medium memory leak potential.
85    Medium,
86    /// High memory leak potential.
87    High,
88    /// Critical memory leak potential.
89    Critical,
90}
91
92/// Recursive call information.
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
94pub struct RecursiveCallInfo {
95    /// Function name.
96    pub function_name: String,
97    /// Maximum recursion depth.
98    pub max_recursion_depth: u32,
99    /// Average recursion depth.
100    pub avg_recursion_depth: f64,
101    /// Tail recursion optimization potential.
102    pub tail_recursion_potential: bool,
103    /// Stack usage per recursion level.
104    pub stack_usage_per_level: usize,
105    /// Performance impact of recursion.
106    pub recursion_performance_impact: RecursionPerformanceImpact,
107}
108
109/// Recursion performance impact.
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct RecursionPerformanceImpact {
112    /// Stack overhead per call.
113    pub stack_overhead_per_call: usize,
114    /// Function call overhead.
115    pub call_overhead_ns: f64,
116    /// Cache impact of deep recursion.
117    pub cache_impact: f64,
118    /// Optimization recommendations.
119    pub optimization_recommendations: Vec<String>,
120}
121
122/// Stack overflow risk assessment.
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
124pub enum StackOverflowRisk {
125    /// Low stack overflow risk.
126    Low,
127    /// Medium stack overflow risk.
128    Medium,
129    /// High stack overflow risk.
130    High,
131    /// Critical stack overflow risk.
132    Critical,
133}
134
135/// Function performance characteristics.
136#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
137pub struct FunctionPerformanceCharacteristics {
138    /// CPU usage percentage.
139    pub cpu_usage_percent: f64,
140    /// Memory usage characteristics.
141    pub memory_characteristics: FunctionMemoryCharacteristics,
142    /// I/O characteristics.
143    pub io_characteristics: IOCharacteristics,
144    /// Concurrency characteristics.
145    pub concurrency_characteristics: ConcurrencyCharacteristics,
146    /// Performance bottlenecks.
147    pub bottlenecks: Vec<PerformanceBottleneck>,
148}
149
150/// Function memory characteristics.
151#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
152pub struct FunctionMemoryCharacteristics {
153    /// Stack memory usage.
154    pub stack_memory_usage: usize,
155    /// Heap memory allocations.
156    pub heap_allocations: u32,
157    /// Memory access pattern.
158    pub access_pattern: MemoryAccessPattern,
159    /// Cache efficiency.
160    pub cache_efficiency: f64,
161    /// Memory bandwidth utilization.
162    pub memory_bandwidth_utilization: f64,
163}
164
165/// I/O characteristics.
166#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
167pub struct IOCharacteristics {
168    /// File I/O operations.
169    pub file_io_operations: u32,
170    /// Network I/O operations.
171    pub network_io_operations: u32,
172    /// Average I/O wait time.
173    pub avg_io_wait_time_ns: f64,
174    /// I/O throughput.
175    pub io_throughput_bytes_per_sec: f64,
176    /// I/O efficiency score.
177    pub io_efficiency_score: f64,
178}
179
180/// Concurrency characteristics.
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
182pub struct ConcurrencyCharacteristics {
183    /// Thread safety level.
184    pub thread_safety_level: ThreadSafetyLevel,
185    /// Lock contention frequency.
186    pub lock_contention_frequency: f64,
187    /// Parallel execution potential.
188    pub parallel_execution_potential: f64,
189    /// Synchronization overhead.
190    pub synchronization_overhead_ns: f64,
191    /// Deadlock risk assessment.
192    pub deadlock_risk: DeadlockRisk,
193}
194
195/// Thread safety levels.
196#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
197pub enum ThreadSafetyLevel {
198    /// Thread safe.
199    ThreadSafe,
200    /// Conditionally thread safe.
201    ConditionallyThreadSafe,
202    /// Not thread safe.
203    NotThreadSafe,
204    /// Unknown thread safety.
205    Unknown,
206}
207
208/// Deadlock risk assessment.
209#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
210pub enum DeadlockRisk {
211    /// No deadlock risk.
212    None,
213    /// Low deadlock risk.
214    Low,
215    /// Medium deadlock risk.
216    Medium,
217    /// High deadlock risk.
218    High,
219}
220
221/// Call pattern information.
222#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
223pub struct CallPattern {
224    /// Pattern type.
225    pub pattern_type: CallPatternType,
226    /// Pattern description.
227    pub description: String,
228    /// Frequency of this pattern.
229    pub frequency: u32,
230    /// Performance impact.
231    pub performance_impact: f64,
232    /// Optimization potential.
233    pub optimization_potential: f64,
234}
235
236/// Types of call patterns.
237#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
238pub enum CallPatternType {
239    /// Sequential call pattern.
240    Sequential,
241    /// Recursive call pattern.
242    Recursive,
243    /// Iterative call pattern.
244    Iterative,
245    /// Conditional call pattern.
246    Conditional,
247    /// Parallel call pattern.
248    Parallel,
249    /// Asynchronous call pattern.
250    Asynchronous,
251    /// Callback call pattern.
252    Callback,
253    /// Event-driven call pattern.
254    EventDriven,
255}
256
257impl From<crate::core::types::FunctionCallTrackingInfo> for FunctionCallTrackingInfo {
258    fn from(old: crate::core::types::FunctionCallTrackingInfo) -> Self {
259        Self {
260            function_name: old.function_name,
261            module_path: old.module_path,
262            total_call_count: old.total_call_count,
263            call_frequency_per_sec: old.call_frequency_per_sec,
264            avg_execution_time_ns: old.avg_execution_time_ns,
265            total_execution_time_ns: old.total_execution_time_ns,
266            call_stack_info: CallStackInfo {
267                max_stack_depth: old.call_stack_info.max_stack_depth,
268                avg_stack_depth: old.call_stack_info.avg_stack_depth,
269                common_call_sequences: old
270                    .call_stack_info
271                    .common_call_sequences
272                    .into_iter()
273                    .map(|s| CallSequence {
274                        function_sequence: s.function_sequence,
275                        frequency: s.frequency,
276                        avg_execution_time_ns: s.avg_execution_time_ns,
277                        memory_usage_pattern: MemoryUsagePattern {
278                            peak_memory_usage: s.memory_usage_pattern.peak_memory_usage,
279                            avg_memory_usage: s.memory_usage_pattern.avg_memory_usage,
280                            allocation_frequency: s.memory_usage_pattern.allocation_frequency,
281                            deallocation_frequency: s.memory_usage_pattern.deallocation_frequency,
282                            leak_potential: match s.memory_usage_pattern.leak_potential {
283                                crate::core::types::LeakPotential::Low => LeakPotential::Low,
284                                crate::core::types::LeakPotential::Medium => LeakPotential::Medium,
285                                crate::core::types::LeakPotential::High => LeakPotential::High,
286                                crate::core::types::LeakPotential::Critical => {
287                                    LeakPotential::Critical
288                                }
289                            },
290                        },
291                    })
292                    .collect(),
293                recursive_calls: old
294                    .call_stack_info
295                    .recursive_calls
296                    .into_iter()
297                    .map(|r| RecursiveCallInfo {
298                        function_name: r.function_name,
299                        max_recursion_depth: r.max_recursion_depth,
300                        avg_recursion_depth: r.avg_recursion_depth,
301                        tail_recursion_potential: r.tail_recursion_potential,
302                        stack_usage_per_level: r.stack_usage_per_level,
303                        recursion_performance_impact: RecursionPerformanceImpact {
304                            stack_overhead_per_call: r
305                                .recursion_performance_impact
306                                .stack_overhead_per_call,
307                            call_overhead_ns: r.recursion_performance_impact.call_overhead_ns,
308                            cache_impact: r.recursion_performance_impact.cache_impact,
309                            optimization_recommendations: r
310                                .recursion_performance_impact
311                                .optimization_recommendations,
312                        },
313                    })
314                    .collect(),
315                stack_overflow_risk: match old.call_stack_info.stack_overflow_risk {
316                    crate::core::types::StackOverflowRisk::Low => StackOverflowRisk::Low,
317                    crate::core::types::StackOverflowRisk::Medium => StackOverflowRisk::Medium,
318                    crate::core::types::StackOverflowRisk::High => StackOverflowRisk::High,
319                    crate::core::types::StackOverflowRisk::Critical => StackOverflowRisk::Critical,
320                },
321            },
322            memory_allocations_per_call: old.memory_allocations_per_call,
323            performance_characteristics: FunctionPerformanceCharacteristics {
324                cpu_usage_percent: old.performance_characteristics.cpu_usage_percent,
325                memory_characteristics: FunctionMemoryCharacteristics {
326                    stack_memory_usage: old
327                        .performance_characteristics
328                        .memory_characteristics
329                        .stack_memory_usage,
330                    heap_allocations: old
331                        .performance_characteristics
332                        .memory_characteristics
333                        .heap_allocations,
334                    access_pattern: match old
335                        .performance_characteristics
336                        .memory_characteristics
337                        .access_pattern
338                    {
339                        crate::core::types::MemoryAccessPattern::Sequential => {
340                            MemoryAccessPattern::Sequential
341                        }
342                        crate::core::types::MemoryAccessPattern::Random => {
343                            MemoryAccessPattern::Random
344                        }
345                        crate::core::types::MemoryAccessPattern::Strided { stride } => {
346                            MemoryAccessPattern::Strided { stride }
347                        }
348                        crate::core::types::MemoryAccessPattern::Clustered => {
349                            MemoryAccessPattern::Clustered
350                        }
351                        crate::core::types::MemoryAccessPattern::Mixed => {
352                            MemoryAccessPattern::Mixed
353                        }
354                    },
355                    cache_efficiency: old
356                        .performance_characteristics
357                        .memory_characteristics
358                        .cache_efficiency,
359                    memory_bandwidth_utilization: old
360                        .performance_characteristics
361                        .memory_characteristics
362                        .memory_bandwidth_utilization,
363                },
364                io_characteristics: IOCharacteristics {
365                    file_io_operations: old
366                        .performance_characteristics
367                        .io_characteristics
368                        .file_io_operations,
369                    network_io_operations: old
370                        .performance_characteristics
371                        .io_characteristics
372                        .network_io_operations,
373                    avg_io_wait_time_ns: old
374                        .performance_characteristics
375                        .io_characteristics
376                        .avg_io_wait_time_ns,
377                    io_throughput_bytes_per_sec: old
378                        .performance_characteristics
379                        .io_characteristics
380                        .io_throughput_bytes_per_sec,
381                    io_efficiency_score: old
382                        .performance_characteristics
383                        .io_characteristics
384                        .io_efficiency_score,
385                },
386                concurrency_characteristics: ConcurrencyCharacteristics {
387                    thread_safety_level: match old
388                        .performance_characteristics
389                        .concurrency_characteristics
390                        .thread_safety_level
391                    {
392                        crate::core::types::ThreadSafetyLevel::ThreadSafe => {
393                            ThreadSafetyLevel::ThreadSafe
394                        }
395                        crate::core::types::ThreadSafetyLevel::ConditionallyThreadSafe => {
396                            ThreadSafetyLevel::ConditionallyThreadSafe
397                        }
398                        crate::core::types::ThreadSafetyLevel::NotThreadSafe => {
399                            ThreadSafetyLevel::NotThreadSafe
400                        }
401                        crate::core::types::ThreadSafetyLevel::Unknown => {
402                            ThreadSafetyLevel::Unknown
403                        }
404                    },
405                    lock_contention_frequency: old
406                        .performance_characteristics
407                        .concurrency_characteristics
408                        .lock_contention_frequency,
409                    parallel_execution_potential: old
410                        .performance_characteristics
411                        .concurrency_characteristics
412                        .parallel_execution_potential,
413                    synchronization_overhead_ns: old
414                        .performance_characteristics
415                        .concurrency_characteristics
416                        .synchronization_overhead_ns,
417                    deadlock_risk: match old
418                        .performance_characteristics
419                        .concurrency_characteristics
420                        .deadlock_risk
421                    {
422                        crate::core::types::DeadlockRisk::None => DeadlockRisk::None,
423                        crate::core::types::DeadlockRisk::Low => DeadlockRisk::Low,
424                        crate::core::types::DeadlockRisk::Medium => DeadlockRisk::Medium,
425                        crate::core::types::DeadlockRisk::High => DeadlockRisk::High,
426                    },
427                },
428                bottlenecks: old
429                    .performance_characteristics
430                    .bottlenecks
431                    .into_iter()
432                    .map(|b| PerformanceBottleneck {
433                        bottleneck_type: match b.bottleneck_type {
434                            crate::core::types::BottleneckType::MemoryAllocation => {
435                                BottleneckType::MemoryAllocation
436                            }
437                            crate::core::types::BottleneckType::MemoryDeallocation => {
438                                BottleneckType::MemoryDeallocation
439                            }
440                            crate::core::types::BottleneckType::CacheMiss => {
441                                BottleneckType::CacheMiss
442                            }
443                            crate::core::types::BottleneckType::BranchMisprediction => {
444                                BottleneckType::BranchMisprediction
445                            }
446                            crate::core::types::BottleneckType::FunctionCall => {
447                                BottleneckType::FunctionCall
448                            }
449                            crate::core::types::BottleneckType::DataMovement => {
450                                BottleneckType::DataMovement
451                            }
452                            crate::core::types::BottleneckType::Synchronization => {
453                                BottleneckType::Synchronization
454                            }
455                            crate::core::types::BottleneckType::IO => BottleneckType::IO,
456                        },
457                        location: b.location,
458                        severity: match b.severity {
459                            crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
460                            crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
461                            crate::core::types::ImpactLevel::High => ImpactLevel::High,
462                            crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
463                        },
464                        description: b.description,
465                        optimization_suggestion: b.optimization_suggestion,
466                    })
467                    .collect(),
468            },
469            call_patterns: old
470                .call_patterns
471                .into_iter()
472                .map(|p| CallPattern {
473                    pattern_type: match p.pattern_type {
474                        crate::core::types::CallPatternType::Sequential => {
475                            CallPatternType::Sequential
476                        }
477                        crate::core::types::CallPatternType::Recursive => {
478                            CallPatternType::Recursive
479                        }
480                        crate::core::types::CallPatternType::Iterative => {
481                            CallPatternType::Iterative
482                        }
483                        crate::core::types::CallPatternType::Conditional => {
484                            CallPatternType::Conditional
485                        }
486                        crate::core::types::CallPatternType::Parallel => CallPatternType::Parallel,
487                        crate::core::types::CallPatternType::Asynchronous => {
488                            CallPatternType::Asynchronous
489                        }
490                        crate::core::types::CallPatternType::Callback => CallPatternType::Callback,
491                        crate::core::types::CallPatternType::EventDriven => {
492                            CallPatternType::EventDriven
493                        }
494                    },
495                    description: p.description,
496                    frequency: p.frequency,
497                    performance_impact: p.performance_impact,
498                    optimization_potential: p.optimization_potential,
499                })
500                .collect(),
501        }
502    }
503}
504
505#[cfg(test)]
506mod tests {
507    use super::*;
508
509    #[test]
510    fn test_function_call_tracking_info() {
511        let info = FunctionCallTrackingInfo {
512            function_name: "test_func".to_string(),
513            module_path: "test::module".to_string(),
514            total_call_count: 100,
515            call_frequency_per_sec: 10.0,
516            avg_execution_time_ns: 1000.0,
517            total_execution_time_ns: 100000,
518            call_stack_info: CallStackInfo {
519                max_stack_depth: 5,
520                avg_stack_depth: 3.0,
521                common_call_sequences: vec![],
522                recursive_calls: vec![],
523                stack_overflow_risk: StackOverflowRisk::Low,
524            },
525            memory_allocations_per_call: 2.0,
526            performance_characteristics: FunctionPerformanceCharacteristics {
527                cpu_usage_percent: 5.0,
528                memory_characteristics: FunctionMemoryCharacteristics {
529                    stack_memory_usage: 1024,
530                    heap_allocations: 5,
531                    access_pattern: MemoryAccessPattern::Sequential,
532                    cache_efficiency: 0.9,
533                    memory_bandwidth_utilization: 0.5,
534                },
535                io_characteristics: IOCharacteristics {
536                    file_io_operations: 0,
537                    network_io_operations: 0,
538                    avg_io_wait_time_ns: 0.0,
539                    io_throughput_bytes_per_sec: 0.0,
540                    io_efficiency_score: 1.0,
541                },
542                concurrency_characteristics: ConcurrencyCharacteristics {
543                    thread_safety_level: ThreadSafetyLevel::ThreadSafe,
544                    lock_contention_frequency: 0.0,
545                    parallel_execution_potential: 0.8,
546                    synchronization_overhead_ns: 0.0,
547                    deadlock_risk: DeadlockRisk::None,
548                },
549                bottlenecks: vec![],
550            },
551            call_patterns: vec![],
552        };
553
554        assert_eq!(info.function_name, "test_func");
555        assert_eq!(info.total_call_count, 100);
556    }
557
558    #[test]
559    fn test_call_pattern_type() {
560        let patterns = vec![
561            CallPatternType::Sequential,
562            CallPatternType::Recursive,
563            CallPatternType::Parallel,
564        ];
565
566        for pattern in patterns {
567            assert!(!format!("{pattern:?}").is_empty());
568        }
569    }
570
571    #[test]
572    fn test_all_leak_potential_variants() {
573        let potentials = [
574            LeakPotential::Low,
575            LeakPotential::Medium,
576            LeakPotential::High,
577            LeakPotential::Critical,
578        ];
579
580        for potential in potentials {
581            let pattern = MemoryUsagePattern {
582                peak_memory_usage: 1024,
583                avg_memory_usage: 512,
584                allocation_frequency: 10.0,
585                deallocation_frequency: 8.0,
586                leak_potential: potential.clone(),
587            };
588            assert_eq!(pattern.leak_potential, potential);
589        }
590    }
591
592    #[test]
593    fn test_all_stack_overflow_risk_variants() {
594        let risks = [
595            StackOverflowRisk::Low,
596            StackOverflowRisk::Medium,
597            StackOverflowRisk::High,
598            StackOverflowRisk::Critical,
599        ];
600
601        for risk in risks {
602            let info = CallStackInfo {
603                max_stack_depth: 10,
604                avg_stack_depth: 5.0,
605                common_call_sequences: vec![],
606                recursive_calls: vec![],
607                stack_overflow_risk: risk.clone(),
608            };
609            assert_eq!(info.stack_overflow_risk, risk);
610        }
611    }
612
613    #[test]
614    fn test_all_thread_safety_level_variants() {
615        let levels = [
616            ThreadSafetyLevel::ThreadSafe,
617            ThreadSafetyLevel::ConditionallyThreadSafe,
618            ThreadSafetyLevel::NotThreadSafe,
619            ThreadSafetyLevel::Unknown,
620        ];
621
622        for level in levels.clone() {
623            let chars = ConcurrencyCharacteristics {
624                thread_safety_level: level.clone(),
625                lock_contention_frequency: 0.5,
626                parallel_execution_potential: 0.8,
627                synchronization_overhead_ns: 100.0,
628                deadlock_risk: DeadlockRisk::None,
629            };
630            assert_eq!(chars.thread_safety_level, level);
631        }
632    }
633
634    #[test]
635    fn test_all_deadlock_risk_variants() {
636        let risks = [
637            DeadlockRisk::None,
638            DeadlockRisk::Low,
639            DeadlockRisk::Medium,
640            DeadlockRisk::High,
641        ];
642
643        for risk in risks {
644            let chars = ConcurrencyCharacteristics {
645                thread_safety_level: ThreadSafetyLevel::ThreadSafe,
646                lock_contention_frequency: 0.5,
647                parallel_execution_potential: 0.8,
648                synchronization_overhead_ns: 100.0,
649                deadlock_risk: risk.clone(),
650            };
651            assert_eq!(chars.deadlock_risk, risk);
652        }
653    }
654
655    #[test]
656    fn test_all_call_pattern_type_variants() {
657        let patterns = [
658            CallPatternType::Sequential,
659            CallPatternType::Recursive,
660            CallPatternType::Iterative,
661            CallPatternType::Conditional,
662            CallPatternType::Parallel,
663            CallPatternType::Asynchronous,
664            CallPatternType::Callback,
665            CallPatternType::EventDriven,
666        ];
667
668        for pattern in patterns {
669            let cp = CallPattern {
670                pattern_type: pattern.clone(),
671                description: "Test pattern".to_string(),
672                frequency: 10,
673                performance_impact: 0.5,
674                optimization_potential: 0.3,
675            };
676            assert_eq!(cp.pattern_type, pattern);
677        }
678    }
679
680    #[test]
681    fn test_call_stack_info_creation() {
682        let info = CallStackInfo {
683            max_stack_depth: 100,
684            avg_stack_depth: 45.5,
685            common_call_sequences: vec![CallSequence {
686                function_sequence: vec!["main".to_string(), "foo".to_string()],
687                frequency: 50,
688                avg_execution_time_ns: 5000.0,
689                memory_usage_pattern: MemoryUsagePattern {
690                    peak_memory_usage: 2048,
691                    avg_memory_usage: 1024,
692                    allocation_frequency: 5.0,
693                    deallocation_frequency: 5.0,
694                    leak_potential: LeakPotential::Low,
695                },
696            }],
697            recursive_calls: vec![],
698            stack_overflow_risk: StackOverflowRisk::Medium,
699        };
700
701        assert_eq!(info.max_stack_depth, 100);
702        assert_eq!(info.common_call_sequences.len(), 1);
703    }
704
705    #[test]
706    fn test_recursive_call_info_creation() {
707        let info = RecursiveCallInfo {
708            function_name: "fibonacci".to_string(),
709            max_recursion_depth: 50,
710            avg_recursion_depth: 25.5,
711            tail_recursion_potential: true,
712            stack_usage_per_level: 64,
713            recursion_performance_impact: RecursionPerformanceImpact {
714                stack_overhead_per_call: 64,
715                call_overhead_ns: 10.0,
716                cache_impact: 0.2,
717                optimization_recommendations: vec!["Convert to iterative".to_string()],
718            },
719        };
720
721        assert_eq!(info.function_name, "fibonacci");
722        assert!(info.tail_recursion_potential);
723    }
724
725    #[test]
726    fn test_memory_usage_pattern_creation() {
727        let pattern = MemoryUsagePattern {
728            peak_memory_usage: 10240,
729            avg_memory_usage: 5120,
730            allocation_frequency: 100.0,
731            deallocation_frequency: 95.0,
732            leak_potential: LeakPotential::High,
733        };
734
735        assert_eq!(pattern.peak_memory_usage, 10240);
736        assert!(matches!(pattern.leak_potential, LeakPotential::High));
737    }
738
739    #[test]
740    fn test_function_memory_characteristics_creation() {
741        let chars = FunctionMemoryCharacteristics {
742            stack_memory_usage: 2048,
743            heap_allocations: 10,
744            access_pattern: MemoryAccessPattern::Random,
745            cache_efficiency: 0.75,
746            memory_bandwidth_utilization: 0.6,
747        };
748
749        assert_eq!(chars.stack_memory_usage, 2048);
750        assert!(matches!(chars.access_pattern, MemoryAccessPattern::Random));
751    }
752
753    #[test]
754    fn test_io_characteristics_creation() {
755        let chars = IOCharacteristics {
756            file_io_operations: 100,
757            network_io_operations: 50,
758            avg_io_wait_time_ns: 5000.0,
759            io_throughput_bytes_per_sec: 1024000.0,
760            io_efficiency_score: 0.85,
761        };
762
763        assert_eq!(chars.file_io_operations, 100);
764        assert_eq!(chars.network_io_operations, 50);
765    }
766
767    #[test]
768    fn test_call_sequence_creation() {
769        let seq = CallSequence {
770            function_sequence: vec!["a".to_string(), "b".to_string(), "c".to_string()],
771            frequency: 25,
772            avg_execution_time_ns: 15000.0,
773            memory_usage_pattern: MemoryUsagePattern {
774                peak_memory_usage: 4096,
775                avg_memory_usage: 2048,
776                allocation_frequency: 2.0,
777                deallocation_frequency: 2.0,
778                leak_potential: LeakPotential::Low,
779            },
780        };
781
782        assert_eq!(seq.function_sequence.len(), 3);
783        assert_eq!(seq.frequency, 25);
784    }
785
786    #[test]
787    fn test_call_pattern_creation() {
788        let pattern = CallPattern {
789            pattern_type: CallPatternType::Recursive,
790            description: "Recursive tree traversal".to_string(),
791            frequency: 100,
792            performance_impact: 0.4,
793            optimization_potential: 0.7,
794        };
795
796        assert!(matches!(pattern.pattern_type, CallPatternType::Recursive));
797        assert_eq!(pattern.optimization_potential, 0.7);
798    }
799
800    #[test]
801    fn test_function_call_tracking_info_serialization() {
802        let info = FunctionCallTrackingInfo {
803            function_name: "serialize_test".to_string(),
804            module_path: "test::serialize".to_string(),
805            total_call_count: 50,
806            call_frequency_per_sec: 5.0,
807            avg_execution_time_ns: 2000.0,
808            total_execution_time_ns: 100000,
809            call_stack_info: CallStackInfo {
810                max_stack_depth: 3,
811                avg_stack_depth: 2.0,
812                common_call_sequences: vec![],
813                recursive_calls: vec![],
814                stack_overflow_risk: StackOverflowRisk::Low,
815            },
816            memory_allocations_per_call: 1.5,
817            performance_characteristics: FunctionPerformanceCharacteristics {
818                cpu_usage_percent: 10.0,
819                memory_characteristics: FunctionMemoryCharacteristics {
820                    stack_memory_usage: 512,
821                    heap_allocations: 2,
822                    access_pattern: MemoryAccessPattern::Sequential,
823                    cache_efficiency: 0.9,
824                    memory_bandwidth_utilization: 0.4,
825                },
826                io_characteristics: IOCharacteristics {
827                    file_io_operations: 0,
828                    network_io_operations: 0,
829                    avg_io_wait_time_ns: 0.0,
830                    io_throughput_bytes_per_sec: 0.0,
831                    io_efficiency_score: 1.0,
832                },
833                concurrency_characteristics: ConcurrencyCharacteristics {
834                    thread_safety_level: ThreadSafetyLevel::ThreadSafe,
835                    lock_contention_frequency: 0.0,
836                    parallel_execution_potential: 0.9,
837                    synchronization_overhead_ns: 0.0,
838                    deadlock_risk: DeadlockRisk::None,
839                },
840                bottlenecks: vec![],
841            },
842            call_patterns: vec![],
843        };
844
845        let json = serde_json::to_string(&info).unwrap();
846        let deserialized: FunctionCallTrackingInfo = serde_json::from_str(&json).unwrap();
847        assert_eq!(deserialized.function_name, info.function_name);
848        assert_eq!(deserialized.total_call_count, info.total_call_count);
849    }
850
851    #[test]
852    fn test_leak_potential_serialization() {
853        let potentials = vec![
854            LeakPotential::Low,
855            LeakPotential::Medium,
856            LeakPotential::High,
857            LeakPotential::Critical,
858        ];
859
860        for potential in potentials {
861            let json = serde_json::to_string(&potential).unwrap();
862            let deserialized: LeakPotential = serde_json::from_str(&json).unwrap();
863            assert_eq!(deserialized, potential);
864        }
865    }
866
867    #[test]
868    fn test_stack_overflow_risk_serialization() {
869        let risks = vec![
870            StackOverflowRisk::Low,
871            StackOverflowRisk::Medium,
872            StackOverflowRisk::High,
873            StackOverflowRisk::Critical,
874        ];
875
876        for risk in risks {
877            let json = serde_json::to_string(&risk).unwrap();
878            let deserialized: StackOverflowRisk = serde_json::from_str(&json).unwrap();
879            assert_eq!(deserialized, risk);
880        }
881    }
882
883    #[test]
884    fn test_thread_safety_level_serialization() {
885        let levels = vec![
886            ThreadSafetyLevel::ThreadSafe,
887            ThreadSafetyLevel::ConditionallyThreadSafe,
888            ThreadSafetyLevel::NotThreadSafe,
889            ThreadSafetyLevel::Unknown,
890        ];
891
892        for level in levels {
893            let json = serde_json::to_string(&level).unwrap();
894            let deserialized: ThreadSafetyLevel = serde_json::from_str(&json).unwrap();
895            assert_eq!(deserialized, level);
896        }
897    }
898
899    #[test]
900    fn test_deadlock_risk_serialization() {
901        let risks = vec![
902            DeadlockRisk::None,
903            DeadlockRisk::Low,
904            DeadlockRisk::Medium,
905            DeadlockRisk::High,
906        ];
907
908        for risk in risks {
909            let json = serde_json::to_string(&risk).unwrap();
910            let deserialized: DeadlockRisk = serde_json::from_str(&json).unwrap();
911            assert_eq!(deserialized, risk);
912        }
913    }
914
915    #[test]
916    fn test_call_pattern_type_serialization() {
917        let patterns = vec![
918            CallPatternType::Sequential,
919            CallPatternType::Recursive,
920            CallPatternType::Iterative,
921            CallPatternType::Conditional,
922            CallPatternType::Parallel,
923            CallPatternType::Asynchronous,
924            CallPatternType::Callback,
925            CallPatternType::EventDriven,
926        ];
927
928        for pattern in patterns {
929            let json = serde_json::to_string(&pattern).unwrap();
930            let deserialized: CallPatternType = serde_json::from_str(&json).unwrap();
931            assert_eq!(deserialized, pattern);
932        }
933    }
934
935    #[test]
936    fn test_function_call_tracking_info_clone() {
937        let info = FunctionCallTrackingInfo {
938            function_name: "clone_test".to_string(),
939            module_path: "test::clone".to_string(),
940            total_call_count: 10,
941            call_frequency_per_sec: 1.0,
942            avg_execution_time_ns: 100.0,
943            total_execution_time_ns: 1000,
944            call_stack_info: CallStackInfo {
945                max_stack_depth: 1,
946                avg_stack_depth: 1.0,
947                common_call_sequences: vec![],
948                recursive_calls: vec![],
949                stack_overflow_risk: StackOverflowRisk::Low,
950            },
951            memory_allocations_per_call: 0.0,
952            performance_characteristics: FunctionPerformanceCharacteristics {
953                cpu_usage_percent: 0.0,
954                memory_characteristics: FunctionMemoryCharacteristics {
955                    stack_memory_usage: 0,
956                    heap_allocations: 0,
957                    access_pattern: MemoryAccessPattern::Sequential,
958                    cache_efficiency: 0.0,
959                    memory_bandwidth_utilization: 0.0,
960                },
961                io_characteristics: IOCharacteristics {
962                    file_io_operations: 0,
963                    network_io_operations: 0,
964                    avg_io_wait_time_ns: 0.0,
965                    io_throughput_bytes_per_sec: 0.0,
966                    io_efficiency_score: 0.0,
967                },
968                concurrency_characteristics: ConcurrencyCharacteristics {
969                    thread_safety_level: ThreadSafetyLevel::Unknown,
970                    lock_contention_frequency: 0.0,
971                    parallel_execution_potential: 0.0,
972                    synchronization_overhead_ns: 0.0,
973                    deadlock_risk: DeadlockRisk::None,
974                },
975                bottlenecks: vec![],
976            },
977            call_patterns: vec![],
978        };
979
980        let cloned = info.clone();
981        assert_eq!(cloned.function_name, info.function_name);
982        assert_eq!(cloned.total_call_count, info.total_call_count);
983    }
984
985    #[test]
986    fn test_function_call_tracking_info_debug() {
987        let info = FunctionCallTrackingInfo {
988            function_name: "debug_test".to_string(),
989            module_path: "test::debug".to_string(),
990            total_call_count: 1,
991            call_frequency_per_sec: 1.0,
992            avg_execution_time_ns: 1.0,
993            total_execution_time_ns: 1,
994            call_stack_info: CallStackInfo {
995                max_stack_depth: 1,
996                avg_stack_depth: 1.0,
997                common_call_sequences: vec![],
998                recursive_calls: vec![],
999                stack_overflow_risk: StackOverflowRisk::Low,
1000            },
1001            memory_allocations_per_call: 0.0,
1002            performance_characteristics: FunctionPerformanceCharacteristics {
1003                cpu_usage_percent: 0.0,
1004                memory_characteristics: FunctionMemoryCharacteristics {
1005                    stack_memory_usage: 0,
1006                    heap_allocations: 0,
1007                    access_pattern: MemoryAccessPattern::Sequential,
1008                    cache_efficiency: 0.0,
1009                    memory_bandwidth_utilization: 0.0,
1010                },
1011                io_characteristics: IOCharacteristics {
1012                    file_io_operations: 0,
1013                    network_io_operations: 0,
1014                    avg_io_wait_time_ns: 0.0,
1015                    io_throughput_bytes_per_sec: 0.0,
1016                    io_efficiency_score: 0.0,
1017                },
1018                concurrency_characteristics: ConcurrencyCharacteristics {
1019                    thread_safety_level: ThreadSafetyLevel::Unknown,
1020                    lock_contention_frequency: 0.0,
1021                    parallel_execution_potential: 0.0,
1022                    synchronization_overhead_ns: 0.0,
1023                    deadlock_risk: DeadlockRisk::None,
1024                },
1025                bottlenecks: vec![],
1026            },
1027            call_patterns: vec![],
1028        };
1029
1030        let debug_str = format!("{:?}", info);
1031        assert!(debug_str.contains("FunctionCallTrackingInfo"));
1032        assert!(debug_str.contains("function_name"));
1033    }
1034
1035    #[test]
1036    fn test_recursion_performance_impact_creation() {
1037        let impact = RecursionPerformanceImpact {
1038            stack_overhead_per_call: 128,
1039            call_overhead_ns: 15.0,
1040            cache_impact: 0.35,
1041            optimization_recommendations: vec![
1042                "Use tail recursion".to_string(),
1043                "Convert to iteration".to_string(),
1044            ],
1045        };
1046
1047        assert_eq!(impact.stack_overhead_per_call, 128);
1048        assert_eq!(impact.optimization_recommendations.len(), 2);
1049    }
1050
1051    #[test]
1052    fn test_memory_access_pattern_variants() {
1053        let patterns = [
1054            MemoryAccessPattern::Sequential,
1055            MemoryAccessPattern::Random,
1056            MemoryAccessPattern::Strided { stride: 64 },
1057            MemoryAccessPattern::Clustered,
1058            MemoryAccessPattern::Mixed,
1059        ];
1060
1061        for pattern in patterns {
1062            let chars = FunctionMemoryCharacteristics {
1063                stack_memory_usage: 1024,
1064                heap_allocations: 5,
1065                access_pattern: pattern.clone(),
1066                cache_efficiency: 0.8,
1067                memory_bandwidth_utilization: 0.5,
1068            };
1069            assert_eq!(chars.access_pattern, pattern);
1070        }
1071    }
1072
1073    #[test]
1074    fn test_performance_bottleneck_in_function() {
1075        let bottleneck = PerformanceBottleneck {
1076            bottleneck_type: BottleneckType::MemoryAllocation,
1077            location: "test_function:42".to_string(),
1078            severity: ImpactLevel::High,
1079            description: "Excessive memory allocations".to_string(),
1080            optimization_suggestion: "Use object pool".to_string(),
1081        };
1082
1083        let chars = FunctionPerformanceCharacteristics {
1084            cpu_usage_percent: 50.0,
1085            memory_characteristics: FunctionMemoryCharacteristics {
1086                stack_memory_usage: 2048,
1087                heap_allocations: 100,
1088                access_pattern: MemoryAccessPattern::Random,
1089                cache_efficiency: 0.5,
1090                memory_bandwidth_utilization: 0.8,
1091            },
1092            io_characteristics: IOCharacteristics {
1093                file_io_operations: 0,
1094                network_io_operations: 0,
1095                avg_io_wait_time_ns: 0.0,
1096                io_throughput_bytes_per_sec: 0.0,
1097                io_efficiency_score: 1.0,
1098            },
1099            concurrency_characteristics: ConcurrencyCharacteristics {
1100                thread_safety_level: ThreadSafetyLevel::ThreadSafe,
1101                lock_contention_frequency: 0.0,
1102                parallel_execution_potential: 0.5,
1103                synchronization_overhead_ns: 0.0,
1104                deadlock_risk: DeadlockRisk::None,
1105            },
1106            bottlenecks: vec![bottleneck],
1107        };
1108
1109        assert_eq!(chars.bottlenecks.len(), 1);
1110        assert!(matches!(
1111            chars.bottlenecks[0].bottleneck_type,
1112            BottleneckType::MemoryAllocation
1113        ));
1114    }
1115
1116    #[test]
1117    fn test_boundary_values_call_count() {
1118        let info = FunctionCallTrackingInfo {
1119            function_name: "boundary_test".to_string(),
1120            module_path: "test::boundary".to_string(),
1121            total_call_count: u64::MAX,
1122            call_frequency_per_sec: f64::MAX,
1123            avg_execution_time_ns: f64::MIN,
1124            total_execution_time_ns: u64::MAX,
1125            call_stack_info: CallStackInfo {
1126                max_stack_depth: u32::MAX,
1127                avg_stack_depth: f64::MAX,
1128                common_call_sequences: vec![],
1129                recursive_calls: vec![],
1130                stack_overflow_risk: StackOverflowRisk::Critical,
1131            },
1132            memory_allocations_per_call: f64::INFINITY,
1133            performance_characteristics: FunctionPerformanceCharacteristics {
1134                cpu_usage_percent: 100.0,
1135                memory_characteristics: FunctionMemoryCharacteristics {
1136                    stack_memory_usage: usize::MAX,
1137                    heap_allocations: u32::MAX,
1138                    access_pattern: MemoryAccessPattern::Mixed,
1139                    cache_efficiency: 1.0,
1140                    memory_bandwidth_utilization: 1.0,
1141                },
1142                io_characteristics: IOCharacteristics {
1143                    file_io_operations: u32::MAX,
1144                    network_io_operations: u32::MAX,
1145                    avg_io_wait_time_ns: f64::MAX,
1146                    io_throughput_bytes_per_sec: f64::MAX,
1147                    io_efficiency_score: 0.0,
1148                },
1149                concurrency_characteristics: ConcurrencyCharacteristics {
1150                    thread_safety_level: ThreadSafetyLevel::NotThreadSafe,
1151                    lock_contention_frequency: f64::MAX,
1152                    parallel_execution_potential: 0.0,
1153                    synchronization_overhead_ns: f64::MAX,
1154                    deadlock_risk: DeadlockRisk::High,
1155                },
1156                bottlenecks: vec![],
1157            },
1158            call_patterns: vec![],
1159        };
1160
1161        assert_eq!(info.total_call_count, u64::MAX);
1162        assert_eq!(info.call_stack_info.max_stack_depth, u32::MAX);
1163    }
1164}