use decy_core::transpile;
#[test]
fn test_transform_array_parameter_to_slice() {
let c_code = r#"
void process(int* arr, int len) {
// Empty function for signature testing
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
result.contains("arr: &[i32]"),
"Should transform (int* arr, int len) to arr: &[i32]\nGenerated:\n{}",
result
);
assert!(
!result.contains("len: i32") && !result.contains("len: usize"),
"Should remove redundant length parameter\nGenerated:\n{}",
result
);
assert!(
!result.contains("unsafe"),
"Should generate safe code\nGenerated:\n{}",
result
);
}
#[test]
fn test_transform_mutable_array_parameter() {
let c_code = r#"
void fill(int* arr, int len) {
arr[0] = 1;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
result.contains("arr: &mut [i32]"),
"Should transform to arr: &mut [i32] for mutable access\nGenerated:\n{}",
result
);
assert!(
!result.contains("unsafe"),
"Should generate safe code\nGenerated:\n{}",
result
);
}
#[test]
fn test_transform_length_usage_in_body() {
let c_code = r#"
int sum(int* arr, int len) {
int total = 0;
for (int i = 0; i < len; i++) {
total += arr[i];
}
return total;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
result.contains("arr: &[i32]"),
"Should use slice parameter\nGenerated:\n{}",
result
);
assert!(
result.contains("arr.len()"),
"Should use arr.len() instead of len parameter\nGenerated:\n{}",
result
);
assert!(
!result.contains("unsafe"),
"Should generate safe code\nGenerated:\n{}",
result
);
}
#[test]
fn test_transform_char_array_parameter() {
let c_code = r#"
void process_buffer(char* buf, int size) {
buf[0] = 65;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
result.contains("buf: &mut [u8]"),
"Should transform char* to &mut [u8]\nGenerated:\n{}",
result
);
assert!(
!result.contains("unsafe"),
"Should generate safe code\nGenerated:\n{}",
result
);
}
#[test]
fn test_transform_multiple_array_parameters() {
let c_code = r#"
void merge(int* arr1, int len1, int* arr2, int len2) {
// Empty for signature testing
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
result.contains("arr1: &[i32]"),
"Should transform arr1 to slice\nGenerated:\n{}",
result
);
assert!(
result.contains("arr2: &[i32]"),
"Should transform arr2 to slice\nGenerated:\n{}",
result
);
assert!(
!result.contains("len1") && !result.contains("len2"),
"Should remove both length parameters\nGenerated:\n{}",
result
);
assert!(
!result.contains("unsafe"),
"Should generate safe code\nGenerated:\n{}",
result
);
}
#[test]
fn test_transform_array_parameter_with_return() {
let c_code = r#"
int first_element(int* arr, int len) {
return arr[0];
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
result.contains("arr: &[i32]"),
"Should use slice parameter\nGenerated:\n{}",
result
);
assert!(
result.contains("arr[0]") || result.contains("arr[0 as usize]"),
"Should use safe indexing\nGenerated:\n{}",
result
);
assert!(
!result.contains("unsafe"),
"Should generate safe code\nGenerated:\n{}",
result
);
}
#[test]
fn test_no_transform_non_array_pointer() {
let c_code = r#"
void process(int* ptr) {
// Single pointer without length - not an array
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
assert!(
!result.contains(": &[i32]"),
"Should NOT transform single pointer to slice\nGenerated:\n{}",
result
);
assert!(
result.contains("ptr: *mut i32") || result.contains("ptr: *const i32"),
"Should keep as raw pointer\nGenerated:\n{}",
result
);
}
#[test]
fn test_array_parameter_transformation_unsafe_count() {
let c_code = r#"
void process1(int* arr, int len) { arr[0] = 1; }
void process2(char* buf, int size) { buf[0] = 'A'; }
int sum(int* arr, int len) {
int total = 0;
for (int i = 0; i < len; i++) {
total += arr[i];
}
return total;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
let unsafe_count = result.matches("unsafe").count();
let loc = result.lines().count();
let unsafe_per_1000 = (unsafe_count as f64 / loc as f64) * 1000.0;
println!("Unsafe count: {}", unsafe_count);
println!("Lines of code: {}", loc);
println!("Unsafe per 1000 LOC: {:.2}", unsafe_per_1000);
assert!(
unsafe_per_1000 < 5.0,
"Must achieve <5 unsafe blocks per 1000 LOC. Got {:.2}",
unsafe_per_1000
);
assert_eq!(
unsafe_count, 0,
"Array parameter transformation should achieve 0 unsafe blocks. Found {}",
unsafe_count
);
}