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