1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! DECY-123: Pointer arithmetic detection tests.
//!
//! When a pointer parameter uses pointer arithmetic (p = p + 1),
//! it should NOT be transformed to a reference.
//!
//! C: void f(int *p) { p = p + 1; }
//! Expected: fn f(p: *mut i32) - keep as raw pointer
//!
//! Note: char* with pointer arithmetic triggers DECY-134 (string iteration)
//! which transforms to slice + index (safer than raw pointers).
use decy_core::transpile;
/// Test that int* pointer arithmetic is detected and parameter stays as raw pointer.
///
/// Note: Using int* to test raw pointer preservation.
/// char* triggers DECY-134 string iteration (safer slice transform).
///
/// C: void f(int *p) { p = p + 1; }
/// Expected: fn f(p: *mut i32) - NOT &mut i32
#[test]
fn test_pointer_arithmetic_detection_int() {
let c_code = r#"
void test(int *p) {
p = p + 1;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
// Should keep as raw pointer due to pointer arithmetic
assert!(
result.contains("*mut i32") || result.contains("*const i32"),
"Should keep int* pointer arithmetic param as raw pointer\nGenerated:\n{}",
result
);
}
/// Test that int* pointer subtraction is also detected.
///
/// C: void f(int *p) { p = p - 1; }
/// Expected: fn f(p: *mut i32)
#[test]
fn test_pointer_subtraction_detection_int() {
let c_code = r#"
void test(int *p) {
p = p - 1;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
// Should keep as raw pointer due to pointer arithmetic
assert!(
result.contains("*mut i32") || result.contains("*const i32"),
"Should keep int* pointer subtraction param as raw pointer\nGenerated:\n{}",
result
);
}
/// Test that char* pointer arithmetic triggers DECY-134 slice transform.
///
/// DECY-134: char* with pointer arithmetic is transformed to slice + index
/// for safe string iteration (preferred over raw pointers).
///
/// C: void f(char *p) { p = p + 1; }
/// Expected: fn f(p: &[u8]) with p_idx indexing
#[test]
fn test_char_ptr_arithmetic_becomes_slice() {
let c_code = r#"
void test(char *p) {
p = p + 1;
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
// DECY-134: char* with arithmetic → slice (safer than raw pointer)
assert!(
result.contains("&[u8]") || result.contains("_idx"),
"char* with pointer arithmetic should use DECY-134 slice pattern\nGenerated:\n{}",
result
);
}
/// Test that simple dereference without arithmetic becomes reference.
///
/// C: void f(char *p) { *p = 'x'; }
/// Expected: fn f(p: &mut u8)
#[test]
fn test_no_arithmetic_becomes_reference() {
let c_code = r#"
void test(char *p) {
*p = 'x';
}
"#;
let result = transpile(c_code).expect("Transpilation should succeed");
println!("Generated Rust code:\n{}", result);
// Should convert to reference (no pointer arithmetic), possibly with lifetime
assert!(
result.contains("&mut u8") || result.contains("&'a mut u8"),
"Should convert to reference when no pointer arithmetic\nGenerated:\n{}",
result
);
}