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