1 use wasmtime::{Result, error::Context as _, format_err};
2 use wasmtime_wasi::WasiCtxBuilder;
3 use wasmtime_wizer::Wizer;
4 use wat::parse_str as wat_to_wasm;
5 
run_wasm(args: &[wasmtime::Val], expected: i32, wasm: &[u8]) -> Result<()>6 async fn run_wasm(args: &[wasmtime::Val], expected: i32, wasm: &[u8]) -> Result<()> {
7     let _ = env_logger::try_init();
8 
9     let mut config = wasmtime::Config::new();
10     wasmtime::Cache::from_file(None)
11         .map(|cache| config.cache(Some(cache)))
12         .unwrap();
13     config.wasm_multi_memory(true);
14     config.wasm_multi_value(true);
15 
16     let engine = wasmtime::Engine::new(&config)?;
17     let wasi_ctx = WasiCtxBuilder::new().build_p1();
18     let mut store = wasmtime::Store::new(&engine, wasi_ctx);
19     let wasm = Wizer::new()
20         .run(&mut store, &wasm, async |store, module| {
21             let mut linker = wasmtime::Linker::new(module.engine());
22             linker.func_wrap("foo", "bar", |x: i32| x + 1)?;
23             linker.instantiate_async(store, module).await
24         })
25         .await?;
26     log::debug!(
27         "=== Wizened Wasm ==========================================================\n\
28        {}\n\
29        ===========================================================================",
30         wasmprinter::print_bytes(&wasm).unwrap()
31     );
32     if log::log_enabled!(log::Level::Debug) {
33         std::fs::write("test.wasm", &wasm).unwrap();
34     }
35 
36     let wasi_ctx = WasiCtxBuilder::new().build_p1();
37     let mut store = wasmtime::Store::new(&engine, wasi_ctx);
38     let module =
39         wasmtime::Module::new(store.engine(), wasm).context("Wasm test case failed to compile")?;
40 
41     let mut linker = wasmtime::Linker::new(&engine);
42     linker.func_wrap("foo", "bar", |_: i32| -> Result<i32> {
43         Err(format_err!("shouldn't be called"))
44     })?;
45 
46     let instance = linker.instantiate_async(&mut store, &module).await?;
47 
48     let run = instance.get_func(&mut store, "run").ok_or_else(|| {
49         wasmtime::format_err!("the test Wasm module does not export a `run` function")
50     })?;
51 
52     let mut actual = vec![wasmtime::Val::I32(0)];
53     run.call_async(&mut store, args, &mut actual).await?;
54     wasmtime::ensure!(actual.len() == 1, "expected one result");
55     let actual = match actual[0] {
56         wasmtime::Val::I32(x) => x,
57         _ => wasmtime::bail!("expected an i32 result"),
58     };
59     wasmtime::ensure!(
60         expected == actual,
61         "expected `{expected}`, found `{actual}`",
62     );
63 
64     Ok(())
65 }
66 
run_wat(args: &[wasmtime::Val], expected: i32, wat: &str) -> Result<()>67 async fn run_wat(args: &[wasmtime::Val], expected: i32, wat: &str) -> Result<()> {
68     let _ = env_logger::try_init();
69     let wasm = wat_to_wasm(wat)?;
70     run_wasm(args, expected, &wasm).await
71 }
72 
73 #[tokio::test]
custom_linker() -> Result<()>74 async fn custom_linker() -> Result<()> {
75     run_wat(
76         &[],
77         1,
78         r#"
79 (module
80   (type (func (param i32) (result i32)))
81   (import "foo" "bar" (func (type 0)))
82   (global $g (mut i32) (i32.const 0))
83   (func (export "wizer-initialize")
84     global.get $g
85     call 0
86     global.set $g
87   )
88   (func (export "run") (result i32)
89     (global.get $g)
90   )
91 )"#,
92     )
93     .await
94 }
95