#[cfg(test)]
mod tests {
#[test]
fn test_basic_vla_int() {
let c_code = r#"
int n = 10;
int arr[n];
"#;
let rust_expected = r#"
let n = 10;
let arr = vec![0i32; n];
"#;
assert!(c_code.contains("int arr[n]"));
assert!(rust_expected.contains("vec![0i32; n]"));
}
#[test]
fn test_vla_runtime_size() {
let c_code = r#"
int n = get_size();
double values[n];
"#;
let rust_expected = r#"
let n = get_size();
let values = vec![0.0f64; n];
"#;
assert!(c_code.contains("double values[n]"));
assert!(rust_expected.contains("vec![0.0f64; n]"));
}
#[test]
fn test_vla_expression_size() {
let c_code = r#"
int n = 5;
int arr[n * 2 + 1];
"#;
let rust_expected = r#"
let n = 5;
let arr = vec![0; n * 2 + 1];
"#;
assert!(c_code.contains("arr[n * 2 + 1]"));
assert!(rust_expected.contains("vec![0; n * 2 + 1]"));
}
#[test]
fn test_vla_char_buffer() {
let c_code = r#"
int len = 256;
char buffer[len];
"#;
let rust_expected = r#"
let len = 256;
let buffer = vec![0u8; len];
"#;
assert!(c_code.contains("char buffer[len]"));
assert!(rust_expected.contains("vec![0u8; len]"));
}
#[test]
fn test_vla_multidimensional() {
let c_code = r#"
int rows = 3;
int cols = 4;
int matrix[rows][cols];
"#;
let rust_expected = r#"
let rows = 3;
let cols = 4;
let matrix: Vec<Vec<i32>> = vec![vec![0; cols]; rows];
"#;
assert!(c_code.contains("int matrix[rows][cols]"));
assert!(rust_expected.contains("vec![vec![0; cols]; rows]"));
}
#[test]
fn test_vla_manual_initialization() {
let c_code = r#"
int n = 100;
int arr[n];
for (int i = 0; i < n; i++) {
arr[i] = 0;
}
"#;
let rust_expected = r#"
let n = 100;
let arr = vec![0; n];
"#;
assert!(c_code.contains("int arr[n]"));
assert!(rust_expected.contains("vec![0; n]"));
}
#[test]
fn test_vla_struct_type() {
let c_code = r#"
int count = 50;
struct Point points[count];
"#;
let rust_expected = r#"
let count = 50;
let points = vec![Point::default(); count];
"#;
assert!(c_code.contains("struct Point points[count]"));
assert!(rust_expected.contains("vec![Point::default(); count]"));
}
#[test]
fn test_vla_scope_lifetime() {
let c_code = r#"
{
int n = 20;
int arr[n];
// Use arr
}
// arr automatically freed
"#;
let rust_expected = r#"
{
let n = 20;
let arr = vec![0; n];
// Use arr
}
// arr automatically dropped
"#;
assert!(c_code.contains("int arr[n]"));
assert!(rust_expected.contains("vec![0; n]"));
}
#[test]
fn test_vla_with_const_size() {
let c_code = r#"
const int SIZE = 100;
int arr[SIZE];
"#;
let rust_expected = r#"
const SIZE: usize = 100;
let arr = [0i32; SIZE];
"#;
assert!(c_code.contains("int arr[SIZE]"));
assert!(rust_expected.contains("[0i32; SIZE]"));
}
#[test]
fn test_vla_in_loop() {
let c_code = r#"
for (int i = 0; i < 10; i++) {
int n = i * 10;
int arr[n];
process(arr, n);
}
"#;
let rust_expected = r#"
for i in 0..10 {
let n = i * 10;
let arr = vec![0; n];
process(&arr);
}
"#;
assert!(c_code.contains("int arr[n]"));
assert!(rust_expected.contains("vec![0; n]"));
}
#[test]
fn test_vla_size_from_function() {
let c_code = r#"
int n = compute_size();
float data[n];
"#;
let rust_expected = r#"
let n = compute_size();
let data = vec![0.0f32; n];
"#;
assert!(c_code.contains("float data[n]"));
assert!(rust_expected.contains("vec![0.0f32; n]"));
}
#[test]
fn test_vla_with_typedef() {
let c_code = r#"
typedef int Integer;
int n = 25;
Integer numbers[n];
"#;
let rust_expected = r#"
type Integer = i32;
let n = 25;
let numbers: Vec<Integer> = vec![0; n];
"#;
assert!(c_code.contains("Integer numbers[n]"));
assert!(rust_expected.contains("Vec<Integer>"));
}
#[test]
fn test_vla_unsigned() {
let c_code = r#"
int n = 50;
unsigned int flags[n];
"#;
let rust_expected = r#"
let n = 50;
let flags = vec![0u32; n];
"#;
assert!(c_code.contains("unsigned int flags[n]"));
assert!(rust_expected.contains("vec![0u32; n]"));
}
#[test]
fn test_vla_safety_stack_overflow() {
let c_note = r#"
// C: DANGEROUS - can cause stack overflow
int n = 1000000; // Very large
int arr[n]; // May crash!
"#;
let rust_code = r#"
// Rust: SAFE - heap allocated
let n = 1000000; // Very large
let arr = vec![0; n]; // No stack overflow
"#;
assert!(c_note.contains("can cause stack overflow"));
assert!(rust_code.contains("No stack overflow"));
}
#[test]
fn test_vla_function_parameter() {
let c_code = r#"
void process(int n, int arr[n]) {
for (int i = 0; i < n; i++) {
arr[i] *= 2;
}
}
"#;
let rust_expected = r#"
fn process(arr: &mut [i32]) {
for i in 0..arr.len() {
arr[i] *= 2;
}
}
"#;
assert!(c_code.contains("int arr[n]"));
assert!(rust_expected.contains("&mut [i32]"));
}
#[test]
fn test_vla_transformation_summary() {
let c_code = r#"
// Rule 1: Basic VLA → vec![0; n]
int n = 10;
int arr[n];
// Rule 2: Different types
double vals[n];
// Rule 3: Expression size
int buf[n * 2];
// Rule 4: Multidimensional
int matrix[rows][cols];
// Rule 5: Function parameter
void f(int n, int arr[n]);
// Rule 6: Manual init → simplified
int tmp[n];
for (int i = 0; i < n; i++) tmp[i] = 0;
"#;
let rust_expected = r#"
// Rule 1: Vec with default value
let n = 10;
let arr = vec![0; n];
// Rule 2: Type-specific default
let vals = vec![0.0f64; n];
// Rule 3: Same expression
let buf = vec![0; n * 2];
// Rule 4: Nested Vec
let matrix: Vec<Vec<i32>> = vec![vec![0; cols]; rows];
// Rule 5: Slice (size implicit)
fn f(arr: &[i32]);
// Rule 6: Direct initialization
let tmp = vec![0; n];
"#;
assert!(c_code.contains("int arr[n]"));
assert!(rust_expected.contains("vec![0; n]"));
assert!(c_code.contains("double vals[n]"));
assert!(rust_expected.contains("vec![0.0f64; n]"));
assert!(c_code.contains("int matrix[rows][cols]"));
assert!(rust_expected.contains("vec![vec![0; cols]; rows]"));
}
}