use cala_cel_interpreter::{CelContext, CelExpression, CelValue};
const SMALL_CALLER_STACK: usize = 128 * 1024;
fn on_small_stack<T: Send + 'static>(f: impl FnOnce() -> T + Send + 'static) -> T {
std::thread::Builder::new()
.stack_size(SMALL_CALLER_STACK)
.spawn(f)
.expect("spawn small-stack thread")
.join()
.expect("small-stack thread panicked")
}
#[test]
fn compiles_realistic_velocity_expression_on_small_caller_stack() {
on_small_stack(|| {
CelExpression::try_from(
"context.vars.entry.units > decimal('100') && context.vars.entry.currency == 'USD'",
)
.expect("realistic velocity expression must compile");
});
}
#[test]
fn compiles_and_evaluates_deeply_nested_expression_on_small_caller_stack() {
on_small_stack(|| {
let source = format!("{}1{}", "(".repeat(64), ")".repeat(64));
let expression = CelExpression::try_from(source).expect("depth-64 nesting must compile");
let context = CelContext::new();
assert_eq!(
expression.evaluate(&context).expect("evaluate"),
CelValue::Int(1)
);
});
}
#[test]
fn nesting_beyond_recursion_cap_errors_without_crashing() {
on_small_stack(|| {
let source = format!("{}1{}", "(".repeat(200), ")".repeat(200));
assert!(CelExpression::try_from(source).is_err());
});
}