()
| 413 | |
| 414 | #[test] |
| 415 | fn trapping() -> Result<(), Error> { |
| 416 | const TRAP_IN_F: i32 = 0; |
| 417 | const TRAP_NEXT_CALL_HOST: i32 = 1; |
| 418 | const TRAP_NEXT_RETURN_HOST: i32 = 2; |
| 419 | const TRAP_NEXT_CALL_WASM: i32 = 3; |
| 420 | const TRAP_NEXT_RETURN_WASM: i32 = 4; |
| 421 | |
| 422 | let engine = Engine::default(); |
| 423 | |
| 424 | let mut linker = Linker::new(&engine); |
| 425 | |
| 426 | linker.func_wrap( |
| 427 | "host", |
| 428 | "f", |
| 429 | |mut caller: Caller<State>, action: i32, recur: i32| -> Result<()> { |
| 430 | assert_eq!(caller.data().context.last(), Some(&Context::Host)); |
| 431 | assert_eq!(caller.data().calls_into_host, caller.data().calls_into_wasm); |
| 432 | |
| 433 | match action { |
| 434 | TRAP_IN_F => bail!("trapping in f"), |
| 435 | TRAP_NEXT_CALL_HOST => caller.data_mut().trap_next_call_host = true, |
| 436 | TRAP_NEXT_RETURN_HOST => caller.data_mut().trap_next_return_host = true, |
| 437 | TRAP_NEXT_CALL_WASM => caller.data_mut().trap_next_call_wasm = true, |
| 438 | TRAP_NEXT_RETURN_WASM => caller.data_mut().trap_next_return_wasm = true, |
| 439 | _ => {} // Do nothing |
| 440 | } |
| 441 | |
| 442 | // recur so that we can trigger a next call. |
| 443 | // propagate its trap, if it traps! |
| 444 | if recur > 0 { |
| 445 | let _ = caller |
| 446 | .get_export("export") |
| 447 | .expect("caller exports \"export\"") |
| 448 | .into_func() |
| 449 | .expect("export is a func") |
| 450 | .typed::<(i32, i32), ()>(&caller) |
| 451 | .expect("export typing") |
| 452 | .call(&mut caller, (action, 0))?; |
| 453 | } |
| 454 | |
| 455 | Ok(()) |
| 456 | }, |
| 457 | )?; |
| 458 | |
| 459 | let wat = r#" |
| 460 | (module |
| 461 | (import "host" "f" |
| 462 | (func $f (param i32) (param i32))) |
| 463 | (func (export "export") (param i32) (param i32) |
| 464 | (call $f (local.get 0) (local.get 1))) |
| 465 | ) |
| 466 | "#; |
| 467 | let module = Module::new(&engine, wat)?; |
| 468 | |
| 469 | let run = |action: i32, recur: bool| -> (State, Option<Error>) { |
| 470 | let mut store = Store::new(&engine, State::default()); |
| 471 | store.call_hook(sync_call_hook); |
| 472 | let inst = linker |
nothing calls this directly
no test coverage detected