use decy_core::transpile;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_printf_integer_transpiles(
value in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("Value: %d\n", {});
return 0;
}}
"#,
value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "printf with integer should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_printf_multiple_integers_transpiles(
a in -1000i32..=1000,
b in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("a=%d, b=%d, sum=%d\n", {}, {}, {});
return 0;
}}
"#,
a, b, a.wrapping_add(b)
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "printf with multiple integers should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_printf_float_transpiles(
value in -1000.0f64..=1000.0
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("Value: %f\n", {});
return 0;
}}
"#,
value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "printf with float should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_sprintf_transpiles(
buffer_size in 10usize..=200,
value in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
char buffer[{}];
sprintf(buffer, "Value: %d", {});
return 0;
}}
"#,
buffer_size, value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "sprintf should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_snprintf_transpiles(
buffer_size in 10usize..=200,
value in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
char buffer[{}];
snprintf(buffer, sizeof(buffer), "Value: %d", {});
return 0;
}}
"#,
buffer_size, value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "snprintf should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_printf_width_transpiles(
width in 1usize..=50,
value in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("%{}d\n", {});
return 0;
}}
"#,
width, value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "printf with width should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_printf_precision_transpiles(
precision in 0usize..=10,
value in -1000.0f64..=1000.0
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("%.{}f\n", {});
return 0;
}}
"#,
precision, value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "printf with precision should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_scanf_width_transpiles(
buffer_size in 5usize..=100
) {
let width = buffer_size - 1;
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
char buffer[{}];
scanf("%{}s", buffer);
return 0;
}}
"#,
buffer_size, width
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "scanf with width should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_printf_hex_transpiles(
value in 0u32..=0xFFFF
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("Hex: 0x%x\n", {});
return 0;
}}
"#,
value
);
let result = transpile(&c_code);
prop_assert!(result.is_ok(), "printf with hex should transpile: {:?}", result.err());
}
}
proptest! {
#[test]
fn prop_unsafe_density_below_target(
a in -1000i32..=1000,
b in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("Values: a=%d, b=%d\n", {}, {});
char buffer[50];
sprintf(buffer, "Sum: %d", {});
return 0;
}}
"#,
a, b, a.wrapping_add(b)
);
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 <= 30.0,
"Unsafe per 1000 LOC should be <=30, got {:.2}",
unsafe_per_1000
);
}
}
proptest! {
#[test]
fn prop_generated_code_balanced(
value in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("Value: %d\n", {});
return 0;
}}
"#,
value
);
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(
value in -1000i32..=1000
) {
let c_code = format!(
r#"
#include <stdio.h>
int main() {{
printf("Value: %d\n", {});
return 0;
}}
"#,
value
);
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"
);
}
}