#![cfg(any(
not(any(
feature = "parser_tests",
feature = "analyzer_tests",
feature = "codegen_tests",
feature = "interpreter_tests",
feature = "conformance_tests",
feature = "integration_tests",
)),
feature = "analyzer_tests",
))]
#[path = "common/test_utils.rs"]
mod test_utils;
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_add_copy_refs() {
let src = r#"
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("a + b"),
"&i32 in BinaryOp: auto-copy. Got:\n{}",
result
);
assert!(
!result.contains("*a + *b"),
"Should not add explicit deref for Copy. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_sub_copy_refs() {
let src = r#"
pub fn sub(a: i32, b: i32) -> i32 {
a - b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a - b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_mul_copy_refs() {
let src = r#"
pub fn mul(a: i32, b: i32) -> i32 {
a * b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a * b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_int_division_preserved() {
let src = r#"
pub fn half(x: i32) -> i32 {
x / 2
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("x / 2"),
"Integer division must stay int. Got:\n{}",
result
);
assert!(
!result.contains("(2) as"),
"CRITICAL: 2 must NOT be cast to float. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_int_mod_preserved() {
let src = r#"
pub fn remainder(x: i32, y: i32) -> i32 {
x % y
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("x % y"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_mixed_int_float_cast() {
let src = r#"
pub fn compute(x: f32, y: i32) -> f32 {
x + y
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("(y) as f32") || result.contains("y as f32"),
"Mixed: y should be cast to f32. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_float_plus_int_literal() {
let src = r#"
pub fn scale(x: f32) -> f32 {
x * 2
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(
result.contains("as f32") || result.contains("2.0"),
"Int literal with float should cast. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_comparison_auto_deref() {
let src = r#"
pub fn compare(a: i32, b: i32) -> bool {
a == b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("a == b"),
"Comparison: auto-deref. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_comparison_lt_gt() {
let src = r#"
pub fn less(a: i32, b: i32) -> bool {
a < b
}
pub fn greater(a: i32, b: i32) -> bool {
a > b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a < b"));
assert!(result.contains("a > b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_nested_precedence() {
let src = r#"
pub fn expr(a: i32, b: i32, c: i32) -> i32 {
a + b * c
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(
result.contains("a + b * c") || result.contains("a + (b * c)"),
"Precedence. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_bitwise_and() {
let src = r#"
pub fn band(a: i32, b: i32) -> i32 {
a & b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a & b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_bitwise_or() {
let src = r#"
pub fn bor(a: i32, b: i32) -> i32 {
a | b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a | b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_logical_and() {
let src = r#"
pub fn land(a: bool, b: bool) -> bool {
a && b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a && b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_logical_or() {
let src = r#"
pub fn lor(a: bool, b: bool) -> bool {
a || b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a || b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_add_three_refs() {
let src = r#"
pub fn add_three(a: i32, b: i32, c: i32) -> i32 {
a + b + c
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a + b + c"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_both_int_arithmetic() {
let src = r#"
pub fn calc(a: i32, b: i32) -> i32 {
(a + b) / 2
}
"#;
let (result, success) = test_utils::compile_single_check(src);
let err = if !success { &result } else { "" };
assert!(success, "Must compile. Error:\n{}", err);
assert!(
result.contains("(a + b) / 2") || (result.contains("a + b") && result.contains("/ 2")),
"Integer arithmetic. Got:\n{}",
result
);
assert!(
!result.contains("(2) as f32"),
"2 must not be cast to float. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_len_comparison() {
let src = r#"
pub fn has_items(items: Vec<i32>) -> bool {
items.len() > 0
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(
(result.contains("len()") && result.contains(">")) || result.contains("is_empty()"),
"Expected len()>0 or is_empty(). Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_field_access() {
let src = r#"
pub struct Point { pub x: i32, pub y: i32 }
pub fn sum(p: Point) -> i32 {
p.x + p.y
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(
result.contains("p.x") && result.contains("p.y") && result.contains("+"),
"Field access in binary. Got:\n{}",
result
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_shift_left() {
let src = r#"
pub fn shl(x: i32, n: i32) -> i32 {
x << n
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("<<"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_xor() {
let src = r#"
pub fn xor(a: i32, b: i32) -> i32 {
a ^ b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a ^ b"));
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_binary_mixed_owned_borrowed() {
let src = r#"
pub fn mix(a: i32, b: i32) -> i32 {
a + b
}
"#;
let (result, success) = test_utils::compile_single_check(src);
assert!(success);
assert!(result.contains("a + b"));
}