use uni_cypher::{parse, parse_expression};
fn parse_on_small_stack(input: String) -> Result<(), String> {
std::thread::Builder::new()
.stack_size(1024 * 1024)
.spawn(move || parse(&input).map(|_| ()).map_err(|e| e.to_string()))
.expect("spawn parse thread")
.join()
.expect("parse thread must not abort the process (stack overflow)")
}
#[test]
fn deeply_nested_parens_error_not_overflow() {
let depth = 5000;
let input = format!("RETURN {}1{}", "(".repeat(depth), ")".repeat(depth));
let res = parse_on_small_stack(input);
assert!(
res.is_err(),
"deeply nested parens must be rejected, not parsed"
);
}
#[test]
fn deeply_nested_lists_error_not_overflow() {
let depth = 5000;
let input = format!("RETURN {}1{}", "[".repeat(depth), "]".repeat(depth));
let res = parse_on_small_stack(input);
assert!(res.is_err(), "deeply nested lists must be rejected");
}
#[test]
fn deeply_nested_maps_error_not_overflow() {
let depth = 3000;
let input = format!("RETURN {}1{}", "{a:".repeat(depth), "}".repeat(depth));
let res = parse_on_small_stack(input);
assert!(res.is_err(), "deeply nested maps must be rejected");
}
#[test]
fn deeply_nested_case_error_not_overflow() {
let depth = 2000;
let input = format!(
"RETURN {}1{}",
"CASE WHEN true THEN ".repeat(depth),
" ELSE 0 END".repeat(depth)
);
let res = parse_on_small_stack(input);
assert!(res.is_err(), "deeply nested CASE must be rejected");
}
#[test]
fn deeply_nested_parenthesized_pattern_error_not_overflow() {
let depth = 3000;
let input = format!(
"MATCH {}(n){} RETURN n",
"(".repeat(depth),
")".repeat(depth)
);
let res = parse_on_small_stack(input);
assert!(
res.is_err(),
"deeply nested parenthesized patterns must be rejected"
);
}
#[test]
fn moderately_nested_expression_still_parses() {
let input = format!("RETURN {}1{}", "(".repeat(16), ")".repeat(16));
assert!(
parse(&input).is_ok(),
"moderate paren nesting must still parse"
);
let nested_list = format!("{}1{}", "[".repeat(8), "]".repeat(8));
assert!(
parse_expression(&nested_list).is_ok(),
"moderate list nesting must still parse"
);
assert!(
parse("RETURN CASE WHEN abs(a.x + (b.y * 2)) > 3 THEN [1, [2, 3]] ELSE {k: 1} END").is_ok(),
"realistic nested expression must still parse"
);
}