use jbuild::interactive::*;
use chrono::Local;
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
use std::sync::mpsc;
#[test]
fn test_build_metrics_lifecycle() {
let metrics = BuildMetrics::new();
assert!(metrics.elapsed().as_millis() >= 0);
assert!(metrics.phase_times.is_empty());
assert!(metrics.current_phase.is_none());
assert_eq!(metrics.processed_dependencies, 0);
assert_eq!(metrics.total_dependencies, 0);
assert!(metrics.memory_usage_mb >= 0);
assert!(metrics.cpu_usage_percent >= 0.0);
}
#[test]
fn test_build_metrics_progress_tracking() {
let mut metrics = BuildMetrics::new();
metrics.update_progress(10, 100);
assert_eq!(metrics.processed_dependencies, 10);
assert_eq!(metrics.total_dependencies, 100);
metrics.update_progress(50, 200);
assert_eq!(metrics.processed_dependencies, 50);
assert_eq!(metrics.total_dependencies, 200);
}
#[test]
fn test_build_metrics_phase_timing() {
let mut metrics = BuildMetrics::new();
metrics.add_phase_time("Phase 1".to_string(), Duration::from_millis(1000));
metrics.add_phase_time("Phase 2".to_string(), Duration::from_millis(2000));
assert_eq!(metrics.phase_times.len(), 2);
assert_eq!(metrics.phase_times[0].0, "Phase 1");
assert_eq!(metrics.phase_times[1].0, "Phase 2");
assert_eq!(metrics.phase_times[0].1, Duration::from_millis(1000));
assert_eq!(metrics.phase_times[1].1, Duration::from_millis(2000));
}
#[test]
fn test_build_metrics_memory_tracking() {
let mut metrics = BuildMetrics::new();
let initial_memory = metrics.memory_usage_mb;
metrics.processed_dependencies = 50;
metrics.memory_usage_mb = 512 + (metrics.processed_dependencies as f64 * 0.1) as u64;
assert!(metrics.memory_usage_mb > initial_memory);
}
#[test]
fn test_build_metrics_cpu_tracking() {
let mut metrics = BuildMetrics::new();
let initial_cpu = metrics.cpu_usage_percent;
metrics.processed_dependencies = 30;
metrics.cpu_usage_percent = (25.0 + (metrics.processed_dependencies as f64 * 0.5)) as f32;
assert!(metrics.cpu_usage_percent > initial_cpu);
assert!(metrics.cpu_usage_percent <= 100.0);
}
#[test]
fn test_profile_report_creation() {
let report = ProfileReport {
build_time: Duration::from_secs(10),
success: true,
error_count: 0,
phases: vec![
("Dependencies".to_string(), Duration::from_millis(2000)),
("Compilation".to_string(), Duration::from_millis(6000)),
("Testing".to_string(), Duration::from_millis(2000)),
],
timestamp: chrono::Local::now(),
};
assert_eq!(report.build_time, Duration::from_secs(10));
assert!(report.success);
assert_eq!(report.error_count, 0);
assert_eq!(report.phases.len(), 3);
assert_eq!(report.phases[0].0, "Dependencies");
}
#[test]
fn test_progress_simulation_structure() {
let (tx, rx) = mpsc::channel();
tx.send("Test update".to_string()).unwrap();
let received = rx.recv().unwrap();
assert_eq!(received, "Test update");
}
#[test]
fn test_markdown_report_generation() {
let report = ProfileReport {
build_time: Duration::from_secs(5),
success: true,
error_count: 1,
phases: vec![
("Test Phase".to_string(), Duration::from_millis(2000)),
],
timestamp: chrono::Local::now(),
};
let markdown = generate_markdown_report(&report);
assert!(markdown.contains("# Build Profile Report"));
assert!(markdown.contains("**Build Time**"));
assert!(markdown.contains("✅ Success"));
assert!(markdown.contains("Test Phase"));
assert!(markdown.contains("40.0%"));
}
#[test]
fn test_text_report_generation() {
let report = ProfileReport {
build_time: Duration::from_secs(8),
success: false,
error_count: 3,
phases: vec![
("Phase 1".to_string(), Duration::from_millis(3000)),
("Phase 2".to_string(), Duration::from_millis(5000)),
],
timestamp: chrono::Local::now(),
};
let text = generate_text_report(&report);
assert!(text.contains("Build Profile Report"));
assert!(text.contains("Build Time: 8.00s"));
assert!(text.contains("FAILED"));
assert!(text.contains("Phase 1: 3.00s (37.5%)"));
assert!(text.contains("Phase 2: 5.00s (62.5%)"));
}
#[test]
fn test_error_handling_for_invalid_formats() {
let result = generate_profile_report(
Duration::from_secs(5),
&None,
"invalid_format"
);
match result {
Ok(_) => {
println!("Invalid format handled gracefully");
}
Err(e) => {
println!("Error handling invalid format: {}", e);
}
}
}
#[test]
fn test_dashboard_display_basic() {
let metrics = BuildMetrics::new();
let start_time = std::time::Instant::now();
let result = display_dashboard(&metrics, &start_time, jbuild::build::BuildSystem::Maven);
assert!(result.is_ok());
}
#[test]
fn test_monitor_functionality() {
use std::thread;
use std::time::Instant;
let metrics = BuildMetrics::new();
let start_time = Instant::now();
let result = display_monitor(&metrics, &start_time, false);
assert!(result.is_ok());
}
#[test]
fn test_performance_calculations() {
let mut metrics = BuildMetrics::new();
let start_time = std::time::Instant::now();
std::thread::sleep(Duration::from_millis(100));
metrics.processed_dependencies = 5;
let elapsed = start_time.elapsed();
let throughput = metrics.processed_dependencies as f64 / elapsed.as_secs_f64();
assert!(throughput > 0.0);
}
#[test]
fn test_concurrent_metrics_access() {
let mut handles = vec![];
for _i in 0..3 {
let handle = std::thread::spawn(move || {
let mut metrics = BuildMetrics::new();
for j in 0..10 {
metrics.processed_dependencies = j;
metrics.memory_usage_mb = 512 + (j as f64 * 0.1) as u64;
}
metrics
});
handles.push(handle);
}
let mut total_processed = 0;
for handle in handles {
let metrics = handle.join().unwrap();
total_processed += metrics.processed_dependencies;
}
assert!(total_processed > 0);
}
#[test]
fn test_phase_timing_accuracy() {
let mut metrics = BuildMetrics::new();
let phase_start = std::time::Instant::now();
std::thread::sleep(Duration::from_millis(50));
let actual_duration = phase_start.elapsed();
metrics.add_phase_time("Test Phase".to_string(), actual_duration);
let recorded_duration = metrics.phase_times[0].1;
assert!((recorded_duration.as_millis() as i64 - actual_duration.as_millis() as i64).abs() < 10);
}
#[test]
fn test_memory_usage_bounds() {
let mut metrics = BuildMetrics::new();
for deps in [0, 10, 50, 100, 500] {
metrics.processed_dependencies = deps;
metrics.memory_usage_mb = 512 + (deps as f64 * 0.1) as u64;
assert!(metrics.memory_usage_mb > 0);
assert!(metrics.memory_usage_mb < 10000); }
}
#[test]
fn test_cpu_usage_bounds() {
let mut metrics = BuildMetrics::new();
for deps in [0, 10, 50, 100, 500] {
metrics.processed_dependencies = deps;
metrics.cpu_usage_percent = (25.0 + (deps as f64 * 0.1)).min(95.0) as f32;
assert!(metrics.cpu_usage_percent >= 0.0);
assert!(metrics.cpu_usage_percent <= 100.0);
}
}
}