trueno_gpu/testing/
mod.rs1pub mod stress;
27pub mod tui;
28
29pub use stress::{
30 verify_performance, Anomaly, AnomalyKind, FrameProfile, PerformanceResult,
31 PerformanceThresholds, StressConfig, StressReport, StressRng, StressTestRunner,
32};
33
34pub use tui::{progress_bar, render_to_string, TuiConfig, TuiState};
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum BugClass {
39 RaceCondition,
41 FloatingPointDrift,
43 AccumulatorInit,
45 LoopCounter,
47 MemoryAddressing,
49 ThreadSync,
51 Unknown,
53}
54
55impl BugClass {
56 #[must_use]
58 pub const fn description(&self) -> &'static str {
59 match self {
60 Self::RaceCondition => "Race condition: non-deterministic output",
61 Self::FloatingPointDrift => "FP precision drift in accumulation",
62 Self::AccumulatorInit => "Accumulator not initialized to zero",
63 Self::LoopCounter => "Loop counter SSA bug (wrong iteration count)",
64 Self::MemoryAddressing => "Memory addressing error (offset/alignment)",
65 Self::ThreadSync => "Thread synchronization issue (barrier)",
66 Self::Unknown => "Unknown bug pattern",
67 }
68 }
69
70 #[must_use]
72 pub const fn suggested_fix(&self) -> &'static str {
73 match self {
74 Self::RaceCondition => "Add __syncthreads() / bar.sync; use atomics",
75 Self::FloatingPointDrift => "Use Kahan summation or pairwise reduction",
76 Self::AccumulatorInit => "Initialize accumulator to 0.0 before loop",
77 Self::LoopCounter => "Fix loop bound; use in-place += instead of reassignment",
78 Self::MemoryAddressing => "Check index calculations and stride",
79 Self::ThreadSync => "Add barrier synchronization at workgroup boundaries",
80 Self::Unknown => "Manual inspection required",
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_bug_class_descriptions() {
91 let variants = [
93 BugClass::RaceCondition,
94 BugClass::FloatingPointDrift,
95 BugClass::AccumulatorInit,
96 BugClass::LoopCounter,
97 BugClass::MemoryAddressing,
98 BugClass::ThreadSync,
99 BugClass::Unknown,
100 ];
101
102 for variant in variants {
103 assert!(
104 !variant.description().is_empty(),
105 "{variant:?} has empty description"
106 );
107 assert!(
108 !variant.suggested_fix().is_empty(),
109 "{variant:?} has empty fix"
110 );
111 }
112 }
113
114 #[test]
115 fn test_bug_class_equality() {
116 assert_eq!(BugClass::RaceCondition, BugClass::RaceCondition);
117 assert_ne!(BugClass::RaceCondition, BugClass::Unknown);
118 }
119
120 #[test]
121 fn test_bug_class_clone() {
122 let original = BugClass::FloatingPointDrift;
123 let cloned = original;
124 assert_eq!(original, cloned);
125 }
126}