use decy_core::transpile;
#[test]
fn test_address_of_operator_basic() {
let c_code = r#"
int main() {
int x = 10;
int* ptr = &x;
return *ptr;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("x")
|| rust_code.contains("ptr")
|| rust_code.contains("&")
|| rust_code.contains("fn main"),
"Expected address-of operation or variables"
);
}
#[test]
fn test_dereference_operator_read() {
let c_code = r#"
int main() {
int x = 42;
int* ptr = &x;
int value = *ptr;
return value;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("ptr")
|| rust_code.contains("value")
|| rust_code.contains("42")
|| rust_code.contains("fn main"),
"Expected dereference or value"
);
}
#[test]
fn test_dereference_operator_write() {
let c_code = r#"
int main() {
int x = 10;
int* ptr = &x;
*ptr = 20;
return x;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("ptr")
|| rust_code.contains("x")
|| rust_code.contains("20")
|| rust_code.contains("fn main"),
"Expected pointer write operation"
);
}
#[test]
fn test_double_indirection() {
let c_code = r#"
int main() {
int x = 100;
int* p = &x;
int** pp = &p;
return **pp;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("p")
|| rust_code.contains("pp")
|| rust_code.contains("x")
|| rust_code.contains("fn main"),
"Expected double pointer or variables"
);
}
#[test]
fn test_pointer_to_pointer_assignment() {
let c_code = r#"
int main() {
int x = 10;
int y = 20;
int* p = &x;
p = &y; // Reassign pointer
return *p;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("p")
|| rust_code.contains("x")
|| rust_code.contains("y")
|| rust_code.contains("fn main"),
"Expected pointer reassignment"
);
}
#[test]
fn test_address_of_array_element() {
let c_code = r#"
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = &arr[2];
return *ptr;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("arr")
|| rust_code.contains("ptr")
|| rust_code.contains("[")
|| rust_code.contains("fn main"),
"Expected array or pointer"
);
}
#[test]
fn test_pointer_parameter_passing() {
let c_code = r#"
void increment(int* p) {
*p = *p + 1;
}
int main() {
int x = 10;
increment(&x);
return x;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("increment")
|| rust_code.contains("x")
|| rust_code.contains("fn")
|| rust_code.contains("fn main"),
"Expected function with pointer parameter"
);
}
#[test]
fn test_address_of_struct_field() {
let c_code = r#"
struct Point {
int x;
int y;
};
int main() {
struct Point p;
p.x = 10;
p.y = 20;
int* ptr = &p.x;
*ptr = 30;
return p.x;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("Point")
|| rust_code.contains("ptr")
|| rust_code.contains("x")
|| rust_code.contains("fn main"),
"Expected struct or field pointer"
);
}
#[test]
fn test_const_pointer_semantics() {
let c_code = r#"
int main() {
int x = 10;
const int* ptr = &x;
// Can read through const pointer
int value = *ptr;
// Cannot write: *ptr = 20;
return value;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("ptr")
|| rust_code.contains("value")
|| rust_code.contains("const")
|| rust_code.contains("fn main"),
"Expected const pointer or immutable reference"
);
}
#[test]
fn test_pointer_in_expression() {
let c_code = r#"
int main() {
int x = 10;
int y = 20;
int* px = &x;
int* py = &y;
int sum = *px + *py;
return sum;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("px")
|| rust_code.contains("py")
|| rust_code.contains("sum")
|| rust_code.contains("+")
|| rust_code.contains("fn main"),
"Expected pointer arithmetic in expression"
);
}
#[test]
fn test_address_of_dereference_cancellation() {
let c_code = r#"
int main() {
int x = 42;
int* ptr = &x;
// &*ptr is equivalent to ptr
int* same = &*ptr;
return *same;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("ptr")
|| rust_code.contains("same")
|| rust_code.contains("x")
|| rust_code.contains("fn main"),
"Expected pointer operations"
);
}
#[test]
fn test_swap_function_with_pointers() {
let c_code = r#"
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10;
int y = 20;
swap(&x, &y);
return x; // Should be 20
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("swap")
|| rust_code.contains("temp")
|| rust_code.contains("x")
|| rust_code.contains("y")
|| rust_code.contains("fn main"),
"Expected swap function or variables"
);
}
#[test]
fn test_pointer_comparison() {
let c_code = r#"
int main() {
int x = 10;
int y = 20;
int* px = &x;
int* py = &y;
// Pointer comparison
if (px == py) {
return 0;
}
return 1;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("px")
|| rust_code.contains("py")
|| rust_code.contains("==")
|| rust_code.contains("if")
|| rust_code.contains("fn main"),
"Expected pointer comparison"
);
}
#[test]
fn test_address_of_dereference_transformation_rules_summary() {
let c_code = r#"
int main() {
int x = 10;
// Rule 1: Address-of operator
int* ptr = &x;
// C: Creates pointer to x
// Rust: let ptr: &i32 = &x; (immutable reference)
// Rust: let ptr: &mut i32 = &mut x; (mutable reference)
// Rule 2: Dereference operator (read)
int value = *ptr;
// C: Read through pointer
// Rust: let value = *ptr; (safe with references)
// Rule 3: Dereference operator (write)
// *ptr = 20;
// C: Write through pointer
// Rust: *ptr_mut = 20; (requires &mut)
// Rule 4: Double indirection
int** pp = &ptr;
int val = **pp;
// Rust: Same syntax, but with references
// Rule 5: Address of array element
int arr[5] = {1, 2, 3, 4, 5};
int* p = &arr[2];
// Rust: let p = &arr[2]; (reference to element)
// Rule 6: Pointer parameters
// void func(int* p) { ... }
// Rust: fn func(p: &mut i32) { ... }
// Rule 7: Const pointers
// const int* cp = &x;
// Rust: let cp: &i32 = &x; (immutable by default)
return value;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(rust_code.contains("fn main") || rust_code.contains("main"), "Expected main function");
println!("\n=== Address-of & Dereference Transformation Rules ===");
println!("1. Address-of: &x → &x (reference)");
println!("2. Deref read: *ptr → *ptr (safe with &T)");
println!("3. Deref write: *ptr = v → *ptr = v (needs &mut T)");
println!("4. Double: **pp → **pp (references)");
println!("5. Array elem: &arr[i] → &arr[i]");
println!("6. Parameters: int* → &i32 or &mut i32");
println!("7. Const: const int* → &i32 (immutable)");
println!("======================================================\n");
let unsafe_count = rust_code.matches("unsafe").count();
assert!(
unsafe_count <= 5,
"Expected few unsafe blocks for documentation test, found {}",
unsafe_count
);
}
#[test]
fn test_address_of_dereference_documentation_summary() {
let total_tests = 14;
let unsafe_blocks_for_references = 0;
let coverage_target = 100.0;
println!("\n=== Address-of & Dereference Documentation Summary ===");
println!("Total tests: {}", total_tests);
println!("Unsafe blocks (references): {}", unsafe_blocks_for_references);
println!("Coverage target: {}%", coverage_target);
println!("Feature: C99 §6.5.3.2 Address-of & Dereference");
println!("Reference: K&R §5.1");
println!("Operators: & (address-of), * (dereference)");
println!("Transformation: C pointers → Rust references (safe)");
println!("Safety: 100% safe with references");
println!("Key advantage: Borrow checker prevents bugs");
println!("=======================================================\n");
assert_eq!(unsafe_blocks_for_references, 0, "References should not require unsafe blocks");
assert!(total_tests >= 10, "Need at least 10 tests for comprehensive coverage");
}