#[cfg(test)]
mod tests {
#[test]
fn test_simple_return_int() {
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
}
"#;
assert!(c_code.contains("int add(int a, int b)"));
assert!(rust_expected.contains("fn add(a: i32, b: i32) -> i32"));
assert!(rust_expected.contains("a + b"));
}
#[test]
fn test_void_function() {
let c_code = r#"
void print_message(int x) {
printf("%d\n", x);
}
"#;
let rust_expected = r#"
fn print_message(x: i32) {
println!("{}", x);
}
"#;
assert!(c_code.contains("void print_message(int x)"));
assert!(rust_expected.contains("fn print_message(x: i32)"));
assert!(!rust_expected.contains("->"));
}
#[test]
fn test_no_parameters() {
let c_code = r#"
int get_constant(void) {
return 42;
}
"#;
let rust_expected = r#"
fn get_constant() -> i32 {
42
}
"#;
assert!(c_code.contains("get_constant(void)"));
assert!(rust_expected.contains("get_constant() -> i32"));
}
#[test]
fn test_multiple_parameters() {
let c_code = r#"
int max3(int a, int b, int c) {
int m = a;
if (b > m) m = b;
if (c > m) m = c;
return m;
}
"#;
let rust_expected = r#"
fn max3(a: i32, b: i32, c: i32) -> i32 {
let mut m = a;
if b > m { m = b; }
if c > m { m = c; }
m
}
"#;
assert!(c_code.contains("int max3(int a, int b, int c)"));
assert!(rust_expected.contains("fn max3(a: i32, b: i32, c: i32)"));
}
#[test]
fn test_early_return() {
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; }
a / b
}
"#;
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_boolean_return() {
let c_code = r#"
int is_positive(int x) {
if (x > 0) return 1;
return 0;
}
"#;
let rust_expected = r#"
fn is_positive(x: i32) -> bool {
x > 0
}
"#;
assert!(c_code.contains("int is_positive"));
assert!(rust_expected.contains("fn is_positive(x: i32) -> bool"));
}
#[test]
fn test_float_function() {
let c_code = r#"
float average(float a, float b) {
return (a + b) / 2.0f;
}
"#;
let rust_expected = r#"
fn average(a: f32, b: f32) -> f32 {
(a + b) / 2.0
}
"#;
assert!(c_code.contains("float average(float a, float b)"));
assert!(rust_expected.contains("fn average(a: f32, b: f32) -> f32"));
}
#[test]
fn test_double_function() {
let c_code = r#"
double square(double x) {
return x * x;
}
"#;
let rust_expected = r#"
fn square(x: f64) -> f64 {
x * x
}
"#;
assert!(c_code.contains("double square(double x)"));
assert!(rust_expected.contains("fn square(x: f64) -> f64"));
}
#[test]
fn test_mixed_parameter_types() {
let c_code = r#"
float scale(int count, float factor) {
return count * factor;
}
"#;
let rust_expected = r#"
fn scale(count: i32, factor: f32) -> f32 {
count as f32 * factor
}
"#;
assert!(c_code.contains("float scale(int count, float factor)"));
assert!(rust_expected.contains("fn scale(count: i32, factor: f32)"));
}
#[test]
fn test_function_calls_function() {
let c_code = r#"
int square(int x) {
return x * x;
}
int sum_of_squares(int a, int b) {
return square(a) + square(b);
}
"#;
let rust_expected = r#"
fn square(x: i32) -> i32 {
x * x
}
fn sum_of_squares(a: i32, b: i32) -> i32 {
square(a) + square(b)
}
"#;
assert!(c_code.contains("square(a) + square(b)"));
assert!(rust_expected.contains("square(a) + square(b)"));
}
#[test]
fn test_complex_function_body() {
let c_code = r#"
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
"#;
let rust_expected = r#"
fn factorial(n: i32) -> i32 {
let mut result = 1;
for i in 1..=n {
result *= i;
}
result
}
"#;
assert!(c_code.contains("int result = 1"));
assert!(rust_expected.contains("let mut result = 1"));
assert!(rust_expected.contains("result"));
}
#[test]
fn test_recursive_function() {
let c_code = r#"
int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
"#;
let rust_expected = r#"
fn fibonacci(n: i32) -> i32 {
if n <= 1 { return n; }
fibonacci(n - 1) + fibonacci(n - 2)
}
"#;
assert!(c_code.contains("fibonacci(n - 1) + fibonacci(n - 2)"));
assert!(rust_expected.contains("fibonacci(n - 1) + fibonacci(n - 2)"));
}
#[test]
fn test_multiple_return_paths() {
let c_code = r#"
int classify(int x) {
if (x < 0) return -1;
if (x > 0) return 1;
return 0;
}
"#;
let rust_expected = r#"
fn classify(x: i32) -> i32 {
if x < 0 { return -1; }
if x > 0 { return 1; }
0
}
"#;
assert!(c_code.contains("if (x < 0) return -1"));
assert!(rust_expected.contains("if x < 0 { return -1; }"));
}
#[test]
fn test_void_early_return() {
let c_code = r#"
void process(int x) {
if (x < 0) return;
printf("%d\n", x);
}
"#;
let rust_expected = r#"
fn process(x: i32) {
if x < 0 { return; }
println!("{}", x);
}
"#;
assert!(c_code.contains("if (x < 0) return"));
assert!(rust_expected.contains("if x < 0 { return; }"));
}
#[test]
fn test_array_parameter() {
let c_code = r#"
int sum_array(int arr[], int len) {
int sum = 0;
for (int i = 0; i < len; i++) {
sum += arr[i];
}
return sum;
}
"#;
let rust_expected = r#"
fn sum_array(arr: &[i32]) -> i32 {
let mut sum = 0;
for &item in arr {
sum += item;
}
sum
}
"#;
assert!(c_code.contains("int arr[], int len"));
assert!(rust_expected.contains("arr: &[i32]"));
}
#[test]
fn test_static_function() {
let c_code = r#"
static int helper(int x) {
return x * 2;
}
"#;
let rust_expected = r#"
fn helper(x: i32) -> i32 {
x * 2
}
"#;
assert!(c_code.contains("static int helper"));
assert!(rust_expected.contains("fn helper"));
}
#[test]
fn test_function_transformation_summary() {
let c_code = r#"
// Rule 1: Simple return
int add(int a, int b) { return a + b; }
// Rule 2: Void function
void print(int x) { printf("%d", x); }
// Rule 3: No parameters
int get_value(void) { return 42; }
// Rule 4: Early return
int divide(int a, int b) {
if (b == 0) return -1;
return a / b;
}
// Rule 5: Boolean (int in C)
int is_even(int x) { return x % 2 == 0; }
// Rule 6: Float/double
float avg(float a, float b) { return (a + b) / 2; }
// Rule 7: Recursive
int fib(int n) {
if (n <= 1) return n;
return fib(n-1) + fib(n-2);
}
// Rule 8: Array parameter
int sum(int arr[], int n) { ... }
"#;
let rust_expected = r#"
// Rule 1: Implicit return
fn add(a: i32, b: i32) -> i32 { a + b }
// Rule 2: Omit return type
fn print(x: i32) { println!("{}", x); }
// Rule 3: Empty () for no params
fn get_value() -> i32 { 42 }
// Rule 4: Explicit early, implicit final
fn divide(a: i32, b: i32) -> i32 {
if b == 0 { return -1; }
a / b
}
// Rule 5: Use bool type
fn is_even(x: i32) -> bool { x % 2 == 0 }
// Rule 6: f32/f64 types
fn avg(a: f32, b: f32) -> f32 { (a + b) / 2.0 }
// Rule 7: Same recursion
fn fib(n: i32) -> i32 {
if n <= 1 { return n; }
fib(n-1) + fib(n-2)
}
// Rule 8: Slice instead of pointer+length
fn sum(arr: &[i32]) -> i32 { ... }
"#;
assert!(c_code.contains("int add(int a, int b)"));
assert!(rust_expected.contains("fn add(a: i32, b: i32) -> i32"));
assert!(c_code.contains("void print(int x)"));
assert!(rust_expected.contains("fn print(x: i32)"));
assert!(c_code.contains("int get_value(void)"));
assert!(rust_expected.contains("fn get_value() -> i32"));
assert!(rust_expected.contains("arr: &[i32]"));
}
}