use decy_codegen::CodeGenerator;
use decy_hir::{HirExpression, HirFunction, HirStatement, HirType};
#[test]
fn test_string_literal_becomes_str_slice() {
let func = HirFunction::new_with_body(
"test_literal".to_string(),
HirType::Void,
vec![],
vec![HirStatement::VariableDeclaration {
name: "s".to_string(),
var_type: HirType::Pointer(Box::new(HirType::Char)),
initializer: Some(HirExpression::StringLiteral("hello".to_string())),
}],
);
let codegen = CodeGenerator::new();
let code = codegen.generate_function(&func);
assert!(code.contains("\"hello\""), "Expected string literal in:\n{}", code);
assert!(
code.contains("&str") || !code.contains("*mut u8"),
"Expected &str type or no raw pointer in:\n{}",
code
);
}
#[test]
fn test_malloc_char_becomes_string() {
let func = HirFunction::new_with_body(
"test_heap_string".to_string(),
HirType::Void,
vec![],
vec![HirStatement::VariableDeclaration {
name: "buf".to_string(),
var_type: HirType::Pointer(Box::new(HirType::Char)),
initializer: Some(HirExpression::FunctionCall {
function: "malloc".to_string(),
arguments: vec![HirExpression::IntLiteral(100)],
}),
}],
);
let codegen = CodeGenerator::new();
let code = codegen.generate_function(&func);
assert!(
code.contains("Vec<u8>") || code.contains("String"),
"Expected Vec<u8> or String type in:\n{}",
code
);
}
#[test]
fn test_strlen_to_len_method() {
let func = HirFunction::new_with_body(
"test_strlen".to_string(),
HirType::Void,
vec![],
vec![HirStatement::VariableDeclaration {
name: "len".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::FunctionCall {
function: "strlen".to_string(),
arguments: vec![HirExpression::Variable("s".to_string())],
}),
}],
);
let codegen = CodeGenerator::new();
let code = codegen.generate_function(&func);
assert!(code.contains(".len()"), "Expected .len() method in:\n{}", code);
let body_only = code.split('{').nth(1).unwrap_or("");
assert!(!body_only.contains("strlen("), "Should not have strlen() call in body:\n{}", code);
}
#[test]
fn test_strcpy_to_safe_copy() {
let func = HirFunction::new_with_body(
"test_strcpy".to_string(),
HirType::Void,
vec![],
vec![HirStatement::Expression(HirExpression::FunctionCall {
function: "strcpy".to_string(),
arguments: vec![
HirExpression::Variable("dest".to_string()),
HirExpression::Variable("src".to_string()),
],
})],
);
let codegen = CodeGenerator::new();
let code = codegen.generate_function(&func);
assert!(
code.contains(".to_string()") || code.contains("clone") || code.contains("copy"),
"Expected safe string operation in:\n{}",
code
);
let body_only = code.split('{').nth(1).unwrap_or("");
assert!(!body_only.contains("strcpy("), "Should not have strcpy() call in body:\n{}", code);
}
#[test]
fn test_string_type_mapping() {
let str_ref = HirType::StringReference;
assert_eq!(CodeGenerator::map_type(&str_ref), "&str");
let owned_string = HirType::OwnedString;
assert_eq!(CodeGenerator::map_type(&owned_string), "String");
let string_lit = HirType::StringLiteral;
assert_eq!(CodeGenerator::map_type(&string_lit), "&str");
}
#[test]
fn test_char_ptr_param_becomes_str_ref() {
let func = HirFunction::new(
"print_msg".to_string(),
HirType::Void,
vec![decy_hir::HirParameter::new(
"msg".to_string(),
HirType::Pointer(Box::new(HirType::Char)),
)],
);
let codegen = CodeGenerator::new();
let sig = codegen.generate_signature(&func);
assert!(
sig.contains("&") || sig.contains("*mut"),
"Expected reference or pointer in signature:\n{}",
sig
);
}
#[test]
fn test_const_char_ptr_to_str_slice() {
let func = HirFunction::new_with_body(
"test_const".to_string(),
HirType::Void,
vec![],
vec![HirStatement::VariableDeclaration {
name: "greeting".to_string(),
var_type: HirType::StringLiteral,
initializer: Some(HirExpression::StringLiteral("Hello".to_string())),
}],
);
let codegen = CodeGenerator::new();
let code = codegen.generate_function(&func);
assert!(code.contains("&str"), "Expected &str type in:\n{}", code);
}