Skip to main content

memscope_rs/capture/types/
scope.rs

1//! Scope tracking types.
2//!
3//! This module contains types for tracking scope lifecycle,
4//! hierarchy, and memory usage within scopes.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9// Re-export RiskDistribution and ImpactLevel from allocation module
10pub use super::allocation::{ImpactLevel, RiskDistribution};
11
12/// Scope information.
13#[derive(Debug, Clone, Serialize)]
14pub struct ScopeInfo {
15    /// Name.
16    pub name: String,
17    /// Parent.
18    pub parent: Option<String>,
19    /// Children.
20    pub children: Vec<String>,
21    /// Depth.
22    pub depth: usize,
23    /// Variables.
24    pub variables: Vec<String>,
25    /// Total Memory.
26    pub total_memory: usize,
27    /// Peak Memory.
28    pub peak_memory: usize,
29    /// Number of allocations.
30    pub allocation_count: usize,
31    /// Lifetime Start.
32    pub lifetime_start: Option<u64>,
33    /// Lifetime End.
34    pub lifetime_end: Option<u64>,
35    /// Is Active.
36    pub is_active: bool,
37    /// Start Time.
38    pub start_time: u64,
39    /// End Time.
40    pub end_time: Option<u64>,
41    /// Memory Usage.
42    pub memory_usage: usize,
43    /// Child Scopes.
44    pub child_scopes: Vec<String>,
45    /// Parent Scope.
46    pub parent_scope: Option<String>,
47}
48
49/// Scope hierarchy.
50#[derive(Debug, Clone, Default, Serialize)]
51pub struct ScopeHierarchy {
52    /// Root Scopes.
53    pub root_scopes: Vec<String>,
54    /// Scope Tree.
55    pub scope_tree: HashMap<String, ScopeInfo>,
56    /// Max Depth.
57    pub max_depth: usize,
58    /// Total Scopes.
59    pub total_scopes: usize,
60    /// Relationships.
61    pub relationships: HashMap<String, Vec<String>>,
62    /// Depth Map.
63    pub depth_map: HashMap<String, usize>,
64}
65
66/// Type-specific lifecycle pattern analysis.
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct TypeLifecyclePattern {
69    /// Type Name.
70    pub type_name: String,
71    /// Average lifetime in milliseconds.
72    pub average_lifetime_ms: f64,
73    /// Typical Size.
74    pub typical_size: usize,
75    /// Growth Pattern.
76    pub growth_pattern: String,
77    /// Risk Level.
78    pub risk_level: String,
79    /// Instance Count.
80    pub instance_count: usize,
81}
82
83/// Growth reason for tracking allocation growth.
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85pub enum GrowthReason {
86    /// Initial allocation.
87    Initial,
88    /// Memory expansion.
89    Expansion,
90    /// Memory reallocation.
91    Reallocation,
92    /// Performance optimization.
93    Optimization,
94    /// User-requested allocation.
95    UserRequested,
96}
97
98/// Type of allocation event.
99#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
100pub enum AllocationEventType {
101    /// Memory allocation event.
102    Allocate,
103    /// Memory deallocation event.
104    Deallocate,
105    /// Memory reallocation event.
106    Reallocate,
107    /// Memory move event.
108    Move,
109    /// Memory borrow event.
110    Borrow,
111    /// Memory return event.
112    Return,
113}
114
115/// Type of scope event.
116#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
117pub enum ScopeEventType {
118    /// Enter scope event.
119    Enter,
120    /// Exit scope event.
121    Exit,
122    /// Create scope event.
123    Create,
124    /// Destroy scope event.
125    Destroy,
126}
127
128/// Growth event tracking allocation growth patterns.
129#[derive(Debug, Clone, Serialize)]
130pub struct GrowthEvent {
131    /// Timestamp.
132    pub timestamp: u64,
133    /// Old Size.
134    pub old_size: usize,
135    /// New Size.
136    pub new_size: usize,
137    /// Growth Factor.
138    pub growth_factor: f64,
139    /// Reason.
140    pub reason: GrowthReason,
141    /// Var Name.
142    pub var_name: String,
143}
144
145/// Borrow event for tracking borrowing patterns.
146#[derive(Debug, Clone, Serialize)]
147pub struct BorrowEvent {
148    /// Timestamp.
149    pub timestamp: u64,
150    /// Memory pointer address.
151    pub ptr: usize,
152    /// Borrow Type.
153    pub borrow_type: String,
154    /// Duration Ms.
155    pub duration_ms: u64,
156    /// Var Name.
157    pub var_name: String,
158}
159
160/// Move event for tracking ownership transfers.
161#[derive(Debug, Clone, Serialize)]
162pub struct MoveEvent {
163    /// Timestamp.
164    pub timestamp: u64,
165    /// From Ptr.
166    pub from_ptr: usize,
167    /// To Ptr.
168    pub to_ptr: usize,
169    /// Size in bytes.
170    pub size: usize,
171    /// Var Name.
172    pub var_name: String,
173}
174
175/// Variable relationship tracking.
176#[derive(Debug, Clone, Serialize)]
177pub struct VariableRelationship {
178    /// Source Var.
179    pub source_var: String,
180    /// Target Var.
181    pub target_var: String,
182    /// Relationship Type.
183    pub relationship_type: String,
184    /// Strength.
185    pub strength: f64,
186}
187
188/// Potential memory leak detection.
189#[derive(Debug, Clone, Serialize)]
190pub struct PotentialLeak {
191    /// Memory pointer address.
192    pub ptr: usize,
193    /// Size in bytes.
194    pub size: usize,
195    /// Age in milliseconds.
196    pub age_ms: u64,
197    /// Var Name.
198    pub var_name: Option<String>,
199    /// Type Name.
200    pub type_name: Option<String>,
201    /// Severity.
202    pub severity: String,
203}
204
205/// Scope analysis results.
206#[derive(Debug, Clone, Default, Serialize)]
207pub struct ScopeAnalysis {
208    /// Total scopes
209    pub total_scopes: usize,
210    /// Active scopes
211    pub active_scopes: usize,
212    /// Max depth
213    pub max_depth: usize,
214    /// Average lifetime in milliseconds
215    pub average_lifetime: f64,
216    /// Memory efficiency ratio
217    pub memory_efficiency: f64,
218    /// Scope information
219    pub scopes: Vec<ScopeInfo>,
220    /// Scope hierarchy
221    pub scope_hierarchy: ScopeHierarchy,
222    /// Cross scope references
223    pub cross_scope_references: Vec<String>,
224}
225
226/// Scope lifecycle metrics.
227#[derive(Debug, Clone, Default, Serialize, Deserialize)]
228pub struct ScopeLifecycleMetrics {
229    /// Name of the scope
230    pub scope_name: String,
231    /// Number of variables in scope
232    pub variable_count: usize,
233    /// Average lifetime in milliseconds
234    pub average_lifetime_ms: f64,
235    /// Total memory used by scope
236    pub total_memory_usage: usize,
237    /// Peak memory usage in scope
238    pub peak_memory_usage: usize,
239    /// Frequency of allocations
240    pub allocation_frequency: f64,
241    /// Efficiency of deallocations
242    pub deallocation_efficiency: f64,
243    /// Number of completed allocations
244    pub completed_allocations: usize,
245    /// Number of memory growth events
246    pub memory_growth_events: usize,
247    /// Peak number of concurrent variables
248    pub peak_concurrent_variables: usize,
249    /// Memory efficiency ratio
250    pub memory_efficiency_ratio: f64,
251    /// Number of ownership transfers
252    pub ownership_transfer_events: usize,
253    /// Fragmentation score
254    pub fragmentation_score: f64,
255    /// Number of instant allocations
256    pub instant_allocations: usize,
257    /// Number of short-term allocations
258    pub short_term_allocations: usize,
259    /// Number of medium-term allocations
260    pub medium_term_allocations: usize,
261    /// Number of long-term allocations
262    pub long_term_allocations: usize,
263    /// Number of suspected memory leaks
264    pub suspected_leaks: usize,
265    /// Risk distribution analysis
266    pub risk_distribution: RiskDistribution,
267    /// Metrics for individual scopes
268    pub scope_metrics: Vec<ScopeLifecycleMetrics>,
269    /// Lifecycle patterns for types
270    pub type_lifecycle_patterns: Vec<TypeLifecyclePattern>,
271}
272
273#[cfg(test)]
274mod tests {
275    use super::*;
276
277    #[test]
278    fn test_risk_distribution_default() {
279        let risk = RiskDistribution::default();
280
281        assert_eq!(risk.low_risk, 0);
282        assert_eq!(risk.medium_risk, 0);
283        assert_eq!(risk.high_risk, 0);
284        assert_eq!(risk.critical_risk, 0);
285    }
286
287    #[test]
288    fn test_allocation_event_type_variants() {
289        let events = vec![
290            AllocationEventType::Allocate,
291            AllocationEventType::Deallocate,
292            AllocationEventType::Reallocate,
293            AllocationEventType::Move,
294            AllocationEventType::Borrow,
295            AllocationEventType::Return,
296        ];
297
298        for event in events {
299            assert!(!format!("{event:?}").is_empty());
300        }
301    }
302
303    #[test]
304    fn test_scope_event_type_variants() {
305        let events = vec![
306            ScopeEventType::Enter,
307            ScopeEventType::Exit,
308            ScopeEventType::Create,
309            ScopeEventType::Destroy,
310        ];
311
312        for event in events {
313            assert!(!format!("{event:?}").is_empty());
314        }
315    }
316
317    #[test]
318    fn test_growth_reason_variants() {
319        let reasons = vec![
320            GrowthReason::Initial,
321            GrowthReason::Expansion,
322            GrowthReason::Reallocation,
323            GrowthReason::Optimization,
324            GrowthReason::UserRequested,
325        ];
326
327        for reason in reasons {
328            assert!(!format!("{reason:?}").is_empty());
329        }
330    }
331
332    #[test]
333    fn test_scope_info_creation() {
334        let scope = ScopeInfo {
335            name: "main".to_string(),
336            parent: None,
337            children: vec![],
338            depth: 0,
339            variables: vec!["x".to_string(), "y".to_string()],
340            total_memory: 1024,
341            peak_memory: 2048,
342            allocation_count: 5,
343            lifetime_start: Some(0),
344            lifetime_end: Some(1000),
345            is_active: false,
346            start_time: 0,
347            end_time: Some(1000),
348            memory_usage: 1024,
349            child_scopes: vec![],
350            parent_scope: None,
351        };
352
353        assert_eq!(scope.name, "main");
354        assert_eq!(scope.variables.len(), 2);
355        assert_eq!(scope.total_memory, 1024);
356    }
357
358    #[test]
359    fn test_scope_info_with_parent() {
360        let scope = ScopeInfo {
361            name: "inner".to_string(),
362            parent: Some("main".to_string()),
363            children: vec![],
364            depth: 1,
365            variables: vec![],
366            total_memory: 0,
367            peak_memory: 0,
368            allocation_count: 0,
369            lifetime_start: None,
370            lifetime_end: None,
371            is_active: true,
372            start_time: 100,
373            end_time: None,
374            memory_usage: 0,
375            child_scopes: vec![],
376            parent_scope: Some("main".to_string()),
377        };
378
379        assert_eq!(scope.depth, 1);
380        assert!(scope.is_active);
381        assert_eq!(scope.parent, Some("main".to_string()));
382    }
383
384    #[test]
385    fn test_scope_hierarchy_default() {
386        let hierarchy = ScopeHierarchy::default();
387
388        assert!(hierarchy.root_scopes.is_empty());
389        assert!(hierarchy.scope_tree.is_empty());
390        assert_eq!(hierarchy.max_depth, 0);
391        assert_eq!(hierarchy.total_scopes, 0);
392    }
393
394    #[test]
395    fn test_scope_hierarchy_with_scopes() {
396        let mut scope_tree = HashMap::new();
397        scope_tree.insert(
398            "main".to_string(),
399            ScopeInfo {
400                name: "main".to_string(),
401                parent: None,
402                children: vec!["inner".to_string()],
403                depth: 0,
404                variables: vec![],
405                total_memory: 1024,
406                peak_memory: 1024,
407                allocation_count: 1,
408                lifetime_start: None,
409                lifetime_end: None,
410                is_active: true,
411                start_time: 0,
412                end_time: None,
413                memory_usage: 1024,
414                child_scopes: vec!["inner".to_string()],
415                parent_scope: None,
416            },
417        );
418
419        let hierarchy = ScopeHierarchy {
420            root_scopes: vec!["main".to_string()],
421            scope_tree,
422            max_depth: 1,
423            total_scopes: 2,
424            relationships: HashMap::new(),
425            depth_map: HashMap::new(),
426        };
427
428        assert_eq!(hierarchy.root_scopes.len(), 1);
429        assert_eq!(hierarchy.total_scopes, 2);
430    }
431
432    #[test]
433    fn test_type_lifecycle_pattern_creation() {
434        let pattern = TypeLifecyclePattern {
435            type_name: "Vec<u8>".to_string(),
436            average_lifetime_ms: 500.0,
437            typical_size: 1024,
438            growth_pattern: "exponential".to_string(),
439            risk_level: "low".to_string(),
440            instance_count: 100,
441        };
442
443        assert_eq!(pattern.type_name, "Vec<u8>");
444        assert_eq!(pattern.average_lifetime_ms, 500.0);
445    }
446
447    #[test]
448    fn test_growth_event_creation() {
449        let event = GrowthEvent {
450            timestamp: 1000,
451            old_size: 1024,
452            new_size: 2048,
453            growth_factor: 2.0,
454            reason: GrowthReason::Expansion,
455            var_name: "buffer".to_string(),
456        };
457
458        assert_eq!(event.growth_factor, 2.0);
459        assert_eq!(event.reason, GrowthReason::Expansion);
460    }
461
462    #[test]
463    fn test_borrow_event_creation() {
464        let event = BorrowEvent {
465            timestamp: 100,
466            ptr: 0x1000,
467            borrow_type: "immutable".to_string(),
468            duration_ms: 50,
469            var_name: "data".to_string(),
470        };
471
472        assert_eq!(event.borrow_type, "immutable");
473        assert_eq!(event.duration_ms, 50);
474    }
475
476    #[test]
477    fn test_move_event_creation() {
478        let event = MoveEvent {
479            timestamp: 200,
480            from_ptr: 0x1000,
481            to_ptr: 0x2000,
482            size: 1024,
483            var_name: "value".to_string(),
484        };
485
486        assert_eq!(event.from_ptr, 0x1000);
487        assert_eq!(event.to_ptr, 0x2000);
488    }
489
490    #[test]
491    fn test_variable_relationship_creation() {
492        let rel = VariableRelationship {
493            source_var: "parent".to_string(),
494            target_var: "child".to_string(),
495            relationship_type: "ownership".to_string(),
496            strength: 0.9,
497        };
498
499        assert_eq!(rel.relationship_type, "ownership");
500        assert_eq!(rel.strength, 0.9);
501    }
502
503    #[test]
504    fn test_potential_leak_creation() {
505        let leak = PotentialLeak {
506            ptr: 0x1000,
507            size: 1024,
508            age_ms: 5000,
509            var_name: Some("leaked".to_string()),
510            type_name: Some("String".to_string()),
511            severity: "high".to_string(),
512        };
513
514        assert_eq!(leak.ptr, 0x1000);
515        assert_eq!(leak.severity, "high");
516    }
517
518    #[test]
519    fn test_scope_analysis_default() {
520        let analysis = ScopeAnalysis::default();
521
522        assert_eq!(analysis.total_scopes, 0);
523        assert_eq!(analysis.active_scopes, 0);
524        assert_eq!(analysis.max_depth, 0);
525    }
526
527    #[test]
528    fn test_scope_lifecycle_metrics_default() {
529        let metrics = ScopeLifecycleMetrics::default();
530
531        assert!(metrics.scope_name.is_empty());
532        assert_eq!(metrics.variable_count, 0);
533        assert_eq!(metrics.average_lifetime_ms, 0.0);
534    }
535
536    #[test]
537    fn test_scope_lifecycle_metrics_with_values() {
538        let metrics = ScopeLifecycleMetrics {
539            scope_name: "test_scope".to_string(),
540            variable_count: 10,
541            average_lifetime_ms: 100.0,
542            total_memory_usage: 4096,
543            peak_memory_usage: 8192,
544            allocation_frequency: 50.0,
545            deallocation_efficiency: 0.95,
546            completed_allocations: 100,
547            memory_growth_events: 5,
548            peak_concurrent_variables: 20,
549            memory_efficiency_ratio: 0.85,
550            ownership_transfer_events: 10,
551            fragmentation_score: 0.1,
552            instant_allocations: 30,
553            short_term_allocations: 40,
554            medium_term_allocations: 20,
555            long_term_allocations: 10,
556            suspected_leaks: 1,
557            risk_distribution: RiskDistribution::default(),
558            scope_metrics: vec![],
559            type_lifecycle_patterns: vec![],
560        };
561
562        assert_eq!(metrics.scope_name, "test_scope");
563        assert_eq!(metrics.variable_count, 10);
564        assert_eq!(metrics.total_memory_usage, 4096);
565    }
566
567    #[test]
568    fn test_allocation_event_type_equality() {
569        assert_eq!(AllocationEventType::Allocate, AllocationEventType::Allocate);
570        assert_ne!(
571            AllocationEventType::Allocate,
572            AllocationEventType::Deallocate
573        );
574    }
575
576    #[test]
577    fn test_scope_event_type_equality() {
578        assert_eq!(ScopeEventType::Enter, ScopeEventType::Enter);
579        assert_ne!(ScopeEventType::Enter, ScopeEventType::Exit);
580    }
581
582    #[test]
583    fn test_growth_reason_equality() {
584        assert_eq!(GrowthReason::Initial, GrowthReason::Initial);
585        assert_ne!(GrowthReason::Initial, GrowthReason::Expansion);
586    }
587}