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