()
| 62 | /* Runs every vm.json case under `Limits::sandbox()` rather than `none()`: the budget / heap / call-depth guards are off under `none` (`sandbox_off` short-circuits them), so only the bounded profile exercises the charge_step / charge_steps / back-edge-budget paths and lets cases assert that runaway allocation, recursion, and materialisation surface as `MemoryError` / `RecursionError` instead of hanging. Every case must therefore stay within the sandbox budget. */ |
| 63 | #[test] |
| 64 | fn test_cases() { |
| 65 | let cases: Vec<Case> = serde_json::from_str(include_str!("cases/vm.json")).expect("invalid JSON"); |
| 66 | |
| 67 | let mut failures: Vec<String> = Vec::new(); |
| 68 | for case in cases { |
| 69 | let (tokens, lex_errs) = lex(&case.src); |
| 70 | // Skip cases whose expected error is already raised by the lexer. |
| 71 | if !lex_errs.is_empty() |
| 72 | && let Some(expected) = &case.error |
| 73 | && lex_errs.iter().any(|e| e.msg.contains(expected.as_str())) |
| 74 | { |
| 75 | continue; |
| 76 | } |
| 77 | let (mut chunk, _errors) = Parser::new(&case.src, tokens.into_iter()).parse(); |
| 78 | // Run the same fold pass production does (exports.rs), so fold-path bugs surface here. |
| 79 | compiler::modules::vm::optimizer::constant_fold(&mut chunk); |
| 80 | let mut vm = VM::with_limits(&chunk, Limits::sandbox()); |
| 81 | vm.input_buffer = case.input.clone(); |
| 82 | for evt in &case.events { vm.push_event(evt).expect("push_event"); } |
| 83 | let result = drive(&mut vm, &case.interactive_events); |
| 84 | |
| 85 | // Collect every mismatch (not panic-on-first) so one run lists all regressions. |
| 86 | match result { |
| 87 | Ok(_obj) => { |
| 88 | if normalize(&vm.output) != normalize(&case.output) { |
| 89 | failures.push(format!("OUTPUT {:?}\n got {:?}\n want {:?}", case.src, vm.output, case.output)); |
| 90 | } |
| 91 | } |
| 92 | Err(e) => match &case.error { |
| 93 | Some(expected) => if !e.to_string().contains(expected.as_str()) { |
| 94 | failures.push(format!("ERR {:?}\n got '{}'\n want '{}'", case.src, e, expected)); |
| 95 | }, |
| 96 | None => failures.push(format!("RAISED {:?}: {}", case.src, e)), |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | if !failures.is_empty() { |
| 101 | let shown = failures.len().min(80); |
| 102 | panic!("{} case(s) failed:\n{}", failures.len(), failures[..shown].join("\n")); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | /* Reruns every vm.json case in strict_input mode (host-supplied buffer; reading past = RuntimeError) under `Limits::sandbox()` (see `test_cases` for why the bounded profile). Lex/parse errors are also asserted here. */ |
| 107 | #[test] |
nothing calls this directly
no test coverage detected