#[cfg(test)]
mod tests {
#[test]
fn test_simple_ternary_max() {
let c_code = r#"
int max = (a > b) ? a : b;
"#;
let rust_expected = r#"
let max = if a > b { a } else { b };
"#;
assert!(c_code.contains("(a > b) ? a : b"));
assert!(rust_expected.contains("if a > b { a } else { b }"));
}
#[test]
fn test_simple_ternary_min() {
let c_code = r#"
int min = (a < b) ? a : b;
"#;
let rust_expected = r#"
let min = if a < b { a } else { b };
"#;
assert!(c_code.contains("(a < b) ? a : b"));
assert!(rust_expected.contains("if a < b { a } else { b }"));
}
#[test]
fn test_ternary_sign() {
let c_code = r#"
int sign = (x >= 0) ? 1 : -1;
"#;
let rust_expected = r#"
let sign = if x >= 0 { 1 } else { -1 };
"#;
assert!(c_code.contains("(x >= 0) ? 1 : -1"));
assert!(rust_expected.contains("if x >= 0 { 1 } else { -1 }"));
}
#[test]
fn test_ternary_in_return() {
let c_code = r#"
int get_abs(int x) {
return (x >= 0) ? x : -x;
}
"#;
let rust_expected = r#"
fn get_abs(x: i32) -> i32 {
if x >= 0 { x } else { -x }
}
"#;
assert!(c_code.contains("return (x >= 0) ? x : -x"));
assert!(rust_expected.contains("if x >= 0 { x } else { -x }"));
}
#[test]
fn test_nested_ternary_grades() {
let c_code = r#"
char grade = (x >= 90) ? 'A' : (x >= 80) ? 'B' : 'C';
"#;
let rust_expected = r#"
let grade = if x >= 90 { 'A' }
else if x >= 80 { 'B' }
else { 'C' };
"#;
assert!(c_code.contains("(x >= 90) ? 'A' : (x >= 80) ? 'B' : 'C'"));
assert!(rust_expected.contains("if x >= 90 { 'A' }"));
assert!(rust_expected.contains("else if x >= 80 { 'B' }"));
}
#[test]
fn test_deeply_nested_ternary() {
let c_code = r#"
char grade = (x >= 90) ? 'A' : (x >= 80) ? 'B' : (x >= 70) ? 'C' : 'F';
"#;
let rust_expected = r#"
let grade = if x >= 90 { 'A' }
else if x >= 80 { 'B' }
else if x >= 70 { 'C' }
else { 'F' };
"#;
assert!(c_code.contains("(x >= 90) ? 'A'"));
assert!(rust_expected.contains("if x >= 90 { 'A' }"));
assert!(rust_expected.contains("else if x >= 70 { 'C' }"));
assert!(rust_expected.contains("else { 'F' }"));
}
#[test]
fn test_ternary_with_function_calls() {
let c_code = r#"
int result = is_cached() ? get_cached_value() : compute_expensive();
"#;
let rust_expected = r#"
let result = if is_cached() { get_cached_value() } else { compute_expensive() };
"#;
assert!(c_code.contains("is_cached() ? get_cached_value() : compute_expensive()"));
assert!(rust_expected
.contains("if is_cached() { get_cached_value() } else { compute_expensive() }"));
}
#[test]
fn test_ternary_null_check() {
let c_code = r#"
int value = (ptr != NULL) ? ptr->data : default_value;
"#;
let rust_expected = r#"
let value = if let Some(ptr) = opt {
ptr.data
} else {
default_value
};
"#;
assert!(c_code.contains("(ptr != NULL) ? ptr->data : default_value"));
assert!(rust_expected.contains("if let Some(ptr) = opt"));
}
#[test]
fn test_ternary_zero_check() {
let c_code = r#"
int result = (b != 0) ? a / b : 0;
"#;
let rust_expected = r#"
let result = if b != 0 { a / b } else { 0 };
"#;
assert!(c_code.contains("(b != 0) ? a / b : 0"));
assert!(rust_expected.contains("if b != 0 { a / b } else { 0 }"));
}
#[test]
fn test_ternary_in_array() {
let c_code = r#"
for (int i = 0; i < n; i++) {
arr[i] = (i % 2 == 0) ? 0 : 1;
}
"#;
let rust_expected = r#"
for i in 0..n {
arr[i] = if i % 2 == 0 { 0 } else { 1 };
}
"#;
assert!(c_code.contains("(i % 2 == 0) ? 0 : 1"));
assert!(rust_expected.contains("if i % 2 == 0 { 0 } else { 1 }"));
}
#[test]
fn test_ternary_clamp() {
let c_code = r#"
int clamped = (x < MIN) ? MIN : (x > MAX) ? MAX : x;
"#;
let rust_expected = r#"
let clamped = if x < MIN { MIN }
else if x > MAX { MAX }
else { x };
"#;
assert!(c_code.contains("(x < MIN) ? MIN : (x > MAX) ? MAX : x"));
assert!(rust_expected.contains("if x < MIN { MIN }"));
assert!(rust_expected.contains("else if x > MAX { MAX }"));
}
#[test]
fn test_ternary_boolean_result() {
let c_code = r#"
int is_valid = (x >= 0 && x < 100) ? 1 : 0;
"#;
let rust_expected = r#"
let is_valid = x >= 0 && x < 100;
"#;
assert!(c_code.contains("(x >= 0 && x < 100) ? 1 : 0"));
assert!(rust_expected.contains("x >= 0 && x < 100"));
}
#[test]
fn test_ternary_in_print() {
let c_code = r#"
printf("%s\n", (x > 0) ? "positive" : "non-positive");
"#;
let rust_expected = r#"
println!("{}", if x > 0 { "positive" } else { "non-positive" });
"#;
assert!(c_code.contains("(x > 0) ? \"positive\" : \"non-positive\""));
assert!(rust_expected.contains("if x > 0 { \"positive\" } else { \"non-positive\" }"));
}
#[test]
fn test_ternary_pointer_truthy() {
let c_code = r#"
int result = (ptr) ? process(ptr) : handle_null();
"#;
let rust_expected = r#"
let result = if let Some(ptr) = opt {
process(ptr)
} else {
handle_null()
};
"#;
assert!(c_code.contains("(ptr) ? process(ptr) : handle_null()"));
assert!(rust_expected.contains("if let Some(ptr) = opt"));
}
#[test]
fn test_ternary_sign_extension() {
let c_code = r#"
int extended = (x & 0x80) ? (x | 0xFF00) : x;
"#;
let rust_expected = r#"
let extended = if (x & 0x80) != 0 { x | 0xFF00 } else { x };
"#;
assert!(c_code.contains("(x & 0x80) ? (x | 0xFF00) : x"));
assert!(rust_expected.contains("if (x & 0x80) != 0"));
}
#[test]
fn test_ternary_default_value() {
let c_code = r#"
int value = (count > 0) ? total / count : 0;
"#;
let rust_expected = r#"
let value = if count > 0 { total / count } else { 0 };
"#;
assert!(c_code.contains("(count > 0) ? total / count : 0"));
assert!(rust_expected.contains("if count > 0 { total / count } else { 0 }"));
}
#[test]
fn test_ternary_operator_transformation_summary() {
let c_code = r#"
// Rule 1: Simple ternary (max/min)
max = (a > b) ? a : b;
// Rule 2: Sign determination
sign = (x >= 0) ? 1 : -1;
// Rule 3: Nested ternary (grades)
grade = (x >= 90) ? 'A' : (x >= 80) ? 'B' : 'C';
// Rule 4: In return statement
return (x >= 0) ? x : -x;
// Rule 5: NULL check
value = (ptr != NULL) ? ptr->data : default;
// Rule 6: Zero check
result = (b != 0) ? a / b : 0;
// Rule 7: Clamp/bounds
clamped = (x < MIN) ? MIN : (x > MAX) ? MAX : x;
// Rule 8: Boolean result (unnecessary ternary)
is_valid = (x >= 0 && x < 100) ? 1 : 0;
// Rule 9: With function calls (short-circuit)
result = is_cached() ? get_cached() : compute();
"#;
let rust_expected = r#"
// Rule 1: Simple if expression
let max = if a > b { a } else { b };
// Rule 2: Sign determination
let sign = if x >= 0 { 1 } else { -1 };
// Rule 3: If-else-if chain (more readable)
let grade = if x >= 90 { 'A' }
else if x >= 80 { 'B' }
else { 'C' };
// Rule 4: If expression as implicit return
if x >= 0 { x } else { -x }
// Rule 5: Option pattern matching
let value = if let Some(ptr) = opt { ptr.data } else { default };
// Rule 6: Zero check guard
let result = if b != 0 { a / b } else { 0 };
// Rule 7: If-else-if clamp
let clamped = if x < MIN { MIN }
else if x > MAX { MAX }
else { x };
// Rule 8: Direct boolean (no if needed)
let is_valid = x >= 0 && x < 100;
// Rule 9: Short-circuit preserved
let result = if is_cached() { get_cached() } else { compute() };
"#;
assert!(c_code.contains("(a > b) ? a : b"));
assert!(rust_expected.contains("if a > b { a } else { b }"));
assert!(c_code.contains("(x >= 90) ? 'A'"));
assert!(rust_expected.contains("if x >= 90 { 'A' }"));
assert!(c_code.contains("(ptr != NULL)"));
assert!(rust_expected.contains("if let Some(ptr) = opt"));
}
}