()
| 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] |
| 108 | fn strict_cases() { |
| 109 | let cases: Vec<Case> = serde_json::from_str(include_str!("cases/vm.json")).expect("invalid JSON"); |
| 110 | |
| 111 | for case in cases { |
| 112 | let (tokens, lex_errs) = lex(&case.src); |
| 113 | // Lex errors are surfaced as diagnostics; match against the expected error and move on. |
| 114 | if !lex_errs.is_empty() { |
| 115 | if let Some(expected) = &case.error { |
| 116 | assert!( |
| 117 | lex_errs.iter().any(|e| e.msg.contains(expected.as_str())), |
| 118 | "wrong lex error on {:?}: got {:?}, expected '{}'", |
| 119 | case.src, |
| 120 | lex_errs.iter().map(|e| e.msg).collect::<Vec<_>>(), |
| 121 | expected |
| 122 | ); |
| 123 | continue; |
| 124 | } |
| 125 | panic!("lex error on {:?}: {:?}", case.src, lex_errs.iter().map(|e| e.msg).collect::<Vec<_>>()); |
| 126 | } |
| 127 | let (mut chunk, errs) = Parser::new(&case.src, tokens.into_iter()).parse(); |
| 128 | if !errs.is_empty() { |
| 129 | match &case.error { |
| 130 | Some(expected) => { |
| 131 | assert!( |
| 132 | errs.iter().any(|e| e.msg.contains(expected.as_str())), |
| 133 | "wrong parse error on {:?}: got {:?}, expected '{}'", |
| 134 | case.src, |
| 135 | errs.iter().map(|e| &e.msg).collect::<Vec<_>>(), |
| 136 | expected |
| 137 | ); |
| 138 | continue; |
| 139 | } |
| 140 | None => panic!("parse error on {:?}: {:?}", case.src, errs.iter().map(|e| &e.msg).collect::<Vec<_>>()), |
| 141 | } |
| 142 | } |
| 143 | // Match production: fold before running. |
| 144 | compiler::modules::vm::optimizer::constant_fold(&mut chunk); |
| 145 | |
| 146 | let mut vm = VM::with_limits(&chunk, Limits::sandbox()); |
| 147 | vm.strict_input = true; |
| 148 | vm.input_buffer = case.input.clone(); |
| 149 | for evt in &case.events { vm.push_event(evt).expect("push_event"); } |
| 150 | let expects_input_error = case.input.is_empty() && (case.src.contains("input(") || case.src.contains("input (")); |
| 151 | |
| 152 | match drive(&mut vm, &case.interactive_events) { |
| 153 | Ok(_) => { |
| 154 | assert!(!expects_input_error, "expected input() to error under strict mode for: {:?}", case.src); |
| 155 | assert_eq!(normalize(&vm.output), normalize(&case.output), "output mismatch on: {:?}", case.src); |
| 156 | } |
| 157 | Err(e) => match &case.error { |
| 158 | Some(expected) => assert!(e.to_string().contains(expected.as_str()), "wrong error on {:?}: got '{}', expected '{}'", case.src, e, expected), |
| 159 | None if expects_input_error => assert!( |
| 160 | e.to_string().contains("input"), |
| 161 | "expected input RuntimeError under strict mode for: {:?}, got: {}", |
| 162 | case.src, e |
| 163 | ), |
| 164 | None => panic!("VM error on {:?}: {}", case.src, e), |
| 165 | } |
nothing calls this directly
no test coverage detected