1 use anyhow::bail;
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 #[cfg_attr(miri, ignore)]
47 fn test_module_serialize_simple() -> Result<()> {
48     let buffer = serialize(
49         &Engine::default(),
50         "(module (func (export \"run\") (result i32) i32.const 42))",
51     )?;
52 
53     let mut store = Store::default();
54     let instance = unsafe { deserialize_and_instantiate(&mut store, &buffer)? };
55     let run = instance.get_typed_func::<(), i32>(&mut store, "run")?;
56     let result = run.call(&mut store, ())?;
57 
58     assert_eq!(42, result);
59     Ok(())
60 }
61 
62 #[test]
63 #[cfg_attr(miri, ignore)]
64 fn test_module_serialize_fail() -> Result<()> {
65     let buffer = serialize(
66         &Engine::default(),
67         "(module (func (export \"run\") (result i32) i32.const 42))",
68     )?;
69 
70     let mut config = Config::new();
71     config.static_memory_maximum_size(0);
72     let mut store = Store::new(&Engine::new(&config)?, ());
73     match unsafe { deserialize_and_instantiate(&mut store, &buffer) } {
74         Ok(_) => bail!("expected failure at deserialization"),
75         Err(_) => (),
76     }
77     Ok(())
78 }
79 
80 #[test]
81 #[cfg_attr(miri, ignore)]
82 fn test_deserialize_from_file() -> Result<()> {
83     serialize_and_call("(module (func (export \"run\") (result i32) i32.const 42))")?;
84     serialize_and_call(
85         "(module
86             (func (export \"run\") (result i32)
87                 call $answer)
88 
89             (func $answer (result i32)
90                 i32.const 42))
91         ",
92     )?;
93     return Ok(());
94 
95     fn serialize_and_call(wat: &str) -> Result<()> {
96         let mut store = Store::<()>::default();
97         let td = tempfile::TempDir::new()?;
98         let buffer = serialize(store.engine(), wat)?;
99 
100         let path = td.path().join("module.bin");
101         fs::write(&path, &buffer)?;
102         let module = unsafe { Module::deserialize_file(store.engine(), &path)? };
103         let instance = Instance::new(&mut store, &module, &[])?;
104         let func = instance.get_typed_func::<(), i32>(&mut store, "run")?;
105         assert_eq!(func.call(&mut store, ())?, 42);
106         Ok(())
107     }
108 }
109 
110 #[test]
111 #[cfg_attr(miri, ignore)]
112 fn deserialize_from_serialized() -> Result<()> {
113     let engine = Engine::default();
114     let buffer1 = serialize(
115         &engine,
116         "(module (func (export \"run\") (result i32) i32.const 42))",
117     )?;
118     let buffer2 = unsafe { Module::deserialize(&engine, &buffer1)?.serialize()? };
119     assert!(buffer1 == buffer2);
120     Ok(())
121 }
122 
123 #[test]
124 #[cfg_attr(miri, ignore)]
125 fn detect_precompiled() -> Result<()> {
126     let engine = Engine::default();
127     let buffer = serialize(
128         &engine,
129         "(module (func (export \"run\") (result i32) i32.const 42))",
130     )?;
131     assert_eq!(engine.detect_precompiled(&[]), None);
132     assert_eq!(engine.detect_precompiled(&buffer[..5]), None);
133     assert_eq!(
134         engine.detect_precompiled(&buffer),
135         Some(Precompiled::Module)
136     );
137     Ok(())
138 }
139