Skip to main content

memscope_rs/analysis/generic/
analyzer.rs

1use crate::analysis::generic::types::*;
2use crate::analysis::generic::utils::{extract_constraints, parse_generic_parameters};
3use crate::core::safe_operations::SafeLock;
4use std::collections::HashMap;
5use std::sync::{Arc, Mutex, OnceLock};
6use std::time::{SystemTime, UNIX_EPOCH};
7
8static GLOBAL_GENERIC_ANALYZER: OnceLock<Arc<GenericAnalyzer>> = OnceLock::new();
9
10pub fn get_global_generic_analyzer() -> Arc<GenericAnalyzer> {
11    GLOBAL_GENERIC_ANALYZER
12        .get_or_init(|| Arc::new(GenericAnalyzer::default()))
13        .clone()
14}
15
16pub struct GenericAnalyzer {
17    pub generic_instances: Mutex<HashMap<String, Vec<GenericInstance>>>,
18    pub constraint_violations: Mutex<Vec<ConstraintViolation>>,
19    pub instantiation_events: Mutex<Vec<InstantiationEvent>>,
20}
21
22impl Default for GenericAnalyzer {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl GenericAnalyzer {
29    pub fn new() -> Self {
30        Self {
31            generic_instances: Mutex::new(HashMap::new()),
32            constraint_violations: Mutex::new(Vec::new()),
33            instantiation_events: Mutex::new(Vec::new()),
34        }
35    }
36
37    pub fn track_generic_instantiation(
38        &self,
39        base_type: &str,
40        type_params: Vec<String>,
41        ptr: usize,
42    ) {
43        self.track_generic_instantiation_with_name(base_type, base_type, type_params, ptr);
44    }
45
46    pub fn track_generic_instantiation_with_name(
47        &self,
48        name: &str,
49        base_type: &str,
50        type_params: Vec<String>,
51        ptr: usize,
52    ) {
53        let event = InstantiationEvent {
54            base_type: base_type.to_string(),
55            type_parameters: type_params.clone(),
56            ptr,
57            timestamp: current_timestamp(),
58            thread_id: format!("{:?}", std::thread::current().id()),
59        };
60
61        if let Ok(mut events) = self.instantiation_events.lock() {
62            events.push(event);
63        }
64
65        let instance = GenericInstance {
66            name: name.to_string(),
67            base_type: base_type.to_string(),
68            underlying_type: base_type.to_string(),
69            type_parameters: type_params.clone(),
70            ptr,
71            size: 0,
72            constraints: extract_constraints(base_type),
73            is_type_alias: name != base_type,
74        };
75
76        if let Ok(mut instances) = self.generic_instances.lock() {
77            instances
78                .entry(name.to_string())
79                .or_default()
80                .push(instance);
81        }
82    }
83
84    pub fn track_type_alias_instantiation(
85        &self,
86        alias_name: &str,
87        underlying_type: &str,
88        type_params: Vec<String>,
89        ptr: usize,
90    ) {
91        let (base_type, resolved_params) = parse_generic_parameters(underlying_type);
92
93        let event = InstantiationEvent {
94            base_type: base_type.clone(),
95            type_parameters: if resolved_params.is_empty() {
96                type_params.clone()
97            } else {
98                resolved_params.clone()
99            },
100            ptr,
101            timestamp: current_timestamp(),
102            thread_id: format!("{:?}", std::thread::current().id()),
103        };
104
105        if let Ok(mut events) = self.instantiation_events.lock() {
106            events.push(event);
107        }
108
109        let instance = GenericInstance {
110            name: alias_name.to_string(),
111            base_type: base_type.clone(),
112            underlying_type: underlying_type.to_string(),
113            type_parameters: if resolved_params.is_empty() {
114                type_params
115            } else {
116                resolved_params
117            },
118            ptr,
119            size: 0,
120            constraints: extract_constraints(underlying_type),
121            is_type_alias: true,
122        };
123
124        if let Ok(mut instances) = self.generic_instances.lock() {
125            instances
126                .entry(alias_name.to_string())
127                .or_default()
128                .push(instance);
129        }
130    }
131
132    pub fn analyze_constraints(&self, type_name: &str) -> Vec<GenericConstraint> {
133        extract_constraints(type_name)
134    }
135
136    pub fn check_constraint_violations(
137        &self,
138        type_name: &str,
139        actual_params: &[String],
140    ) -> Vec<ConstraintViolation> {
141        let constraints = self.analyze_constraints(type_name);
142        let mut violations = Vec::new();
143
144        for constraint in constraints {
145            if !self.validate_constraint(&constraint, actual_params) {
146                violations.push(ConstraintViolation {
147                    constraint: constraint.clone(),
148                    actual_type: actual_params.join(", "),
149                    violation_type: ViolationType::ConstraintNotSatisfied,
150                    timestamp: current_timestamp(),
151                });
152            }
153        }
154
155        violations
156    }
157
158    pub fn get_generic_statistics(&self) -> GenericStatistics {
159        let instances = self
160            .generic_instances
161            .safe_lock()
162            .expect("Failed to acquire lock on generic_instances");
163        let events = self
164            .instantiation_events
165            .safe_lock()
166            .expect("Failed to acquire lock on instantiation_events");
167        let violations = self
168            .constraint_violations
169            .safe_lock()
170            .expect("Failed to acquire lock on constraint_violations");
171        let total_instances: usize = instances.values().map(|v| v.len()).sum();
172        let unique_base_types = instances.len();
173        let total_instantiations = events.len();
174        let constraint_violations = violations.len();
175
176        let mut type_usage: HashMap<String, usize> = HashMap::new();
177        let mut alias_count = 0;
178
179        for (_name, instance_list) in instances.iter() {
180            for instance in instance_list {
181                if instance.is_type_alias {
182                    alias_count += 1;
183                    *type_usage
184                        .entry(instance.underlying_type.clone())
185                        .or_insert(0) += 1;
186                } else {
187                    *type_usage.entry(instance.name.clone()).or_insert(0) += 1;
188                }
189            }
190        }
191
192        let most_used_types: Vec<(String, usize)> = {
193            let mut sorted: Vec<_> = type_usage.into_iter().collect();
194            sorted.sort_by_key(|b| std::cmp::Reverse(b.1));
195            sorted.into_iter().take(10).collect()
196        };
197
198        GenericStatistics {
199            total_instances,
200            unique_base_types,
201            total_instantiations,
202            constraint_violations,
203            most_used_types,
204            type_aliases_count: alias_count,
205        }
206    }
207
208    pub fn get_type_aliases(&self) -> Vec<TypeAliasInfo> {
209        let instances = self
210            .generic_instances
211            .safe_lock()
212            .expect("Failed to acquire lock on generic_instances");
213        let mut alias_map: HashMap<String, TypeAliasInfo> = HashMap::new();
214
215        for (_name, instance_list) in instances.iter() {
216            for instance in instance_list {
217                if instance.is_type_alias {
218                    let alias_name = instance.name.clone();
219
220                    if let Some(existing) = alias_map.get_mut(&alias_name) {
221                        existing.usage_count += 1;
222                    } else {
223                        alias_map.insert(
224                            alias_name.clone(),
225                            TypeAliasInfo {
226                                alias_name,
227                                underlying_type: instance.underlying_type.clone(),
228                                base_type: instance.base_type.clone(),
229                                type_parameters: instance.type_parameters.clone(),
230                                usage_count: 1,
231                            },
232                        );
233                    }
234                }
235            }
236        }
237
238        alias_map.into_values().collect()
239    }
240
241    pub fn resolve_type_alias(&self, alias_name: &str) -> Option<String> {
242        let instances = self
243            .generic_instances
244            .safe_lock()
245            .expect("Failed to acquire lock on generic_instances");
246
247        if let Some(instance_list) = instances.get(alias_name) {
248            for instance in instance_list {
249                if instance.is_type_alias {
250                    return Some(instance.underlying_type.clone());
251                }
252            }
253        }
254        None
255    }
256
257    fn validate_constraint(
258        &self,
259        constraint: &GenericConstraint,
260        actual_params: &[String],
261    ) -> bool {
262        match &constraint.constraint_type {
263            ConstraintType::Trait(trait_name) => {
264                self.type_implements_trait(actual_params, trait_name)
265            }
266            ConstraintType::Lifetime => true,
267            ConstraintType::Sized => !actual_params
268                .iter()
269                .any(|t| t.contains("dyn ") || t.contains("?Sized")),
270            ConstraintType::Send => self.type_is_send(actual_params),
271            ConstraintType::Sync => self.type_is_sync(actual_params),
272        }
273    }
274
275    fn type_implements_trait(&self, types: &[String], trait_name: &str) -> bool {
276        match trait_name {
277            "Clone" => types.iter().all(|t| self.is_cloneable_type(t)),
278            "Debug" => types.iter().all(|t| self.is_debug_type(t)),
279            "Default" => types.iter().all(|t| self.is_default_type(t)),
280            "PartialEq" => types.iter().all(|t| self.is_partial_eq_type(t)),
281            _ => true,
282        }
283    }
284
285    fn type_is_send(&self, types: &[String]) -> bool {
286        !types
287            .iter()
288            .any(|t| t.contains("Rc<") || t.contains("RefCell<"))
289    }
290
291    fn type_is_sync(&self, types: &[String]) -> bool {
292        !types
293            .iter()
294            .any(|t| t.contains("Cell<") || t.contains("RefCell<"))
295    }
296
297    fn is_cloneable_type(&self, type_name: &str) -> bool {
298        !type_name.contains("Mutex<") && !type_name.contains("File")
299    }
300
301    fn is_debug_type(&self, type_name: &str) -> bool {
302        !type_name.contains("fn(")
303    }
304
305    fn is_default_type(&self, type_name: &str) -> bool {
306        type_name.contains("Vec<") || type_name.contains("HashMap<") || type_name.contains("String")
307    }
308
309    fn is_partial_eq_type(&self, type_name: &str) -> bool {
310        !type_name.contains("fn(") && !type_name.contains("Mutex<")
311    }
312}
313
314fn current_timestamp() -> u64 {
315    SystemTime::now()
316        .duration_since(UNIX_EPOCH)
317        .unwrap_or_default()
318        .as_secs()
319}
320
321#[cfg(test)]
322mod tests {
323    use super::*;
324
325    /// Objective: Verify GenericAnalyzer creation with default values
326    /// Invariants: New analyzer should have empty collections
327    #[test]
328    fn test_generic_analyzer_creation() {
329        let analyzer = GenericAnalyzer::new();
330
331        let instances = analyzer.generic_instances.lock().unwrap();
332        let violations = analyzer.constraint_violations.lock().unwrap();
333        let events = analyzer.instantiation_events.lock().unwrap();
334
335        assert!(
336            instances.is_empty(),
337            "New analyzer should have no instances"
338        );
339        assert!(
340            violations.is_empty(),
341            "New analyzer should have no violations"
342        );
343        assert!(events.is_empty(), "New analyzer should have no events");
344    }
345
346    /// Objective: Verify Default trait implementation
347    /// Invariants: Default should create same as new()
348    #[test]
349    fn test_generic_analyzer_default() {
350        let analyzer = GenericAnalyzer::default();
351
352        let instances = analyzer.generic_instances.lock().unwrap();
353        assert!(
354            instances.is_empty(),
355            "Default analyzer should have no instances"
356        );
357    }
358
359    /// Objective: Verify track_generic_instantiation functionality
360    /// Invariants: Should add instance and event correctly
361    #[test]
362    fn test_track_generic_instantiation() {
363        let analyzer = GenericAnalyzer::new();
364
365        analyzer.track_generic_instantiation("Vec", vec!["i32".to_string()], 0x1000);
366
367        let instances = analyzer.generic_instances.lock().unwrap();
368        assert!(instances.contains_key("Vec"), "Should contain Vec instance");
369        assert_eq!(
370            instances.get("Vec").unwrap().len(),
371            1,
372            "Should have one Vec instance"
373        );
374
375        let events = analyzer.instantiation_events.lock().unwrap();
376        assert_eq!(events.len(), 1, "Should have one event");
377    }
378
379    /// Objective: Verify track_generic_instantiation_with_name functionality
380    /// Invariants: Should track instance with custom name
381    #[test]
382    fn test_track_generic_instantiation_with_name() {
383        let analyzer = GenericAnalyzer::new();
384
385        analyzer.track_generic_instantiation_with_name(
386            "MyVec",
387            "Vec",
388            vec!["String".to_string()],
389            0x2000,
390        );
391
392        let instances = analyzer.generic_instances.lock().unwrap();
393        assert!(
394            instances.contains_key("MyVec"),
395            "Should contain MyVec instance"
396        );
397
398        let instance = &instances.get("MyVec").unwrap()[0];
399        assert_eq!(instance.name, "MyVec", "Name should be MyVec");
400        assert_eq!(instance.base_type, "Vec", "Base type should be Vec");
401        assert!(instance.is_type_alias, "Should be marked as type alias");
402    }
403
404    /// Objective: Verify track_type_alias_instantiation functionality
405    /// Invariants: Should track type alias correctly
406    #[test]
407    fn test_track_type_alias_instantiation() {
408        let analyzer = GenericAnalyzer::new();
409
410        analyzer.track_type_alias_instantiation("StringList", "Vec<String>", vec![], 0x3000);
411
412        let instances = analyzer.generic_instances.lock().unwrap();
413        assert!(
414            instances.contains_key("StringList"),
415            "Should contain StringList instance"
416        );
417
418        let instance = &instances.get("StringList").unwrap()[0];
419        assert_eq!(instance.name, "StringList", "Name should be StringList");
420        assert_eq!(
421            instance.underlying_type, "Vec<String>",
422            "Underlying type should be Vec<String>"
423        );
424        assert!(instance.is_type_alias, "Should be marked as type alias");
425    }
426
427    /// Objective: Verify analyze_constraints functionality
428    /// Invariants: Should extract constraints from type name
429    #[test]
430    fn test_analyze_constraints() {
431        let analyzer = GenericAnalyzer::new();
432
433        let constraints = analyzer.analyze_constraints("Vec<T: Clone>");
434
435        assert!(
436            !constraints.is_empty(),
437            "Should have constraints for Vec<T: Clone>"
438        );
439    }
440
441    /// Objective: Verify check_constraint_violations with valid params
442    /// Invariants: Should return empty violations for valid params
443    #[test]
444    fn test_check_constraint_violations_valid() {
445        let analyzer = GenericAnalyzer::new();
446
447        let violations = analyzer.check_constraint_violations("Vec<T>", &["i32".to_string()]);
448
449        assert!(
450            violations.is_empty(),
451            "Should have no violations for valid params"
452        );
453    }
454
455    /// Objective: Verify get_generic_statistics with no data
456    /// Invariants: Should return zero statistics
457    #[test]
458    fn test_get_generic_statistics_empty() {
459        let analyzer = GenericAnalyzer::new();
460
461        let stats = analyzer.get_generic_statistics();
462
463        assert_eq!(stats.total_instances, 0, "Should have 0 total instances");
464        assert_eq!(
465            stats.unique_base_types, 0,
466            "Should have 0 unique base types"
467        );
468        assert_eq!(
469            stats.total_instantiations, 0,
470            "Should have 0 instantiations"
471        );
472        assert_eq!(stats.constraint_violations, 0, "Should have 0 violations");
473    }
474
475    /// Objective: Verify get_generic_statistics with data
476    /// Invariants: Should return correct statistics
477    #[test]
478    fn test_get_generic_statistics_with_data() {
479        let analyzer = GenericAnalyzer::new();
480
481        analyzer.track_generic_instantiation("Vec", vec!["i32".to_string()], 0x1000);
482        analyzer.track_generic_instantiation("Vec", vec!["String".to_string()], 0x2000);
483        analyzer.track_generic_instantiation(
484            "HashMap",
485            vec!["String".to_string(), "i32".to_string()],
486            0x3000,
487        );
488
489        let stats = analyzer.get_generic_statistics();
490
491        assert_eq!(stats.total_instances, 3, "Should have 3 total instances");
492        assert_eq!(
493            stats.unique_base_types, 2,
494            "Should have 2 unique base types (Vec, HashMap)"
495        );
496        assert_eq!(
497            stats.total_instantiations, 3,
498            "Should have 3 instantiations"
499        );
500    }
501
502    /// Objective: Verify get_type_aliases with no aliases
503    /// Invariants: Should return empty list
504    #[test]
505    fn test_get_type_aliases_empty() {
506        let analyzer = GenericAnalyzer::new();
507
508        analyzer.track_generic_instantiation("Vec", vec!["i32".to_string()], 0x1000);
509
510        let aliases = analyzer.get_type_aliases();
511
512        assert!(aliases.is_empty(), "Should have no type aliases");
513    }
514
515    /// Objective: Verify get_type_aliases with aliases
516    /// Invariants: Should return correct alias info
517    #[test]
518    fn test_get_type_aliases_with_data() {
519        let analyzer = GenericAnalyzer::new();
520
521        analyzer.track_type_alias_instantiation("StringList", "Vec<String>", vec![], 0x1000);
522        analyzer.track_type_alias_instantiation("StringList", "Vec<String>", vec![], 0x2000);
523
524        let aliases = analyzer.get_type_aliases();
525
526        assert_eq!(aliases.len(), 1, "Should have 1 type alias");
527        assert_eq!(
528            aliases[0].alias_name, "StringList",
529            "Alias name should be StringList"
530        );
531        assert_eq!(aliases[0].usage_count, 2, "Usage count should be 2");
532    }
533
534    /// Objective: Verify resolve_type_alias functionality
535    /// Invariants: Should resolve alias to underlying type
536    #[test]
537    fn test_resolve_type_alias() {
538        let analyzer = GenericAnalyzer::new();
539
540        analyzer.track_type_alias_instantiation("IntList", "Vec<i32>", vec![], 0x1000);
541
542        let resolved = analyzer.resolve_type_alias("IntList");
543
544        assert!(resolved.is_some(), "Should resolve IntList");
545        assert_eq!(resolved.unwrap(), "Vec<i32>", "Should resolve to Vec<i32>");
546    }
547
548    /// Objective: Verify resolve_type_alias for non-existent alias
549    /// Invariants: Should return None
550    #[test]
551    fn test_resolve_type_alias_nonexistent() {
552        let analyzer = GenericAnalyzer::new();
553
554        let resolved = analyzer.resolve_type_alias("NonExistent");
555
556        assert!(
557            resolved.is_none(),
558            "Should return None for non-existent alias"
559        );
560    }
561
562    /// Objective: Verify type_implements_trait for Clone
563    /// Invariants: Should correctly identify Clone types
564    #[test]
565    fn test_type_implements_trait_clone() {
566        let analyzer = GenericAnalyzer::new();
567
568        assert!(
569            analyzer.type_implements_trait(&["i32".to_string()], "Clone"),
570            "i32 should implement Clone"
571        );
572        assert!(
573            analyzer.type_implements_trait(&["String".to_string()], "Clone"),
574            "String should implement Clone"
575        );
576        assert!(
577            !analyzer.type_implements_trait(&["Mutex<i32>".to_string()], "Clone"),
578            "Mutex should not implement Clone"
579        );
580    }
581
582    /// Objective: Verify type_implements_trait for Debug
583    /// Invariants: Should correctly identify Debug types
584    #[test]
585    fn test_type_implements_trait_debug() {
586        let analyzer = GenericAnalyzer::new();
587
588        assert!(
589            analyzer.type_implements_trait(&["i32".to_string()], "Debug"),
590            "i32 should implement Debug"
591        );
592        assert!(
593            !analyzer.type_implements_trait(&["fn()".to_string()], "Debug"),
594            "fn() should not implement Debug"
595        );
596    }
597
598    /// Objective: Verify type_implements_trait for Default
599    /// Invariants: Should correctly identify Default types
600    #[test]
601    fn test_type_implements_trait_default() {
602        let analyzer = GenericAnalyzer::new();
603
604        assert!(
605            analyzer.type_implements_trait(&["Vec<i32>".to_string()], "Default"),
606            "Vec should implement Default"
607        );
608        assert!(
609            analyzer.type_implements_trait(&["String".to_string()], "Default"),
610            "String should implement Default"
611        );
612        assert!(
613            !analyzer.type_implements_trait(&["i32".to_string()], "Default"),
614            "i32 should not implement Default"
615        );
616    }
617
618    /// Objective: Verify type_implements_trait for PartialEq
619    /// Invariants: Should correctly identify PartialEq types
620    #[test]
621    fn test_type_implements_trait_partial_eq() {
622        let analyzer = GenericAnalyzer::new();
623
624        assert!(
625            analyzer.type_implements_trait(&["i32".to_string()], "PartialEq"),
626            "i32 should implement PartialEq"
627        );
628        assert!(
629            !analyzer.type_implements_trait(&["fn()".to_string()], "PartialEq"),
630            "fn() should not implement PartialEq"
631        );
632    }
633
634    /// Objective: Verify type_is_send functionality
635    /// Invariants: Should correctly identify Send types
636    #[test]
637    fn test_type_is_send() {
638        let analyzer = GenericAnalyzer::new();
639
640        assert!(
641            analyzer.type_is_send(&["i32".to_string()]),
642            "i32 should be Send"
643        );
644        assert!(
645            analyzer.type_is_send(&["Arc<i32>".to_string()]),
646            "Arc should be Send"
647        );
648        assert!(
649            !analyzer.type_is_send(&["Rc<i32>".to_string()]),
650            "Rc should not be Send"
651        );
652        assert!(
653            !analyzer.type_is_send(&["RefCell<i32>".to_string()]),
654            "RefCell should not be Send"
655        );
656    }
657
658    /// Objective: Verify type_is_sync functionality
659    /// Invariants: Should correctly identify Sync types
660    #[test]
661    fn test_type_is_sync() {
662        let analyzer = GenericAnalyzer::new();
663
664        assert!(
665            analyzer.type_is_sync(&["i32".to_string()]),
666            "i32 should be Sync"
667        );
668        assert!(
669            analyzer.type_is_sync(&["Arc<i32>".to_string()]),
670            "Arc should be Sync"
671        );
672        assert!(
673            !analyzer.type_is_sync(&["Cell<i32>".to_string()]),
674            "Cell should not be Sync"
675        );
676        assert!(
677            !analyzer.type_is_sync(&["RefCell<i32>".to_string()]),
678            "RefCell should not be Sync"
679        );
680    }
681
682    /// Objective: Verify is_cloneable_type functionality
683    /// Invariants: Should correctly identify cloneable types
684    #[test]
685    fn test_is_cloneable_type() {
686        let analyzer = GenericAnalyzer::new();
687
688        assert!(analyzer.is_cloneable_type("i32"), "i32 should be cloneable");
689        assert!(
690            analyzer.is_cloneable_type("String"),
691            "String should be cloneable"
692        );
693        assert!(
694            !analyzer.is_cloneable_type("Mutex<i32>"),
695            "Mutex should not be cloneable"
696        );
697        assert!(
698            !analyzer.is_cloneable_type("File"),
699            "File should not be cloneable"
700        );
701    }
702
703    /// Objective: Verify is_debug_type functionality
704    /// Invariants: Should correctly identify Debug types
705    #[test]
706    fn test_is_debug_type() {
707        let analyzer = GenericAnalyzer::new();
708
709        assert!(analyzer.is_debug_type("i32"), "i32 should be Debug");
710        assert!(analyzer.is_debug_type("String"), "String should be Debug");
711        assert!(
712            !analyzer.is_debug_type("fn() -> i32"),
713            "fn() should not be Debug"
714        );
715    }
716
717    /// Objective: Verify is_default_type functionality
718    /// Invariants: Should correctly identify Default types
719    #[test]
720    fn test_is_default_type() {
721        let analyzer = GenericAnalyzer::new();
722
723        assert!(
724            analyzer.is_default_type("Vec<i32>"),
725            "Vec should be Default"
726        );
727        assert!(
728            analyzer.is_default_type("HashMap<String, i32>"),
729            "HashMap should be Default"
730        );
731        assert!(
732            analyzer.is_default_type("String"),
733            "String should be Default"
734        );
735        assert!(
736            !analyzer.is_default_type("i32"),
737            "i32 should not be Default"
738        );
739    }
740
741    /// Objective: Verify is_partial_eq_type functionality
742    /// Invariants: Should correctly identify PartialEq types
743    #[test]
744    fn test_is_partial_eq_type() {
745        let analyzer = GenericAnalyzer::new();
746
747        assert!(
748            analyzer.is_partial_eq_type("i32"),
749            "i32 should be PartialEq"
750        );
751        assert!(
752            analyzer.is_partial_eq_type("String"),
753            "String should be PartialEq"
754        );
755        assert!(
756            !analyzer.is_partial_eq_type("fn()"),
757            "fn() should not be PartialEq"
758        );
759        assert!(
760            !analyzer.is_partial_eq_type("Mutex<i32>"),
761            "Mutex should not be PartialEq"
762        );
763    }
764
765    /// Objective: Verify get_global_generic_analyzer singleton
766    /// Invariants: Should return same instance
767    #[test]
768    fn test_global_generic_analyzer_singleton() {
769        let analyzer1 = get_global_generic_analyzer();
770        let analyzer2 = get_global_generic_analyzer();
771
772        assert!(
773            Arc::ptr_eq(&analyzer1, &analyzer2),
774            "Should return same instance"
775        );
776    }
777
778    /// Objective: Verify current_timestamp returns valid value
779    /// Invariants: Timestamp should be positive
780    #[test]
781    fn test_current_timestamp() {
782        let ts = current_timestamp();
783        assert!(ts > 0, "Timestamp should be positive");
784    }
785
786    /// Objective: Verify multiple instantiations of same type
787    /// Invariants: Should track all instances
788    #[test]
789    fn test_multiple_instantiations_same_type() {
790        let analyzer = GenericAnalyzer::new();
791
792        for i in 0..5 {
793            analyzer.track_generic_instantiation("Vec", vec!["i32".to_string()], 0x1000 + i);
794        }
795
796        let instances = analyzer.generic_instances.lock().unwrap();
797        assert_eq!(
798            instances.get("Vec").unwrap().len(),
799            5,
800            "Should have 5 Vec instances"
801        );
802
803        let events = analyzer.instantiation_events.lock().unwrap();
804        assert_eq!(events.len(), 5, "Should have 5 events");
805    }
806
807    /// Objective: Verify validate_constraint for Sized
808    /// Invariants: Should correctly validate Sized constraint
809    #[test]
810    fn test_validate_constraint_sized() {
811        let analyzer = GenericAnalyzer::new();
812
813        let sized_constraint = GenericConstraint {
814            constraint_type: ConstraintType::Sized,
815            parameter_name: "T".to_string(),
816            description: String::new(),
817        };
818
819        assert!(
820            analyzer.validate_constraint(&sized_constraint, &["i32".to_string()]),
821            "i32 should be Sized"
822        );
823        assert!(
824            !analyzer.validate_constraint(&sized_constraint, &["dyn Any".to_string()]),
825            "dyn Any should not be Sized"
826        );
827        assert!(
828            !analyzer.validate_constraint(&sized_constraint, &["?Sized".to_string()]),
829            "?Sized should not satisfy Sized constraint"
830        );
831    }
832
833    /// Objective: Verify validate_constraint for Lifetime
834    /// Invariants: Should always return true for Lifetime constraint
835    #[test]
836    fn test_validate_constraint_lifetime() {
837        let analyzer = GenericAnalyzer::new();
838
839        let lifetime_constraint = GenericConstraint {
840            constraint_type: ConstraintType::Lifetime,
841            parameter_name: "'a".to_string(),
842            description: String::new(),
843        };
844
845        assert!(
846            analyzer.validate_constraint(&lifetime_constraint, &["i32".to_string()]),
847            "Lifetime constraint should always be valid"
848        );
849    }
850
851    /// Objective: Verify validate_constraint for Send
852    /// Invariants: Should correctly validate Send constraint
853    #[test]
854    fn test_validate_constraint_send() {
855        let analyzer = GenericAnalyzer::new();
856
857        let send_constraint = GenericConstraint {
858            constraint_type: ConstraintType::Send,
859            parameter_name: "T".to_string(),
860            description: String::new(),
861        };
862
863        assert!(
864            analyzer.validate_constraint(&send_constraint, &["i32".to_string()]),
865            "i32 should be Send"
866        );
867        assert!(
868            !analyzer.validate_constraint(&send_constraint, &["Rc<i32>".to_string()]),
869            "Rc should not be Send"
870        );
871    }
872
873    /// Objective: Verify validate_constraint for Sync
874    /// Invariants: Should correctly validate Sync constraint
875    #[test]
876    fn test_validate_constraint_sync() {
877        let analyzer = GenericAnalyzer::new();
878
879        let sync_constraint = GenericConstraint {
880            constraint_type: ConstraintType::Sync,
881            parameter_name: "T".to_string(),
882            description: String::new(),
883        };
884
885        assert!(
886            analyzer.validate_constraint(&sync_constraint, &["i32".to_string()]),
887            "i32 should be Sync"
888        );
889        assert!(
890            !analyzer.validate_constraint(&sync_constraint, &["Cell<i32>".to_string()]),
891            "Cell should not be Sync"
892        );
893    }
894
895    /// Objective: Verify type_implements_trait for unknown trait
896    /// Invariants: Should return true for unknown traits
897    #[test]
898    fn test_type_implements_trait_unknown() {
899        let analyzer = GenericAnalyzer::new();
900
901        assert!(
902            analyzer.type_implements_trait(&["i32".to_string()], "UnknownTrait"),
903            "Unknown traits should return true by default"
904        );
905    }
906
907    /// Objective: Verify concurrent access to GenericAnalyzer
908    /// Invariants: Should handle concurrent operations safely
909    #[test]
910    fn test_concurrent_access() {
911        use std::sync::Arc;
912        use std::thread;
913
914        let analyzer = Arc::new(GenericAnalyzer::new());
915        let mut handles = vec![];
916
917        for i in 0..5 {
918            let analyzer_clone = analyzer.clone();
919            let handle = thread::spawn(move || {
920                analyzer_clone.track_generic_instantiation(
921                    "Vec",
922                    vec![format!("Type{}", i)],
923                    0x1000 + i,
924                );
925            });
926            handles.push(handle);
927        }
928
929        for handle in handles {
930            handle.join().unwrap();
931        }
932
933        let instances = analyzer.generic_instances.lock().unwrap();
934        assert_eq!(
935            instances.get("Vec").unwrap().len(),
936            5,
937            "Should have 5 instances from 5 threads"
938        );
939    }
940
941    /// Objective: Verify statistics with type aliases
942    /// Invariants: Should correctly count type aliases
943    #[test]
944    fn test_statistics_with_type_aliases() {
945        let analyzer = GenericAnalyzer::new();
946
947        analyzer.track_generic_instantiation("Vec", vec!["i32".to_string()], 0x1000);
948        analyzer.track_type_alias_instantiation("IntVec", "Vec<i32>", vec![], 0x2000);
949        analyzer.track_type_alias_instantiation("IntVec", "Vec<i32>", vec![], 0x3000);
950
951        let stats = analyzer.get_generic_statistics();
952
953        assert_eq!(stats.total_instances, 3, "Should have 3 total instances");
954        assert_eq!(
955            stats.type_aliases_count, 2,
956            "Should have 2 type alias instances"
957        );
958    }
959}