use decy_core::transpile;
use std::process::Command;
fn compile_rust_code(code: &str) -> Result<(), String> {
let dir = tempfile::tempdir().map_err(|e| e.to_string())?;
let rs_path = dir.path().join("test_output.rs");
let rlib_path = dir.path().join("test_output.rlib");
std::fs::write(&rs_path, code).map_err(|e| e.to_string())?;
let output = Command::new("rustc")
.args([
"--edition",
"2021",
"--crate-type=lib",
"-o",
rlib_path.to_str().unwrap(),
rs_path.to_str().unwrap(),
])
.output()
.map_err(|e| format!("Failed to run rustc: {}", e))?;
if output.status.success() {
Ok(())
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
let errors: Vec<&str> = stderr
.lines()
.filter(|l| l.starts_with("error"))
.collect();
if errors.is_empty() {
Ok(()) } else {
Err(errors.join("\n"))
}
}
}
fn strip_noise(code: &str) -> String {
let lines: Vec<&str> = code.lines().collect();
let mut result = Vec::new();
let mut skip_next_brace = false;
for line in &lines {
if line.contains("ℹ Note:") || line.contains("rustc --crate-type") {
continue;
}
if line.starts_with("fn __") {
skip_next_brace = true;
continue;
}
if skip_next_brace && line.trim() == "}" {
skip_next_brace = false;
continue;
}
skip_next_brace = false;
if line.starts_with("static mut ERRNO") {
continue;
}
result.push(*line);
}
result.join("\n")
}
#[test]
fn test_cpp_class_compiles_with_rustc() {
let cpp_code = r#"
extern "C" { void __mode(); }
class Counter {
public:
int count;
Counter(int initial) : count(initial) {}
int get() { return count; }
void increment() { count = count + 1; }
~Counter() {}
};
"#;
let rust_code = transpile(cpp_code).expect("Transpilation failed");
let clean = strip_noise(&rust_code);
let result = compile_rust_code(&clean);
assert!(result.is_ok(), "Transpiled class should compile:\n{}\nErrors: {:?}", clean, result.err());
}
#[test]
fn test_cpp_namespace_compiles_with_rustc() {
let cpp_code = r#"
extern "C" { void __mode(); }
namespace math {
int square(int x) { return x * x; }
struct Point { int x; int y; };
}
"#;
let rust_code = transpile(cpp_code).expect("Transpilation failed");
let clean = strip_noise(&rust_code);
let result = compile_rust_code(&clean);
assert!(result.is_ok(), "Transpiled namespace should compile:\n{}\nErrors: {:?}", clean, result.err());
}
#[test]
fn test_cpp_operator_overload_compiles_with_rustc() {
let cpp_code = r#"
extern "C" { void __mode(); }
class Vec2 {
public:
int x;
int y;
Vec2(int a, int b) : x(a), y(b) {}
Vec2 operator+(Vec2 other) { Vec2 r(0,0); return r; }
bool operator==(Vec2 other) { return x == other.x; }
};
"#;
let rust_code = transpile(cpp_code).expect("Transpilation failed");
let clean = strip_noise(&rust_code);
let result = compile_rust_code(&clean);
assert!(result.is_ok(), "Transpiled operators should compile:\n{}\nErrors: {:?}", clean, result.err());
}
#[test]
fn test_cpp_inheritance_compiles_with_rustc() {
let cpp_code = r#"
extern "C" { void __mode(); }
class Shape {
public:
int color;
int get_color() { return color; }
};
class Circle : public Shape {
public:
int radius;
int area() { return 3 * radius * radius; }
};
"#;
let rust_code = transpile(cpp_code).expect("Transpilation failed");
let clean = strip_noise(&rust_code);
let result = compile_rust_code(&clean);
assert!(result.is_ok(), "Transpiled inheritance should compile:\n{}\nErrors: {:?}", clean, result.err());
}
#[test]
fn test_cpp_full_program_compiles_with_rustc() {
let cpp_code = r#"
extern "C" { void __mode(); }
class StringBuilder {
public:
int pos;
StringBuilder() : pos(0) {}
void append(int c) {
pos = pos + 1;
}
int size() { return pos; }
};
namespace collections {
class Stack {
public:
int top;
Stack() : top(0) {}
void push(int val) {
top = top + 1;
}
int pop() {
if (top > 0) {
top = top - 1;
return top;
}
return -1;
}
bool is_empty() { return top == 0; }
};
}
"#;
let rust_code = transpile(cpp_code).expect("Transpilation failed");
let clean = strip_noise(&rust_code);
let result = compile_rust_code(&clean);
assert!(
result.is_ok(),
"Full C++ program should compile:\n{}\nErrors: {:?}",
clean,
result.err()
);
}
#[test]
#[ignore = "Known limitation: new returns Box<T> but var type is *mut T — needs ownership inference upgrade"]
fn test_cpp_new_delete_compiles_with_rustc() {
let cpp_code = r#"
extern "C" { void __m(); }
class Resource {
public:
int handle;
Resource(int h) : handle(h) {}
int get() { return handle; }
~Resource() {}
};
void use_resource() {
Resource* r = new Resource(42);
delete r;
}
"#;
let rust_code = transpile(cpp_code).expect("Transpilation failed");
let clean = strip_noise(&rust_code);
let result = compile_rust_code(&clean);
assert!(
result.is_ok(),
"new/delete transpilation should compile:\n{}\nErrors: {:?}",
clean,
result.err()
);
}