memscope_rs/core/
enhanced_pointer_extractor.rs

1//! Enhanced pointer extraction with real pointer prioritization
2//!
3//! This module provides improved pointer extraction logic that prioritizes
4//! real heap pointers over synthetic ones, with clear marking of pointer types.
5
6use crate::Trackable;
7use serde::{Deserialize, Serialize};
8
9/// Information about a pointer and its origin
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub enum PointerInfo {
12    /// Real heap pointer obtained from the actual allocation
13    Real(usize),
14    /// Synthetic pointer generated when real pointer is unavailable
15    Synthetic { ptr: usize, reason: SyntheticReason },
16}
17
18/// Reasons why a synthetic pointer was generated
19#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
20pub enum SyntheticReason {
21    /// No heap allocation (stack-only data)
22    NoHeapAllocation,
23    /// Empty container (no capacity allocated)
24    EmptyContainer,
25    /// Smart pointer without direct heap access
26    SmartPointerIndirection,
27    /// Complex type requiring synthetic tracking
28    ComplexType,
29    /// Invalid or unsafe pointer detected
30    InvalidPointer,
31}
32
33/// Enhanced pointer extractor with validation and categorization
34pub struct EnhancedPointerExtractor;
35
36impl EnhancedPointerExtractor {
37    /// Extract pointer information with validation and categorization
38    pub fn extract_pointer_info<T: Trackable>(value: &T) -> PointerInfo {
39        match value.get_heap_ptr() {
40            Some(ptr) if Self::is_valid_heap_pointer(ptr) => PointerInfo::Real(ptr),
41            Some(ptr) if Self::is_synthetic_pointer(ptr) => {
42                // This is already a synthetic pointer from the Trackable implementation
43                let reason = Self::determine_synthetic_reason(ptr);
44                PointerInfo::Synthetic { ptr, reason }
45            }
46            Some(_ptr) => {
47                // Invalid pointer, generate a new synthetic one
48                let synthetic = Self::generate_synthetic_pointer();
49                PointerInfo::Synthetic {
50                    ptr: synthetic,
51                    reason: SyntheticReason::InvalidPointer,
52                }
53            }
54            None => {
55                // No pointer available, generate synthetic
56                let synthetic = Self::generate_synthetic_pointer();
57                PointerInfo::Synthetic {
58                    ptr: synthetic,
59                    reason: SyntheticReason::NoHeapAllocation,
60                }
61            }
62        }
63    }
64
65    /// Check if a pointer is a valid heap pointer
66    pub fn is_valid_heap_pointer(ptr: usize) -> bool {
67        // Check if pointer is in reasonable heap address range
68        // Exclude null pointer and very low addresses (likely stack or invalid)
69        if ptr < 0x1000 {
70            return false;
71        }
72
73        // Exclude very high addresses that are likely invalid
74        #[cfg(target_pointer_width = "64")]
75        {
76            if ptr > 0x7FFF_FFFF_FFFF_FFFF {
77                return false;
78            }
79        }
80
81        #[cfg(target_pointer_width = "32")]
82        {
83            if ptr > 0x7FFF_FFFF {
84                return false;
85            }
86        }
87
88        // Check if it's not a synthetic pointer
89        !Self::is_synthetic_pointer(ptr)
90    }
91
92    /// Check if a pointer is synthetic (generated by our tracking system)
93    pub fn is_synthetic_pointer(ptr: usize) -> bool {
94        // Check for known synthetic pointer ranges
95        match ptr {
96            // Range used by Rc/Arc synthetic pointers
97            0x5000_0000..=0x5FFF_FFFF => true,
98            // Range used by fast tracking synthetic pointers
99            0x8000_0000..=0x8FFF_FFFF => true,
100            // Range used by generate_synthetic_pointer
101            0x9000_0000..=0x9FFF_FFFF => true,
102            // Ranges used by advanced trackable macro
103            0xA000_0000..=0xFFFF_FFFF => true,
104            _ => false,
105        }
106    }
107
108    /// Determine the reason for synthetic pointer generation based on pointer value
109    fn determine_synthetic_reason(ptr: usize) -> SyntheticReason {
110        match ptr {
111            0x5000_0000..=0x5FFF_FFFF => SyntheticReason::SmartPointerIndirection,
112            0x8000_0000..=0x8FFF_FFFF => SyntheticReason::NoHeapAllocation,
113            0x9000_0000..=0x9FFF_FFFF => SyntheticReason::NoHeapAllocation,
114            0xA000_0000..=0xFFFF_FFFF => SyntheticReason::ComplexType,
115            _ => SyntheticReason::InvalidPointer,
116        }
117    }
118
119    /// Generate a new synthetic pointer
120    fn generate_synthetic_pointer() -> usize {
121        use std::sync::atomic::{AtomicUsize, Ordering};
122        static SYNTHETIC_COUNTER: AtomicUsize = AtomicUsize::new(0);
123
124        let id = SYNTHETIC_COUNTER.fetch_add(1, Ordering::Relaxed);
125        0x9000_0000 + (id % 0x0FFF_FFFF)
126    }
127
128    /// Enhanced extraction for Vec with capacity validation
129    pub fn extract_vec_pointer<T>(vec: &Vec<T>) -> PointerInfo {
130        if vec.capacity() > 0 {
131            let ptr = vec.as_ptr() as usize;
132            if Self::is_valid_heap_pointer(ptr) {
133                PointerInfo::Real(ptr)
134            } else {
135                PointerInfo::Synthetic {
136                    ptr: Self::generate_synthetic_pointer(),
137                    reason: SyntheticReason::InvalidPointer,
138                }
139            }
140        } else {
141            PointerInfo::Synthetic {
142                ptr: Self::generate_synthetic_pointer(),
143                reason: SyntheticReason::EmptyContainer,
144            }
145        }
146    }
147
148    /// Enhanced extraction for String with capacity validation
149    pub fn extract_string_pointer(string: &String) -> PointerInfo {
150        if string.capacity() > 0 {
151            let ptr = string.as_ptr() as usize;
152            if Self::is_valid_heap_pointer(ptr) {
153                PointerInfo::Real(ptr)
154            } else {
155                PointerInfo::Synthetic {
156                    ptr: Self::generate_synthetic_pointer(),
157                    reason: SyntheticReason::InvalidPointer,
158                }
159            }
160        } else {
161            PointerInfo::Synthetic {
162                ptr: Self::generate_synthetic_pointer(),
163                reason: SyntheticReason::EmptyContainer,
164            }
165        }
166    }
167
168    /// Enhanced extraction for Box with validation
169    #[allow(clippy::borrowed_box)]
170    pub fn extract_box_pointer<T>(boxed: &Box<T>) -> PointerInfo {
171        let ptr = boxed.as_ref() as *const T as usize;
172        if Self::is_valid_heap_pointer(ptr) {
173            PointerInfo::Real(ptr)
174        } else {
175            PointerInfo::Synthetic {
176                ptr: Self::generate_synthetic_pointer(),
177                reason: SyntheticReason::InvalidPointer,
178            }
179        }
180    }
181
182    /// Enhanced extraction for HashMap with bucket validation
183    pub fn extract_hashmap_pointer<K, V, S>(
184        map: &std::collections::HashMap<K, V, S>,
185    ) -> PointerInfo {
186        if map.is_empty() {
187            PointerInfo::Synthetic {
188                ptr: Self::generate_synthetic_pointer(),
189                reason: SyntheticReason::EmptyContainer,
190            }
191        } else {
192            // HashMap internal structure is complex, use synthetic pointer
193            PointerInfo::Synthetic {
194                ptr: Self::generate_synthetic_pointer(),
195                reason: SyntheticReason::ComplexType,
196            }
197        }
198    }
199
200    /// Get pointer statistics for analysis
201    pub fn get_pointer_statistics(pointers: &[PointerInfo]) -> PointerStatistics {
202        let mut real_count = 0;
203        let mut synthetic_count = 0;
204        let mut reason_counts = std::collections::HashMap::new();
205
206        for pointer in pointers {
207            match pointer {
208                PointerInfo::Real(_) => real_count += 1,
209                PointerInfo::Synthetic { reason, .. } => {
210                    synthetic_count += 1;
211                    *reason_counts.entry(reason.clone()).or_insert(0) += 1;
212                }
213            }
214        }
215
216        let total = pointers.len();
217        let real_ratio = if total > 0 {
218            real_count as f64 / total as f64
219        } else {
220            0.0
221        };
222
223        PointerStatistics {
224            total_pointers: total,
225            real_pointers: real_count,
226            synthetic_pointers: synthetic_count,
227            real_pointer_ratio: real_ratio,
228            synthetic_reasons: reason_counts,
229        }
230    }
231}
232
233/// Statistics about pointer extraction
234#[derive(Debug, Clone, Serialize)]
235pub struct PointerStatistics {
236    pub total_pointers: usize,
237    pub real_pointers: usize,
238    pub synthetic_pointers: usize,
239    pub real_pointer_ratio: f64,
240    pub synthetic_reasons: std::collections::HashMap<SyntheticReason, usize>,
241}
242
243/// Enhanced Trackable trait with pointer info
244pub trait EnhancedTrackable {
245    /// Get enhanced pointer information
246    fn get_pointer_info(&self) -> PointerInfo;
247
248    /// Get size estimate for the tracked data
249    fn get_size_estimate(&self) -> usize;
250
251    /// Get type information
252    fn get_type_info(&self) -> TypeInfo;
253}
254
255/// Type information for enhanced tracking
256#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct TypeInfo {
258    pub type_name: String,
259    pub category: TypeCategory,
260    pub complexity_score: u32,
261    pub is_heap_allocated: bool,
262}
263
264/// Categories of types for better analysis
265#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
266pub enum TypeCategory {
267    Primitive,
268    Collection,
269    SmartPointer,
270    Complex,
271    Atomic,
272    Synchronization,
273    Custom,
274}
275
276// Implement EnhancedTrackable for common types
277impl<T> EnhancedTrackable for Vec<T> {
278    fn get_pointer_info(&self) -> PointerInfo {
279        EnhancedPointerExtractor::extract_vec_pointer(self)
280    }
281
282    fn get_size_estimate(&self) -> usize {
283        std::mem::size_of::<Vec<T>>() + (self.capacity() * std::mem::size_of::<T>())
284    }
285
286    fn get_type_info(&self) -> TypeInfo {
287        TypeInfo {
288            type_name: format!("Vec<{}>", std::any::type_name::<T>()),
289            category: TypeCategory::Collection,
290            complexity_score: 2,
291            is_heap_allocated: self.capacity() > 0,
292        }
293    }
294}
295
296impl EnhancedTrackable for String {
297    fn get_pointer_info(&self) -> PointerInfo {
298        EnhancedPointerExtractor::extract_string_pointer(self)
299    }
300
301    fn get_size_estimate(&self) -> usize {
302        std::mem::size_of::<String>() + self.capacity()
303    }
304
305    fn get_type_info(&self) -> TypeInfo {
306        TypeInfo {
307            type_name: "String".to_string(),
308            category: TypeCategory::Collection,
309            complexity_score: 1,
310            is_heap_allocated: self.capacity() > 0,
311        }
312    }
313}
314
315impl<T> EnhancedTrackable for Box<T> {
316    fn get_pointer_info(&self) -> PointerInfo {
317        EnhancedPointerExtractor::extract_box_pointer(self)
318    }
319
320    fn get_size_estimate(&self) -> usize {
321        std::mem::size_of::<Box<T>>() + std::mem::size_of::<T>()
322    }
323
324    fn get_type_info(&self) -> TypeInfo {
325        TypeInfo {
326            type_name: format!("Box<{}>", std::any::type_name::<T>()),
327            category: TypeCategory::SmartPointer,
328            complexity_score: 2,
329            is_heap_allocated: true,
330        }
331    }
332}
333
334#[cfg(test)]
335mod tests {
336    use super::*;
337    use std::thread;
338
339    #[test]
340    fn test_valid_heap_pointer_detection() {
341        // Valid heap pointers
342        assert!(EnhancedPointerExtractor::is_valid_heap_pointer(0x1000));
343        assert!(EnhancedPointerExtractor::is_valid_heap_pointer(0x7FFF_0000));
344
345        // Invalid pointers
346        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(0));
347        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(0x100));
348
349        // Synthetic pointers
350        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(
351            0x8000_0000
352        ));
353        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(
354            0xA000_0000
355        ));
356    }
357
358    #[test]
359    fn test_synthetic_pointer_detection() {
360        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x5000_0000));
361        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x8000_0000));
362        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0xA000_0000));
363
364        assert!(!EnhancedPointerExtractor::is_synthetic_pointer(0x1000));
365        assert!(!EnhancedPointerExtractor::is_synthetic_pointer(0x7FFF_0000));
366    }
367
368    #[test]
369    fn test_vec_pointer_extraction() {
370        let vec = vec![1, 2, 3, 4, 5];
371        let pointer_info = EnhancedPointerExtractor::extract_vec_pointer(&vec);
372
373        match pointer_info {
374            PointerInfo::Real(_) => {
375                // This is expected for a Vec with capacity
376            }
377            PointerInfo::Synthetic { reason, .. } => {
378                panic!("Expected real pointer, got synthetic: {reason:?}");
379            }
380        }
381    }
382
383    #[test]
384    fn test_empty_vec_pointer_extraction() {
385        let vec: Vec<i32> = Vec::new();
386        let pointer_info = EnhancedPointerExtractor::extract_vec_pointer(&vec);
387
388        match pointer_info {
389            PointerInfo::Synthetic {
390                reason: SyntheticReason::EmptyContainer,
391                ..
392            } => {
393                // This is expected for an empty Vec
394            }
395            _ => {
396                panic!("Expected synthetic pointer with EmptyContainer reason");
397            }
398        }
399    }
400
401    #[test]
402    fn test_enhanced_trackable_vec() {
403        let vec = vec![1, 2, 3];
404        let pointer_info = vec.get_pointer_info();
405        let size_estimate = Trackable::get_size_estimate(&vec);
406        let type_info = vec.get_type_info();
407
408        match pointer_info {
409            PointerInfo::Real(_) => {
410                // Expected for Vec with data
411            }
412            _ => panic!("Expected real pointer for Vec with data"),
413        }
414
415        assert!(size_estimate > 0);
416        assert_eq!(type_info.category, TypeCategory::Collection);
417        assert!(type_info.is_heap_allocated);
418    }
419
420    #[test]
421    fn test_pointer_statistics() {
422        let pointers = vec![
423            PointerInfo::Real(0x1000),
424            PointerInfo::Real(0x2000),
425            PointerInfo::Synthetic {
426                ptr: 0x8000_0000,
427                reason: SyntheticReason::EmptyContainer,
428            },
429            PointerInfo::Synthetic {
430                ptr: 0x9000_0000,
431                reason: SyntheticReason::ComplexType,
432            },
433        ];
434
435        let stats = EnhancedPointerExtractor::get_pointer_statistics(&pointers);
436
437        assert_eq!(stats.total_pointers, 4);
438        assert_eq!(stats.real_pointers, 2);
439        assert_eq!(stats.synthetic_pointers, 2);
440        assert_eq!(stats.real_pointer_ratio, 0.5);
441        assert_eq!(stats.synthetic_reasons.len(), 2);
442    }
443
444    #[test]
445    fn test_boundary_pointer_values() {
446        // Test zero pointer
447        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(0));
448
449        // Test minimum valid pointer
450        assert!(EnhancedPointerExtractor::is_valid_heap_pointer(0x1000));
451        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(0xFFF));
452
453        // Test maximum values based on architecture
454        #[cfg(target_pointer_width = "64")]
455        {
456            assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(
457                0x8000_0000_0000_0000
458            ));
459            assert!(EnhancedPointerExtractor::is_valid_heap_pointer(
460                0x7FFF_FFFF_FFFF_FFFF
461            ));
462        }
463
464        #[cfg(target_pointer_width = "32")]
465        {
466            assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(
467                0x8000_0000
468            ));
469            assert!(EnhancedPointerExtractor::is_valid_heap_pointer(0x7FFF_FFFF));
470        }
471
472        // Test usize::MAX
473        assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(usize::MAX));
474    }
475
476    #[test]
477    fn test_synthetic_pointer_ranges() {
478        // Test all synthetic pointer ranges
479        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x5000_0000));
480        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x5FFF_FFFF));
481        assert!(!EnhancedPointerExtractor::is_synthetic_pointer(0x4FFF_FFFF));
482        assert!(!EnhancedPointerExtractor::is_synthetic_pointer(0x6000_0000));
483
484        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x8000_0000));
485        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x8FFF_FFFF));
486        assert!(!EnhancedPointerExtractor::is_synthetic_pointer(0x7FFF_FFFF));
487        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x9000_0000));
488
489        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0xA000_0000));
490        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0xFFFF_FFFF));
491        assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x9FFF_FFFF));
492    }
493
494    #[test]
495    fn test_synthetic_reason_determination() {
496        // Test different synthetic pointer ranges and their reasons
497        assert_eq!(
498            EnhancedPointerExtractor::determine_synthetic_reason(0x5000_0000),
499            SyntheticReason::SmartPointerIndirection
500        );
501        assert_eq!(
502            EnhancedPointerExtractor::determine_synthetic_reason(0x5FFF_FFFF),
503            SyntheticReason::SmartPointerIndirection
504        );
505
506        assert_eq!(
507            EnhancedPointerExtractor::determine_synthetic_reason(0x8000_0000),
508            SyntheticReason::NoHeapAllocation
509        );
510        assert_eq!(
511            EnhancedPointerExtractor::determine_synthetic_reason(0x8FFF_FFFF),
512            SyntheticReason::NoHeapAllocation
513        );
514
515        assert_eq!(
516            EnhancedPointerExtractor::determine_synthetic_reason(0xA000_0000),
517            SyntheticReason::ComplexType
518        );
519        assert_eq!(
520            EnhancedPointerExtractor::determine_synthetic_reason(0xFFFF_FFFF),
521            SyntheticReason::ComplexType
522        );
523
524        // Test invalid pointer reason
525        assert_eq!(
526            EnhancedPointerExtractor::determine_synthetic_reason(0x1000),
527            SyntheticReason::InvalidPointer
528        );
529    }
530
531    #[test]
532    fn test_synthetic_pointer_generation() {
533        // Generate multiple synthetic pointers and verify they're unique
534        let ptr1 = EnhancedPointerExtractor::generate_synthetic_pointer();
535        let ptr2 = EnhancedPointerExtractor::generate_synthetic_pointer();
536        let ptr3 = EnhancedPointerExtractor::generate_synthetic_pointer();
537
538        assert_ne!(ptr1, ptr2);
539        assert_ne!(ptr2, ptr3);
540        assert_ne!(ptr1, ptr3);
541
542        // Verify they're in the expected range
543        assert!(ptr1 >= 0x9000_0000);
544        assert!(ptr2 >= 0x9000_0000);
545        assert!(ptr3 >= 0x9000_0000);
546
547        // Verify they're synthetic
548        assert!(EnhancedPointerExtractor::is_synthetic_pointer(ptr1));
549        assert!(EnhancedPointerExtractor::is_synthetic_pointer(ptr2));
550        assert!(EnhancedPointerExtractor::is_synthetic_pointer(ptr3));
551    }
552
553    #[test]
554    fn test_string_pointer_extraction() {
555        // Test non-empty string
556        let string = String::from("Hello, World!");
557        let pointer_info = EnhancedPointerExtractor::extract_string_pointer(&string);
558
559        match pointer_info {
560            PointerInfo::Real(_) => {
561                // Expected for String with capacity
562            }
563            PointerInfo::Synthetic { reason, .. } => {
564                panic!("Expected real pointer for non-empty string, got synthetic: {reason:?}");
565            }
566        }
567
568        // Test empty string
569        let empty_string = String::new();
570        let pointer_info = EnhancedPointerExtractor::extract_string_pointer(&empty_string);
571
572        match pointer_info {
573            PointerInfo::Synthetic {
574                reason: SyntheticReason::EmptyContainer,
575                ..
576            } => {
577                // Expected for empty string
578            }
579            _ => {
580                panic!("Expected synthetic pointer with EmptyContainer reason for empty string");
581            }
582        }
583
584        // Test string with capacity but no content
585        let mut string_with_capacity = String::new();
586        string_with_capacity.reserve(100);
587        let pointer_info = EnhancedPointerExtractor::extract_string_pointer(&string_with_capacity);
588
589        match pointer_info {
590            PointerInfo::Real(_) => {
591                // Expected for string with capacity
592            }
593            _ => {
594                panic!("Expected real pointer for string with capacity");
595            }
596        }
597    }
598
599    #[test]
600    fn test_box_pointer_extraction() {
601        let boxed_value = Box::new(42);
602        let pointer_info = EnhancedPointerExtractor::extract_box_pointer(&boxed_value);
603
604        match pointer_info {
605            PointerInfo::Real(_) => {
606                // Expected for Box
607            }
608            PointerInfo::Synthetic { reason, .. } => {
609                panic!("Expected real pointer for Box, got synthetic: {reason:?}");
610            }
611        }
612
613        // Test with large boxed value
614        let large_boxed = Box::new([0u8; 1024]);
615        let pointer_info = EnhancedPointerExtractor::extract_box_pointer(&large_boxed);
616
617        match pointer_info {
618            PointerInfo::Real(_) => {
619                // Expected for Box
620            }
621            _ => {
622                panic!("Expected real pointer for large Box");
623            }
624        }
625    }
626
627    #[test]
628    fn test_hashmap_pointer_extraction() {
629        use std::collections::HashMap;
630
631        // Test empty HashMap
632        let empty_map: HashMap<String, i32> = HashMap::new();
633        let pointer_info = EnhancedPointerExtractor::extract_hashmap_pointer(&empty_map);
634
635        match pointer_info {
636            PointerInfo::Synthetic {
637                reason: SyntheticReason::EmptyContainer,
638                ..
639            } => {
640                // Expected for empty HashMap
641            }
642            _ => {
643                panic!("Expected synthetic pointer with EmptyContainer reason for empty HashMap");
644            }
645        }
646
647        // Test non-empty HashMap
648        let mut map = HashMap::new();
649        map.insert("key1".to_string(), 1);
650        map.insert("key2".to_string(), 2);
651        let pointer_info = EnhancedPointerExtractor::extract_hashmap_pointer(&map);
652
653        match pointer_info {
654            PointerInfo::Synthetic {
655                reason: SyntheticReason::ComplexType,
656                ..
657            } => {
658                // Expected for non-empty HashMap (complex internal structure)
659            }
660            _ => {
661                panic!("Expected synthetic pointer with ComplexType reason for non-empty HashMap");
662            }
663        }
664    }
665
666    #[test]
667    fn test_enhanced_trackable_string() {
668        let string = String::from("Test string");
669        let pointer_info = string.get_pointer_info();
670        let size_estimate = EnhancedTrackable::get_size_estimate(&string);
671        let type_info = string.get_type_info();
672
673        match pointer_info {
674            PointerInfo::Real(_) => {
675                // Expected for non-empty string
676            }
677            _ => panic!("Expected real pointer for non-empty string"),
678        }
679
680        assert!(size_estimate > 0);
681        assert_eq!(type_info.type_name, "String");
682        assert_eq!(type_info.category, TypeCategory::Collection);
683        assert_eq!(type_info.complexity_score, 1);
684        assert!(type_info.is_heap_allocated);
685
686        // Test empty string
687        let empty_string = String::new();
688        let type_info = empty_string.get_type_info();
689        assert!(!type_info.is_heap_allocated);
690    }
691
692    #[test]
693    fn test_enhanced_trackable_box() {
694        let boxed_value = Box::new(42);
695        let pointer_info = boxed_value.get_pointer_info();
696        let size_estimate = EnhancedTrackable::get_size_estimate(&boxed_value);
697        let type_info = boxed_value.get_type_info();
698
699        match pointer_info {
700            PointerInfo::Real(_) => {
701                // Expected for Box
702            }
703            _ => panic!("Expected real pointer for Box"),
704        }
705
706        assert!(size_estimate > 0);
707        assert!(type_info.type_name.starts_with("Box<"));
708        assert_eq!(type_info.category, TypeCategory::SmartPointer);
709        assert_eq!(type_info.complexity_score, 2);
710        assert!(type_info.is_heap_allocated);
711    }
712
713    #[test]
714    fn test_pointer_statistics_edge_cases() {
715        // Test empty pointer list
716        let empty_pointers: Vec<PointerInfo> = vec![];
717        let stats = EnhancedPointerExtractor::get_pointer_statistics(&empty_pointers);
718
719        assert_eq!(stats.total_pointers, 0);
720        assert_eq!(stats.real_pointers, 0);
721        assert_eq!(stats.synthetic_pointers, 0);
722        assert_eq!(stats.real_pointer_ratio, 0.0);
723        assert!(stats.synthetic_reasons.is_empty());
724
725        // Test all real pointers
726        let all_real = vec![
727            PointerInfo::Real(0x1000),
728            PointerInfo::Real(0x2000),
729            PointerInfo::Real(0x3000),
730        ];
731        let stats = EnhancedPointerExtractor::get_pointer_statistics(&all_real);
732
733        assert_eq!(stats.total_pointers, 3);
734        assert_eq!(stats.real_pointers, 3);
735        assert_eq!(stats.synthetic_pointers, 0);
736        assert_eq!(stats.real_pointer_ratio, 1.0);
737        assert!(stats.synthetic_reasons.is_empty());
738
739        // Test all synthetic pointers
740        let all_synthetic = vec![
741            PointerInfo::Synthetic {
742                ptr: 0x8000_0000,
743                reason: SyntheticReason::EmptyContainer,
744            },
745            PointerInfo::Synthetic {
746                ptr: 0x9000_0000,
747                reason: SyntheticReason::EmptyContainer,
748            },
749            PointerInfo::Synthetic {
750                ptr: 0xA000_0000,
751                reason: SyntheticReason::ComplexType,
752            },
753        ];
754        let stats = EnhancedPointerExtractor::get_pointer_statistics(&all_synthetic);
755
756        assert_eq!(stats.total_pointers, 3);
757        assert_eq!(stats.real_pointers, 0);
758        assert_eq!(stats.synthetic_pointers, 3);
759        assert_eq!(stats.real_pointer_ratio, 0.0);
760        assert_eq!(stats.synthetic_reasons.len(), 2);
761        assert_eq!(stats.synthetic_reasons[&SyntheticReason::EmptyContainer], 2);
762        assert_eq!(stats.synthetic_reasons[&SyntheticReason::ComplexType], 1);
763    }
764
765    #[test]
766    fn test_synthetic_reason_variants() {
767        // Test all SyntheticReason variants
768        let reasons = vec![
769            SyntheticReason::NoHeapAllocation,
770            SyntheticReason::EmptyContainer,
771            SyntheticReason::SmartPointerIndirection,
772            SyntheticReason::ComplexType,
773            SyntheticReason::InvalidPointer,
774        ];
775
776        // Test that they can be cloned, compared, and hashed
777        for reason in &reasons {
778            let cloned = reason.clone();
779            assert_eq!(reason, &cloned);
780
781            // Test that they can be used as HashMap keys
782            let mut map = std::collections::HashMap::new();
783            map.insert(reason.clone(), 1);
784            assert_eq!(map.get(reason), Some(&1));
785        }
786    }
787
788    #[test]
789    fn test_type_category_variants() {
790        // Test all TypeCategory variants
791        let categories = vec![
792            TypeCategory::Primitive,
793            TypeCategory::Collection,
794            TypeCategory::SmartPointer,
795            TypeCategory::Complex,
796            TypeCategory::Atomic,
797            TypeCategory::Synchronization,
798            TypeCategory::Custom,
799        ];
800
801        for category in &categories {
802            let cloned = category.clone();
803            assert_eq!(category, &cloned);
804        }
805    }
806
807    #[test]
808    fn test_pointer_info_serialization() {
809        // Test serialization of PointerInfo variants
810        let real_pointer = PointerInfo::Real(0x1000);
811        let synthetic_pointer = PointerInfo::Synthetic {
812            ptr: 0x8000_0000,
813            reason: SyntheticReason::EmptyContainer,
814        };
815
816        // Test that they can be serialized (basic check)
817        let _real_json =
818            serde_json::to_string(&real_pointer).expect("Failed to serialize real pointer");
819        let _synthetic_json = serde_json::to_string(&synthetic_pointer)
820            .expect("Failed to serialize synthetic pointer");
821    }
822
823    #[test]
824    fn test_concurrent_pointer_operations() {
825        // Test that pointer operations are thread-safe
826        let handles: Vec<_> = (0..10)
827            .map(|_| {
828                thread::spawn(|| {
829                    // Generate synthetic pointers concurrently
830                    let ptr1 = EnhancedPointerExtractor::generate_synthetic_pointer();
831                    let ptr2 = EnhancedPointerExtractor::generate_synthetic_pointer();
832
833                    // Test pointer validation concurrently
834                    assert!(EnhancedPointerExtractor::is_synthetic_pointer(ptr1));
835                    assert!(EnhancedPointerExtractor::is_synthetic_pointer(ptr2));
836                    assert_ne!(ptr1, ptr2);
837
838                    // Test with various pointer values
839                    assert!(EnhancedPointerExtractor::is_valid_heap_pointer(0x1000));
840                    assert!(!EnhancedPointerExtractor::is_valid_heap_pointer(0));
841                    assert!(EnhancedPointerExtractor::is_synthetic_pointer(0x8000_0000));
842
843                    (ptr1, ptr2)
844                })
845            })
846            .collect();
847
848        let mut all_pointers = Vec::new();
849        for handle in handles {
850            let (ptr1, ptr2) = handle.join().expect("Thread panicked");
851            all_pointers.push(ptr1);
852            all_pointers.push(ptr2);
853        }
854
855        // Verify all generated pointers are unique
856        all_pointers.sort();
857        all_pointers.dedup();
858        assert_eq!(all_pointers.len(), 20); // 10 threads * 2 pointers each
859    }
860
861    #[test]
862    fn test_vec_with_reserved_capacity() {
863        // Test Vec with reserved capacity but no elements
864        let vec: Vec<i32> = Vec::with_capacity(100);
865
866        let pointer_info = EnhancedPointerExtractor::extract_vec_pointer(&vec);
867        match pointer_info {
868            PointerInfo::Real(_) => {
869                // Expected for Vec with capacity
870            }
871            _ => panic!("Expected real pointer for Vec with reserved capacity"),
872        }
873
874        let type_info = vec.get_type_info();
875        assert!(type_info.is_heap_allocated);
876    }
877
878    #[test]
879    fn test_large_data_structures() {
880        // Test with large Vec
881        let large_vec: Vec<u8> = vec![0; 10000];
882        let pointer_info = large_vec.get_pointer_info();
883        let size_estimate = EnhancedTrackable::get_size_estimate(&large_vec);
884
885        match pointer_info {
886            PointerInfo::Real(_) => {
887                // Expected for large Vec
888            }
889            _ => panic!("Expected real pointer for large Vec"),
890        }
891
892        assert!(size_estimate >= 10000);
893
894        // Test with large String
895        let large_string = "x".repeat(10000);
896        let pointer_info = large_string.get_pointer_info();
897        let size_estimate = EnhancedTrackable::get_size_estimate(&large_string);
898
899        match pointer_info {
900            PointerInfo::Real(_) => {
901                // Expected for large String
902            }
903            _ => panic!("Expected real pointer for large String"),
904        }
905
906        assert!(size_estimate >= 10000);
907    }
908}