use super::super::super::*;
#[test]
#[ignore = "Environment-dependent: timing varies on CI runners under load"]
fn test_f150_cpu_cycles_overhead() {
for _ in 0..100 {
let _ = cpu_cycles();
}
let start = std::time::Instant::now();
for _ in 0..10000 {
let _ = cpu_cycles();
}
let elapsed = start.elapsed();
let avg_ns = elapsed.as_nanos() as f64 / 10000.0;
assert!(avg_ns < 50.0, "cpu_cycles() overhead should be < 50ns, got {:.1}ns", avg_ns);
}
#[test]
fn test_f151_cpu_cycles_monotonic() {
let c1 = cpu_cycles();
let mut sum = 0u64;
for i in 0..1000 {
sum = sum.wrapping_add(i);
}
let _ = sum; let c2 = cpu_cycles();
assert!(c2 >= c1, "Cycle count should be monotonic: {} >= {}", c2, c1);
}
#[test]
fn test_f152_cached_time_precision() {
init_time_service();
std::thread::sleep(std::time::Duration::from_millis(2));
let cached = cached_nanos();
let reference_start = std::time::Instant::now();
std::thread::sleep(std::time::Duration::from_micros(100));
let cached_after = cached_nanos();
let elapsed_real = reference_start.elapsed().as_nanos() as u64;
if cached > 0 && cached_after > 0 {
let cached_elapsed = cached_after.saturating_sub(cached);
let drift = elapsed_real.abs_diff(cached_elapsed);
assert!(
drift < 2_000_000, "Cached time drift should be < 2ms, got {}us",
drift / 1000
);
}
}
#[test]
#[ignore = "Environment-dependent: timing varies on CI runners under load"]
fn test_f153_cached_time_overhead() {
init_time_service();
std::thread::sleep(std::time::Duration::from_millis(1));
for _ in 0..100 {
let _ = cached_nanos();
}
let start = std::time::Instant::now();
for _ in 0..100000 {
let _ = cached_nanos();
}
let elapsed = start.elapsed();
let avg_ns = elapsed.as_nanos() as f64 / 100000.0;
assert!(avg_ns < 20.0, "cached_nanos() overhead should be < 20ns, got {:.1}ns", avg_ns);
}
#[test]
fn test_f154_poll_count_accuracy() {
let mut profiler = AsyncTaskProfiler::new("test_task");
for i in 0..5 {
profiler.on_poll_start();
let is_ready = i == 4; profiler.on_poll_end(is_ready);
}
assert_eq!(profiler.poll_count, 5, "Should have 5 polls");
assert_eq!(profiler.yield_count, 4, "Should have 4 yields (Pending)");
assert!((profiler.efficiency() - 0.2).abs() < 0.01, "Efficiency should be 1/5 = 0.2");
assert!((profiler.yield_ratio() - 0.8).abs() < 0.01, "Yield ratio should be 4/5 = 0.8");
}
#[test]
fn test_f155_page_fault_detection() {
let (minor1, major1) = get_page_faults();
let v: Vec<u8> = vec![0u8; 4096 * 10]; let _ = v.iter().sum::<u8>();
let (minor2, major2) = get_page_faults();
#[cfg(target_os = "linux")]
{
assert!(minor2 >= minor1, "Minor faults should not decrease: {} >= {}", minor2, minor1);
}
assert!(major2 - major1 < 10, "Should have minimal major faults: {} - {} < 10", major2, major1);
}
#[test]
fn test_brick_stats_cycle_tracking() {
let mut stats = BrickStats::new("test_brick");
stats.add_sample_with_cycles(1000, 100, 3000); stats.add_sample_with_cycles(2000, 200, 6000);
assert_eq!(stats.total_cycles, 9000);
assert_eq!(stats.min_cycles, 3000);
assert_eq!(stats.max_cycles, 6000);
assert!((stats.cycles_per_element() - 30.0).abs() < 0.1); assert!((stats.avg_cycles() - 4500.0).abs() < 0.1);
let ipc = stats.estimated_ipc();
assert!(ipc > 0.0 && ipc < 1.0, "IPC should be low (memory bound)");
let diagnosis = stats.diagnose_from_cycles();
assert!(
diagnosis.contains("memory") || diagnosis.contains("insufficient"),
"Low IPC should indicate memory bound"
);
}
#[test]
fn test_async_task_profiler_to_execution_node() {
let mut profiler = AsyncTaskProfiler::new("request_handler");
profiler.poll_count = 3;
profiler.yield_count = 2;
profiler.total_poll_ns = 1500;
let node = profiler.to_execution_node();
if let ExecutionNode::AsyncTask { name, poll_count, yield_count, total_poll_ns } = node {
assert_eq!(name, "request_handler");
assert_eq!(poll_count, 3);
assert_eq!(yield_count, 2);
assert_eq!(total_poll_ns, 1500);
} else {
panic!("Expected AsyncTask node");
}
}
#[test]
fn test_execution_graph_async_task() {
let mut graph = ExecutionGraph::new();
graph.add_node(ExecutionNode::AsyncTask {
name: "inference".into(),
poll_count: 5,
yield_count: 4,
total_poll_ns: 2500,
});
let tree = graph.to_ascii_tree();
assert!(tree.contains("inference"), "Should contain task name");
assert!(tree.contains("polls:5"), "Should contain poll count");
let dot = graph.to_dot();
assert!(dot.contains("inference"), "DOT should contain task name");
assert!(dot.contains("lightcyan"), "AsyncTask should have cyan color");
}
#[test]
fn test_with_page_fault_tracking() {
let (result, minor, major) = with_page_fault_tracking("test_alloc", || {
let v: Vec<u8> = vec![42u8; 100];
v.len() });
assert_eq!(result, 100);
assert!(minor < 1_000_000, "Minor faults should be bounded");
assert!(major < 100, "Major faults should be minimal");
}