Files
Pac-Man/tests/profiling.rs

126 lines
4.5 KiB
Rust

use pacman::systems::profiling::{SystemId, SystemTimings};
use std::time::Duration;
use strum::IntoEnumIterator;
macro_rules! assert_close {
($actual:expr, $expected:expr, $concern:expr) => {
let tolerance = Duration::from_micros(500);
let diff = $actual.abs_diff($expected);
assert!(
diff < tolerance,
"Expected {expected:?} ± {tolerance:.0?}, got {actual:?}, off by {diff:?} ({concern})",
concern = $concern,
expected = $expected,
actual = $actual,
tolerance = tolerance,
diff = diff
);
};
}
#[test]
fn test_timing_statistics() {
let timings = SystemTimings::default();
// Add consecutive timing measurements (no skipped ticks to avoid zero padding)
timings.add_timing(SystemId::PlayerControls, Duration::from_millis(10), 1);
timings.add_timing(SystemId::PlayerControls, Duration::from_millis(12), 2);
timings.add_timing(SystemId::PlayerControls, Duration::from_millis(8), 3);
// Add consecutive timing measurements for another system
timings.add_timing(SystemId::Blinking, Duration::from_millis(3), 1);
timings.add_timing(SystemId::Blinking, Duration::from_millis(2), 2);
timings.add_timing(SystemId::Blinking, Duration::from_millis(1), 3);
{
let stats = timings.get_stats(3);
let (avg, std_dev) = stats.get(&SystemId::PlayerControls).unwrap();
assert_close!(*avg, Duration::from_millis(10), "PlayerControls average timing");
assert_close!(*std_dev, Duration::from_millis(2), "PlayerControls standard deviation timing");
}
// Note: get_total_stats() was removed as we now use the Total system directly
// This test now focuses on individual system statistics
}
#[test]
fn test_default_zero_timing_for_unused_systems() {
let timings = SystemTimings::default();
// Add timing data for only one system
timings.add_timing(SystemId::PlayerControls, Duration::from_millis(5), 1);
let stats = timings.get_stats(1);
// Verify all SystemId variants are present in the stats
let expected_count = SystemId::iter().count();
assert_eq!(stats.len(), expected_count, "All SystemId variants should be in stats");
// Verify that the system with data has non-zero timing
let (avg, std_dev) = stats.get(&SystemId::PlayerControls).unwrap();
assert_close!(*avg, Duration::from_millis(5), "System with data should have correct timing");
assert_close!(*std_dev, Duration::ZERO, "Single measurement should have zero std dev");
// Verify that all other systems have zero timing (excluding Total which is special)
for id in SystemId::iter() {
if id != SystemId::PlayerControls && id != SystemId::Total {
let (avg, std_dev) = stats.get(&id).unwrap();
assert_close!(
*avg,
Duration::ZERO,
format!("Unused system {:?} should have zero avg timing", id)
);
assert_close!(
*std_dev,
Duration::ZERO,
format!("Unused system {:?} should have zero std dev", id)
);
}
}
}
#[test]
fn test_pre_populated_timing_entries() {
let timings = SystemTimings::default();
// Verify that we can add timing to any SystemId without panicking
// (this would fail with the old implementation if the entry didn't exist)
// Use the same tick for all systems to avoid zero-padding
for id in SystemId::iter() {
timings.add_timing(id, Duration::from_nanos(1), 1);
}
// Verify all systems now have non-zero timing
let stats = timings.get_stats(1);
for id in SystemId::iter() {
let (avg, _) = stats.get(&id).unwrap();
assert!(
*avg > Duration::ZERO,
"System {:?} should have non-zero timing after add_timing",
id
);
}
}
#[test]
fn test_total_system_timing() {
let timings = SystemTimings::default();
// Add some timing data to the Total system
timings.add_total_timing(Duration::from_millis(16), 1);
timings.add_total_timing(Duration::from_millis(18), 2);
timings.add_total_timing(Duration::from_millis(14), 3);
let stats = timings.get_stats(3);
let (avg, std_dev) = stats.get(&SystemId::Total).unwrap();
// Should have 16ms average (16+18+14)/3 = 16ms
assert_close!(*avg, Duration::from_millis(16), "Total system average timing");
// Should have some standard deviation
assert!(
*std_dev > Duration::ZERO,
"Total system should have non-zero std dev with multiple measurements"
);
}