(func_store: &FunctionStore, func: &Function, details: &Details)
| 77 | } |
| 78 | |
| 79 | fn run_test(func_store: &FunctionStore, func: &Function, details: &Details) -> anyhow::Result<()> { |
| 80 | for comment in details.comments.iter() { |
| 81 | if let Some(command) = parse_run_command(comment.text, &func.signature)? { |
| 82 | trace!("Parsed run command: {command}"); |
| 83 | |
| 84 | command |
| 85 | .run(|func_name, run_args| { |
| 86 | // Rebuild the interpreter state on every run to ensure that we don't accidentally depend on |
| 87 | // some leftover state |
| 88 | let state = InterpreterState::default() |
| 89 | .with_function_store(func_store.clone()) |
| 90 | .with_libcall_handler(|libcall: LibCall, args: LibCallValues| { |
| 91 | use LibCall::*; |
| 92 | Ok(smallvec![match (libcall, &args[..]) { |
| 93 | (CeilF32, [DataValue::F32(a)]) => DataValue::F32(a.ceil()), |
| 94 | (CeilF64, [DataValue::F64(a)]) => DataValue::F64(a.ceil()), |
| 95 | (FloorF32, [DataValue::F32(a)]) => DataValue::F32(a.floor()), |
| 96 | (FloorF64, [DataValue::F64(a)]) => DataValue::F64(a.floor()), |
| 97 | (TruncF32, [DataValue::F32(a)]) => DataValue::F32(a.trunc()), |
| 98 | (TruncF64, [DataValue::F64(a)]) => DataValue::F64(a.trunc()), |
| 99 | _ => unreachable!(), |
| 100 | }]) |
| 101 | }); |
| 102 | |
| 103 | let mut args = Vec::with_capacity(run_args.len()); |
| 104 | args.extend_from_slice(run_args); |
| 105 | |
| 106 | // Because we have stored function names with a leading %, we need to re-add it. |
| 107 | let func_name = &format!("%{func_name}"); |
| 108 | match Interpreter::new(state).call_by_name(func_name, &args) { |
| 109 | Ok(ControlFlow::Return(results)) => Ok(results.to_vec()), |
| 110 | Ok(e) => { |
| 111 | panic!("Unexpected returned control flow: {e:?}") |
| 112 | } |
| 113 | Err(t) => Err(format!("unexpected trap: {t:?}")), |
| 114 | } |
| 115 | }) |
| 116 | .map_err(|e| anyhow::anyhow!("{e}"))?; |
| 117 | } |
| 118 | } |
| 119 | Ok(()) |
| 120 | } |
no test coverage detected