use super::super::analyzer::*;
use super::super::types::*;
#[test]
fn test_loop_branch_to_end_detection() {
let ptx = r"
.visible .entry test() {
main_loop:
// loop body
bra main_loop_end;
main_loop_end:
ret;
}
";
let result = PtxBugAnalyzer::strict().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::LoopBranchToEnd));
}
#[test]
fn test_conditional_branch_not_flagged() {
let ptx = r"
.visible .entry test() {
loop_start:
@%p0 bra loop_end;
bra loop_start;
loop_end:
ret;
}
";
let result = PtxBugAnalyzer::strict().analyze(ptx);
assert!(!result.has_bug(&PtxBugClass::LoopBranchToEnd));
}
#[test]
fn test_register_spills_detection() {
let ptx = r"
.visible .entry test() {
.local .align 4 .b8 __local_depot[32];
ret;
}
";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::RegisterSpills));
}
#[test]
fn test_missing_entry_point_detection() {
let ptx = r"
.version 8.0
.target sm_70
.reg .f32 %f<4>;
";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::MissingEntryPoint));
}
#[test]
fn test_valid_kernel_no_bugs() {
let ptx = r"
.version 8.0
.target sm_70
.visible .entry valid_kernel() {
.reg .f32 %f<4>;
.reg .u32 %r<4>;
ret;
}
";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert!(result.is_valid());
assert!(!result.has_bugs());
}
#[test]
fn test_bug_severity_classification() {
assert_eq!(
PtxBugClass::MissingBarrierSync.severity(),
BugSeverity::Critical
);
assert_eq!(
PtxBugClass::SharedMemU64Addressing.severity(),
BugSeverity::Critical
);
assert_eq!(PtxBugClass::RegisterSpills.severity(), BugSeverity::High);
assert_eq!(
PtxBugClass::MissingEntryPoint.severity(),
BugSeverity::FalsePositive
);
}
#[test]
fn test_bug_report_format() {
let ptx = r"
.visible .entry test() {
.shared .b8 smem[1024];
st.shared.f32 [%rd0], %f0;
ret;
}
";
let result = PtxBugAnalyzer::new().analyze(ptx);
let report = result.format_report();
assert!(report.contains("PTX BUG HUNTING REPORT"));
assert!(report.contains("P0 CRITICAL BUGS:"));
assert!(report.contains("SUMMARY"));
}
#[test]
fn test_kernel_name_extraction() {
let ptx = r"
.visible .entry gemm_tiled() {
ret;
}
";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert_eq!(result.kernel_name, Some("gemm_tiled".to_string()));
}
#[test]
fn test_count_by_severity() {
let report = PtxBugReport {
kernel_name: Some("test".to_string()),
bugs: vec![
PtxBug {
class: PtxBugClass::MissingBarrierSync,
line: 1,
instruction: "test".to_string(),
message: "test".to_string(),
fix: None,
},
PtxBug {
class: PtxBugClass::RegisterSpills,
line: 2,
instruction: "test".to_string(),
message: "test".to_string(),
fix: None,
},
],
lines_analyzed: 10,
strict_mode: true,
};
assert_eq!(report.count_by_severity(BugSeverity::Critical), 1);
assert_eq!(report.count_by_severity(BugSeverity::High), 1);
assert_eq!(report.count_by_severity(BugSeverity::Medium), 0);
}
#[test]
fn f101_detect_shared_u64_addressing() {
let ptx = "st.shared.f32 [%rd5], %f0;";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::SharedMemU64Addressing));
}
#[test]
fn f102_detect_missing_barrier() {
let ptx = r"
.visible .entry test() {
.shared .b8 smem[1024];
st.shared.f32 [%r0], %f0;
ld.shared.f32 %f1, [%r1];
ret;
}
";
let result = PtxBugAnalyzer::strict().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::MissingBarrierSync));
}
#[test]
fn f103_detect_loop_branch_end() {
let ptx = r"
.entry test() {
test_loop:
bra test_loop_end;
test_loop_end:
ret;
}
";
let result = PtxBugAnalyzer::strict().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::LoopBranchToEnd));
}
#[test]
fn f104_valid_ptx_passes() {
let ptx = r"
.version 8.0
.target sm_70
.visible .entry valid() {
.reg .f32 %f<4>;
ret;
}
";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert!(result.is_valid());
}
#[test]
fn f106_missing_entry_detected() {
let ptx = ".version 8.0
.target sm_70
.reg .f32 %f<4>;";
let result = PtxBugAnalyzer::new().analyze(ptx);
assert!(result.has_bug(&PtxBugClass::MissingEntryPoint));
}