1 use anyhow::{bail, Result};
2 use std::fs;
3 use wasmtime::*;
4 
5 fn serialize(engine: &Engine, wat: &str) -> Result<Vec<u8>> {
6     let module = Module::new(&engine, wat)?;
7     Ok(module.serialize()?)
8 }
9 
10 unsafe fn deserialize_and_instantiate(store: &mut Store<()>, buffer: &[u8]) -> Result<Instance> {
11     let module = Module::deserialize(store.engine(), buffer)?;
12     Ok(Instance::new(store, &module, &[])?)
13 }
14 
15 #[test]
16 fn test_version_mismatch() -> Result<()> {
17     let engine = Engine::default();
18     let buffer = serialize(&engine, "(module)")?;
19 
20     let mut config = Config::new();
21     config
22         .module_version(ModuleVersionStrategy::Custom("custom!".to_owned()))
23         .unwrap();
24     let custom_version_engine = Engine::new(&config).unwrap();
25     match unsafe { Module::deserialize(&custom_version_engine, &buffer) } {
26         Ok(_) => bail!("expected deserialization to fail"),
27         Err(e) => assert!(e
28             .to_string()
29             .starts_with("Module was compiled with incompatible version")),
30     }
31 
32     let mut config = Config::new();
33     config.module_version(ModuleVersionStrategy::None).unwrap();
34     let none_version_engine = Engine::new(&config).unwrap();
35     unsafe { Module::deserialize(&none_version_engine, &buffer) }
36         .expect("accepts the wasmtime versioned module");
37 
38     let buffer = serialize(&custom_version_engine, "(module)")?;
39     unsafe { Module::deserialize(&none_version_engine, &buffer) }
40         .expect("accepts the custom versioned module");
41 
42     Ok(())
43 }
44 
45 #[test]
46 fn test_module_serialize_simple() -> Result<()> {
47     let buffer = serialize(
48         &Engine::default(),
49         "(module (func (export \"run\") (result i32) i32.const 42))",
50     )?;
51 
52     let mut store = Store::default();
53     let instance = unsafe { deserialize_and_instantiate(&mut store, &buffer)? };
54     let run = instance.get_typed_func::<(), i32, _>(&mut store, "run")?;
55     let result = run.call(&mut store, ())?;
56 
57     assert_eq!(42, result);
58     Ok(())
59 }
60 
61 #[test]
62 fn test_module_serialize_fail() -> Result<()> {
63     let buffer = serialize(
64         &Engine::default(),
65         "(module (func (export \"run\") (result i32) i32.const 42))",
66     )?;
67 
68     let mut config = Config::new();
69     config.static_memory_maximum_size(0);
70     let mut store = Store::new(&Engine::new(&config)?, ());
71     match unsafe { deserialize_and_instantiate(&mut store, &buffer) } {
72         Ok(_) => bail!("expected failure at deserialization"),
73         Err(_) => (),
74     }
75     Ok(())
76 }
77 
78 #[test]
79 fn test_deserialize_from_file() -> Result<()> {
80     serialize_and_call("(module (func (export \"run\") (result i32) i32.const 42))")?;
81     serialize_and_call(
82         "(module
83             (func (export \"run\") (result i32)
84                 call $answer)
85 
86             (func $answer (result i32)
87                 i32.const 42))
88         ",
89     )?;
90     return Ok(());
91 
92     fn serialize_and_call(wat: &str) -> Result<()> {
93         let mut store = Store::<()>::default();
94         let td = tempfile::TempDir::new()?;
95         let buffer = serialize(store.engine(), wat)?;
96 
97         let path = td.path().join("module.bin");
98         fs::write(&path, &buffer)?;
99         let module = unsafe { Module::deserialize_file(store.engine(), &path)? };
100         let instance = Instance::new(&mut store, &module, &[])?;
101         let func = instance.get_typed_func::<(), i32, _>(&mut store, "run")?;
102         assert_eq!(func.call(&mut store, ())?, 42);
103         Ok(())
104     }
105 }
106