use super::super::*;
use crate::brick::exec_graph::{BrickBottleneck, ExecutionNode};
#[test]
fn test_fnv1a_checksum_empty() {
let data: [f32; 0] = [];
let checksum = fnv1a_f32_checksum(&data);
assert_eq!(checksum, 0xcbf29ce484222325);
}
#[test]
fn test_fnv1a_checksum_deterministic() {
let data = [1.0f32, 2.0, 3.0, 4.0];
let c1 = fnv1a_f32_checksum(&data);
let c2 = fnv1a_f32_checksum(&data);
assert_eq!(c1, c2);
}
#[test]
fn test_fnv1a_checksum_different_inputs() {
let data1 = [1.0f32, 2.0, 3.0];
let data2 = [1.0f32, 2.0, 4.0];
let c1 = fnv1a_f32_checksum(&data1);
let c2 = fnv1a_f32_checksum(&data2);
assert_ne!(c1, c2);
}
#[test]
fn test_fnv1a_checksum_truncates_at_64() {
let data_short: Vec<f32> = (0..64).map(|i| i as f32).collect();
let data_long: Vec<f32> = (0..100).map(|i| i as f32).collect();
let c1 = fnv1a_f32_checksum(&data_short);
let c2 = fnv1a_f32_checksum(&data_long);
assert_eq!(c1, c2);
}
#[test]
fn test_brick_profiler_divergence_detection() {
let mut cpu_profiler = BrickProfiler::new();
let mut gpu_profiler = BrickProfiler::new();
cpu_profiler.enable();
gpu_profiler.enable();
let data = [1.0f32, 2.0, 3.0, 4.0];
cpu_profiler.record_checksum("TestKernel", 0, 0, &data);
gpu_profiler.record_checksum("TestKernel", 0, 0, &data);
assert!(gpu_profiler.find_divergence(&cpu_profiler).is_none());
let different_data = [1.0f32, 2.0, 3.0, 5.0]; gpu_profiler.reset_checksums();
gpu_profiler.record_checksum("TestKernel", 0, 0, &different_data);
let div = gpu_profiler.find_divergence(&cpu_profiler);
assert!(div.is_some());
let div = div.unwrap();
assert_eq!(div.kernel_name, "TestKernel");
assert_eq!(div.layer_idx, 0);
assert_eq!(div.position, 0);
}
#[test]
fn test_falsify_tile_stats_min_max_monotonicity() {
let mut stats = TileStats::new(TileLevel::Macro);
for ns in [1000, 500, 2000, 100, 5000, 50] {
stats.add_sample(ns, 10, 20);
assert!(
stats.min_ns <= stats.max_ns,
"FALSIFICATION FAILED: min {} > max {} after adding {}",
stats.min_ns,
stats.max_ns,
ns
);
}
assert_eq!(stats.min_ns, 50);
assert_eq!(stats.max_ns, 5000);
}
#[test]
fn test_falsify_total_tokens_accumulation() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let mut expected_total = 0u64;
let element_counts = [10, 20, 30, 15, 25];
for &count in &element_counts {
let timer = profiler.start_brick(BrickId::RmsNorm);
profiler.stop_brick(timer, count);
expected_total += count;
}
assert_eq!(
profiler.total_tokens(),
expected_total,
"FALSIFICATION FAILED: total_tokens {} != expected {}",
profiler.total_tokens(),
expected_total
);
}
#[test]
fn test_falsify_checksum_collision_resistance() {
let patterns: Vec<Vec<f32>> = vec![
vec![0.0; 10],
vec![1.0; 10],
vec![-1.0; 10],
(0..10).map(|i| i as f32).collect(),
(0..10).map(|i| -(i as f32)).collect(),
vec![f32::MIN_POSITIVE; 10],
vec![f32::MAX; 10],
];
let checksums: Vec<u64> = patterns.iter().map(|p| fnv1a_f32_checksum(p)).collect();
for i in 0..checksums.len() {
for j in (i + 1)..checksums.len() {
assert_ne!(
checksums[i], checksums[j],
"FALSIFICATION FAILED: patterns {} and {} collide with checksum {:016X}",
i, j, checksums[i]
);
}
}
}
#[test]
fn test_tile_stats_cache_efficiency() {
let mut stats = TileStats::new(TileLevel::Macro);
assert_eq!(stats.cache_efficiency(0.0), 0.0);
assert_eq!(stats.cache_efficiency(-1.0), 0.0);
stats.add_sample(1_000_000_000, 100, 1_000_000_000);
let efficiency = stats.cache_efficiency(10.0); assert!((efficiency - 0.1).abs() < 0.01);
let capped = stats.cache_efficiency(0.5); assert!((capped - 1.0).abs() < 0.001);
}
#[test]
fn test_brick_profiler_record_elapsed() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let duration = std::time::Duration::from_micros(1000);
profiler.record_elapsed("MyBrick", duration, 100);
assert!(profiler.total_tokens() >= 100);
assert!(profiler.total_ns() > 0);
}
#[test]
fn test_brick_profiler_record_elapsed_disabled() {
let mut profiler = BrickProfiler::new();
let duration = std::time::Duration::from_micros(1000);
profiler.record_elapsed("MyBrick", duration, 100);
assert_eq!(profiler.total_tokens(), 0);
}
#[test]
fn test_brick_profiler_record_elapsed_with_bytes() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let duration = std::time::Duration::from_micros(500);
profiler.record_elapsed_with_bytes("ByteBrick", duration, 200, 4096, 2048);
assert!(profiler.total_tokens() >= 200);
}
#[test]
fn test_brick_profiler_set_brick_bottleneck() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let timer = profiler.start("TestBrick");
profiler.stop(timer, 10);
profiler.set_brick_bottleneck("TestBrick", BrickBottleneck::Memory);
}
#[test]
fn test_brick_profiler_category_stats() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let timer = profiler.start_brick(BrickId::RmsNorm);
std::thread::sleep(std::time::Duration::from_micros(10));
profiler.stop_brick(timer, 100);
let category_stats = profiler.category_stats();
let norm_stats = &category_stats[BrickCategory::Norm as usize];
assert!(norm_stats.count >= 1);
}
#[test]
fn test_brick_profiler_graph_operations() {
let mut profiler = BrickProfiler::new();
profiler.enable();
assert!(!profiler.is_graph_enabled());
profiler.enable_graph();
assert!(profiler.is_graph_enabled());
let node = ExecutionNode::Layer { index: 0 };
let scope_id = profiler.graph_push_scope(node);
assert!(scope_id.is_some());
profiler.graph_record_brick(BrickId::RmsNorm, 1000, 100);
let popped_id = profiler.graph_pop_scope();
assert!(popped_id.is_some());
assert!(profiler.graph_is_scope_balanced());
profiler.disable_graph();
assert!(!profiler.is_graph_enabled());
}
#[test]
fn test_brick_profiler_graph_to_dot() {
let mut profiler = BrickProfiler::new();
profiler.enable();
profiler.enable_graph();
let node = ExecutionNode::Layer { index: 1 };
profiler.graph_push_scope(node);
profiler.graph_record_brick(BrickId::RmsNorm, 500, 50);
profiler.graph_pop_scope();
let dot = profiler.graph_to_dot();
assert!(dot.contains("digraph"));
}
#[test]
fn test_brick_profiler_graph_clear() {
let mut profiler = BrickProfiler::new();
profiler.enable();
profiler.enable_graph();
let node = ExecutionNode::Layer { index: 2 };
profiler.graph_push_scope(node);
profiler.graph_pop_scope();
profiler.graph_clear();
assert!(profiler.graph_is_scope_balanced());
}
#[test]
fn test_brick_profiler_l2_cache_hit_rate() {
let mut profiler = BrickProfiler::new();
assert!(profiler.l2_cache_hit_rate().is_none());
profiler.set_l2_cache_hit_rate(0.95);
assert_eq!(profiler.l2_cache_hit_rate(), Some(0.95));
}
#[test]
fn test_brick_profiler_zero_copy() {
let mut profiler = BrickProfiler::new();
assert!(!profiler.is_zero_copy());
profiler.set_zero_copy(true);
assert!(profiler.is_zero_copy());
profiler.set_zero_copy(false);
assert!(!profiler.is_zero_copy());
}
#[test]
fn test_brick_profiler_reset_epoch() {
let mut profiler = BrickProfiler::new();
profiler.enable();
std::thread::sleep(std::time::Duration::from_micros(100));
let ns1 = profiler.elapsed_ns();
assert!(ns1 > 0);
profiler.reset_epoch();
let ns2 = profiler.elapsed_ns();
assert!(ns2 < ns1);
}
#[test]
fn test_brick_profiler_brick_stats_mut() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let stats = profiler.brick_stats_mut(BrickId::RmsNorm);
stats.count = 42;
let stats = profiler.brick_stats(BrickId::RmsNorm);
assert_eq!(stats.count, 42);
}
#[test]
fn test_brick_profiler_record_deferred_dynamic() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let start_ns = profiler.elapsed_ns();
std::thread::sleep(std::time::Duration::from_micros(50));
profiler.record_deferred_dynamic("DynamicBrick", start_ns, 75);
assert!(profiler.has_pending());
assert_eq!(profiler.pending_count(), 1);
let end_ns = profiler.elapsed_ns();
profiler.finalize(end_ns);
assert!(!profiler.has_pending());
}
#[test]
fn test_tile_stats_default() {
let stats = TileStats::default();
assert_eq!(stats.level, TileLevel::Macro); assert_eq!(stats.count, 0);
}
#[test]
fn test_tile_level_default() {
let level = TileLevel::default();
assert_eq!(level, TileLevel::Macro);
}
#[test]
fn test_brick_profiler_execution_graph_accessors() {
let mut profiler = BrickProfiler::new();
let _graph = profiler.execution_graph();
let _graph_mut = profiler.execution_graph_mut();
}
#[test]
fn test_brick_profiler_graph_record_kernel() {
let mut profiler = BrickProfiler::new();
profiler.enable();
profiler.enable_graph();
let node = ExecutionNode::Layer { index: 3 };
profiler.graph_push_scope(node);
profiler.graph_record_kernel("my_kernel", 0x12345678, (1, 1, 1), (256, 1, 1), 4096);
profiler.graph_pop_scope();
let dot = profiler.graph_to_dot();
assert!(!dot.is_empty());
}
#[test]
fn test_brick_profiler_graph_disabled_operations() {
let mut profiler = BrickProfiler::new();
profiler.enable();
let node = ExecutionNode::Layer { index: 4 };
let scope_id = profiler.graph_push_scope(node);
assert!(scope_id.is_none());
let popped = profiler.graph_pop_scope();
assert!(popped.is_none());
}