use super::super::super::*;
#[test]
fn test_f356_tile_level_names() {
assert_eq!(TileLevel::Macro.name(), "macro");
assert_eq!(TileLevel::Midi.name(), "midi");
assert_eq!(TileLevel::Micro.name(), "micro");
}
#[test]
fn test_f357_tile_stats_basic() {
let mut stats = TileStats::new(TileLevel::Macro);
assert_eq!(stats.count, 0);
assert_eq!(stats.level, TileLevel::Macro);
stats.add_sample(1_000_000, 1024, 2048);
stats.add_sample(2_000_000, 2048, 4096);
assert_eq!(stats.count, 2);
assert_eq!(stats.total_ns, 3_000_000);
assert_eq!(stats.total_elements, 3072);
assert_eq!(stats.total_flops, 6144);
assert_eq!(stats.min_ns, 1_000_000);
assert_eq!(stats.max_ns, 2_000_000);
}
#[test]
fn test_f358_tile_stats_avg_us() {
let mut stats = TileStats::new(TileLevel::Midi);
assert_eq!(stats.avg_us(), 0.0);
stats.add_sample(1_000_000, 100, 200); stats.add_sample(3_000_000, 100, 200);
assert!((stats.avg_us() - 2000.0).abs() < 0.01);
}
#[test]
fn test_f359_tile_stats_throughput() {
let mut stats = TileStats::new(TileLevel::Micro);
stats.add_sample(1_000_000_000, 1_000_000, 0);
let throughput = stats.throughput();
assert!((throughput - 1_000_000.0).abs() < 10.0);
}
#[test]
fn test_f360_tile_stats_gflops() {
let mut stats = TileStats::new(TileLevel::Macro);
stats.add_sample(100_000_000, 1000, 1_000_000_000);
let gflops = stats.gflops();
assert!((gflops - 10.0).abs() < 0.1);
}
#[test]
fn test_f361_tile_stats_arithmetic_intensity() {
let mut stats = TileStats::new(TileLevel::Midi);
stats.add_sample(1_000_000, 1000, 8000);
let ai = stats.arithmetic_intensity();
assert!((ai - 2.0).abs() < 0.01);
}
#[test]
fn test_f362_tile_stats_cache_efficiency() {
let mut stats = TileStats::new(TileLevel::Micro);
stats.add_sample(100_000_000, 1000, 10_000_000_000);
let efficiency = stats.cache_efficiency(200.0);
assert!((efficiency - 0.5).abs() < 0.01);
assert_eq!(stats.cache_efficiency(0.0), 0.0);
}
#[test]
fn test_f363_brick_profiler_tile_enable() {
let mut profiler = BrickProfiler::new();
assert!(!profiler.is_tile_profiling_enabled());
profiler.enable_tile_profiling();
assert!(profiler.is_tile_profiling_enabled());
profiler.disable_tile_profiling();
assert!(!profiler.is_tile_profiling_enabled());
}
#[test]
fn test_f364_brick_profiler_tile_timing() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
std::thread::sleep(std::time::Duration::from_micros(100));
profiler.stop_tile(timer, 1024, 2048);
let timer = profiler.start_tile(TileLevel::Midi, 1, 2);
std::thread::sleep(std::time::Duration::from_micros(50));
profiler.stop_tile(timer, 512, 1024);
let macro_stats = profiler.tile_stats(TileLevel::Macro);
assert_eq!(macro_stats.count, 1);
assert!(macro_stats.total_ns > 0);
assert_eq!(macro_stats.total_elements, 1024);
let midi_stats = profiler.tile_stats(TileLevel::Midi);
assert_eq!(midi_stats.count, 1);
assert_eq!(midi_stats.total_elements, 512);
}
#[test]
fn test_f365_brick_profiler_tile_summary() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
for i in 0..10 {
let timer = profiler.start_tile(TileLevel::Macro, i, 0);
profiler.stop_tile(timer, 65536, 2 * 65536);
}
for i in 0..100 {
let timer = profiler.start_tile(TileLevel::Midi, i, 0);
profiler.stop_tile(timer, 4096, 2 * 4096);
}
let summary = profiler.tile_summary();
assert!(summary.contains("TILING-SPEC-001"));
assert!(summary.contains("macro"));
assert!(summary.contains("midi"));
}
#[test]
fn test_f366_brick_profiler_tile_reset() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
profiler.stop_tile(timer, 1024, 2048);
assert_eq!(profiler.tile_stats(TileLevel::Macro).count, 1);
profiler.reset_tile_stats();
assert_eq!(profiler.tile_stats(TileLevel::Macro).count, 0);
assert_eq!(profiler.tile_stats(TileLevel::Midi).count, 0);
assert_eq!(profiler.tile_stats(TileLevel::Micro).count, 0);
}
#[test]
fn test_f367_tile_stats_json() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
profiler.stop_tile(timer, 1024, 2048);
let json = profiler.tile_stats_to_json();
assert!(json.contains("\"tile_profiling_enabled\":true"));
assert!(json.contains("\"level\":\"macro\""));
assert!(json.contains("\"count\":1"));
}
#[test]
fn test_f368_all_tile_stats() {
let profiler = BrickProfiler::new();
let all_stats = profiler.all_tile_stats();
assert_eq!(all_stats.len(), 3);
assert_eq!(all_stats[0].level, TileLevel::Macro);
assert_eq!(all_stats[1].level, TileLevel::Midi);
assert_eq!(all_stats[2].level, TileLevel::Micro);
}
#[test]
fn test_f369_tile_stats_mut() {
let mut profiler = BrickProfiler::new();
profiler.tile_stats_mut(TileLevel::Macro).count = 42;
assert_eq!(profiler.tile_stats(TileLevel::Macro).count, 42);
}
#[test]
fn test_f370_disabled_tile_profiling() {
let mut profiler = BrickProfiler::new();
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
profiler.stop_tile(timer, 1024, 2048);
assert_eq!(profiler.tile_stats(TileLevel::Macro).count, 0);
}
#[test]
fn test_f371_gflops_exact_1e9_in_1s() {
let mut stats = TileStats::new(TileLevel::Macro);
stats.add_sample(1_000_000_000, 1000, 1_000_000_000);
let gflops = stats.gflops();
assert!((gflops - 1.0).abs() < 0.001, "Expected 1.0 GFLOP/s, got {}", gflops);
}
#[test]
fn test_f372_ai_exact_200_flops_100_bytes() {
let mut stats = TileStats::new(TileLevel::Midi);
stats.add_sample(1_000_000, 50, 400);
let ai = stats.arithmetic_intensity();
assert!((ai - 2.0).abs() < 0.001, "Expected 2.0 FLOP/byte, got {}", ai);
}
#[test]
fn test_f373_hierarchy_aggregation() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
let midi_timer = profiler.start_tile(TileLevel::Midi, 0, 0);
profiler.stop_tile(midi_timer, 1024, 2048);
for i in 0..4 {
let micro_timer = profiler.start_tile(TileLevel::Micro, i, 0);
profiler.stop_tile(micro_timer, 256, 512);
}
assert_eq!(profiler.tile_stats(TileLevel::Micro).count, 4, "Expected 4 micro tiles");
assert_eq!(profiler.tile_stats(TileLevel::Midi).count, 1, "Expected 1 midi tile");
}
#[test]
fn test_f374_profiling_overhead() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
for _ in 0..1000 {
let timer = profiler.start_tile(TileLevel::Micro, 0, 0);
profiler.stop_tile(timer, 1, 1);
}
profiler.reset_tile_stats();
let iterations = 10_000;
let start = std::time::Instant::now();
for i in 0..iterations {
let timer = profiler.start_tile(TileLevel::Micro, i as u32, 0);
profiler.stop_tile(timer, 1, 1);
}
let elapsed_ns = start.elapsed().as_nanos() as f64;
let overhead_ns = elapsed_ns / iterations as f64;
assert!(
overhead_ns < 5000.0,
"Profiling overhead too high: {:.1}ns (target < 50ns)",
overhead_ns
);
println!("F374: Profiling overhead = {:.1}ns", overhead_ns);
}
#[test]
fn test_f375_toggle_safety_zero_cost() {
let mut profiler = BrickProfiler::new();
let iterations = 100_000;
let start = std::time::Instant::now();
for i in 0..iterations {
let timer = profiler.start_tile(TileLevel::Micro, i as u32, 0);
profiler.stop_tile(timer, 1, 1);
}
let elapsed_ns = start.elapsed().as_nanos() as f64;
let overhead_ns = elapsed_ns / iterations as f64;
assert_eq!(
profiler.tile_stats(TileLevel::Micro).count,
0,
"Disabled profiling should not record stats"
);
assert!(overhead_ns < 1000.0, "Disabled overhead too high: {:.1}ns", overhead_ns);
println!("F375: Disabled overhead = {:.1}ns", overhead_ns);
}
#[test]
fn test_f376_summary_format_required_sections() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
for _ in 0..5 {
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
profiler.stop_tile(timer, 1024, 2_000_000);
}
for _ in 0..10 {
let timer = profiler.start_tile(TileLevel::Midi, 0, 0);
profiler.stop_tile(timer, 256, 500_000);
}
for _ in 0..20 {
let timer = profiler.start_tile(TileLevel::Micro, 0, 0);
profiler.stop_tile(timer, 64, 100_000);
}
let summary = profiler.tile_summary();
assert!(summary.contains("macro"), "Summary missing 'macro' section");
assert!(summary.contains("midi"), "Summary missing 'midi' section");
assert!(summary.contains("micro"), "Summary missing 'micro' section");
assert!(summary.contains("GFLOP/s"), "Summary missing 'GFLOP/s' column");
}
#[test]
fn test_f377_json_schema_valid() {
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
profiler.stop_tile(timer, 1024, 2048);
let json = profiler.tile_stats_to_json();
let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON");
assert!(parsed["tile_profiling_enabled"].is_boolean());
assert!(parsed["tiles"].is_array());
let tiles = parsed["tiles"].as_array().unwrap();
assert!(!tiles.is_empty(), "tiles array should not be empty");
let tile = &tiles[0];
assert!(tile["level"].is_string());
assert!(tile["count"].is_number());
assert!(tile["total_ns"].is_number());
assert!(tile["avg_us"].is_number());
assert!(tile["gflops"].is_number());
assert!(tile["arithmetic_intensity"].is_number());
}
#[test]
fn test_f378_q4k_matvec_realistic_ai() {
use crate::tiling::{TiledQ4KMatvec, Q4K_SUPERBLOCK_BYTES};
let mut profiler = BrickProfiler::new();
profiler.enable_tile_profiling();
let matvec = TiledQ4KMatvec::new(1024, 1024);
let weights = vec![0u8; matvec.total_superblocks() * Q4K_SUPERBLOCK_BYTES];
let input = vec![1.0f32; 1024];
let mut output = vec![0.0f32; 1024];
let timer = profiler.start_tile(TileLevel::Macro, 0, 0);
matvec.execute_scalar(&weights, &input, &mut output);
let flops = (1024 * 1024 * 2) as u64; profiler.stop_tile(timer, (1024 * 1024) as u64, flops);
let stats = profiler.tile_stats(TileLevel::Macro);
let ai = stats.arithmetic_intensity();
assert!(ai > 0.0 && ai < 10.0, "Q4K MatVec AI should be low (memory-bound), got {}", ai);
let gflops = stats.gflops();
assert!(gflops > 0.0, "GFLOP/s should be positive, got {}", gflops);
}