1 use wasmtime::Result;
2 use wasmtime::component::types::ComponentItem;
3 use wasmtime::component::{Component, Linker, Type};
4 use wasmtime::{Engine, Module, Precompiled, Store};
5
6 #[test]
module_component_mismatch() -> Result<()>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]
bare_bones() -> Result<()>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)]
mildly_more_interesting() -> Result<()>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]
deserialize_from_serialized() -> Result<()>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]
cannot_serialize_exported_module() -> Result<()>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)]
usable_exported_modules() -> Result<()>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)]
detect_precompiled() -> Result<()>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]
reflect_resource_import() -> Result<()>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)]
truncated_component_binaries_dont_panic() -> Result<()>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