#![cfg(all(feature = "monitor", any(target_os = "linux", target_os = "macos")))]
#![allow(
clippy::unwrap_used,
clippy::approx_constant,
clippy::manual_range_contains,
unused_variables,
dead_code
)]
use std::time::Duration;
use trueno_viz::monitor::collectors::{
CpuCollector, DiskCollector, MemoryCollector, NetworkCollector, ProcessCollector,
};
use trueno_viz::monitor::types::Collector;
#[cfg(target_os = "macos")]
use trueno_viz::monitor::collectors::AppleGpuCollector;
#[test]
fn pixel_cpu_values_valid_range() {
let mut cpu = CpuCollector::new();
let _ = cpu.collect();
std::thread::sleep(Duration::from_millis(200));
let metrics = cpu.collect().expect("CPU collection failed");
if let Some(total) = metrics.get_gauge("cpu.total") {
assert!(total >= 0.0, "PIXEL FAIL: CPU total {total}% is negative (impossible)");
assert!(total <= 100.0, "PIXEL FAIL: CPU total {total}% exceeds 100% (bug in calculation)");
assert!(total.is_finite(), "PIXEL FAIL: CPU total is NaN or Infinity");
}
}
#[test]
fn pixel_cpu_values_change_over_time() {
let mut cpu = CpuCollector::new();
let _ = cpu.collect();
std::thread::sleep(Duration::from_millis(100));
let mut samples = Vec::new();
for _ in 0..5 {
std::thread::sleep(Duration::from_millis(200));
if let Ok(metrics) = cpu.collect() {
if let Some(total) = metrics.get_gauge("cpu.total") {
samples.push(total);
}
}
}
assert!(samples.len() >= 3, "PIXEL FAIL: Could not collect enough CPU samples");
let non_zero = samples.iter().filter(|&&v| v > 0.1).count();
println!("CPU samples: {samples:?}");
let all_same = samples.windows(2).all(|w| (w[0] - w[1]).abs() < 0.001);
if all_same && samples.len() > 2 {
println!("WARNING: All CPU samples identical: {samples:?}");
}
}
#[test]
fn pixel_cpu_history_updates() {
let mut cpu = CpuCollector::new();
let _ = cpu.collect();
let initial_len = cpu.history().len();
for _ in 0..5 {
std::thread::sleep(Duration::from_millis(100));
let _ = cpu.collect();
}
let final_len = cpu.history().len();
assert!(
final_len > initial_len,
"PIXEL FAIL: CPU history not updating - graph would be static! Initial: {initial_len}, Final: {final_len}"
);
}
#[test]
fn pixel_cpu_per_core_valid() {
let mut cpu = CpuCollector::new();
let _ = cpu.collect();
std::thread::sleep(Duration::from_millis(200));
let metrics = cpu.collect().expect("CPU collection failed");
let core_count = cpu.core_count();
assert!(core_count >= 1, "PIXEL FAIL: No CPU cores detected");
for i in 0..core_count {
if let Some(core_pct) = metrics.get_gauge(&format!("cpu.core.{i}")) {
assert!(
core_pct >= 0.0 && core_pct <= 100.0,
"PIXEL FAIL: Core {i} at {core_pct}% outside valid range"
);
assert!(core_pct.is_finite(), "PIXEL FAIL: Core {i} value is NaN/Infinity");
}
}
}
#[cfg(target_os = "macos")]
mod gpu_tests {
use super::*;
#[test]
fn pixel_gpu_utilization_not_always_zero() {
let mut gpu = AppleGpuCollector::new();
if !gpu.is_available() {
println!("GPU not available, skipping test");
return;
}
let mut samples = Vec::new();
for _ in 0..5 {
if let Ok(metrics) = gpu.collect() {
if let Some(util) = metrics.get_gauge("gpu.0.util") {
samples.push(util);
}
}
std::thread::sleep(Duration::from_millis(200));
}
println!("GPU utilization samples: {:?}", samples);
assert!(!samples.is_empty(), "PIXEL FAIL: No GPU samples collected");
for &sample in &samples {
assert!(
sample >= 0.0 && sample <= 100.0,
"PIXEL FAIL: GPU util {}% outside valid range",
sample
);
}
let has_activity = samples.iter().any(|&v| v > 0.0);
if !has_activity {
println!("WARNING: All GPU samples are 0.0 - this may indicate GPU is truly idle");
println!("But the fix ensures the graph will at least update (not be static)");
}
}
#[test]
fn pixel_gpu_history_updates() {
let mut gpu = AppleGpuCollector::new();
if !gpu.is_available() {
println!("GPU not available, skipping test");
return;
}
let _ = gpu.collect();
let initial_len = gpu.util_history(0).map(|h| h.len()).unwrap_or(0);
for _ in 0..5 {
std::thread::sleep(Duration::from_millis(100));
let _ = gpu.collect();
}
let final_len = gpu.util_history(0).map(|h| h.len()).unwrap_or(0);
assert!(
final_len > initial_len,
"PIXEL FAIL: GPU history not updating - graph would be static! Initial: {}, Final: {}",
initial_len,
final_len
);
}
#[test]
fn pixel_gpu_detection() {
let gpu = AppleGpuCollector::new();
#[cfg(target_os = "macos")]
{
assert!(gpu.is_available(), "PIXEL FAIL: GPU should be available on macOS");
if let Some(info) = gpu.primary_gpu() {
assert!(!info.name.is_empty(), "PIXEL FAIL: GPU name is empty");
println!("Detected GPU: {}", info.name);
}
}
}
}
#[test]
fn pixel_memory_values_consistent() {
let mut mem = MemoryCollector::new();
let metrics = mem.collect().expect("Memory collection failed");
let total = metrics.get_counter("memory.total").expect("No memory.total");
let used = metrics.get_counter("memory.used").unwrap_or(0);
let available = metrics.get_counter("memory.available").unwrap_or(0);
assert!(total > 0, "PIXEL FAIL: Total memory is 0");
assert!(used <= total, "PIXEL FAIL: Used memory ({used}) > Total ({total})");
assert!(available <= total, "PIXEL FAIL: Available memory ({available}) > Total ({total})");
if let Some(pct) = metrics.get_gauge("memory.used.percent") {
assert!(
pct >= 0.0 && pct <= 100.0,
"PIXEL FAIL: Memory percent {pct}% outside 0-100 range"
);
}
println!(
"Memory: Total={} MB, Used={} MB, Available={} MB",
total / 1024 / 1024,
used / 1024 / 1024,
available / 1024 / 1024
);
}
#[test]
fn pixel_memory_history_updates() {
let mut mem = MemoryCollector::new();
let _ = mem.collect();
let initial_len = mem.history().len();
for _ in 0..5 {
std::thread::sleep(Duration::from_millis(100));
let _ = mem.collect();
}
let final_len = mem.history().len();
assert!(final_len > initial_len, "PIXEL FAIL: Memory history not updating");
}
#[test]
fn pixel_network_interfaces_detected() {
let mut net = NetworkCollector::new();
let _ = net.collect();
std::thread::sleep(Duration::from_millis(100));
let _ = net.collect();
let interfaces = net.interfaces();
assert!(!interfaces.is_empty(), "PIXEL FAIL: No network interfaces detected");
println!("Detected interfaces: {interfaces:?}");
#[cfg(target_os = "macos")]
{
let has_en = interfaces.iter().any(|i| i.starts_with("en"));
assert!(has_en, "PIXEL FAIL: No en* interface on macOS");
}
}
#[test]
fn pixel_network_rates_valid() {
let mut net = NetworkCollector::new();
let _ = net.collect();
std::thread::sleep(Duration::from_millis(200));
let _ = net.collect();
if let Some(rates) = net.current_rates() {
assert!(
rates.rx_bytes_per_sec >= 0.0,
"PIXEL FAIL: Negative RX rate: {}",
rates.rx_bytes_per_sec
);
assert!(
rates.tx_bytes_per_sec >= 0.0,
"PIXEL FAIL: Negative TX rate: {}",
rates.tx_bytes_per_sec
);
assert!(rates.rx_bytes_per_sec.is_finite(), "PIXEL FAIL: RX rate is NaN/Infinity");
assert!(rates.tx_bytes_per_sec.is_finite(), "PIXEL FAIL: TX rate is NaN/Infinity");
}
}
#[test]
fn pixel_disk_mounts_valid() {
let mut disk = DiskCollector::new();
let _ = disk.collect();
let mounts = disk.mounts();
assert!(!mounts.is_empty(), "PIXEL FAIL: No disk mounts detected");
let has_root = mounts.iter().any(|m| m.mount_point == "/");
assert!(has_root, "PIXEL FAIL: No root mount (/) detected");
for mount in mounts {
let pct = mount.usage_percent();
assert!(
pct >= 0.0 && pct <= 100.0,
"PIXEL FAIL: Mount {} at {}% outside valid range",
mount.mount_point,
pct
);
if mount.total_bytes > 0 {
assert!(
mount.used_bytes <= mount.total_bytes,
"PIXEL FAIL: Mount {} used ({}) > total ({})",
mount.mount_point,
mount.used_bytes,
mount.total_bytes
);
}
}
}
#[test]
fn pixel_process_count_reasonable() {
let mut proc = ProcessCollector::new();
let _ = proc.collect();
let count = proc.count();
assert!(count >= 50, "PIXEL FAIL: Only {count} processes, expected >= 50");
assert!(count < 10000, "PIXEL FAIL: {count} processes seems unreasonable");
println!("Process count: {count}");
}
#[test]
fn pixel_process_pid1_exists() {
let mut proc = ProcessCollector::new();
let _ = proc.collect();
let has_pid1 = proc.processes().contains_key(&1);
assert!(has_pid1, "PIXEL FAIL: PID 1 (init/launchd) not found");
}
#[test]
fn pixel_process_tree_valid() {
let mut proc = ProcessCollector::new();
let _ = proc.collect();
let tree = proc.build_tree();
assert!(!tree.is_empty(), "PIXEL FAIL: Process tree is empty");
if let Some(children) = tree.get(&0) {
assert!(!children.is_empty(), "PIXEL FAIL: Root process has no children");
}
}
#[test]
fn pixel_process_cpu_percentages_valid() {
let mut proc = ProcessCollector::new();
let _ = proc.collect();
std::thread::sleep(Duration::from_millis(200));
let _ = proc.collect();
for p in proc.processes().values() {
assert!(
p.cpu_percent >= 0.0,
"PIXEL FAIL: Process {} has negative CPU: {}%",
p.name,
p.cpu_percent
);
assert!(
p.cpu_percent < 10000.0,
"PIXEL FAIL: Process {} has unreasonable CPU: {}%",
p.name,
p.cpu_percent
);
}
}
#[test]
fn pixel_all_collectors_produce_changing_output() {
let mut cpu = CpuCollector::new();
let _ = cpu.collect();
std::thread::sleep(Duration::from_millis(100));
let m1 = cpu.collect().ok();
std::thread::sleep(Duration::from_millis(100));
let m2 = cpu.collect().ok();
assert!(cpu.history().len() >= 2, "PIXEL FAIL: CPU history not growing");
let mut mem = MemoryCollector::new();
let _ = mem.collect();
std::thread::sleep(Duration::from_millis(100));
let _ = mem.collect();
assert!(mem.history().len() >= 2, "PIXEL FAIL: Memory history not growing");
let mut net = NetworkCollector::new();
let _ = net.collect();
std::thread::sleep(Duration::from_millis(100));
let _ = net.collect();
let mut disk = DiskCollector::new();
let _ = disk.collect();
assert!(!disk.mounts().is_empty(), "PIXEL FAIL: No disk mounts");
let mut proc = ProcessCollector::new();
let _ = proc.collect();
assert!(proc.count() > 0, "PIXEL FAIL: No processes");
println!("All collectors producing output");
}
#[test]
#[cfg(target_os = "macos")]
fn pixel_bug_macos_cpu_delta_on_percentage() {
let mut cpu = CpuCollector::new();
let _ = cpu.collect();
std::thread::sleep(Duration::from_millis(500));
let start = std::time::Instant::now();
while start.elapsed() < Duration::from_millis(100) {
let _ = (0..1000).sum::<i32>();
}
let metrics = cpu.collect().expect("CPU collection failed");
if let Some(total) = metrics.get_gauge("cpu.total") {
println!("CPU total after busy loop: {}%", total);
assert!(
total >= 0.0 && total <= 100.0 && total.is_finite(),
"PIXEL FAIL: CPU value {}% is invalid - delta calculation bug!",
total
);
}
}
#[test]
#[cfg(target_os = "macos")]
fn pixel_gpu_returns_actual_values() {
let mut gpu = AppleGpuCollector::new();
if !gpu.is_available() {
return;
}
for _ in 0..3 {
let _ = gpu.collect();
std::thread::sleep(Duration::from_millis(100));
}
if let Some(info) = gpu.primary_gpu() {
println!("GPU: {}, util: {}%", info.name, info.gpu_util);
assert!(!info.name.is_empty(), "GPU name should not be empty");
assert!(
info.gpu_util >= 0.0 && info.gpu_util <= 100.0,
"GPU util {}% outside valid range",
info.gpu_util
);
println!("GPU utilization: {}% (graph should now animate)", info.gpu_util);
}
}