use decy_codegen::CodeGenerator;
use decy_hir::{HirExpression, HirFunction, HirStatement, HirType};
fn create_function(name: &str, body: Vec<HirStatement>) -> HirFunction {
HirFunction::new_with_body(name.to_string(), HirType::Int, vec![], body)
}
#[test]
fn test_wexitstatus_generates_code() {
let func = create_function(
"get_exit_code",
vec![HirStatement::VariableDeclaration {
name: "code".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::FunctionCall {
function: "WEXITSTATUS".to_string(),
arguments: vec![HirExpression::Variable("status".to_string())],
}),
}],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
code.contains(".code()"),
"Should generate .code() for WEXITSTATUS:\n{}",
code
);
}
#[test]
fn test_wifexited_generates_success() {
let func = create_function(
"check_exited",
vec![HirStatement::If {
condition: HirExpression::FunctionCall {
function: "WIFEXITED".to_string(),
arguments: vec![HirExpression::Variable("status".to_string())],
},
then_block: vec![HirStatement::Return(Some(HirExpression::IntLiteral(0)))],
else_block: None,
}],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
code.contains(".success()"),
"Should generate .success() for WIFEXITED:\n{}",
code
);
}
#[test]
fn test_wifsignaled_generates_signal_check() {
let func = create_function(
"check_signaled",
vec![HirStatement::If {
condition: HirExpression::FunctionCall {
function: "WIFSIGNALED".to_string(),
arguments: vec![HirExpression::Variable("status".to_string())],
},
then_block: vec![HirStatement::Return(Some(HirExpression::IntLiteral(1)))],
else_block: None,
}],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
code.contains(".signal()"),
"Should generate .signal() for WIFSIGNALED:\n{}",
code
);
}
#[test]
fn test_wtermsig_generates_signal() {
let func = create_function(
"get_signal",
vec![HirStatement::VariableDeclaration {
name: "sig".to_string(),
var_type: HirType::Int,
initializer: Some(HirExpression::FunctionCall {
function: "WTERMSIG".to_string(),
arguments: vec![HirExpression::Variable("status".to_string())],
}),
}],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
code.contains(".signal()"),
"Should generate .signal() for WTERMSIG:\n{}",
code
);
}
#[test]
fn test_wait_generates_wait_call() {
let func = create_function(
"wait_for_child",
vec![HirStatement::Expression(HirExpression::FunctionCall {
function: "wait".to_string(),
arguments: vec![HirExpression::AddressOf(Box::new(HirExpression::Variable(
"status".to_string(),
)))],
})],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
code.contains(".wait()"),
"Should generate .wait() call:\n{}",
code
);
}
#[test]
fn test_no_wait_macros_no_status() {
let func = create_function(
"regular_func",
vec![HirStatement::Return(Some(HirExpression::IntLiteral(0)))],
);
let generator = CodeGenerator::new();
let code = generator.generate_function(&func);
assert!(
!code.contains(".code()") && !code.contains(".success()") && !code.contains(".signal()"),
"Should NOT generate status methods for non-wait code:\n{}",
code
);
}