use super::*;
fn parse_source(src: &str) -> assura_parser::ast::SourceFile {
let (sf, errs) = assura_parser::parse(src);
assert!(errs.is_empty(), "parse errors: {errs:?}");
sf.unwrap()
}
#[test]
fn no_effects_clause_no_errors() {
let sf = parse_source(r#"contract Simple { requires { true } }"#);
assert!(run_effect_checks(&sf).is_empty());
}
#[test]
fn declared_effects_with_io_no_error() {
let sf = parse_source(r#"contract WithIo { effects { io } requires { true } }"#);
let errs = run_effect_checks(&sf);
assert!(
!errs.iter().any(|e| e.code == "A07003"),
"unexpected undeclared effect error: {errs:?}"
);
}
#[test]
fn test_effect_polymorphism_basic() {
let sf = parse_source(
r#"contract EffPoly {
effects <io | E>
fn map_with_effect(f: (Int) -> Int) -> List<Int>
}"#,
);
let errs = run_effect_checks(&sf);
let a07003_errors: Vec<_> = errs.iter().filter(|e| e.code == "A07003").collect();
assert!(
a07003_errors.is_empty(),
"effect variable E should not produce A07003, got: {a07003_errors:?}"
);
}
#[test]
fn must_not_io_with_effects_io_a07003() {
let sf = parse_source(
r#"contract Forbidden {
effects { io }
must-not { io }
requires { true }
}"#,
);
let errs = run_effect_checks(&sf);
let must_not = errs
.iter()
.find(|e| e.code == "A07003" && e.message.contains("must-not"))
.expect("effects(io) + must-not(io) must be A07003");
let suggestion = must_not
.suggestion
.as_deref()
.expect("must-not A07003 must not fall back to the unknown-effect catalog Help");
assert_eq!(
suggestion, "Remove the effect from `effects`, or drop it from `must-not`.",
"must-not Help must be the shipped fix text, got: {suggestion}"
);
}
#[test]
fn must_not_database_allows_effects_io() {
let sf = parse_source(
r#"contract OkIo {
effects { io }
must-not { database }
requires { true }
}"#,
);
let errs = run_effect_checks(&sf);
assert!(
!errs.iter().any(|e| e.message.contains("must-not")),
"io is not in must-not database, got: {errs:?}"
);
}
#[test]
fn must_not_unknown_name_a07003() {
let sf = parse_source(
r#"contract BadForbid {
must-not { teleport }
requires { true }
}"#,
);
let errs = run_effect_checks(&sf);
let unknown = errs
.iter()
.find(|e| e.code == "A07003")
.expect("unknown must-not name must be A07003");
assert!(
unknown.suggestion.is_none(),
"unknown must-not name must keep catalog Help, got: {:?}",
unknown.suggestion
);
}