#![cfg_attr(coverage_nightly, coverage(off))]
use crate::cli::handlers::comply_handlers::comply_cb_detect::{
classify_satd_by_pattern_id, classify_satd_manifestation, detect_cb050_code_stubs_in_str,
detect_cb050_code_stubs_in_str_with_path, detect_ptx_barrier_divergence_in_str,
detect_shared_memory_unbounded_in_str, detect_tiled_kernel_no_bounds_in_str,
detect_wgsl_barrier_divergence_in_str, CbViolation, SATDManifestationType, Severity,
SuppressionConfig, SuppressionResult, SuppressionRule,
};
#[test]
fn test_satd_manifestation_type_equality() {
assert_eq!(
SATDManifestationType::Comment,
SATDManifestationType::Comment
);
assert_eq!(SATDManifestationType::Code, SATDManifestationType::Code);
assert_ne!(SATDManifestationType::Comment, SATDManifestationType::Code);
}
#[test]
fn test_satd_manifestation_type_clone() {
let original = SATDManifestationType::Code;
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_satd_manifestation_type_copy() {
let original = SATDManifestationType::Comment;
let copied: SATDManifestationType = original;
assert_eq!(original, copied);
}
#[test]
fn test_satd_manifestation_type_debug() {
let comment = SATDManifestationType::Comment;
let code = SATDManifestationType::Code;
assert!(format!("{:?}", comment).contains("Comment"));
assert!(format!("{:?}", code).contains("Code"));
}
#[test]
fn test_satd_manifestation_type_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(SATDManifestationType::Comment);
set.insert(SATDManifestationType::Code);
assert_eq!(set.len(), 2);
set.insert(SATDManifestationType::Comment);
assert_eq!(set.len(), 2);
}
#[test]
fn test_severity_equality() {
assert_eq!(Severity::Low, Severity::Low);
assert_eq!(Severity::Medium, Severity::Medium);
assert_eq!(Severity::High, Severity::High);
assert_eq!(Severity::Critical, Severity::Critical);
}
#[test]
fn test_severity_ordering() {
assert!(Severity::Low < Severity::Medium);
assert!(Severity::Medium < Severity::High);
assert!(Severity::High < Severity::Critical);
assert!(Severity::Low < Severity::Critical);
}
#[test]
fn test_severity_clone() {
let original = Severity::High;
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_severity_copy() {
let original = Severity::Medium;
let copied: Severity = original;
assert_eq!(original, copied);
}
#[test]
fn test_severity_debug() {
assert!(format!("{:?}", Severity::Low).contains("Low"));
assert!(format!("{:?}", Severity::Medium).contains("Medium"));
assert!(format!("{:?}", Severity::High).contains("High"));
assert!(format!("{:?}", Severity::Critical).contains("Critical"));
}
#[test]
fn test_comment_manifestation_no_escalation() {
let comment = SATDManifestationType::Comment;
assert_eq!(comment.escalate_severity(Severity::Low), Severity::Low);
assert_eq!(
comment.escalate_severity(Severity::Medium),
Severity::Medium
);
assert_eq!(comment.escalate_severity(Severity::High), Severity::High);
assert_eq!(
comment.escalate_severity(Severity::Critical),
Severity::Critical
);
}
#[test]
fn test_code_manifestation_escalation() {
let code = SATDManifestationType::Code;
assert_eq!(code.escalate_severity(Severity::Low), Severity::Medium);
assert_eq!(code.escalate_severity(Severity::Medium), Severity::High);
assert_eq!(code.escalate_severity(Severity::High), Severity::Critical);
assert_eq!(
code.escalate_severity(Severity::Critical),
Severity::Critical
);
}
#[test]
fn test_classify_satd_todo_macro() {
assert_eq!(
classify_satd_manifestation("todo!()"),
SATDManifestationType::Code
);
assert_eq!(
classify_satd_manifestation("fn test() { todo!(); }"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_satd_unimplemented_macro() {
assert_eq!(
classify_satd_manifestation("unimplemented!()"),
SATDManifestationType::Code
);
assert_eq!(
classify_satd_manifestation("fn test() { unimplemented!(); }"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_satd_panic_not_implemented() {
assert_eq!(
classify_satd_manifestation(r#"panic!("not implemented")"#),
SATDManifestationType::Code
);
assert_eq!(
classify_satd_manifestation(r#"panic!("Not implemented yet")"#),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_satd_python_not_implemented_error() {
assert_eq!(
classify_satd_manifestation("raise NotImplementedError"),
SATDManifestationType::Code
);
assert_eq!(
classify_satd_manifestation("raise NotImplementedError()"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_satd_function_marker() {
assert_eq!(
classify_satd_manifestation("fn stub() {}"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_satd_empty_body() {
assert_eq!(
classify_satd_manifestation("{}"),
SATDManifestationType::Code
);
assert_eq!(
classify_satd_manifestation("{ }"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_satd_comment_todo() {
assert_eq!(
classify_satd_manifestation("// TODO: fix this"),
SATDManifestationType::Comment
);
assert_eq!(
classify_satd_manifestation("/* FIXME: broken */"),
SATDManifestationType::Comment
);
}
#[test]
fn test_classify_satd_regular_comment() {
assert_eq!(
classify_satd_manifestation("// This is a regular comment"),
SATDManifestationType::Comment
);
}
#[test]
fn test_classify_by_pattern_id_cb050_a() {
assert_eq!(
classify_satd_by_pattern_id("CB-050-A"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_by_pattern_id_cb050_b() {
assert_eq!(
classify_satd_by_pattern_id("CB-050-B"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_by_pattern_id_cb050_c() {
assert_eq!(
classify_satd_by_pattern_id("CB-050-C"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_by_pattern_id_cb050_d() {
assert_eq!(
classify_satd_by_pattern_id("CB-050-D"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_by_pattern_id_cb050_e() {
assert_eq!(
classify_satd_by_pattern_id("CB-050-E"),
SATDManifestationType::Code
);
}
#[test]
fn test_classify_by_pattern_id_cb050_f() {
assert_eq!(
classify_satd_by_pattern_id("CB-050-F"),
SATDManifestationType::Comment
);
}
#[test]
fn test_classify_by_pattern_id_unknown() {
assert_eq!(
classify_satd_by_pattern_id("CB-999"),
SATDManifestationType::Comment
);
assert_eq!(
classify_satd_by_pattern_id("UNKNOWN"),
SATDManifestationType::Comment
);
}
#[test]
fn test_cb_violation_creation() {
let violation = CbViolation {
line: 42,
pattern_id: "CB-050-A",
description: "todo!() macro".to_string(),
code_snippet: Some("todo!()".to_string()),
};
assert_eq!(violation.line, 42);
assert_eq!(violation.pattern_id, "CB-050-A");
assert!(violation.description.contains("todo!"));
assert!(violation.code_snippet.is_some());
}
#[test]
fn test_cb_violation_equality() {
let v1 = CbViolation {
line: 10,
pattern_id: "CB-050-A",
description: "test".to_string(),
code_snippet: None,
};
let v2 = CbViolation {
line: 10,
pattern_id: "CB-050-A",
description: "test".to_string(),
code_snippet: None,
};
let v3 = CbViolation {
line: 20,
pattern_id: "CB-050-A",
description: "test".to_string(),
code_snippet: None,
};
assert_eq!(v1, v2);
assert_ne!(v1, v3);
}
#[test]
fn test_cb_violation_clone() {
let original = CbViolation {
line: 5,
pattern_id: "CB-050-B",
description: "unimplemented".to_string(),
code_snippet: Some("code".to_string()),
};
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_cb_violation_debug() {
let violation = CbViolation {
line: 1,
pattern_id: "CB-050-A",
description: "test".to_string(),
code_snippet: None,
};
let debug_str = format!("{:?}", violation);
assert!(debug_str.contains("CbViolation"));
assert!(debug_str.contains("CB-050-A"));
}
#[test]
fn test_suppression_rule_creation() {
let rule = SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: Some("examples/**".to_string()),
file: None,
lines: None,
expires: None,
reason: "Example code".to_string(),
};
assert_eq!(rule.check_ids.len(), 1);
assert!(rule.glob_pattern.is_some());
assert!(rule.file.is_none());
assert!(rule.lines.is_none());
assert!(rule.expires.is_none());
}
#[test]
fn test_suppression_rule_with_all_fields() {
let rule = SuppressionRule {
check_ids: vec!["CB-050-A".to_string(), "CB-050-B".to_string()],
glob_pattern: Some("**/test/**".to_string()),
file: Some("src/lib.rs".to_string()),
lines: Some(vec![10, 20, 30]),
expires: Some("2027-12-31".to_string()),
reason: "Known technical debt".to_string(),
};
assert_eq!(rule.check_ids.len(), 2);
assert_eq!(rule.lines.as_ref().unwrap().len(), 3);
}
#[test]
fn test_suppression_rule_equality() {
let r1 = SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: Some("test.rs".to_string()),
lines: None,
expires: None,
reason: "test".to_string(),
};
let r2 = r1.clone();
assert_eq!(r1, r2);
}
#[test]
fn test_suppression_config_new() {
let config = SuppressionConfig::new();
let result = config.should_suppress("CB-050-A", "src/lib.rs", 1);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_config_add_rule_file_exact() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: Some("src/lib.rs".to_string()),
lines: None,
expires: None,
reason: "Known issue".to_string(),
});
let result = config.should_suppress("CB-050-A", "src/lib.rs", 1);
assert!(result.suppressed);
assert!(result.reason.unwrap().contains("Known issue"));
let result = config.should_suppress("CB-050-A", "src/main.rs", 1);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_config_add_rule_glob() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: Some("examples/*.rs".to_string()),
file: None,
lines: None,
expires: None,
reason: "Example code".to_string(),
});
let result = config.should_suppress("CB-050-A", "examples/demo.rs", 1);
assert!(result.suppressed);
let result = config.should_suppress("CB-050-A", "src/lib.rs", 1);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_config_line_specific() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: Some("src/lib.rs".to_string()),
lines: Some(vec![10, 20]),
expires: None,
reason: "Specific lines".to_string(),
});
let result = config.should_suppress("CB-050-A", "src/lib.rs", 10);
assert!(result.suppressed);
let result = config.should_suppress("CB-050-A", "src/lib.rs", 20);
assert!(result.suppressed);
let result = config.should_suppress("CB-050-A", "src/lib.rs", 15);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_config_check_id_filter() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: None,
lines: None,
expires: None,
reason: "All files".to_string(),
});
let result = config.should_suppress("CB-050-A", "any.rs", 1);
assert!(result.suppressed);
let result = config.should_suppress("CB-050-B", "any.rs", 1);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_config_expired_rule() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: None,
lines: None,
expires: Some("2020-01-01".to_string()), reason: "Old suppression".to_string(),
});
let result = config.should_suppress("CB-050-A", "any.rs", 1);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_config_future_expiry() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: None,
lines: None,
expires: Some("2099-12-31".to_string()), reason: "Future suppression".to_string(),
});
let result = config.should_suppress("CB-050-A", "any.rs", 1);
assert!(result.suppressed);
}
#[test]
fn test_suppression_config_windows_path_normalization() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec!["CB-050-A".to_string()],
glob_pattern: None,
file: Some("src/lib.rs".to_string()),
lines: None,
expires: None,
reason: "test".to_string(),
});
let result = config.should_suppress("CB-050-A", "src\\lib.rs", 1);
assert!(result.suppressed);
}
#[test]
fn test_suppression_config_empty_check_ids_matches_all() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec![], glob_pattern: None,
file: Some("suppress_all.rs".to_string()),
lines: None,
expires: None,
reason: "Suppress all checks".to_string(),
});
let result = config.should_suppress("CB-050-A", "suppress_all.rs", 1);
assert!(result.suppressed);
let result = config.should_suppress("CB-060-A", "suppress_all.rs", 1);
assert!(result.suppressed);
}
#[test]
fn test_suppression_result_fields() {
let result = SuppressionResult {
suppressed: true,
reason: Some("Test reason".to_string()),
};
assert!(result.suppressed);
assert_eq!(result.reason.unwrap(), "Test reason");
}
#[test]
fn test_detect_todo_macro() {
let code = "fn test() { todo!(); }";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-A");
}
#[test]
fn test_detect_todo_with_message() {
let code = r#"fn test() { todo!("implement this"); }"#;
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-A");
}
#[test]
fn test_detect_unimplemented_macro() {
let code = "fn test() { unimplemented!(); }";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-B");
}
#[test]
fn test_detect_panic_not_implemented() {
let code = r#"fn test() { panic!("not implemented"); }"#;
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-C");
}
#[test]
fn test_detect_panic_not_implemented_variant() {
let code = r#"fn test() { panic!("not implemented yet"); }"#;
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-C");
}
#[test]
fn test_detect_panic_not_implemented_caps_not_matched() {
let code = r#"fn test() { panic!("Not implemented"); }"#;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050c = violations
.iter()
.filter(|(_, id, _)| *id == "CB-050-C")
.count();
assert_eq!(cb050c, 0, "Capital 'Not' doesn't match current pattern");
}
#[test]
fn test_detect_python_not_implemented_error() {
let code = "def test():\n raise NotImplementedError";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-E");
}
#[test]
fn test_detect_python_pass_stub() {
let code = "def test():\n pass # stub";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-F");
}
#[test]
fn test_detect_python_pass_todo() {
let code = "def test():\n pass # TODO";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-F");
}
#[test]
fn test_detect_empty_function_body() {
let code = "fn empty_stub() {}";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-D");
}
#[test]
fn test_detect_empty_function_with_return_type() {
let code = "fn stub() -> Result<(), Error> { }";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-050-D");
}
#[test]
fn test_skip_trait_default_methods() {
let code = r#"
trait MyTrait {
fn default_method() {}
}
"#;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_skip_marker_functions() {
let code = "fn marker() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_skip_sentinel_function() {
let code = "fn type_sentinel() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_skip_phantom_function() {
let code = "fn phantom_data() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_skip_noop_function() {
let code = "fn noop() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_skip_dummy_function() {
let code = "fn dummy() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_skip_test_file_path() {
let code = "fn stub() { todo!(); }";
let violations = detect_cb050_code_stubs_in_str_with_path(code, "src/tests/mod.rs");
assert!(violations.is_empty());
}
#[test]
fn test_skip_tests_directory() {
let code = "fn stub() { todo!(); }";
let violations = detect_cb050_code_stubs_in_str_with_path(code, "tests/integration.rs");
assert!(violations.is_empty());
}
#[test]
fn test_skip_test_suffix_file() {
let code = "fn stub() { todo!(); }";
let violations = detect_cb050_code_stubs_in_str_with_path(code, "src/foo_test.rs");
assert!(violations.is_empty());
}
#[test]
fn test_detect_in_production_file() {
let code = "fn stub() { todo!(); }";
let violations = detect_cb050_code_stubs_in_str_with_path(code, "src/lib.rs");
assert!(!violations.is_empty());
}
#[test]
fn test_skip_comment_lines() {
let code = "// todo!() in comment\nfn real() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_skip_doc_comments() {
let code = "/// Example: todo!()\nfn example() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_skip_inner_doc_comments() {
let code = "//! Module doc: todo!()\nfn test() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_skip_python_comments() {
let code = "# todo!() in python comment\ndef test(): pass";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_not_skip_rust_attributes() {
let code = "#[test]\nfn test() { todo!(); }";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
}
#[test]
fn test_line_numbers_correct() {
let code = "fn line1() {}\nfn line2() { todo!(); }\nfn line3() {}";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].0, 2); }
#[test]
fn test_multiple_violations() {
let code = r#"
fn stub1() { todo!(); }
fn stub2() { unimplemented!(); }
fn stub3() { panic!("not implemented"); }
"#;
let violations = detect_cb050_code_stubs_in_str(code);
assert!(violations.len() >= 3);
}
#[test]
fn test_no_false_positive_string_literal() {
let code = r#"let s = "todo!() is not real code";"#;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_no_false_positive_code_generation() {
let code = r#"code.push_str("todo!(\"test\")");"#;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_ptx_barrier_divergence_detected() {
let ptx = r#"
@%p1 bra skip_label
ld.shared.f32 %f1, [%r2]
bar.sync 0
skip_label:
"#;
let violations = detect_ptx_barrier_divergence_in_str(ptx);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-060-A");
}
#[test]
fn test_ptx_no_divergence_no_barrier() {
let ptx = r#"
@%p1 bra skip_label
ld.shared.f32 %f1, [%r2]
skip_label:
st.global.f32 [%r3], %f1
"#;
let violations = detect_ptx_barrier_divergence_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_ptx_barrier_no_branch() {
let ptx = r#"
ld.shared.f32 %f1, [%r2]
bar.sync 0
st.global.f32 [%r3], %f1
"#;
let violations = detect_ptx_barrier_divergence_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_ptx_branch_after_barrier_safe() {
let ptx = r#"
bar.sync 0
@%p1 bra skip_label
skip_label:
"#;
let violations = detect_ptx_barrier_divergence_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_ptx_skip_comments() {
let ptx = r#"
// @%p1 bra divergent
// bar.sync 0
ld.global.f32 %f1, [%r2]
"#;
let violations = detect_ptx_barrier_divergence_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_wgsl_barrier_in_if_divergent() {
let wgsl = r#"
fn main() {
if (condition) {
workgroupBarrier();
}
}
"#;
let violations = detect_wgsl_barrier_divergence_in_str(wgsl);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-060-D");
}
#[test]
fn test_wgsl_barrier_outside_if_safe() {
let wgsl = r#"
fn main() {
if (condition) {
// some work
}
workgroupBarrier();
}
"#;
let violations = detect_wgsl_barrier_divergence_in_str(wgsl);
assert!(violations.is_empty());
}
#[test]
fn test_wgsl_barrier_in_divergent_loop() {
let wgsl = r#"
fn main() {
for (var i = 0u; i < local_id.x; i++) {
workgroupBarrier();
}
}
"#;
let violations = detect_wgsl_barrier_divergence_in_str(wgsl);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-060-D");
}
#[test]
fn test_wgsl_no_barrier_safe() {
let wgsl = r#"
fn main() {
if (condition) {
// no barrier
}
}
"#;
let violations = detect_wgsl_barrier_divergence_in_str(wgsl);
assert!(violations.is_empty());
}
#[test]
fn test_wgsl_skip_comments() {
let wgsl = r#"
// workgroupBarrier() in comment
fn main() {
let x = 1;
}
"#;
let violations = detect_wgsl_barrier_divergence_in_str(wgsl);
assert!(violations.is_empty());
}
#[test]
fn test_shared_memory_unbounded_detected() {
let ptx = r#"
ld.shared.f32 %f1, [%r2]
"#;
let violations = detect_shared_memory_unbounded_in_str(ptx);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-060-B");
}
#[test]
fn test_shared_memory_predicated_safe() {
let ptx = r#"
@%p1 ld.shared.f32 %f1, [%r2]
"#;
let violations = detect_shared_memory_unbounded_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_shared_memory_constant_offset_safe() {
let ptx = r#"
ld.shared.f32 %f1, [shared_mem + 128]
"#;
let violations = detect_shared_memory_unbounded_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_shared_memory_bounds_checked_safe() {
let ptx = r#"
setp.lt.u32 %p1, %r1, 256
ld.shared.f32 %f1, [%r2]
"#;
let violations = detect_shared_memory_unbounded_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_shared_store_unbounded() {
let ptx = r#"
st.shared.f32 [%r2], %f1
"#;
let violations = detect_shared_memory_unbounded_in_str(ptx);
assert!(!violations.is_empty());
}
#[test]
fn test_shared_memory_skip_comments() {
let ptx = r#"
// ld.shared.f32 %f1, [%r2]
ld.global.f32 %f1, [%r2]
"#;
let violations = detect_shared_memory_unbounded_in_str(ptx);
assert!(violations.is_empty());
}
#[test]
fn test_tiled_kernel_no_bounds() {
let code = r#"
fn kernel() {
c[row * n + col] = result;
}
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
assert!(!violations.is_empty());
assert_eq!(violations[0].1, "CB-060-C");
}
#[test]
fn test_tiled_kernel_with_proper_bounds() {
let code = r#"
fn kernel() {
if row < m && col < n {
c[row * n + col] = result;
}
}
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
let cb060c: Vec<_> = violations
.iter()
.filter(|(_, id, desc)| *id == "CB-060-C" && desc.contains("without bounds"))
.collect();
assert!(cb060c.is_empty());
}
#[test]
fn test_tiled_kernel_partial_bounds() {
let code = r#"
fn kernel() {
if row < m {
c[row * n + col] = result;
}
}
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
let partial: Vec<_> = violations
.iter()
.filter(|(_, _, desc)| desc.contains("Partial bounds"))
.collect();
assert!(!partial.is_empty());
}
#[test]
fn test_tiled_kernel_skip_string_literal() {
let code = r#"
let kernel_src = "c[row * n + col] = result";
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
let cb060c: Vec<_> = violations
.iter()
.filter(|(_, id, _)| *id == "CB-060-C")
.collect();
assert!(cb060c.is_empty());
}
#[test]
fn test_tiled_kernel_skip_comments() {
let code = r#"
// c[row * n + col] = result
fn kernel() {
// actual work
}
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
let cb060c: Vec<_> = violations
.iter()
.filter(|(_, id, _)| *id == "CB-060-C")
.collect();
assert!(cb060c.is_empty());
}
#[test]
fn test_ptx_early_exit_detected() {
let code = r#"
@%p1 bra exit
ld.shared.f32 %f1, [%r2]
bar.sync 0
exit:
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
let early_exit: Vec<_> = violations
.iter()
.filter(|(_, _, desc)| desc.contains("Early exit"))
.collect();
assert!(!early_exit.is_empty());
}
#[test]
fn test_wgsl_tiled_pattern_no_bounds() {
let code = r#"
fn kernel() {
a[global_id.x * size] = value;
}
"#;
let violations = detect_tiled_kernel_no_bounds_in_str(code);
let wgsl_tiled: Vec<_> = violations
.iter()
.filter(|(_, _, desc)| desc.contains("WGSL tiled"))
.collect();
assert!(!wgsl_tiled.is_empty());
}
#[test]
fn test_empty_input() {
assert!(detect_cb050_code_stubs_in_str("").is_empty());
assert!(detect_ptx_barrier_divergence_in_str("").is_empty());
assert!(detect_wgsl_barrier_divergence_in_str("").is_empty());
assert!(detect_shared_memory_unbounded_in_str("").is_empty());
assert!(detect_tiled_kernel_no_bounds_in_str("").is_empty());
}
#[test]
fn test_whitespace_only() {
assert!(detect_cb050_code_stubs_in_str(" \n\t\n ").is_empty());
}
#[test]
fn test_empty_path() {
let violations = detect_cb050_code_stubs_in_str_with_path("fn stub() {}", "");
assert!(!violations.is_empty());
}
#[test]
fn test_todo_with_spacing_variations() {
let code = "fn test() { todo ! ( ); }";
let violations = detect_cb050_code_stubs_in_str(code);
assert!(!violations.is_empty());
}
#[test]
fn test_doc_test_block_skipped() {
let code = r#"
/// Example:
/// ```
/// todo!()
/// ```
fn example() {}
"#;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations.iter().filter(|(_, id, _)| *id == "CB-050-A");
assert_eq!(cb050a.count(), 0);
}
#[test]
fn test_multiline_raw_string_handling() {
let code = r###"let s = r#"
todo!()
"#;
fn normal() { let x = 1; }
"###;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a = violations
.iter()
.filter(|(_, id, _)| *id == "CB-050-A")
.count();
assert_eq!(cb050a, 0, "todo!() inside raw string should be skipped");
}
#[test]
fn test_raw_string_on_same_line() {
let code = r###"let s = r#"todo!()"#;
fn stub() { todo!(); }
"###;
let violations = detect_cb050_code_stubs_in_str(code);
let cb050a: Vec<_> = violations
.iter()
.filter(|(_, id, _)| *id == "CB-050-A")
.collect();
assert!(!cb050a.is_empty(), "todo!() on line 2 should be detected");
}
#[test]
fn test_underscore_function_is_marker() {
let code = "fn _() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_marker_prefix() {
let code = "fn marker_type() {}";
let violations = detect_cb050_code_stubs_in_str(code);
let cb050d = violations.iter().filter(|(_, id, _)| *id == "CB-050-D");
assert_eq!(cb050d.count(), 0);
}
#[test]
fn test_suppression_config_default() {
let config = SuppressionConfig::default();
let result = config.should_suppress("CB-050-A", "test.rs", 1);
assert!(!result.suppressed);
}
#[test]
fn test_suppression_glob_recursive() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec![],
glob_pattern: Some("**/examples/**".to_string()),
file: None,
lines: None,
expires: None,
reason: "Examples".to_string(),
});
let result = config.should_suppress("CB-050-A", "deep/nested/examples/test.rs", 1);
assert!(result.suppressed);
}
#[test]
fn test_suppression_file_suffix_match() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec![],
glob_pattern: None,
file: Some("lib.rs".to_string()), lines: None,
expires: None,
reason: "Match by suffix".to_string(),
});
let result = config.should_suppress("CB-050-A", "src/lib.rs", 1);
assert!(result.suppressed);
}
#[test]
fn test_invalid_glob_pattern_graceful() {
let mut config = SuppressionConfig::new();
config.add_rule(SuppressionRule {
check_ids: vec![],
glob_pattern: Some("[invalid".to_string()), file: Some("fallback.rs".to_string()),
lines: None,
expires: None,
reason: "Invalid glob".to_string(),
});
let result = config.should_suppress("CB-050-A", "fallback.rs", 1);
assert!(result.suppressed);
}