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