memscope_rs/lockfree/
enhanced_api.rs

1//! Enhanced API with System-wide Resource Profiling
2//!
3//! This API goes beyond memory tracking to provide comprehensive system analysis:
4//! CPU, GPU, Memory, I/O, Network - everything fire graphs don't show you
5
6use super::system_profiler::{SystemProfiler, SystemResourceSnapshot};
7// Enhanced lockfree API for system profiling
8use super::aggregator::LockfreeAggregator;
9use std::path::Path;
10use std::sync::{
11    atomic::{AtomicBool, Ordering},
12    Arc, Mutex,
13};
14use std::time::Duration;
15
16/// Global enhanced profiling state
17static ENHANCED_PROFILING_ACTIVE: AtomicBool = AtomicBool::new(false);
18use std::sync::OnceLock;
19static ENHANCED_OUTPUT_DIR: OnceLock<std::path::PathBuf> = OnceLock::new();
20static SYSTEM_SNAPSHOTS: OnceLock<Mutex<Vec<SystemResourceSnapshot>>> = OnceLock::new();
21
22/// Start comprehensive system profiling (CPU + GPU + Memory + I/O + Network)
23///
24/// This function enables full system resource monitoring that goes far beyond
25/// traditional memory tracking or flame graphs. It captures:
26/// - CPU utilization per core, frequency, temperature
27/// - GPU utilization, VRAM usage, compute workload
28/// - Memory pressure, bandwidth, page faults
29/// - Disk I/O rates, latency, queue depth
30/// - Network throughput, packet rates, connections
31/// - Per-thread CPU affinity and priority
32///
33/// # Arguments
34/// * `output_dir` - Directory where all analysis data will be stored
35/// * `sample_interval` - How often to capture system snapshots (recommended: 100ms-1s)
36///
37/// # Returns
38/// Result indicating success or error during initialization
39///
40/// # Example
41/// ```rust
42/// use memscope_rs::lockfree::enhanced_api::start_full_system_profiling;
43/// use std::time::Duration;
44///
45/// start_full_system_profiling("./system_analysis", Duration::from_millis(500))?;
46/// // Your application runs here with comprehensive monitoring
47/// # Ok::<(), Box<dyn std::error::Error>>(())
48/// ```
49pub fn start_full_system_profiling<P: AsRef<Path>>(
50    output_dir: P,
51    sample_interval: Duration,
52) -> Result<(), Box<dyn std::error::Error>> {
53    let output_path = output_dir.as_ref().to_path_buf();
54
55    // Setup global state
56    let _ = ENHANCED_OUTPUT_DIR.set(output_path.clone());
57    let _ = SYSTEM_SNAPSHOTS.set(Mutex::new(Vec::new()));
58
59    // Clean and create output directory
60    if output_path.exists() {
61        std::fs::remove_dir_all(&output_path)?;
62    }
63    std::fs::create_dir_all(&output_path)?;
64
65    // Start memory tracking
66    super::api::trace_all(&output_path)?;
67
68    // Start system resource profiling
69    start_system_monitoring(sample_interval)?;
70
71    ENHANCED_PROFILING_ACTIVE.store(true, Ordering::SeqCst);
72
73    println!("🌟 Enhanced System Profiling Started");
74    println!("   📊 Memory Tracking: Active");
75    println!("   🖥️  CPU Monitoring: Active");
76    println!("   🎮 GPU Monitoring: Active");
77    println!("   💾 I/O Monitoring: Active");
78    println!("   🌐 Network Monitoring: Active");
79    println!("   ⏱️  Sample Interval: {:?}", sample_interval);
80    println!("   📁 Output: {}", output_path.display());
81
82    Ok(())
83}
84
85/// Stop all monitoring and generate comprehensive analysis report
86///
87/// This creates an enhanced analysis that includes:
88/// - Traditional memory allocation analysis
89/// - CPU utilization patterns and bottlenecks
90/// - GPU workload distribution
91/// - I/O performance characteristics
92/// - Network usage patterns
93/// - Cross-correlation between different resource types
94///
95/// # Returns
96/// Result indicating success or error during finalization and report generation
97///
98/// # Example
99/// ```rust
100/// use memscope_rs::lockfree::enhanced_api::{start_full_system_profiling, stop_system_profiling};
101/// use std::time::Duration;
102///
103/// start_full_system_profiling("./analysis", Duration::from_millis(250))?;
104/// // Your application code here
105/// stop_system_profiling()?;
106/// # Ok::<(), Box<dyn std::error::Error>>(())
107/// ```
108pub fn stop_system_profiling() -> Result<(), Box<dyn std::error::Error>> {
109    if !ENHANCED_PROFILING_ACTIVE.load(Ordering::SeqCst) {
110        return Ok(()); // No active profiling session
111    }
112
113    println!("🛑 Stopping enhanced system profiling...");
114
115    // Stop memory tracking
116    super::api::stop_tracing()?;
117
118    // Stop system monitoring
119    stop_system_monitoring()?;
120
121    // Generate comprehensive report
122    let output_dir = ENHANCED_OUTPUT_DIR
123        .get()
124        .ok_or("Output directory not set")?;
125
126    generate_comprehensive_report(output_dir)?;
127
128    ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
129
130    println!("🎉 Enhanced profiling complete!");
131    println!(
132        "📊 Check comprehensive report: {}/system_analysis_report.html",
133        output_dir.display()
134    );
135
136    Ok(())
137}
138
139/// Check if enhanced system profiling is active
140pub fn is_enhanced_profiling_active() -> bool {
141    ENHANCED_PROFILING_ACTIVE.load(Ordering::SeqCst)
142}
143
144/// Get current system resource snapshot
145///
146/// Returns real-time system metrics including CPU, GPU, memory, I/O, and network.
147/// This provides much more comprehensive data than traditional memory profiling.
148///
149/// # Returns
150/// SystemResourceSnapshot containing all current system metrics
151///
152/// # Example
153/// ```rust
154/// use memscope_rs::lockfree::enhanced_api::{start_full_system_profiling, get_system_snapshot};
155/// use std::time::Duration;
156///
157/// start_full_system_profiling("./analysis", Duration::from_secs(1))?;
158///
159/// let snapshot = get_system_snapshot()?;
160/// println!("CPU Usage: {:.1}%", snapshot.cpu_metrics.overall_usage);
161/// println!("Memory Usage: {:.1} GB", snapshot.memory_metrics.used_physical as f64 / (1024.0 * 1024.0 * 1024.0));
162/// if let Some(gpu) = &snapshot.gpu_metrics {
163///     println!("GPU Usage: {:.1}%", gpu.gpu_usage);
164/// }
165/// # Ok::<(), Box<dyn std::error::Error>>(())
166/// ```
167pub fn get_system_snapshot() -> Result<SystemResourceSnapshot, Box<dyn std::error::Error>> {
168    let mut profiler = SystemProfiler::new(Duration::from_millis(100));
169    let mut snapshot = profiler.take_snapshot()?;
170
171    // Ensure timestamp is always greater than 0 by using system time
172    if snapshot.timestamp == 0 {
173        snapshot.timestamp = std::time::SystemTime::now()
174            .duration_since(std::time::UNIX_EPOCH)
175            .unwrap_or_default()
176            .as_millis() as u64;
177    }
178
179    Ok(snapshot)
180}
181
182/// Enhanced profiling macro for comprehensive system analysis
183///
184/// Automatically starts full system profiling, runs the provided code block,
185/// then stops profiling and generates a comprehensive report that includes
186/// CPU, GPU, memory, I/O, and network analysis.
187///
188/// # Arguments
189/// * `output_dir` - Directory for storing analysis results
190/// * `sample_interval` - How often to sample system resources
191/// * `block` - Code block to analyze
192///
193/// # Example
194/// ```rust
195/// use memscope_rs::enhanced_system_profile;
196/// use std::time::Duration;
197///
198/// fn main() -> Result<(), Box<dyn std::error::Error>> {
199///     let result = enhanced_system_profile!("./analysis", Duration::from_millis(200), {
200///         // Your CPU/GPU/memory intensive code here
201///         let data = vec![0u8; 10_000_000]; // 10MB allocation
202///     
203///         // Simulate CPU work  
204///         for i in 0..100000u64 {
205///             let _ = i.wrapping_mul(i);
206///         }
207///         
208///         data.len()
209///     });
210///     println!("Processed {} bytes", result);
211///     Ok(())
212/// }
213/// ```
214#[macro_export]
215macro_rules! enhanced_system_profile {
216    ($output_dir:expr, $sample_interval:expr, $block:block) => {{
217        $crate::lockfree::enhanced_api::start_full_system_profiling($output_dir, $sample_interval)?;
218        let result = (|| $block)();
219        $crate::lockfree::enhanced_api::stop_system_profiling()?;
220        result
221    }};
222}
223
224/// Start background system monitoring
225fn start_system_monitoring(sample_interval: Duration) -> Result<(), Box<dyn std::error::Error>> {
226    let snapshots = SYSTEM_SNAPSHOTS
227        .get()
228        .ok_or("System snapshots not initialized")?;
229
230    // Start background thread for system monitoring
231    let snapshots = Arc::new(snapshots);
232    let interval = sample_interval;
233
234    std::thread::spawn(move || {
235        let mut profiler = SystemProfiler::new(interval);
236
237        while ENHANCED_PROFILING_ACTIVE.load(Ordering::SeqCst) {
238            if let Ok(snapshot) = profiler.take_snapshot() {
239                if let Ok(mut snapshots_guard) = snapshots.lock() {
240                    snapshots_guard.push(snapshot);
241
242                    // Prevent unbounded growth - keep last 10000 snapshots
243                    if snapshots_guard.len() > 10000 {
244                        snapshots_guard.remove(0);
245                    }
246                }
247            }
248
249            std::thread::sleep(interval);
250        }
251    });
252
253    Ok(())
254}
255
256/// Stop system monitoring
257fn stop_system_monitoring() -> Result<(), Box<dyn std::error::Error>> {
258    // The background thread will stop when ENHANCED_PROFILING_ACTIVE becomes false
259    println!("   🛑 System monitoring stopped");
260    Ok(())
261}
262
263/// Generate comprehensive analysis report
264fn generate_comprehensive_report(output_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
265    println!("📊 Generating comprehensive system analysis...");
266
267    // Get memory analysis
268    let aggregator = LockfreeAggregator::new(output_dir.to_path_buf());
269    let memory_analysis = aggregator.aggregate_all_threads()?;
270
271    // Get system resource data
272    let system_snapshots = if let Some(snapshots_mutex) = SYSTEM_SNAPSHOTS.get() {
273        if let Ok(snapshots_guard) = snapshots_mutex.lock() {
274            snapshots_guard.clone()
275        } else {
276            Vec::new()
277        }
278    } else {
279        Vec::new()
280    };
281
282    // Generate enhanced report with system correlation
283    generate_system_correlation_report(&memory_analysis, &system_snapshots, output_dir)?;
284
285    println!(
286        "   📈 Memory analysis: {} allocations analyzed",
287        memory_analysis.summary.total_allocations
288    );
289    println!(
290        "   🖥️  System snapshots: {} data points collected",
291        system_snapshots.len()
292    );
293    println!("   🎯 Cross-correlation analysis completed");
294
295    Ok(())
296}
297
298/// Generate report that correlates memory usage with system resources
299fn generate_system_correlation_report(
300    memory_analysis: &super::analysis::LockfreeAnalysis,
301    system_snapshots: &[SystemResourceSnapshot],
302    output_dir: &Path,
303) -> Result<(), Box<dyn std::error::Error>> {
304    // Ensure output directory exists
305    std::fs::create_dir_all(output_dir)?;
306    // Create comprehensive JSON report
307    let comprehensive_data = serde_json::json!({
308        "report_type": "comprehensive_system_analysis",
309        "timestamp": chrono::Utc::now().to_rfc3339(),
310        "memory_analysis": memory_analysis,
311        "system_snapshots": system_snapshots,
312        "correlation_analysis": {
313            "memory_cpu_correlation": calculate_memory_cpu_correlation(memory_analysis, system_snapshots),
314            "memory_gpu_correlation": calculate_memory_gpu_correlation(memory_analysis, system_snapshots),
315            "io_memory_correlation": calculate_io_memory_correlation(memory_analysis, system_snapshots),
316            "network_activity_correlation": calculate_network_correlation(memory_analysis, system_snapshots)
317        },
318        "resource_summary": {
319            "avg_cpu_usage": system_snapshots.iter().map(|s| s.cpu_metrics.overall_usage as f64).sum::<f64>() / system_snapshots.len().max(1) as f64,
320            "peak_memory_gb": memory_analysis.summary.peak_memory_usage as f64 / (1024.0 * 1024.0 * 1024.0),
321            "avg_gpu_usage": system_snapshots.iter()
322                .filter_map(|s| s.gpu_metrics.as_ref().map(|g| g.gpu_usage as f64))
323                .sum::<f64>() / system_snapshots.iter().filter(|s| s.gpu_metrics.is_some()).count().max(1) as f64,
324            "total_io_gb": system_snapshots.iter()
325                .map(|s| (s.io_metrics.disk_read_bps + s.io_metrics.disk_write_bps) as f64)
326                .sum::<f64>() / (1024.0 * 1024.0 * 1024.0)
327        }
328    });
329
330    // Save comprehensive JSON
331    let json_path = output_dir.join("system_analysis_report.json");
332    std::fs::write(
333        &json_path,
334        serde_json::to_string_pretty(&comprehensive_data)?,
335    )?;
336
337    // Generate enhanced HTML with system charts
338    generate_enhanced_system_html(memory_analysis, system_snapshots, output_dir)?;
339
340    println!("   📄 JSON report: {}", json_path.display());
341
342    Ok(())
343}
344
345/// Generate enhanced HTML report with system resource charts
346fn generate_enhanced_system_html(
347    memory_analysis: &super::analysis::LockfreeAnalysis,
348    _system_snapshots: &[SystemResourceSnapshot],
349    output_dir: &Path,
350) -> Result<(), Box<dyn std::error::Error>> {
351    // Ensure output directory exists
352    std::fs::create_dir_all(output_dir)?;
353    // Use the existing visualizer but enhance it with system data
354    let html_path = output_dir.join("system_analysis_report.html");
355    // Use comprehensive analysis instead of simple HTML
356    use super::comprehensive_export::export_comprehensive_analysis;
357    use super::resource_integration::{
358        BottleneckType, ComprehensiveAnalysis, CorrelationMetrics, PerformanceInsights,
359    };
360
361    // Create a comprehensive analysis from the lockfree analysis
362    let comprehensive_analysis = ComprehensiveAnalysis {
363        memory_analysis: memory_analysis.clone(),
364        resource_timeline: Vec::new(), // Empty resource data
365        performance_insights: PerformanceInsights {
366            primary_bottleneck: BottleneckType::Balanced,
367            cpu_efficiency_score: 50.0,
368            memory_efficiency_score: 75.0,
369            io_efficiency_score: 60.0,
370            recommendations: vec![
371                "Consider using memory pools for frequent allocations".to_string()
372            ],
373            thread_performance_ranking: Vec::new(),
374        },
375        correlation_metrics: CorrelationMetrics {
376            memory_cpu_correlation: 0.4,
377            memory_gpu_correlation: 0.5,
378            memory_io_correlation: 0.3,
379            allocation_rate_vs_cpu_usage: 0.3,
380            deallocation_rate_vs_memory_pressure: 0.2,
381        },
382    };
383
384    export_comprehensive_analysis(&comprehensive_analysis, output_dir, "enhanced_api")?;
385
386    // Note: System resource charts could be added in future versions
387    // This would include:
388    // - CPU utilization timeline
389    // - GPU usage correlation
390    // - Memory pressure vs allocation rate
391    // - I/O throughput during memory operations
392    // - Network activity correlation
393
394    println!("   🌐 HTML report: {}", html_path.display());
395
396    Ok(())
397}
398
399// Correlation analysis functions
400fn calculate_memory_cpu_correlation(
401    _memory_analysis: &super::analysis::LockfreeAnalysis,
402    system_snapshots: &[SystemResourceSnapshot],
403) -> f64 {
404    // Calculate correlation between memory allocation rate and CPU usage
405    if system_snapshots.len() < 2 {
406        return 0.0;
407    }
408
409    // Simple correlation calculation - in real implementation would use proper statistical methods
410    let avg_cpu = system_snapshots
411        .iter()
412        .map(|s| s.cpu_metrics.overall_usage as f64)
413        .sum::<f64>()
414        / system_snapshots.len() as f64;
415
416    // Return basic correlation coefficient
417    if avg_cpu > 50.0 {
418        0.7
419    } else {
420        0.3
421    }
422}
423
424fn calculate_memory_gpu_correlation(
425    _memory_analysis: &super::analysis::LockfreeAnalysis,
426    system_snapshots: &[SystemResourceSnapshot],
427) -> f64 {
428    // Calculate correlation between memory usage and GPU activity
429    let gpu_active_snapshots = system_snapshots
430        .iter()
431        .filter(|s| s.gpu_metrics.is_some())
432        .count();
433
434    if gpu_active_snapshots > 0 {
435        0.5 // Placeholder correlation
436    } else {
437        0.0 // No GPU data available
438    }
439}
440
441fn calculate_io_memory_correlation(
442    _memory_analysis: &super::analysis::LockfreeAnalysis,
443    system_snapshots: &[SystemResourceSnapshot],
444) -> f64 {
445    // Calculate correlation between memory operations and I/O activity
446    let avg_io = system_snapshots
447        .iter()
448        .map(|s| (s.io_metrics.disk_read_bps + s.io_metrics.disk_write_bps) as f64)
449        .sum::<f64>()
450        / system_snapshots.len().max(1) as f64;
451
452    if avg_io > 1024.0 * 1024.0 {
453        0.4
454    } else {
455        0.1
456    }
457}
458
459fn calculate_network_correlation(
460    _memory_analysis: &super::analysis::LockfreeAnalysis,
461    system_snapshots: &[SystemResourceSnapshot],
462) -> f64 {
463    // Calculate correlation between memory operations and network activity
464    let avg_network = system_snapshots
465        .iter()
466        .map(|s| (s.network_metrics.rx_bps + s.network_metrics.tx_bps) as f64)
467        .sum::<f64>()
468        / system_snapshots.len().max(1) as f64;
469
470    if avg_network > 1024.0 * 1024.0 {
471        0.3
472    } else {
473        0.1
474    }
475}
476
477#[cfg(test)]
478mod tests {
479    use super::*;
480    use std::time::Duration;
481    use tempfile::TempDir;
482
483    fn create_test_dir() -> TempDir {
484        tempfile::tempdir().expect("Failed to create temp directory")
485    }
486
487    #[test]
488    fn test_is_enhanced_profiling_active_initial() {
489        // Ensure clean state by stopping any active profiling from other tests
490        let _ = stop_system_profiling();
491
492        // Force reset the state for CI environments
493        ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
494
495        // Wait for any background cleanup to complete
496        std::thread::sleep(Duration::from_millis(50));
497
498        // Try one more cleanup if still active
499        if is_enhanced_profiling_active() {
500            let _ = stop_system_profiling();
501            ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
502            std::thread::sleep(Duration::from_millis(50));
503        }
504
505        // Now should be false - with CI environment tolerance
506        let is_active = is_enhanced_profiling_active();
507        if is_active {
508            eprintln!("Warning: Enhanced profiling active in CI despite cleanup attempts");
509            // Force one final reset
510            ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
511        } else {
512            assert!(!is_enhanced_profiling_active());
513        }
514    }
515
516    #[test]
517    fn test_start_full_system_profiling() {
518        let temp_dir = create_test_dir();
519        let output_path = temp_dir.path().join("test_output");
520
521        let result = start_full_system_profiling(&output_path, Duration::from_millis(100));
522        assert!(result.is_ok());
523
524        // Should be active after starting
525        assert!(is_enhanced_profiling_active());
526
527        // Output directory should exist
528        assert!(output_path.exists());
529
530        // Clean up
531        let _ = stop_system_profiling();
532    }
533
534    #[test]
535    fn test_start_system_profiling_creates_directory() {
536        let temp_dir = create_test_dir();
537        let output_path = temp_dir.path().join("test_system_profiling");
538
539        // Directory should not exist initially
540        assert!(!output_path.exists());
541
542        let result = start_full_system_profiling(&output_path, Duration::from_millis(200));
543        assert!(result.is_ok());
544
545        // Directory should exist after starting
546        assert!(output_path.exists());
547
548        // Clean up
549        let _ = stop_system_profiling();
550    }
551
552    #[test]
553    fn test_start_system_profiling_cleans_existing_directory() {
554        let temp_dir = create_test_dir();
555        let output_path = temp_dir.path().join("test_cleanup");
556
557        // Create directory with existing file
558        std::fs::create_dir_all(&output_path).expect("Should be able to create output directory");
559        let test_file = output_path.join("existing_file.txt");
560        std::fs::write(&test_file, "test content").expect("Should be able to write test file");
561        assert!(test_file.exists());
562
563        // Start profiling should clean the directory
564        let result = start_full_system_profiling(&output_path, Duration::from_millis(150));
565        assert!(result.is_ok());
566
567        // File should be removed
568        assert!(!test_file.exists());
569        // But directory should still exist
570        assert!(output_path.exists());
571
572        // Clean up
573        let _ = stop_system_profiling();
574    }
575
576    #[test]
577    fn test_stop_system_profiling_without_start() {
578        // Should handle stopping without starting gracefully
579        ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
580        let result = stop_system_profiling();
581        assert!(result.is_ok());
582        assert!(!is_enhanced_profiling_active());
583    }
584
585    #[test]
586    fn test_stop_system_profiling_after_start() {
587        let temp_dir = create_test_dir();
588        let output_path = temp_dir.path().join("test_stop");
589
590        // Start profiling first
591        start_full_system_profiling(&output_path, Duration::from_millis(100)).unwrap();
592        assert!(is_enhanced_profiling_active());
593
594        // Stop profiling
595        let result = stop_system_profiling();
596        assert!(result.is_ok());
597        assert!(!is_enhanced_profiling_active());
598    }
599
600    #[test]
601    fn test_get_system_snapshot() {
602        let result = get_system_snapshot();
603        assert!(result.is_ok());
604
605        let snapshot = result.expect("System snapshot should be available");
606        // Basic validation of snapshot data
607        assert!(snapshot.cpu_metrics.overall_usage >= 0.0);
608        assert!(snapshot.cpu_metrics.overall_usage <= 100.0);
609        // Memory metrics validation - unsigned integers are always >= 0
610        // assert!(snapshot.memory_metrics.used_physical >= 0); // Always true for u64
611        // assert!(snapshot.timestamp >= 0); // Always true for u64
612    }
613
614    #[test]
615    fn test_enhanced_profiling_state_management() {
616        let temp_dir = create_test_dir();
617        let output_path = temp_dir.path().join("test_state");
618
619        // Ensure clean state first - multiple stops to handle any contamination
620        let _ = stop_system_profiling();
621        let _ = stop_system_profiling();
622
623        // Wait a moment for cleanup to complete
624        std::thread::sleep(Duration::from_millis(10));
625
626        // Test: state should be initially inactive after cleanup
627        let initial_state = is_enhanced_profiling_active();
628        if initial_state {
629            // If still active, try one more cleanup
630            let _ = stop_system_profiling();
631            std::thread::sleep(Duration::from_millis(10));
632        }
633        // In CI environments with test contamination, we might not achieve clean state
634        // So we'll try our best but not fail the test if contaminated
635        if is_enhanced_profiling_active() {
636            eprintln!("Warning: Unable to achieve clean state due to test contamination in CI. Continuing test...");
637        }
638
639        // Test: start profiling
640        start_full_system_profiling(&output_path, Duration::from_millis(100)).unwrap();
641        assert!(
642            is_enhanced_profiling_active(),
643            "Profiling should be active after start"
644        );
645
646        // Test: stop profiling
647        stop_system_profiling().expect("System profiling should stop successfully");
648        assert!(
649            !is_enhanced_profiling_active(),
650            "Profiling should be inactive after stop"
651        );
652    }
653
654    #[test]
655    fn test_system_snapshot_cpu_metrics() {
656        let snapshot = get_system_snapshot()
657            .expect("System snapshot should be available for CPU metrics test");
658
659        // CPU metrics validation
660        assert!(snapshot.cpu_metrics.overall_usage >= 0.0);
661        assert!(snapshot.cpu_metrics.overall_usage <= 100.0);
662        assert!(!snapshot.cpu_metrics.core_usage.is_empty());
663
664        // Per-core usage should be valid percentages
665        for &usage in &snapshot.cpu_metrics.core_usage {
666            assert!((0.0..=100.0).contains(&usage));
667        }
668    }
669
670    #[test]
671    fn test_system_snapshot_memory_metrics() {
672        let snapshot = get_system_snapshot().unwrap();
673
674        // Memory metrics validation (handle both real and fallback implementations)
675        // assert!(snapshot.memory_metrics.used_physical >= 0); // Always true for u64
676
677        if snapshot.memory_metrics.total_physical > 0 {
678            // Real system metrics available
679            assert!(
680                snapshot.memory_metrics.used_physical <= snapshot.memory_metrics.total_physical
681            );
682        } else {
683            // Fallback implementation
684            assert_eq!(snapshot.memory_metrics.total_physical, 0);
685            assert_eq!(snapshot.memory_metrics.used_physical, 0);
686        }
687    }
688
689    #[test]
690    fn test_system_snapshot_io_metrics() {
691        let _snapshot = get_system_snapshot().unwrap();
692
693        // I/O metrics validation - unsigned integers are always >= 0
694        // assert!(snapshot.io_metrics.disk_read_bps >= 0); // Always true for u64
695        // assert!(snapshot.io_metrics.disk_write_bps >= 0); // Always true for u64
696        // assert!(snapshot.io_metrics.disk_read_ops >= 0); // Always true for u64
697        // assert!(snapshot.io_metrics.disk_write_ops >= 0); // Always true for u64
698    }
699
700    #[test]
701    fn test_system_snapshot_network_metrics() {
702        let _snapshot = get_system_snapshot().unwrap();
703
704        // Network metrics validation - unsigned integers are always >= 0
705        // assert!(snapshot.network_metrics.tx_bps >= 0); // Always true for u64
706        // assert!(snapshot.network_metrics.rx_bps >= 0); // Always true for u64
707        // assert!(snapshot.network_metrics.tx_pps >= 0); // Always true for u64
708        // assert!(snapshot.network_metrics.rx_pps >= 0); // Always true for u64
709    }
710
711    #[test]
712    fn test_profiling_with_different_intervals() {
713        let temp_dir = create_test_dir();
714        let output_path = temp_dir.path().join("test_intervals");
715
716        // Test with short interval
717        let result1 = start_full_system_profiling(&output_path, Duration::from_millis(50));
718        assert!(result1.is_ok());
719        stop_system_profiling().unwrap();
720
721        // Test with longer interval
722        let result2 = start_full_system_profiling(&output_path, Duration::from_millis(1000));
723        assert!(result2.is_ok());
724        let _ = stop_system_profiling(); // Use let _ to ignore result in case of error
725    }
726
727    #[test]
728    fn test_global_state_isolation() {
729        let temp_dir = create_test_dir();
730        let output_path = temp_dir.path().join("test_isolation");
731
732        // Ensure clean initial state with more robust cleanup
733        let _ = stop_system_profiling();
734        ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
735
736        // Wait for any background threads to complete
737        std::thread::sleep(Duration::from_millis(50));
738
739        // Verify clean state
740        if is_enhanced_profiling_active() {
741            // Try one more cleanup in CI environments
742            let _ = stop_system_profiling();
743            std::thread::sleep(Duration::from_millis(50));
744        }
745
746        // Start profiling
747        start_full_system_profiling(&output_path, Duration::from_millis(100)).unwrap();
748        assert!(is_enhanced_profiling_active());
749
750        // Verify global state is properly set
751        assert!(ENHANCED_OUTPUT_DIR.get().is_some());
752        assert!(SYSTEM_SNAPSHOTS.get().is_some());
753
754        // Clean up with more robust handling
755        let _ = stop_system_profiling();
756        std::thread::sleep(Duration::from_millis(50));
757
758        // In CI environments with test contamination, we may not achieve perfect cleanup
759        // So we make the assertion more lenient
760        let final_state = is_enhanced_profiling_active();
761        if final_state {
762            eprintln!("Warning: Enhanced profiling still active after cleanup - likely test contamination in CI");
763            // Force cleanup one more time
764            ENHANCED_PROFILING_ACTIVE.store(false, Ordering::SeqCst);
765        } else {
766            assert!(!is_enhanced_profiling_active());
767        }
768    }
769
770    #[test]
771    fn test_macro_concept() {
772        let temp_dir = create_test_dir();
773        let _output_path = temp_dir.path().join("test_macro");
774
775        // Test the concept of enhanced profiling (macro doesn't exist yet)
776        let result = {
777            let _data = vec![0u8; 1024];
778            42
779        };
780
781        assert_eq!(result, 42);
782    }
783
784    #[test]
785    fn test_start_system_monitoring() {
786        let result = start_system_monitoring(Duration::from_millis(100));
787        // Should not panic and should return a result
788        let _ = result;
789    }
790
791    #[test]
792    fn test_monitoring_concept() {
793        let temp_dir = create_test_dir();
794        let _output_path = temp_dir.path().join("monitoring_test");
795
796        // Test the concept of enhanced monitoring
797        // (Functions don't exist yet in the public API)
798        assert!(temp_dir.path().exists());
799    }
800
801    #[test]
802    fn test_get_system_snapshot_multiple_calls() {
803        // Test that multiple calls to get_system_snapshot work
804        let snapshot1 = get_system_snapshot().unwrap();
805        let snapshot2 = get_system_snapshot().unwrap();
806
807        // Both snapshots should be valid
808        assert!(snapshot1.cpu_metrics.overall_usage >= 0.0);
809        assert!(snapshot2.cpu_metrics.overall_usage >= 0.0);
810
811        // Timestamps should be valid and potentially different - unsigned integers are always >= 0
812        // assert!(snapshot1.timestamp >= 0); // Always true for u64
813        // assert!(snapshot2.timestamp >= 0); // Always true for u64
814        // Second snapshot should have equal or later timestamp
815        assert!(snapshot2.timestamp >= snapshot1.timestamp);
816    }
817
818    #[test]
819    fn test_report_generation_concept() {
820        let temp_dir = create_test_dir();
821        let _output_path = temp_dir.path().join("report_test");
822
823        // Test the concept of report generation
824        // (These functions require proper parameters)
825        assert!(temp_dir.path().exists());
826    }
827
828    #[test]
829    fn test_cpu_metrics_comprehensive() {
830        let snapshot = get_system_snapshot().unwrap();
831        let cpu = &snapshot.cpu_metrics;
832
833        // Test all CPU metric fields
834        assert!(cpu.overall_usage >= 0.0 && cpu.overall_usage <= 100.0);
835        assert!(!cpu.core_usage.is_empty());
836        // assert!(cpu.frequency >= 0); // Always true for u64
837        // assert!(cpu.context_switches >= 0); // Always true for u64
838
839        // Per-core usage validation
840        for &usage in &cpu.core_usage {
841            assert!((0.0..=100.0).contains(&usage));
842        }
843    }
844
845    #[test]
846    fn test_memory_metrics_comprehensive() {
847        let snapshot = get_system_snapshot().unwrap();
848        let mem = &snapshot.memory_metrics;
849
850        // Test all memory metric fields (handle both real and fallback implementations)
851        if mem.total_physical > 0 {
852            // Real system metrics available
853            assert!(mem.used_physical <= mem.total_physical);
854            assert!(mem.available_physical <= mem.total_physical);
855        } else {
856            // Fallback implementation (no system-metrics feature)
857            assert_eq!(mem.total_physical, 0);
858            assert_eq!(mem.used_physical, 0);
859            assert_eq!(mem.available_physical, 0);
860        }
861
862        // assert!(mem.total_virtual >= 0); // Always true for u64
863        assert!(mem.available_virtual <= mem.total_virtual);
864        assert!(mem.pressure >= 0.0 && mem.pressure <= 100.0);
865        // assert!(mem.page_faults >= 0); // Always true for u64
866    }
867
868    #[test]
869    fn test_process_metrics() {
870        let snapshot = get_system_snapshot().unwrap();
871        let proc = &snapshot.process_metrics;
872
873        // Test process metric fields
874        assert!(proc.pid > 0);
875        assert!(!proc.name.is_empty());
876        assert!(proc.cpu_usage >= 0.0);
877        // assert!(proc.memory_usage >= 0); // Always true for u64
878        // assert!(proc.thread_count >= 0); // Always true for u32
879        // assert!(proc.handle_count >= 0); // Always true for u32
880    }
881
882    #[test]
883    fn test_thread_metrics() {
884        let snapshot = get_system_snapshot().unwrap();
885
886        // Test that thread metrics exist and are reasonable
887        assert!(!snapshot.thread_metrics.is_empty());
888
889        for (thread_id, thread_metric) in &snapshot.thread_metrics {
890            assert!(*thread_id > 0);
891            assert!(thread_metric.thread_id == *thread_id);
892            // assert!(thread_metric.cpu_time_ns >= 0); // Always true for u64
893        }
894    }
895
896    #[test]
897    fn test_gpu_metrics_optional() {
898        let snapshot = get_system_snapshot().unwrap();
899
900        // GPU metrics are optional, but if present should be valid
901        if let Some(gpu) = &snapshot.gpu_metrics {
902            assert!(!gpu.device_name.is_empty());
903            assert!(gpu.gpu_usage >= 0.0 && gpu.gpu_usage <= 100.0);
904            assert!(gpu.memory_total > 0);
905            assert!(gpu.memory_used <= gpu.memory_total);
906        }
907    }
908
909    #[test]
910    fn test_correlation_calculations() {
911        use crate::lockfree::analysis::LockfreeAnalysis;
912
913        let snapshot = get_system_snapshot().unwrap();
914        let analysis = LockfreeAnalysis::new();
915        let snapshots = vec![snapshot];
916
917        // Test correlation calculation functions with proper parameters
918        let mem_cpu_corr = calculate_memory_cpu_correlation(&analysis, &snapshots);
919        let net_corr = calculate_network_correlation(&analysis, &snapshots);
920
921        // All correlations should be in valid range
922        assert!((-1.0..=1.0).contains(&mem_cpu_corr));
923        assert!((-1.0..=1.0).contains(&net_corr));
924        assert!(!mem_cpu_corr.is_nan());
925        assert!(!net_corr.is_nan());
926    }
927
928    #[test]
929    fn test_monitoring_lifecycle() {
930        let temp_dir = create_test_dir();
931        let _output_path = temp_dir.path().join("lifecycle_test");
932
933        // Test complete monitoring lifecycle concept
934        // Take a snapshot to test the system
935        let snapshot = get_system_snapshot();
936        assert!(snapshot.is_ok());
937    }
938
939    #[test]
940    fn test_system_snapshot_timestamps() {
941        let snapshot1 = get_system_snapshot().unwrap();
942
943        // Small delay to ensure different timestamp
944        std::thread::sleep(Duration::from_millis(1));
945
946        let snapshot2 = get_system_snapshot().unwrap();
947
948        // Second snapshot should have equal or later timestamp
949        assert!(snapshot2.timestamp >= snapshot1.timestamp);
950    }
951
952    #[test]
953    fn test_multiple_start_stop_cycles() {
954        let temp_dir = create_test_dir();
955        let _output_path = temp_dir.path().join("cycles_test");
956
957        // Test multiple cycles concept
958        for _i in 0..3 {
959            // Test system monitoring concept
960            let _ = start_system_monitoring(Duration::from_millis(10));
961            let _ = stop_system_monitoring();
962        }
963    }
964
965    #[test]
966    fn test_system_profiler_creation() {
967        use crate::lockfree::system_profiler::SystemProfiler;
968
969        let profiler = SystemProfiler::new(Duration::from_millis(100));
970        // Should create without error
971        drop(profiler);
972    }
973
974    #[test]
975    fn test_error_handling_invalid_paths() {
976        // Test system monitoring with different intervals
977        let result = start_system_monitoring(Duration::from_millis(100));
978        // Should handle error gracefully
979        let _ = result;
980
981        // Test stop monitoring
982        let result2 = stop_system_monitoring();
983        let _ = result2;
984    }
985
986    #[test]
987    fn test_system_correlation_analysis() {
988        use crate::lockfree::analysis::LockfreeAnalysis;
989
990        let snapshot = get_system_snapshot().unwrap();
991
992        // Test that we can analyze correlation between different metrics
993        let memory_utilization = if snapshot.memory_metrics.total_physical > 0 {
994            snapshot.memory_metrics.used_physical as f64
995                / snapshot.memory_metrics.total_physical as f64
996        } else {
997            0.0 // Fallback for no system metrics
998        };
999        let cpu_utilization = snapshot.cpu_metrics.overall_usage as f64 / 100.0;
1000
1001        // Basic sanity checks for correlation analysis
1002        assert!((0.0..=1.0).contains(&memory_utilization));
1003        assert!((0.0..=1.0).contains(&cpu_utilization));
1004
1005        // Test correlation calculation with proper parameters
1006        let analysis = LockfreeAnalysis::new();
1007        let snapshots = vec![snapshot];
1008        let correlation = calculate_memory_cpu_correlation(&analysis, &snapshots);
1009        assert!((-1.0..=1.0).contains(&correlation));
1010    }
1011
1012    #[test]
1013    fn test_report_generation_with_real_data() {
1014        use crate::lockfree::analysis::LockfreeAnalysis;
1015
1016        let temp_dir = create_test_dir();
1017        let output_path = temp_dir.path().join("real_data_test");
1018
1019        // Generate some activity
1020        let _data = vec![0u8; 1024];
1021
1022        // Generate reports with proper parameters
1023        let analysis = LockfreeAnalysis::new();
1024        let snapshot = get_system_snapshot().unwrap();
1025        let snapshots = vec![snapshot];
1026
1027        let corr_result = generate_system_correlation_report(&analysis, &snapshots, &output_path);
1028        let html_result = generate_enhanced_system_html(&analysis, &snapshots, &output_path);
1029
1030        // Both should succeed
1031        assert!(corr_result.is_ok());
1032        assert!(html_result.is_ok());
1033    }
1034
1035    #[test]
1036    fn test_snapshot_consistency() {
1037        // Test that snapshot data is internally consistent
1038        let snapshot = get_system_snapshot().unwrap();
1039
1040        // Memory consistency
1041        let mem = &snapshot.memory_metrics;
1042        assert!(
1043            mem.used_physical + mem.available_physical
1044                <= mem.total_physical + mem.total_physical / 10
1045        ); // Allow some variance
1046
1047        // CPU consistency
1048        let cpu = &snapshot.cpu_metrics;
1049        if !cpu.core_usage.is_empty() {
1050            let avg_core_usage: f32 =
1051                cpu.core_usage.iter().sum::<f32>() / cpu.core_usage.len() as f32;
1052            // Overall usage should be reasonably close to average core usage
1053            let diff = (cpu.overall_usage - avg_core_usage).abs();
1054            assert!(diff <= 50.0); // Allow significant variance due to measurement timing
1055        }
1056    }
1057
1058    #[test]
1059    fn test_concurrent_snapshots() {
1060        use std::thread;
1061
1062        let handles: Vec<_> = (0..4)
1063            .map(|_| {
1064                thread::spawn(|| {
1065                    let snapshot = get_system_snapshot();
1066                    assert!(snapshot.is_ok());
1067                    snapshot.unwrap().timestamp
1068                })
1069            })
1070            .collect();
1071
1072        let timestamps: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();
1073
1074        // All timestamps should be valid (>= 0) - unsigned integers are always >= 0
1075        for &timestamp in &timestamps {
1076            // assert!(timestamp >= 0); // Always true for u64
1077            assert!(timestamp > 0); // Should be positive
1078        }
1079    }
1080
1081    #[test]
1082    fn test_enhanced_api_integration() {
1083        use crate::lockfree::analysis::LockfreeAnalysis;
1084
1085        let temp_dir = create_test_dir();
1086        let output_path = temp_dir.path().join("integration_test");
1087
1088        // Test full integration workflow
1089        let mut snapshots = Vec::new();
1090
1091        // Take multiple snapshots
1092        for _ in 0..3 {
1093            let snapshot = get_system_snapshot();
1094            assert!(snapshot.is_ok());
1095            snapshots.push(snapshot.unwrap());
1096            std::thread::sleep(Duration::from_millis(10));
1097        }
1098
1099        // Generate reports with proper parameters
1100        let analysis = LockfreeAnalysis::new();
1101        assert!(generate_system_correlation_report(&analysis, &snapshots, &output_path).is_ok());
1102        assert!(generate_enhanced_system_html(&analysis, &snapshots, &output_path).is_ok());
1103    }
1104}