1 use wasmtime::Result;
2 use wasmtime::{Instance, Linker, Module};
3 use wasmtime_wizer::Wizer;
4 use wat::parse_str as wat_to_wasm;
5 
6 const PRELOAD1: &'static str = r#"
7 (module
8  (func (export "f") (param i32) (result i32)
9   local.get 0
10   i32.const 1
11   i32.add))
12   "#;
13 
14 const PRELOAD2: &'static str = r#"
15 (module
16  (func (export "f") (param i32) (result i32)
17   local.get 0
18   i32.const 2
19   i32.add))
20   "#;
21 
run_with_preloads(args: &[wasmtime::Val], wat: &str) -> Result<wasmtime::Val>22 async fn run_with_preloads(args: &[wasmtime::Val], wat: &str) -> Result<wasmtime::Val> {
23     let wasm = wat_to_wasm(wat)?;
24     let engine = wasmtime::Engine::default();
25     let mut store = wasmtime::Store::new(&engine, ());
26     let mod1 = Module::new(store.engine(), PRELOAD1)?;
27     let mod2 = Module::new(store.engine(), PRELOAD2)?;
28 
29     let processed = Wizer::new()
30         .run(&mut store, &wasm, async |store, module| {
31             let i1 = Instance::new_async(&mut *store, &mod1, &[]).await?;
32             let i2 = Instance::new_async(&mut *store, &mod2, &[]).await?;
33             let mut linker = Linker::new(store.engine());
34             linker.instance(&mut *store, "mod1", i1)?;
35             linker.instance(&mut *store, "mod2", i2)?;
36             linker.instantiate_async(store, module).await
37         })
38         .await?;
39 
40     let testmod = wasmtime::Module::new(&engine, &processed[..])?;
41 
42     let mod1_inst = wasmtime::Instance::new_async(&mut store, &mod1, &[]).await?;
43     let mod2_inst = wasmtime::Instance::new_async(&mut store, &mod2, &[]).await?;
44     let mut linker = wasmtime::Linker::new(&engine);
45     linker.instance(&mut store, "mod1", mod1_inst)?;
46     linker.instance(&mut store, "mod2", mod2_inst)?;
47 
48     let inst = linker.instantiate_async(&mut store, &testmod).await?;
49     let run = inst
50         .get_func(&mut store, "run")
51         .ok_or_else(|| wasmtime::format_err!("no `run` function on test module"))?;
52     let mut returned = vec![wasmtime::Val::I32(0)];
53     run.call_async(&mut store, args, &mut returned).await?;
54     Ok(returned[0])
55 }
56 
57 #[tokio::test]
test_preloads()58 async fn test_preloads() {
59     const WAT: &'static str = r#"
60     (module
61      (import "mod1" "f" (func $mod1f (param i32) (result i32)))
62      (import "mod2" "f" (func $mod2f (param i32) (result i32)))
63      (global $g1 (mut i32) (i32.const 0))
64      (global $g2 (mut i32) (i32.const 0))
65      (func (export "wizer-initialize")
66       i32.const 100
67       call $mod1f
68       global.set $g1
69       i32.const 100
70       call $mod2f
71       global.set $g2)
72      (func (export "run") (param i32 i32) (result i32)
73       local.get 0
74       call $mod1f
75       local.get 1
76       call $mod2f
77       i32.add
78       global.get $g1
79       global.get $g2
80       i32.add
81       i32.add))
82     "#;
83 
84     let result = run_with_preloads(&[wasmtime::Val::I32(200), wasmtime::Val::I32(201)], WAT)
85         .await
86         .unwrap();
87     assert!(matches!(result, wasmtime::Val::I32(607)));
88 }
89