use decy_core::transpile;
use proptest::prelude::*;
fn array_size_strategy() -> impl Strategy<Value = usize> {
1usize..=100
}
proptest! {
#[test]
fn prop_pointer_increment_transpiles(
array_size in array_size_strategy()
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = array;
for (int i = 0; i < {}; i++) {{
*ptr = i;
ptr++;
}}
return 0;
}}
"#,
array_size, array_size
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Pointer increment should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_pointer_addition_transpiles(
size in 10usize..=50,
offset in 0usize..=9
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = array;
int value = *(ptr + {});
return value;
}}
"#,
size, offset
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Pointer addition should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_array_traversal_transpiles(
size in array_size_strategy()
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = array;
int sum = 0;
for (int i = 0; i < {}; i++) {{
sum += *ptr;
ptr++;
}}
return sum;
}}
"#,
size, size
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Array traversal should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_pointer_indexing_transpiles(
size in 10usize..=50,
index in 0usize..=9
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = array;
int value = ptr[{}];
return value;
}}
"#,
size, index
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Pointer indexing should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_unsafe_density_below_target(
size in 10usize..=30
) {
let c_code = format!(
r#"
int main() {{
int data[{}];
int* ptr = data;
for (int i = 0; i < {}; i++) {{
*ptr = i;
ptr++;
}}
return 0;
}}
"#,
size, size
);
let result = transpile(&c_code).expect("Should transpile");
let unsafe_count = result.matches("unsafe").count();
let lines = result.lines().count();
let unsafe_per_1000 = if lines > 0 {
(unsafe_count as f64 / lines as f64) * 1000.0
} else {
0.0
};
prop_assert!(
unsafe_per_1000 < 250.0,
"Unsafe per 1000 LOC should be <250, got {:.2}",
unsafe_per_1000
);
}
}
proptest! {
#[test]
fn prop_generated_code_balanced(
size in array_size_strategy()
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = array;
int value = *ptr;
return value;
}}
"#,
size
);
let result = transpile(&c_code).expect("Should transpile");
let open_braces = result.matches('{').count();
let close_braces = result.matches('}').count();
prop_assert_eq!(
open_braces, close_braces,
"Braces should be balanced: {} open, {} close",
open_braces, close_braces
);
}
}
proptest! {
#[test]
fn prop_transpilation_deterministic(
size in 1usize..=30
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = array;
*ptr = 42;
return *ptr;
}}
"#,
size
);
let result1 = transpile(&c_code).expect("Should transpile (1)");
let result2 = transpile(&c_code).expect("Should transpile (2)");
prop_assert_eq!(
result1, result2,
"Transpilation should be deterministic"
);
}
}
proptest! {
#[test]
fn prop_pointer_comparison_transpiles(
size in array_size_strategy()
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* start = array;
int* end = &array[{}];
int* current = start;
int count = 0;
while (current < end) {{
count++;
current++;
}}
return count;
}}
"#,
size, size
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Pointer comparison should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_pointer_difference_transpiles(
size in 20usize..=50,
offset1 in 0usize..=10,
offset2 in 11usize..=19
) {
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr1 = &array[{}];
int* ptr2 = &array[{}];
int distance = ptr2 - ptr1;
return distance;
}}
"#,
size, offset1, offset2
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Pointer difference should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_backwards_traversal_transpiles(
size in array_size_strategy()
) {
let last_index = if size > 0 { size - 1 } else { 0 };
let c_code = format!(
r#"
int main() {{
int array[{}];
int* ptr = &array[{}];
int sum = 0;
for (int i = 0; i < {}; i++) {{
sum += *ptr;
ptr--;
}}
return sum;
}}
"#,
size, last_index, size
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "Backwards traversal should transpile: {:?}", result.err());
}
}