1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9pub use super::allocation::{ImpactLevel, RiskDistribution};
11
12#[derive(Debug, Clone, Serialize)]
14pub struct ScopeInfo {
15 pub name: String,
17 pub parent: Option<String>,
19 pub children: Vec<String>,
21 pub depth: usize,
23 pub variables: Vec<String>,
25 pub total_memory: usize,
27 pub peak_memory: usize,
29 pub allocation_count: usize,
31 pub lifetime_start: Option<u64>,
33 pub lifetime_end: Option<u64>,
35 pub is_active: bool,
37 pub start_time: u64,
39 pub end_time: Option<u64>,
41 pub memory_usage: usize,
43 pub child_scopes: Vec<String>,
45 pub parent_scope: Option<String>,
47}
48
49#[derive(Debug, Clone, Default, Serialize)]
51pub struct ScopeHierarchy {
52 pub root_scopes: Vec<String>,
54 pub scope_tree: HashMap<String, ScopeInfo>,
56 pub max_depth: usize,
58 pub total_scopes: usize,
60 pub relationships: HashMap<String, Vec<String>>,
62 pub depth_map: HashMap<String, usize>,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct TypeLifecyclePattern {
69 pub type_name: String,
71 pub average_lifetime_ms: f64,
73 pub typical_size: usize,
75 pub growth_pattern: String,
77 pub risk_level: String,
79 pub instance_count: usize,
81}
82
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
85pub enum GrowthReason {
86 Initial,
88 Expansion,
90 Reallocation,
92 Optimization,
94 UserRequested,
96}
97
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
100pub enum AllocationEventType {
101 Allocate,
103 Deallocate,
105 Reallocate,
107 Move,
109 Borrow,
111 Return,
113}
114
115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
117pub enum ScopeEventType {
118 Enter,
120 Exit,
122 Create,
124 Destroy,
126}
127
128#[derive(Debug, Clone, Serialize)]
130pub struct GrowthEvent {
131 pub timestamp: u64,
133 pub old_size: usize,
135 pub new_size: usize,
137 pub growth_factor: f64,
139 pub reason: GrowthReason,
141 pub var_name: String,
143}
144
145#[derive(Debug, Clone, Serialize)]
147pub struct BorrowEvent {
148 pub timestamp: u64,
150 pub ptr: usize,
152 pub borrow_type: String,
154 pub duration_ms: u64,
156 pub var_name: String,
158}
159
160#[derive(Debug, Clone, Serialize)]
162pub struct MoveEvent {
163 pub timestamp: u64,
165 pub from_ptr: usize,
167 pub to_ptr: usize,
169 pub size: usize,
171 pub var_name: String,
173}
174
175#[derive(Debug, Clone, Serialize)]
177pub struct VariableRelationship {
178 pub source_var: String,
180 pub target_var: String,
182 pub relationship_type: String,
184 pub strength: f64,
186}
187
188#[derive(Debug, Clone, Serialize)]
190pub struct PotentialLeak {
191 pub ptr: usize,
193 pub size: usize,
195 pub age_ms: u64,
197 pub var_name: Option<String>,
199 pub type_name: Option<String>,
201 pub severity: String,
203}
204
205#[derive(Debug, Clone, Default, Serialize)]
207pub struct ScopeAnalysis {
208 pub total_scopes: usize,
210 pub active_scopes: usize,
212 pub max_depth: usize,
214 pub average_lifetime: f64,
216 pub memory_efficiency: f64,
218 pub scopes: Vec<ScopeInfo>,
220 pub scope_hierarchy: ScopeHierarchy,
222 pub cross_scope_references: Vec<String>,
224}
225
226#[derive(Debug, Clone, Default, Serialize, Deserialize)]
228pub struct ScopeLifecycleMetrics {
229 pub scope_name: String,
231 pub variable_count: usize,
233 pub average_lifetime_ms: f64,
235 pub total_memory_usage: usize,
237 pub peak_memory_usage: usize,
239 pub allocation_frequency: f64,
241 pub deallocation_efficiency: f64,
243 pub completed_allocations: usize,
245 pub memory_growth_events: usize,
247 pub peak_concurrent_variables: usize,
249 pub memory_efficiency_ratio: f64,
251 pub ownership_transfer_events: usize,
253 pub fragmentation_score: f64,
255 pub instant_allocations: usize,
257 pub short_term_allocations: usize,
259 pub medium_term_allocations: usize,
261 pub long_term_allocations: usize,
263 pub suspected_leaks: usize,
265 pub risk_distribution: RiskDistribution,
267 pub scope_metrics: Vec<ScopeLifecycleMetrics>,
269 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}