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