1 use anyhow::Result; 2 use wasmtime::component::types::ComponentItem; 3 use wasmtime::component::{Component, Linker, Type}; 4 use wasmtime::{Engine, Module, Precompiled, Store}; 5 6 #[test] 7 fn module_component_mismatch() -> Result<()> { 8 let engine = super::engine(); 9 let module = Module::new(&engine, "(module)")?.serialize()?; 10 let component = Component::new(&engine, "(component)")?.serialize()?; 11 12 unsafe { 13 assert!(Module::deserialize(&engine, &component).is_err()); 14 assert!(Component::deserialize(&engine, &module).is_err()); 15 } 16 17 Ok(()) 18 } 19 20 #[test] 21 fn bare_bones() -> Result<()> { 22 let engine = super::engine(); 23 let component = Component::new(&engine, "(component)")?.serialize()?; 24 assert_eq!(component, engine.precompile_component(b"(component)")?); 25 26 let component = unsafe { Component::deserialize(&engine, &component)? }; 27 let mut store = Store::new(&engine, ()); 28 Linker::new(&engine).instantiate(&mut store, &component)?; 29 30 Ok(()) 31 } 32 33 #[test] 34 #[cfg_attr(miri, ignore)] 35 fn mildly_more_interesting() -> Result<()> { 36 let engine = super::engine(); 37 let component = Component::new( 38 &engine, 39 r#" 40 (component 41 (core module $a 42 (func (export "a") (result i32) 43 i32.const 100) 44 ) 45 (core instance $a (instantiate $a)) 46 47 (core module $b 48 (import "a" "a" (func $import (result i32))) 49 (func (export "a") (result i32) 50 call $import 51 i32.const 3 52 i32.add) 53 ) 54 (core instance $b (instantiate $b (with "a" (instance $a)))) 55 56 (func (export "a") (result u32) 57 (canon lift (core func $b "a")) 58 ) 59 ) 60 "#, 61 )? 62 .serialize()?; 63 64 let component = unsafe { Component::deserialize(&engine, &component)? }; 65 let mut store = Store::new(&engine, ()); 66 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 67 let func = instance.get_typed_func::<(), (u32,)>(&mut store, "a")?; 68 assert_eq!(func.call(&mut store, ())?, (103,)); 69 70 Ok(()) 71 } 72 73 #[test] 74 fn deserialize_from_serialized() -> Result<()> { 75 let engine = super::engine(); 76 let buffer1 = Component::new(&engine, "(component (core module))")?.serialize()?; 77 let buffer2 = unsafe { Component::deserialize(&engine, &buffer1)?.serialize()? }; 78 assert!(buffer1 == buffer2); 79 Ok(()) 80 } 81 82 // This specifically tests the current behavior that it's an error, but this can 83 // be made to work if necessary in the future. Currently the implementation of 84 // `serialize` is not conducive to easily implementing this feature and 85 // otherwise it's not seen as too important to implement. 86 #[test] 87 fn cannot_serialize_exported_module() -> Result<()> { 88 let engine = super::engine(); 89 let component = Component::new( 90 &engine, 91 r#"(component 92 (core module $m) 93 (export "a" (core module $m)) 94 )"#, 95 )?; 96 let mut store = Store::new(&engine, ()); 97 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 98 let module = instance.get_module(&mut store, "a").unwrap(); 99 assert!(module.serialize().is_err()); 100 Ok(()) 101 } 102 103 #[test] 104 #[cfg_attr(miri, ignore)] 105 fn usable_exported_modules() -> Result<()> { 106 let engine = super::engine(); 107 let component = Component::new( 108 &engine, 109 r#"(component 110 (core module $m) 111 (core module $m1 (export "a") 112 (import "" "" (func (param i32))) 113 ) 114 )"#, 115 )?; 116 let mut store = Store::new(&engine, ()); 117 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 118 let module = instance.get_module(&mut store, "a").unwrap(); 119 let mut core_linker = wasmtime::Linker::new(&engine); 120 core_linker.func_wrap("", "", |_: u32| {})?; 121 core_linker.instantiate(&mut store, &module)?; 122 Ok(()) 123 } 124 125 #[test] 126 #[cfg_attr(miri, ignore)] 127 fn detect_precompiled() -> Result<()> { 128 let engine = super::engine(); 129 let buffer = Component::new(&engine, "(component)")?.serialize()?; 130 assert_eq!(Engine::detect_precompiled(&[]), None); 131 assert_eq!(Engine::detect_precompiled(&buffer[..5]), None); 132 assert_eq!( 133 Engine::detect_precompiled(&buffer), 134 Some(Precompiled::Component) 135 ); 136 Ok(()) 137 } 138 139 #[test] 140 fn reflect_resource_import() -> Result<()> { 141 let engine = super::engine(); 142 let c = Component::new( 143 &engine, 144 r#" 145 (component 146 (import "x" (type $x (sub resource))) 147 (import "y" (func (result (own $x)))) 148 ) 149 "#, 150 )?; 151 let ty = c.component_type(); 152 let mut imports = ty.imports(&engine); 153 let (_, x) = imports.next().unwrap(); 154 let (_, y) = imports.next().unwrap(); 155 let x = match x { 156 ComponentItem::Resource(t) => t, 157 _ => unreachable!(), 158 }; 159 let y = match y { 160 ComponentItem::ComponentFunc(t) => t, 161 _ => unreachable!(), 162 }; 163 let result = y.results().next().unwrap(); 164 assert_eq!(result, Type::Own(x)); 165 166 Ok(()) 167 } 168 169 #[test] 170 #[cfg_attr(miri, ignore)] 171 fn truncated_component_binaries_dont_panic() -> Result<()> { 172 let engine = super::engine(); 173 174 let binary = wat::parse_str( 175 r#" 176 (component 177 (import "a" (core module $m0 178 (import "" "" (func)) 179 )) 180 181 (core module $m1 182 (func (export "")) 183 ) 184 (core instance $i1 (instantiate (module $m1))) 185 (func $f (canon lift (core func $i1 "f"))) 186 187 (component $c1 188 (import "f" (func)) 189 (core module $m2 190 (func (export "g")) 191 ) 192 (core instance $i2 (instantiate $m2)) 193 (func (export "g") 194 (canon lift (core func $i2 "g")) 195 ) 196 ) 197 (instance $i3 (instantiate $c1 (with "f" (func $f)))) 198 (func (export "g") (alias export $i3 "g")) 199 ) 200 "#, 201 )?; 202 203 // Check that if we feed each truncation of the component binary into 204 // `Component::new` we don't get any panics. 205 for i in 1..binary.len() - 1 { 206 let _ = Component::from_binary(&engine, &binary[0..i]); 207 } 208 209 Ok(()) 210 } 211