1use serde::{Deserialize, Serialize};
7
8use super::generic::SourceLocation;
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub struct ObjectLifecycleInfo {
13 pub object_id: usize,
15 pub type_name: String,
17 pub lifecycle_events: Vec<LifecycleEvent>,
19 pub total_lifetime_ns: Option<u64>,
21 pub stage_durations: LifecycleStageDurations,
23 pub efficiency_metrics: LifecycleEfficiencyMetrics,
25 pub lifecycle_patterns: Vec<LifecyclePattern>,
27}
28
29#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
31pub struct LifecycleEvent {
32 pub event_type: LifecycleEventType,
34 pub timestamp: u64,
36 pub location: SourceLocation,
38 pub memory_state: MemoryState,
40 pub performance_metrics: EventPerformanceMetrics,
42 pub call_stack: Vec<String>,
44}
45
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48pub enum LifecycleEventType {
49 Creation,
51 Initialization,
53 FirstUse,
55 Move,
57 Copy,
59 Clone,
61 Borrow,
63 MutableBorrow,
65 BorrowRelease,
67 Modification,
69 LastUse,
71 Drop,
73 Destruction,
75 MemoryReclaim,
77}
78
79#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81pub struct MemoryState {
82 pub memory_location: MemoryLocationType,
84 pub memory_address: usize,
86 pub object_size: usize,
88 pub reference_count: Option<u32>,
90 pub borrow_state: BorrowState,
92}
93
94#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
96pub enum BorrowState {
97 NotBorrowed,
99 SharedBorrow {
101 count: u32,
103 },
104 MutableBorrow,
106 MovedOut,
108}
109
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112pub enum MemoryLocationType {
113 Stack,
115 Heap,
117 Register,
119 Static,
121 ThreadLocal,
123}
124
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
127pub struct EventPerformanceMetrics {
128 pub cpu_cycles: u64,
130 pub memory_bandwidth_bytes: usize,
132 pub cache_misses: u32,
134 pub processing_time_ns: u64,
136}
137
138#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
140pub struct LifecycleStageDurations {
141 pub creation_to_first_use_ns: Option<u64>,
143 pub active_use_duration_ns: Option<u64>,
145 pub last_use_to_destruction_ns: Option<u64>,
147 pub borrowed_duration_ns: u64,
149 pub idle_duration_ns: u64,
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
155pub struct LifecycleEfficiencyMetrics {
156 pub utilization_ratio: f64,
158 pub memory_efficiency: f64,
160 pub performance_efficiency: f64,
162 pub resource_waste: ResourceWasteAssessment,
164}
165
166impl Default for LifecycleEfficiencyMetrics {
167 fn default() -> Self {
168 Self {
169 utilization_ratio: 0.0,
170 memory_efficiency: 0.0,
171 performance_efficiency: 0.0,
172 resource_waste: ResourceWasteAssessment {
173 wasted_memory_percent: 0.0,
174 wasted_cpu_percent: 0.0,
175 premature_destructions: 0,
176 unused_instances: 0,
177 optimization_opportunities: Vec::new(),
178 },
179 }
180 }
181}
182
183#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
185pub struct ResourceWasteAssessment {
186 pub wasted_memory_percent: f64,
188 pub wasted_cpu_percent: f64,
190 pub premature_destructions: u32,
192 pub unused_instances: u32,
194 pub optimization_opportunities: Vec<String>,
196}
197
198#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
200pub struct LifecyclePattern {
201 pub pattern_type: LifecyclePatternType,
203 pub frequency: u32,
205 pub efficiency_score: f64,
207 pub performance_impact: f64,
209 pub optimization_suggestions: Vec<String>,
211}
212
213#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
215pub enum LifecyclePatternType {
216 ShortLived,
218 LongLived,
220 Cyclical,
222 OnDemand,
224 Cached,
226 Pooled,
228 Singleton,
230 Factory,
232 RAII,
234}
235
236#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
238pub enum SimpleLifecyclePattern {
239 Instant,
241 ShortLived,
243 MediumLived,
245 LongLived,
247 Persistent,
249}
250
251impl From<crate::core::types::ObjectLifecycleInfo> for ObjectLifecycleInfo {
252 fn from(old: crate::core::types::ObjectLifecycleInfo) -> Self {
253 Self {
254 object_id: old.object_id,
255 type_name: old.type_name,
256 lifecycle_events: old
257 .lifecycle_events
258 .into_iter()
259 .map(|e| LifecycleEvent {
260 event_type: match e.event_type {
261 crate::core::types::LifecycleEventType::Creation => {
262 LifecycleEventType::Creation
263 }
264 crate::core::types::LifecycleEventType::Initialization => {
265 LifecycleEventType::Initialization
266 }
267 crate::core::types::LifecycleEventType::FirstUse => {
268 LifecycleEventType::FirstUse
269 }
270 crate::core::types::LifecycleEventType::Move => LifecycleEventType::Move,
271 crate::core::types::LifecycleEventType::Copy => LifecycleEventType::Copy,
272 crate::core::types::LifecycleEventType::Clone => LifecycleEventType::Clone,
273 crate::core::types::LifecycleEventType::Borrow => {
274 LifecycleEventType::Borrow
275 }
276 crate::core::types::LifecycleEventType::MutableBorrow => {
277 LifecycleEventType::MutableBorrow
278 }
279 crate::core::types::LifecycleEventType::BorrowRelease => {
280 LifecycleEventType::BorrowRelease
281 }
282 crate::core::types::LifecycleEventType::Modification => {
283 LifecycleEventType::Modification
284 }
285 crate::core::types::LifecycleEventType::LastUse => {
286 LifecycleEventType::LastUse
287 }
288 crate::core::types::LifecycleEventType::Drop => LifecycleEventType::Drop,
289 crate::core::types::LifecycleEventType::Destruction => {
290 LifecycleEventType::Destruction
291 }
292 crate::core::types::LifecycleEventType::MemoryReclaim => {
293 LifecycleEventType::MemoryReclaim
294 }
295 },
296 timestamp: e.timestamp,
297 location: SourceLocation {
298 file: e.location.file,
299 line: e.location.line,
300 column: e.location.column,
301 },
302 memory_state: MemoryState {
303 memory_location: match e.memory_state.memory_location {
304 crate::core::types::MemoryLocationType::Stack => {
305 MemoryLocationType::Stack
306 }
307 crate::core::types::MemoryLocationType::Heap => {
308 MemoryLocationType::Heap
309 }
310 crate::core::types::MemoryLocationType::Register => {
311 MemoryLocationType::Register
312 }
313 crate::core::types::MemoryLocationType::Static => {
314 MemoryLocationType::Static
315 }
316 crate::core::types::MemoryLocationType::ThreadLocal => {
317 MemoryLocationType::ThreadLocal
318 }
319 },
320 memory_address: e.memory_state.memory_address,
321 object_size: e.memory_state.object_size,
322 reference_count: e.memory_state.reference_count,
323 borrow_state: match e.memory_state.borrow_state {
324 crate::core::types::BorrowState::NotBorrowed => {
325 BorrowState::NotBorrowed
326 }
327 crate::core::types::BorrowState::SharedBorrow { count } => {
328 BorrowState::SharedBorrow { count }
329 }
330 crate::core::types::BorrowState::MutableBorrow => {
331 BorrowState::MutableBorrow
332 }
333 crate::core::types::BorrowState::MovedOut => BorrowState::MovedOut,
334 },
335 },
336 performance_metrics: EventPerformanceMetrics {
337 cpu_cycles: e.performance_metrics.cpu_cycles,
338 memory_bandwidth_bytes: e.performance_metrics.memory_bandwidth_bytes,
339 cache_misses: e.performance_metrics.cache_misses,
340 processing_time_ns: e.performance_metrics.processing_time_ns,
341 },
342 call_stack: e.call_stack,
343 })
344 .collect(),
345 total_lifetime_ns: old.total_lifetime_ns,
346 stage_durations: LifecycleStageDurations {
347 creation_to_first_use_ns: old.stage_durations.creation_to_first_use_ns,
348 active_use_duration_ns: old.stage_durations.active_use_duration_ns,
349 last_use_to_destruction_ns: old.stage_durations.last_use_to_destruction_ns,
350 borrowed_duration_ns: old.stage_durations.borrowed_duration_ns,
351 idle_duration_ns: old.stage_durations.idle_duration_ns,
352 },
353 efficiency_metrics: LifecycleEfficiencyMetrics {
354 utilization_ratio: old.efficiency_metrics.utilization_ratio,
355 memory_efficiency: old.efficiency_metrics.memory_efficiency,
356 performance_efficiency: old.efficiency_metrics.performance_efficiency,
357 resource_waste: ResourceWasteAssessment {
358 wasted_memory_percent: old
359 .efficiency_metrics
360 .resource_waste
361 .wasted_memory_percent,
362 wasted_cpu_percent: old.efficiency_metrics.resource_waste.wasted_cpu_percent,
363 premature_destructions: old
364 .efficiency_metrics
365 .resource_waste
366 .premature_destructions,
367 unused_instances: old.efficiency_metrics.resource_waste.unused_instances,
368 optimization_opportunities: old
369 .efficiency_metrics
370 .resource_waste
371 .optimization_opportunities,
372 },
373 },
374 lifecycle_patterns: old
375 .lifecycle_patterns
376 .into_iter()
377 .map(|p| LifecyclePattern {
378 pattern_type: match p.pattern_type {
379 crate::core::types::LifecyclePatternType::ShortLived => {
380 LifecyclePatternType::ShortLived
381 }
382 crate::core::types::LifecyclePatternType::LongLived => {
383 LifecyclePatternType::LongLived
384 }
385 crate::core::types::LifecyclePatternType::Cyclical => {
386 LifecyclePatternType::Cyclical
387 }
388 crate::core::types::LifecyclePatternType::OnDemand => {
389 LifecyclePatternType::OnDemand
390 }
391 crate::core::types::LifecyclePatternType::Cached => {
392 LifecyclePatternType::Cached
393 }
394 crate::core::types::LifecyclePatternType::Pooled => {
395 LifecyclePatternType::Pooled
396 }
397 crate::core::types::LifecyclePatternType::Singleton => {
398 LifecyclePatternType::Singleton
399 }
400 crate::core::types::LifecyclePatternType::Factory => {
401 LifecyclePatternType::Factory
402 }
403 crate::core::types::LifecyclePatternType::RAII => {
404 LifecyclePatternType::RAII
405 }
406 },
407 frequency: p.frequency,
408 efficiency_score: p.efficiency_score,
409 performance_impact: p.performance_impact,
410 optimization_suggestions: p.optimization_suggestions,
411 })
412 .collect(),
413 }
414 }
415}
416
417#[cfg(test)]
418mod tests {
419 use super::*;
420
421 #[test]
424 fn test_object_lifecycle_info() {
425 let info = ObjectLifecycleInfo {
426 object_id: 1,
427 type_name: "String".to_string(),
428 lifecycle_events: vec![],
429 total_lifetime_ns: Some(1000000),
430 stage_durations: LifecycleStageDurations {
431 creation_to_first_use_ns: Some(100),
432 active_use_duration_ns: Some(900000),
433 last_use_to_destruction_ns: Some(99900),
434 borrowed_duration_ns: 100000,
435 idle_duration_ns: 50000,
436 },
437 efficiency_metrics: LifecycleEfficiencyMetrics::default(),
438 lifecycle_patterns: vec![],
439 };
440
441 assert_eq!(info.object_id, 1, "Object ID should match");
442 assert_eq!(info.type_name, "String", "Type name should match");
443 assert_eq!(
444 info.total_lifetime_ns,
445 Some(1000000),
446 "Total lifetime should match"
447 );
448 }
449
450 #[test]
453 fn test_lifecycle_event_type() {
454 let events = vec![
455 LifecycleEventType::Creation,
456 LifecycleEventType::Initialization,
457 LifecycleEventType::FirstUse,
458 LifecycleEventType::Move,
459 LifecycleEventType::Copy,
460 LifecycleEventType::Clone,
461 LifecycleEventType::Borrow,
462 LifecycleEventType::MutableBorrow,
463 LifecycleEventType::BorrowRelease,
464 LifecycleEventType::Modification,
465 LifecycleEventType::LastUse,
466 LifecycleEventType::Drop,
467 LifecycleEventType::Destruction,
468 LifecycleEventType::MemoryReclaim,
469 ];
470
471 for event in events {
472 let debug_str = format!("{event:?}");
473 assert!(
474 !debug_str.is_empty(),
475 "LifecycleEventType should have debug representation"
476 );
477 }
478 }
479
480 #[test]
483 fn test_lifecycle_event() {
484 let event = LifecycleEvent {
485 event_type: LifecycleEventType::Creation,
486 timestamp: 1000,
487 location: SourceLocation {
488 file: "test.rs".to_string(),
489 line: 10,
490 column: 5,
491 },
492 memory_state: MemoryState {
493 memory_location: MemoryLocationType::Heap,
494 memory_address: 0x1000,
495 object_size: 64,
496 reference_count: Some(1),
497 borrow_state: BorrowState::NotBorrowed,
498 },
499 performance_metrics: EventPerformanceMetrics {
500 cpu_cycles: 1000,
501 memory_bandwidth_bytes: 64,
502 cache_misses: 2,
503 processing_time_ns: 500,
504 },
505 call_stack: vec!["main".to_string(), "test".to_string()],
506 };
507
508 assert_eq!(
509 event.event_type,
510 LifecycleEventType::Creation,
511 "Event type should be Creation"
512 );
513 assert_eq!(event.timestamp, 1000, "Timestamp should match");
514 assert_eq!(event.call_stack.len(), 2, "Call stack should have 2 frames");
515 }
516
517 #[test]
520 fn test_memory_state() {
521 let state = MemoryState {
522 memory_location: MemoryLocationType::Stack,
523 memory_address: 0x7fff0000,
524 object_size: 32,
525 reference_count: None,
526 borrow_state: BorrowState::SharedBorrow { count: 3 },
527 };
528
529 assert_eq!(
530 state.memory_location,
531 MemoryLocationType::Stack,
532 "Memory location should be Stack"
533 );
534 assert_eq!(
535 state.borrow_state,
536 BorrowState::SharedBorrow { count: 3 },
537 "Borrow state should be SharedBorrow with count 3"
538 );
539 }
540
541 #[test]
544 fn test_borrow_state_variants() {
545 let states = vec![
546 BorrowState::NotBorrowed,
547 BorrowState::SharedBorrow { count: 1 },
548 BorrowState::MutableBorrow,
549 BorrowState::MovedOut,
550 ];
551
552 for state in &states {
553 let debug_str = format!("{state:?}");
554 assert!(
555 !debug_str.is_empty(),
556 "BorrowState should have debug representation"
557 );
558 }
559
560 assert_eq!(BorrowState::NotBorrowed, BorrowState::NotBorrowed);
561 assert_ne!(BorrowState::NotBorrowed, BorrowState::MutableBorrow);
562 }
563
564 #[test]
567 fn test_memory_location_type_variants() {
568 let locations = vec![
569 MemoryLocationType::Stack,
570 MemoryLocationType::Heap,
571 MemoryLocationType::Register,
572 MemoryLocationType::Static,
573 MemoryLocationType::ThreadLocal,
574 ];
575
576 for location in &locations {
577 let debug_str = format!("{location:?}");
578 assert!(
579 !debug_str.is_empty(),
580 "MemoryLocationType should have debug representation"
581 );
582 }
583 }
584
585 #[test]
588 fn test_event_performance_metrics() {
589 let metrics = EventPerformanceMetrics {
590 cpu_cycles: 5000,
591 memory_bandwidth_bytes: 1024,
592 cache_misses: 10,
593 processing_time_ns: 2000,
594 };
595
596 assert_eq!(metrics.cpu_cycles, 5000, "CPU cycles should match");
597 assert_eq!(
598 metrics.memory_bandwidth_bytes, 1024,
599 "Memory bandwidth should match"
600 );
601 assert_eq!(metrics.cache_misses, 10, "Cache misses should match");
602 }
603
604 #[test]
607 fn test_lifecycle_stage_durations() {
608 let durations = LifecycleStageDurations {
609 creation_to_first_use_ns: Some(100),
610 active_use_duration_ns: Some(1000),
611 last_use_to_destruction_ns: Some(50),
612 borrowed_duration_ns: 200,
613 idle_duration_ns: 100,
614 };
615
616 assert_eq!(
617 durations.creation_to_first_use_ns,
618 Some(100),
619 "Creation to first use should match"
620 );
621 assert_eq!(
622 durations.active_use_duration_ns,
623 Some(1000),
624 "Active use duration should match"
625 );
626 }
627
628 #[test]
631 fn test_lifecycle_efficiency_metrics_default() {
632 let metrics = LifecycleEfficiencyMetrics::default();
633
634 assert_eq!(
635 metrics.utilization_ratio, 0.0,
636 "Utilization ratio should be 0"
637 );
638 assert_eq!(
639 metrics.memory_efficiency, 0.0,
640 "Memory efficiency should be 0"
641 );
642 assert_eq!(
643 metrics.performance_efficiency, 0.0,
644 "Performance efficiency should be 0"
645 );
646 assert_eq!(
647 metrics.resource_waste.wasted_memory_percent, 0.0,
648 "Wasted memory should be 0"
649 );
650 }
651
652 #[test]
655 fn test_lifecycle_efficiency_metrics_with_values() {
656 let metrics = LifecycleEfficiencyMetrics {
657 utilization_ratio: 0.85,
658 memory_efficiency: 0.9,
659 performance_efficiency: 0.95,
660 resource_waste: ResourceWasteAssessment {
661 wasted_memory_percent: 5.0,
662 wasted_cpu_percent: 3.0,
663 premature_destructions: 2,
664 unused_instances: 5,
665 optimization_opportunities: vec!["Use pool".to_string()],
666 },
667 };
668
669 assert_eq!(
670 metrics.utilization_ratio, 0.85,
671 "Utilization ratio should match"
672 );
673 assert_eq!(
674 metrics.resource_waste.premature_destructions, 2,
675 "Premature destructions should match"
676 );
677 assert_eq!(
678 metrics.resource_waste.optimization_opportunities.len(),
679 1,
680 "Should have one optimization opportunity"
681 );
682 }
683
684 #[test]
687 fn test_resource_waste_assessment() {
688 let assessment = ResourceWasteAssessment {
689 wasted_memory_percent: 10.0,
690 wasted_cpu_percent: 5.0,
691 premature_destructions: 3,
692 unused_instances: 10,
693 optimization_opportunities: vec!["Optimize A".to_string(), "Optimize B".to_string()],
694 };
695
696 assert_eq!(
697 assessment.wasted_memory_percent, 10.0,
698 "Wasted memory percent should match"
699 );
700 assert_eq!(
701 assessment.unused_instances, 10,
702 "Unused instances should match"
703 );
704 }
705
706 #[test]
709 fn test_lifecycle_pattern() {
710 let pattern = LifecyclePattern {
711 pattern_type: LifecyclePatternType::ShortLived,
712 frequency: 100,
713 efficiency_score: 0.8,
714 performance_impact: 0.2,
715 optimization_suggestions: vec!["Consider pooling".to_string()],
716 };
717
718 assert_eq!(
719 pattern.pattern_type,
720 LifecyclePatternType::ShortLived,
721 "Pattern type should match"
722 );
723 assert_eq!(pattern.frequency, 100, "Frequency should match");
724 }
725
726 #[test]
729 fn test_lifecycle_pattern_type_variants() {
730 let patterns = vec![
731 LifecyclePatternType::ShortLived,
732 LifecyclePatternType::LongLived,
733 LifecyclePatternType::Cyclical,
734 LifecyclePatternType::OnDemand,
735 LifecyclePatternType::Cached,
736 LifecyclePatternType::Pooled,
737 LifecyclePatternType::Singleton,
738 LifecyclePatternType::Factory,
739 LifecyclePatternType::RAII,
740 ];
741
742 for pattern in &patterns {
743 let debug_str = format!("{pattern:?}");
744 assert!(
745 !debug_str.is_empty(),
746 "LifecyclePatternType should have debug representation"
747 );
748 }
749 }
750
751 #[test]
754 fn test_simple_lifecycle_pattern_variants() {
755 let patterns = vec![
756 SimpleLifecyclePattern::Instant,
757 SimpleLifecyclePattern::ShortLived,
758 SimpleLifecyclePattern::MediumLived,
759 SimpleLifecyclePattern::LongLived,
760 SimpleLifecyclePattern::Persistent,
761 ];
762
763 for pattern in &patterns {
764 let debug_str = format!("{pattern:?}");
765 assert!(
766 !debug_str.is_empty(),
767 "SimpleLifecyclePattern should have debug representation"
768 );
769 }
770 }
771
772 #[test]
775 fn test_lifecycle_event_type_serialization() {
776 let event_type = LifecycleEventType::Clone;
777 let json = serde_json::to_string(&event_type);
778 assert!(json.is_ok(), "Should serialize to JSON");
779
780 let deserialized: Result<LifecycleEventType, _> = serde_json::from_str(&json.unwrap());
781 assert!(deserialized.is_ok(), "Should deserialize from JSON");
782 assert_eq!(
783 deserialized.unwrap(),
784 LifecycleEventType::Clone,
785 "Should preserve value"
786 );
787 }
788
789 #[test]
792 fn test_borrow_state_serialization() {
793 let state = BorrowState::SharedBorrow { count: 5 };
794 let json = serde_json::to_string(&state);
795 assert!(json.is_ok(), "Should serialize to JSON");
796
797 let deserialized: Result<BorrowState, _> = serde_json::from_str(&json.unwrap());
798 assert!(deserialized.is_ok(), "Should deserialize from JSON");
799 assert_eq!(
800 deserialized.unwrap(),
801 BorrowState::SharedBorrow { count: 5 },
802 "Should preserve value"
803 );
804 }
805
806 #[test]
809 fn test_memory_location_type_serialization() {
810 let location = MemoryLocationType::Heap;
811 let json = serde_json::to_string(&location);
812 assert!(json.is_ok(), "Should serialize to JSON");
813
814 let deserialized: Result<MemoryLocationType, _> = serde_json::from_str(&json.unwrap());
815 assert!(deserialized.is_ok(), "Should deserialize from JSON");
816 assert_eq!(
817 deserialized.unwrap(),
818 MemoryLocationType::Heap,
819 "Should preserve value"
820 );
821 }
822
823 #[test]
826 fn test_object_lifecycle_info_with_events() {
827 let events = vec![
828 LifecycleEvent {
829 event_type: LifecycleEventType::Creation,
830 timestamp: 0,
831 location: SourceLocation {
832 file: "test.rs".to_string(),
833 line: 1,
834 column: 1,
835 },
836 memory_state: MemoryState {
837 memory_location: MemoryLocationType::Heap,
838 memory_address: 0x1000,
839 object_size: 64,
840 reference_count: None,
841 borrow_state: BorrowState::NotBorrowed,
842 },
843 performance_metrics: EventPerformanceMetrics {
844 cpu_cycles: 100,
845 memory_bandwidth_bytes: 64,
846 cache_misses: 0,
847 processing_time_ns: 50,
848 },
849 call_stack: vec![],
850 },
851 LifecycleEvent {
852 event_type: LifecycleEventType::Drop,
853 timestamp: 1000000,
854 location: SourceLocation {
855 file: "test.rs".to_string(),
856 line: 10,
857 column: 1,
858 },
859 memory_state: MemoryState {
860 memory_location: MemoryLocationType::Heap,
861 memory_address: 0x1000,
862 object_size: 64,
863 reference_count: None,
864 borrow_state: BorrowState::NotBorrowed,
865 },
866 performance_metrics: EventPerformanceMetrics {
867 cpu_cycles: 50,
868 memory_bandwidth_bytes: 0,
869 cache_misses: 0,
870 processing_time_ns: 25,
871 },
872 call_stack: vec![],
873 },
874 ];
875
876 let info = ObjectLifecycleInfo {
877 object_id: 1,
878 type_name: "String".to_string(),
879 lifecycle_events: events,
880 total_lifetime_ns: Some(1000000),
881 stage_durations: LifecycleStageDurations {
882 creation_to_first_use_ns: None,
883 active_use_duration_ns: None,
884 last_use_to_destruction_ns: None,
885 borrowed_duration_ns: 0,
886 idle_duration_ns: 0,
887 },
888 efficiency_metrics: LifecycleEfficiencyMetrics::default(),
889 lifecycle_patterns: vec![],
890 };
891
892 assert_eq!(info.lifecycle_events.len(), 2, "Should have 2 events");
893 assert_eq!(
894 info.lifecycle_events[0].event_type,
895 LifecycleEventType::Creation,
896 "First event should be Creation"
897 );
898 assert_eq!(
899 info.lifecycle_events[1].event_type,
900 LifecycleEventType::Drop,
901 "Second event should be Drop"
902 );
903 }
904
905 #[test]
908 fn test_object_lifecycle_info_clone() {
909 let original = ObjectLifecycleInfo {
910 object_id: 42,
911 type_name: "Vec<u8>".to_string(),
912 lifecycle_events: vec![],
913 total_lifetime_ns: Some(5000),
914 stage_durations: LifecycleStageDurations {
915 creation_to_first_use_ns: Some(100),
916 active_use_duration_ns: Some(4000),
917 last_use_to_destruction_ns: Some(900),
918 borrowed_duration_ns: 500,
919 idle_duration_ns: 200,
920 },
921 efficiency_metrics: LifecycleEfficiencyMetrics::default(),
922 lifecycle_patterns: vec![],
923 };
924
925 let cloned = original.clone();
926
927 assert_eq!(
928 original.object_id, cloned.object_id,
929 "Object ID should match"
930 );
931 assert_eq!(
932 original.type_name, cloned.type_name,
933 "Type name should match"
934 );
935 }
936}