#[cfg(test)]
mod tests {
#[test]
fn test_simple_return_integer() {
let c_code = r#"
int get_value() {
return 42;
}
"#;
let rust_expected = r#"
fn get_value() -> i32 {
42 // Idiomatic: no return keyword for final expression
}
"#;
assert!(c_code.contains("return 42;"));
assert!(rust_expected.contains("42 //"));
assert!(!rust_expected.contains("return 42"));
}
#[test]
fn test_return_with_expression() {
let c_code = r#"
int add(int a, int b) {
return a + b;
}
"#;
let rust_expected = r#"
fn add(a: i32, b: i32) -> i32 {
a + b // Implicit return
}
"#;
assert!(c_code.contains("return a + b"));
assert!(rust_expected.contains("a + b //"));
}
#[test]
fn test_void_return() {
let c_code = r#"
void process() {
do_work();
return;
}
"#;
let rust_expected = r#"
fn process() {
do_work();
// return omitted (implicit () return)
}
"#;
assert!(c_code.contains("return;"));
assert!(rust_expected.contains("// return omitted"));
}
#[test]
fn test_void_no_return() {
let c_code = r#"
void init() {
setup();
configure();
}
"#;
let rust_expected = r#"
fn init() {
setup();
configure();
}
"#;
assert!(!c_code.contains("return"));
assert!(!rust_expected.contains("return"));
}
#[test]
fn test_early_return_guard() {
let c_code = r#"
int divide(int a, int b) {
if (b == 0) return -1;
return a / b;
}
"#;
let rust_expected = r#"
fn divide(a: i32, b: i32) -> i32 {
if b == 0 { return -1; } // Explicit return for early exit
a / b // Implicit return for success case
}
"#;
assert!(c_code.contains("if (b == 0) return -1;"));
assert!(rust_expected.contains("if b == 0 { return -1; }"));
assert!(rust_expected.contains("a / b //"));
}
#[test]
fn test_multiple_early_returns() {
let c_code = r#"
int classify(int x) {
if (x < 0) return -1;
if (x == 0) return 0;
return 1;
}
"#;
let rust_expected = r#"
fn classify(x: i32) -> i32 {
if x < 0 { return -1; }
if x == 0 { return 0; }
1 // Final case: implicit
}
"#;
assert_eq!(c_code.matches("return").count(), 3);
assert!(rust_expected.contains("{ return -1; }"));
assert!(rust_expected.contains("{ return 0; }"));
}
#[test]
fn test_return_in_if_else_expression_style() {
let c_code = r#"
int get_sign(int x) {
if (x >= 0) {
return 1;
} else {
return -1;
}
}
"#;
let rust_idiomatic = r#"
fn get_sign(x: i32) -> i32 {
if x >= 0 { 1 } else { -1 } // If as expression
}
"#;
assert_eq!(c_code.matches("return").count(), 2);
assert!(!rust_idiomatic.contains("return"));
}
#[test]
fn test_return_in_loop_search() {
let c_code = r#"
int find_positive(int arr[], int len) {
for (int i = 0; i < len; i++) {
if (arr[i] > 0) return arr[i];
}
return -1; // Not found
}
"#;
let rust_expected = r#"
fn find_positive(arr: &[i32]) -> i32 {
for &val in arr.iter() {
if val > 0 { return val; }
}
-1 // Not found: implicit return
}
"#;
assert!(c_code.contains("if (arr[i] > 0) return arr[i];"));
assert!(rust_expected.contains("if val > 0 { return val; }"));
}
#[test]
fn test_return_function_call() {
let c_code = r#"
int wrapper(int x) {
return process(x);
}
"#;
let rust_expected = r#"
fn wrapper(x: i32) -> i32 {
process(x) // No keyword needed
}
"#;
assert!(c_code.contains("return process(x)"));
assert!(rust_expected.contains("process(x) //"));
assert!(!rust_expected.contains("return "));
}
#[test]
fn test_return_complex_expression() {
let c_code = r#"
int compute(int a, int b, int c) {
return a * b + c * 2;
}
"#;
let rust_expected = r#"
fn compute(a: i32, b: i32, c: i32) -> i32 {
a * b + c * 2 // Implicit return
}
"#;
assert!(c_code.contains("return a * b + c * 2"));
assert!(rust_expected.contains("a * b + c * 2 //"));
}
#[test]
fn test_return_comparison() {
let c_code = r#"
int is_positive(int x) {
return x > 0;
}
"#;
let rust_expected = r#"
fn is_positive(x: i32) -> bool {
x > 0 // Returns bool, not int
}
"#;
assert!(c_code.contains("int is_positive"));
assert!(rust_expected.contains("-> bool"));
}
#[test]
fn test_return_with_ternary() {
let c_code = r#"
int max(int a, int b) {
return (a > b) ? a : b;
}
"#;
let rust_expected = r#"
fn max(a: i32, b: i32) -> i32 {
if a > b { a } else { b } // If as expression
}
"#;
assert!(c_code.contains("?"));
assert!(!rust_expected.contains("?"));
assert!(rust_expected.contains("if a > b"));
}
#[test]
fn test_return_in_nested_if() {
let c_code = r#"
int categorize(int x) {
if (x < 0) {
return -1;
} else {
if (x < 10) {
return 0;
} else {
return 1;
}
}
}
"#;
let rust_expected = r#"
fn categorize(x: i32) -> i32 {
if x < 0 {
-1
} else if x < 10 {
0
} else {
1
} // Nested if as expression
}
"#;
assert_eq!(c_code.matches("return").count(), 3);
assert!(!rust_expected.contains("return"));
}
#[test]
fn test_return_after_assignment() {
let c_code = r#"
int compute_sum(int a, int b) {
int sum = a + b;
return sum;
}
"#;
let rust_expected = r#"
fn compute_sum(a: i32, b: i32) -> i32 {
let sum = a + b;
sum // Return variable value
}
"#;
assert!(c_code.contains("return sum;"));
assert!(rust_expected.contains("sum //"));
}
#[test]
fn test_multiple_statements_before_return() {
let c_code = r#"
int process(int x) {
int step1 = x * 2;
int step2 = step1 + 10;
int result = step2 / 3;
return result;
}
"#;
let rust_expected = r#"
fn process(x: i32) -> i32 {
let step1 = x * 2;
let step2 = step1 + 10;
let result = step2 / 3;
result // Final expression returns
}
"#;
assert!(c_code.contains("return result;"));
assert!(rust_expected.contains("result //"));
}
#[test]
fn test_return_in_switch() {
let c_code = r#"
int handle_state(int state) {
switch (state) {
case 0: return 10;
case 1: return 20;
case 2: return 30;
default: return -1;
}
}
"#;
let rust_expected = r#"
fn handle_state(state: i32) -> i32 {
match state {
0 => 10,
1 => 20,
2 => 30,
_ => -1,
} // Match as expression
}
"#;
assert_eq!(c_code.matches("return").count(), 4);
assert!(!rust_expected.contains("return "));
}
#[test]
fn test_return_transformation_rules_summary() {
let c_code = r#"
// Rule 1: Simple return
int get_value() { return 42; }
// Rule 2: Return with expression
int add(int a, int b) { return a + b; }
// Rule 3: Void return (optional)
void process() { do_work(); return; }
// Rule 4: Early return guard
int divide(int a, int b) {
if (b == 0) return -1;
return a / b;
}
// Rule 5: Multiple early returns
int classify(int x) {
if (x < 0) return -1;
if (x == 0) return 0;
return 1;
}
// Rule 6: If-else with returns
int get_sign(int x) {
if (x >= 0) return 1;
return -1;
}
// Rule 7: Return in loop
int find_first(int arr[], int len, int target) {
for (int i = 0; i < len; i++) {
if (arr[i] == target) return i;
}
return -1;
}
// Rule 8: Return function call
int wrapper(int x) { return process(x); }
"#;
let rust_expected = r#"
// Rule 1: Simple return (implicit)
fn get_value() -> i32 { 42 }
// Rule 2: Return with expression (implicit)
fn add(a: i32, b: i32) -> i32 { a + b }
// Rule 3: Unit return (omit return)
fn process() { do_work(); }
// Rule 4: Early return guard (explicit)
fn divide(a: i32, b: i32) -> i32 {
if b == 0 { return -1; }
a / b
}
// Rule 5: Multiple early returns (explicit)
fn classify(x: i32) -> i32 {
if x < 0 { return -1; }
if x == 0 { return 0; }
1
}
// Rule 6: If-else as expression
fn get_sign(x: i32) -> i32 {
if x >= 0 { 1 } else { -1 }
}
// Rule 7: Return in loop (explicit in loop)
fn find_first(arr: &[i32], target: i32) -> i32 {
for (i, &val) in arr.iter().enumerate() {
if val == target { return i as i32; }
}
-1
}
// Rule 8: Return function call (implicit)
fn wrapper(x: i32) -> i32 { process(x) }
"#;
assert!(c_code.contains("return 42"));
assert!(rust_expected.contains("{ 42 }"));
assert!(c_code.contains("return a + b"));
assert!(rust_expected.contains("{ a + b }"));
}
}