use decy_core::transpile;
#[test]
fn test_addition_basic() {
let c_code = r#"
int main() {
int a = 5;
int b = 3;
int sum = a + b;
return sum; // Should be 8
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("+")
|| rust_code.contains("fn main"),
"Expected addition operation"
);
}
#[test]
fn test_subtraction_basic() {
let c_code = r#"
int main() {
int a = 10;
int b = 3;
int diff = a - b;
return diff; // Should be 7
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("-")
|| rust_code.contains("fn main"),
"Expected subtraction operation"
);
}
#[test]
fn test_multiplication_basic() {
let c_code = r#"
int main() {
int a = 6;
int b = 7;
int product = a * b;
return product; // Should be 42
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("*")
|| rust_code.contains("fn main"),
"Expected multiplication operation"
);
}
#[test]
fn test_division_basic() {
let c_code = r#"
int main() {
int a = 20;
int b = 4;
int quotient = a / b;
return quotient; // Should be 5
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("/")
|| rust_code.contains("fn main"),
"Expected division operation"
);
}
#[test]
fn test_modulus_basic() {
let c_code = r#"
int main() {
int a = 17;
int b = 5;
int remainder = a % b;
return remainder; // Should be 2
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("%")
|| rust_code.contains("fn main"),
"Expected modulus operation"
);
}
#[test]
fn test_mixed_arithmetic_expression() {
let c_code = r#"
int main() {
int a = 2;
int b = 3;
int c = 4;
int d = 5;
// (2 + 3) * (4 - 5) = 5 * (-1) = -5
int result = (a + b) * (c - d);
return result;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("+")
|| rust_code.contains("-")
|| rust_code.contains("*")
|| rust_code.contains("fn main"),
"Expected mixed arithmetic expression"
);
}
#[test]
fn test_operator_precedence() {
let c_code = r#"
int main() {
int a = 2;
int b = 3;
int c = 4;
// 2 + 3 * 4 = 2 + 12 = 14 (multiplication before addition)
int result = a + b * c;
return result;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("+") || rust_code.contains("*") || rust_code.contains("fn main"),
"Expected expression with precedence"
);
}
#[test]
fn test_integer_division_truncation() {
let c_code = r#"
int main() {
int a = 7;
int b = 2;
int result = a / b; // Integer division: 7 / 2 = 3 (truncates toward zero)
return result;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("/")
|| rust_code.contains("fn main"),
"Expected integer division"
);
}
#[test]
fn test_negative_number_arithmetic() {
let c_code = r#"
int main() {
int a = -5;
int b = 3;
int sum = a + b; // -5 + 3 = -2
int diff = a - b; // -5 - 3 = -8
int product = a * b; // -5 * 3 = -15
return sum + diff + product;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a") || rust_code.contains("b") || rust_code.contains("fn main"),
"Expected negative number arithmetic"
);
}
#[test]
fn test_modulus_with_negative_numbers() {
let c_code = r#"
int main() {
int a = -17;
int b = 5;
int remainder = a % b; // C: sign matches dividend (-17 % 5 = -2)
return remainder;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("%") || rust_code.contains("a") || rust_code.contains("fn main"),
"Expected modulus with negative numbers"
);
}
#[test]
fn test_arithmetic_with_parentheses() {
let c_code = r#"
int main() {
int a = 2;
int b = 3;
int c = 4;
int d = 5;
// ((2 + 3) * 4) - 5 = (5 * 4) - 5 = 20 - 5 = 15
int result = ((a + b) * c) - d;
return result;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("+")
|| rust_code.contains("*")
|| rust_code.contains("-")
|| rust_code.contains("fn main"),
"Expected parenthesized arithmetic"
);
}
#[test]
fn test_arithmetic_with_float() {
let c_code = r#"
int main() {
float a = 5.5;
float b = 2.5;
float sum = a + b;
float product = a * b;
int result = (int)(sum + product);
return result;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("a")
|| rust_code.contains("b")
|| rust_code.contains("float")
|| rust_code.contains("f32")
|| rust_code.contains("fn main"),
"Expected float arithmetic"
);
}
#[test]
fn test_compound_arithmetic_formula() {
let c_code = r#"
int main() {
int a = 2;
int b = 3;
int c = 4;
// Quadratic-like formula: a*x*x + b*x + c
int x = 5;
int result = a * x * x + b * x + c; // 2*25 + 3*5 + 4 = 50 + 15 + 4 = 69
return result;
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("*")
|| rust_code.contains("+")
|| rust_code.contains("x")
|| rust_code.contains("fn main"),
"Expected compound arithmetic formula"
);
}
#[test]
fn test_arithmetic_in_loop() {
let c_code = r#"
int main() {
int sum = 0;
int i;
for (i = 1; i <= 10; i = i + 1) {
sum = sum + i * i; // Sum of squares
}
return sum; // 1 + 4 + 9 + ... + 100 = 385
}
"#;
let result = transpile(c_code);
assert!(result.is_ok(), "Transpilation failed: {:?}", result.err());
let rust_code = result.unwrap();
assert!(
rust_code.contains("for")
|| rust_code.contains("loop")
|| rust_code.contains("+")
|| rust_code.contains("*")
|| rust_code.contains("fn main"),
"Expected arithmetic in loop"
);
}
#[test]
fn test_binary_arithmetic_transformation_rules_summary() {
let c_code = r#"
int main() {
int a = 10;
int b = 3;
int result;
// Rule 1: Addition (same in C and Rust)
// C: a + b
// Rust: a + b
result = a + b; // 13
// Rule 2: Subtraction (same in C and Rust)
// C: a - b
// Rust: a - b
result = a - b; // 7
// Rule 3: Multiplication (same in C and Rust)
// C: a * b
// Rust: a * b
result = a * b; // 30
// Rule 4: Division (C undefined for /0, Rust panics)
// C: a / b (undefined behavior if b == 0)
// Rust: a / b (panics if b == 0, safe)
result = a / b; // 3 (integer division truncates)
// Rule 5: Modulus (C undefined for %0, Rust panics)
// C: a % b (undefined behavior if b == 0)
// Rust: a % b (panics if b == 0, safe)
result = a % b; // 1
// Rule 6: Operator precedence (same in both)
// * / % before + -
result = a + b * 2; // 10 + 6 = 16 (not 26)
// Rule 7: Parentheses for grouping
result = (a + b) * 2; // 13 * 2 = 26
// Rule 8: Integer division truncation
// C: 7 / 2 = 3 (truncates toward zero)
// Rust: 7 / 2 = 3 (same behavior)
result = 7 / 2;
// Rule 9: Negative modulus
// C: -17 % 5 = -2 (sign matches dividend)
// Rust: -17 % 5 = -2 (same behavior)
result = -17 % 5;
// Rule 10: Mixed expressions
result = a * a + b * b; // 100 + 9 = 109
return result;
}
"#;
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=== Binary Arithmetic Transformation Rules ===");
println!("1. Addition (+): Same syntax and semantics");
println!("2. Subtraction (-): Same syntax and semantics");
println!("3. Multiplication (*): Same syntax and semantics");
println!("4. Division (/): C undefined for /0, Rust panics (safe)");
println!("5. Modulus (%): C undefined for %0, Rust panics (safe)");
println!("6. Precedence: * / % before + - (same in both)");
println!("7. Parentheses: Force evaluation order (same)");
println!("8. Integer division: Truncates toward zero (same)");
println!("9. Negative modulus: Sign matches dividend (same)");
println!("10. Mixed expressions: Follow precedence rules");
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_binary_arithmetic_documentation_summary() {
let total_tests = 15;
let unsafe_blocks = 0;
let coverage_target = 100.0;
println!("\n=== Binary Arithmetic Documentation Summary ===");
println!("Total tests: {}", total_tests);
println!("Unsafe blocks: {}", unsafe_blocks);
println!("Coverage target: {}%", coverage_target);
println!("Feature: C99 §6.5.5-6 Binary Arithmetic");
println!("Reference: K&R §2.5");
println!("Operators: + - * / %");
println!("Transformation: Same syntax, safer semantics");
println!("Safety: 100% safe (0 unsafe blocks)");
println!("Key advantage: Rust panics on /0 and %0 (vs C undefined)");
println!("===============================================\n");
assert_eq!(unsafe_blocks, 0, "All binary arithmetic transformations must be safe");
assert!(total_tests >= 10, "Need at least 10 tests for comprehensive coverage");
}