1 use super::*;
2 use std::path::Path;
3 use wasmtime::*;
4 
5 #[test]
6 #[cfg_attr(miri, ignore)]
smoke() -> Result<()>7 fn smoke() -> Result<()> {
8     let engine = Engine::default();
9     let linker = component::Linker::new(&engine);
10 
11     let component = unsafe {
12         CodeBuilder::new(&engine)
13             .expose_unsafe_intrinsics("unsafe-intrinsics")
14             .compile_time_builtins_binary_or_text(
15                 "host-api",
16                 r#"
17                     (component
18                         (import "unsafe-intrinsics"
19                             (instance $intrinsics
20                                 (export "store-data-address" (func (result u64)))
21                                 (export "u8-native-load" (func (param "pointer" u64) (result u8)))
22                             )
23                         )
24 
25                         (core func $store-data-address' (canon lower (func $intrinsics "store-data-address")))
26                         (core func $u8-native-load' (canon lower (func $intrinsics "u8-native-load")))
27 
28                         (core module $m
29                             (import "" "store-data-address" (func $store-data-address (result i64)))
30                             (import "" "u8-native-load" (func $u8-native-load (param i64) (result i32)))
31                             (func (export "get") (result i32)
32                                 (call $u8-native-load (call $store-data-address))
33                             )
34                         )
35 
36                         (core instance $i
37                             (instantiate $m
38                                 (with "" (instance (export "store-data-address" (func $store-data-address'))
39                                                    (export "u8-native-load" (func $u8-native-load'))))
40                             )
41                         )
42 
43                         (func (export "get") (result u8)
44                             (canon lift (core func $i "get"))
45                         )
46                     )
47                 "#.as_bytes(),
48                 Some(Path::new("host-api.wat")),
49             )?
50             .wasm_binary_or_text(
51                 r#"
52                     (component
53                         (import "host-api"
54                             (instance $host-api
55                                 (export "get" (func (result u8)))
56                             )
57                         )
58 
59                         (core func $get' (canon lower (func $host-api "get")))
60 
61                         (core module $m
62                             (import "" "get" (func $get (result i32)))
63                             (func (export "double-get") (result i32)
64                                 (i32.add (call $get) (call $get))
65                             )
66                         )
67 
68                         (core instance $i
69                             (instantiate $m (with "" (instance (export "get" (func $get')))))
70                         )
71 
72                         (func (export "double-get") (result u8)
73                             (canon lift (core func $i "double-get"))
74                         )
75                     )
76                 "#.as_bytes(),
77                 Some(Path::new("main.wat")),
78             )?
79             .compile_component()?
80     };
81 
82     let mut store = Store::new(&engine, 42_u8);
83     let instance = linker.instantiate(&mut store, &component)?;
84 
85     let (result,) = instance
86         .get_typed_func::<(), (u8,)>(&mut store, "double-get")?
87         .call(&mut store, ())?;
88     assert_eq!(result, 84);
89 
90     Ok(())
91 }
92 
93 #[test]
94 #[cfg_attr(miri, ignore)]
unused_compile_time_builtins() -> Result<()>95 fn unused_compile_time_builtins() -> Result<()> {
96     let engine = Engine::default();
97     let linker = component::Linker::new(&engine);
98 
99     let component = unsafe {
100         CodeBuilder::new(&engine)
101             .expose_unsafe_intrinsics("unsafe-intrinsics")
102             .compile_time_builtins_binary_or_text(
103                 "host-api",
104                 "(component)".as_bytes(),
105                 Some(Path::new("host-api.wat")),
106             )?
107             .wasm_binary_or_text(
108                 r#"
109                     (component
110                         (core module $m
111                             (func (export "foo") (result i32)
112                                 (i32.const 42)
113                             )
114                         )
115 
116                         (core instance $i (instantiate $m))
117 
118                         (func (export "foo") (result u8)
119                             (canon lift (core func $i "foo"))
120                         )
121                     )
122                 "#
123                 .as_bytes(),
124                 Some(Path::new("main.wat")),
125             )?
126             .compile_component()?
127     };
128 
129     let mut store = Store::new(&engine, ());
130     let instance = linker.instantiate(&mut store, &component)?;
131 
132     let (result,) = instance
133         .get_typed_func::<(), (u8,)>(&mut store, "foo")?
134         .call(&mut store, ())?;
135     assert_eq!(result, 42);
136 
137     Ok(())
138 }
139 
140 #[test]
141 #[cfg_attr(miri, ignore)]
multiple_compile_time_builtins() -> Result<()>142 fn multiple_compile_time_builtins() -> Result<()> {
143     let engine = Engine::default();
144     let linker = component::Linker::new(&engine);
145 
146     let component = unsafe {
147         CodeBuilder::new(&engine)
148             .expose_unsafe_intrinsics("unsafe-intrinsics")
149             .compile_time_builtins_binary_or_text(
150                 "host-api1",
151                 "(component)".as_bytes(),
152                 Some(Path::new("host-api1.wat")),
153             )?
154             .compile_time_builtins_binary_or_text(
155                 "host-api2",
156                 "(component)".as_bytes(),
157                 Some(Path::new("host-api2.wat")),
158             )?
159             .compile_time_builtins_binary_or_text(
160                 "host-api3",
161                 "(component)".as_bytes(),
162                 Some(Path::new("host-api3.wat")),
163             )?
164             .wasm_binary_or_text(
165                 r#"
166                     (component
167                         (import "host-api2" (instance))
168                         (import "host-api3" (instance))
169 
170                         (core module $m
171                             (func (export "foo") (result i32)
172                                 (i32.const 42)
173                             )
174                         )
175 
176                         (core instance $i (instantiate $m))
177 
178                         (func (export "foo") (result u8)
179                             (canon lift (core func $i "foo"))
180                         )
181                     )
182                 "#
183                 .as_bytes(),
184                 Some(Path::new("main.wat")),
185             )?
186             .compile_component()?
187     };
188 
189     let mut store = Store::new(&engine, ());
190     let instance = linker.instantiate(&mut store, &component)?;
191 
192     let (result,) = instance
193         .get_typed_func::<(), (u8,)>(&mut store, "foo")?
194         .call(&mut store, ())?;
195     assert_eq!(result, 42);
196 
197     Ok(())
198 }
199 
200 #[test]
201 #[cfg_attr(miri, ignore)]
main_wasm_cannot_use_intrinsics() -> Result<()>202 fn main_wasm_cannot_use_intrinsics() -> Result<()> {
203     let engine = Engine::default();
204 
205     let err = unsafe {
206         CodeBuilder::new(&engine)
207             .expose_unsafe_intrinsics("unsafe-intrinsics")
208             .compile_time_builtins_binary_or_text(
209                 "host-api",
210                 "(component)".as_bytes(),
211                 Some(Path::new("host-api.wat")),
212             )?
213             .wasm_binary_or_text(
214                 r#"
215                     (component
216                         (import "unsafe-intrinsics" (instance $intrinsics))
217                     )
218                 "#
219                 .as_bytes(),
220                 Some(Path::new("main.wat")),
221             )?
222             .compile_component()
223             .map(|_| ())
224             .unwrap_err()
225     };
226 
227     err.assert_contains("main Wasm cannot import the unsafe intrinsics");
228     Ok(())
229 }
230 
231 #[test]
232 #[cfg_attr(miri, ignore)]
import_erased() -> Result<()>233 fn import_erased() -> Result<()> {
234     let engine = Engine::default();
235 
236     let component = unsafe {
237         CodeBuilder::new(&engine)
238             .expose_unsafe_intrinsics("unsafe-intrinsics")
239             .compile_time_builtins_binary_or_text(
240                 "compile-time-api",
241                 "(component)".as_bytes(),
242                 Some(Path::new("compile-time-api.wat")),
243             )?
244             .wasm_binary_or_text(
245                 r#"
246                     (component
247                         (import "compile-time-api" (instance))
248                         (import "link-time-api" (instance))
249                     )
250                 "#
251                 .as_bytes(),
252                 Some(Path::new("main.wat")),
253             )?
254             .compile_component()?
255     };
256 
257     let component_type = component.component_type();
258     let imports = component_type
259         .imports(&engine)
260         .map(|(name, _ty)| name)
261         .collect::<Vec<_>>();
262     assert_eq!(imports, ["link-time-api"]);
263 
264     Ok(())
265 }
266