test: guard joinir strict env usage

This commit is contained in:
2025-12-30 07:42:52 +09:00
parent bb84612ac4
commit c87bdad59d
4 changed files with 89 additions and 55 deletions

View File

@ -199,6 +199,7 @@ fn is_var_named(node: &ASTNode, name: &str) -> bool {
mod tests {
use super::*;
use crate::ast::{BinaryOperator, Span};
use crate::tests::helpers::joinir_env::with_joinir_env_lock;
fn var(name: &str) -> ASTNode {
ASTNode::Variable {
@ -306,51 +307,53 @@ mod tests {
#[test]
fn strict_rejects_when_local_init_missing() {
// escape pattern exists, but `local ch = ...` is absent -> strict should reject
let body = vec![
ASTNode::If {
condition: Box::new(binop(BinaryOperator::Equal, var("ch"), str_lit("\""))),
then_body: vec![ASTNode::Break { span: Span::unknown() }],
else_body: None,
span: Span::unknown(),
},
ASTNode::If {
condition: Box::new(binop(BinaryOperator::Equal, var("ch"), str_lit("\\"))),
then_body: vec![
assignment(var("i"), binop(BinaryOperator::Add, var("i"), int_lit(1))),
assignment(
var("ch"),
method_call(
"s",
"substring",
vec![var("i"), binop(BinaryOperator::Add, var("i"), int_lit(1))],
with_joinir_env_lock(|| {
// escape pattern exists, but `local ch = ...` is absent -> strict should reject
let body = vec![
ASTNode::If {
condition: Box::new(binop(BinaryOperator::Equal, var("ch"), str_lit("\""))),
then_body: vec![ASTNode::Break { span: Span::unknown() }],
else_body: None,
span: Span::unknown(),
},
ASTNode::If {
condition: Box::new(binop(BinaryOperator::Equal, var("ch"), str_lit("\\"))),
then_body: vec![
assignment(var("i"), binop(BinaryOperator::Add, var("i"), int_lit(1))),
assignment(
var("ch"),
method_call(
"s",
"substring",
vec![var("i"), binop(BinaryOperator::Add, var("i"), int_lit(1))],
),
),
),
],
else_body: None,
span: Span::unknown(),
},
assignment(var("i"), binop(BinaryOperator::Add, var("i"), int_lit(1))),
];
],
else_body: None,
span: Span::unknown(),
},
assignment(var("i"), binop(BinaryOperator::Add, var("i"), int_lit(1))),
];
let prev = std::env::var("HAKO_JOINIR_STRICT").ok();
std::env::set_var("HAKO_JOINIR_STRICT", "1");
let decision = classify_p5b_escape_derived(&body, "i");
if let Some(v) = prev {
std::env::set_var("HAKO_JOINIR_STRICT", v);
} else {
std::env::remove_var("HAKO_JOINIR_STRICT");
}
match decision {
P5bEscapeDerivedDecision::Reject(reason) => {
assert!(
reason.contains("missing_local_init"),
"unexpected reason: {}",
reason
);
let prev = std::env::var("HAKO_JOINIR_STRICT").ok();
std::env::set_var("HAKO_JOINIR_STRICT", "1");
let decision = classify_p5b_escape_derived(&body, "i");
if let Some(v) = prev {
std::env::set_var("HAKO_JOINIR_STRICT", v);
} else {
std::env::remove_var("HAKO_JOINIR_STRICT");
}
other => panic!("expected Reject, got {:?}", other),
}
match decision {
P5bEscapeDerivedDecision::Reject(reason) => {
assert!(
reason.contains("missing_local_init"),
"unexpected reason: {}",
reason
);
}
other => panic!("expected Reject, got {:?}", other),
}
});
}
}