xref: /wasmtime-44.0.1/tests/all/globals.rs (revision 94740588)
1 use wasmtime::*;
2 
3 #[test]
smoke() -> wasmtime::Result<()>4 fn smoke() -> wasmtime::Result<()> {
5     let mut store = Store::<()>::default();
6     let g = Global::new(
7         &mut store,
8         GlobalType::new(ValType::I32, Mutability::Const),
9         0.into(),
10     )?;
11     assert_eq!(g.get(&mut store).i32(), Some(0));
12     assert!(g.set(&mut store, 0.into()).is_err());
13 
14     let g = Global::new(
15         &mut store,
16         GlobalType::new(ValType::I32, Mutability::Const),
17         1i32.into(),
18     )?;
19     assert_eq!(g.get(&mut store).i32(), Some(1));
20 
21     let g = Global::new(
22         &mut store,
23         GlobalType::new(ValType::I64, Mutability::Const),
24         2i64.into(),
25     )?;
26     assert_eq!(g.get(&mut store).i64(), Some(2));
27 
28     let g = Global::new(
29         &mut store,
30         GlobalType::new(ValType::F32, Mutability::Const),
31         3.0f32.into(),
32     )?;
33     assert_eq!(g.get(&mut store).f32(), Some(3.0));
34 
35     let g = Global::new(
36         &mut store,
37         GlobalType::new(ValType::F64, Mutability::Const),
38         4.0f64.into(),
39     )?;
40     assert_eq!(g.get(&mut store).f64(), Some(4.0));
41     Ok(())
42 }
43 
44 #[test]
mutability() -> wasmtime::Result<()>45 fn mutability() -> wasmtime::Result<()> {
46     let mut store = Store::<()>::default();
47     let g = Global::new(
48         &mut store,
49         GlobalType::new(ValType::I32, Mutability::Var),
50         0.into(),
51     )?;
52     assert_eq!(g.get(&mut store).i32(), Some(0));
53     g.set(&mut store, 1.into())?;
54     assert_eq!(g.get(&mut store).i32(), Some(1));
55     Ok(())
56 }
57 
58 // Make sure that a global is still usable after its original instance is
59 // dropped. This is a bit of a weird test and really only fails depending on the
60 // implementation, but for now should hopefully be resilient enough to catch at
61 // least some cases of heap corruption.
62 #[test]
use_after_drop() -> wasmtime::Result<()>63 fn use_after_drop() -> wasmtime::Result<()> {
64     let mut store = Store::<()>::default();
65     let module = Module::new(
66         store.engine(),
67         r#"
68             (module
69                 (global (export "foo") (mut i32) (i32.const 100)))
70         "#,
71     )?;
72     let instance = Instance::new(&mut store, &module, &[])?;
73     let g = instance.get_global(&mut store, "foo").unwrap();
74     assert_eq!(g.get(&mut store).i32(), Some(100));
75     g.set(&mut store, 101.into())?;
76     assert_eq!(g.get(&mut store).i32(), Some(101));
77     Instance::new(&mut store, &module, &[])?;
78     assert_eq!(g.get(&mut store).i32(), Some(101));
79     drop(module);
80     assert_eq!(g.get(&mut store).i32(), Some(101));
81 
82     // spray some heap values
83     let mut x = Vec::new();
84     for _ in 0..100 {
85         x.push("xy".to_string());
86     }
87     drop(x);
88     assert_eq!(g.get(&mut store).i32(), Some(101));
89     Ok(())
90 }
91 
92 #[test]
v128() -> wasmtime::Result<()>93 fn v128() -> wasmtime::Result<()> {
94     let mut store = Store::<()>::default();
95     let g = Global::new(
96         &mut store,
97         GlobalType::new(ValType::V128, Mutability::Var),
98         0u128.into(),
99     )?;
100     assert_eq!(g.get(&mut store).v128(), Some(V128::from(0)));
101     g.set(&mut store, 1u128.into())?;
102     assert_eq!(g.get(&mut store).v128(), Some(V128::from(1)));
103     Ok(())
104 }
105 
106 #[test]
i31ref_global_new() -> Result<()>107 fn i31ref_global_new() -> Result<()> {
108     let mut config = Config::new();
109     config.wasm_function_references(true);
110     config.wasm_gc(true);
111 
112     let engine = Engine::new(&config)?;
113     let mut store = Store::new(&engine, ());
114 
115     for mutability in [Mutability::Const, Mutability::Var] {
116         for val in [
117             Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
118             None,
119         ] {
120             Global::new(
121                 &mut store,
122                 GlobalType::new(ValType::I31REF, mutability),
123                 val.into(),
124             )?;
125         }
126     }
127     Ok(())
128 }
129 
130 #[test]
i31ref_global_get() -> Result<()>131 fn i31ref_global_get() -> Result<()> {
132     let mut config = Config::new();
133     config.wasm_function_references(true);
134     config.wasm_gc(true);
135 
136     let engine = Engine::new(&config)?;
137     let mut store = Store::new(&engine, ());
138 
139     for mutability in [Mutability::Const, Mutability::Var] {
140         for val in [
141             Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
142             None,
143         ] {
144             let val = Val::from(val);
145             let global = Global::new(
146                 &mut store,
147                 GlobalType::new(ValType::I31REF, mutability),
148                 val,
149             )?;
150 
151             let got = global.get(&mut store);
152 
153             let val = val
154                 .anyref()
155                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
156             let got = got
157                 .anyref()
158                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
159 
160             assert_eq!(val, got);
161         }
162     }
163     Ok(())
164 }
165 
166 #[test]
i31ref_global_set() -> Result<()>167 fn i31ref_global_set() -> Result<()> {
168     let mut config = Config::new();
169     config.wasm_function_references(true);
170     config.wasm_gc(true);
171 
172     let engine = Engine::new(&config)?;
173     let mut store = Store::new(&engine, ());
174 
175     for init in [
176         Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
177         None,
178     ] {
179         for new_val in [
180             Some(AnyRef::from_i31(&mut store, I31::new_u32(36).unwrap())),
181             None,
182         ] {
183             let global = Global::new(
184                 &mut store,
185                 GlobalType::new(ValType::I31REF, Mutability::Var),
186                 init.into(),
187             )?;
188 
189             let new_val = Val::from(new_val);
190             global.set(&mut store, new_val)?;
191             let got = global.get(&mut store);
192 
193             let new_val = new_val
194                 .anyref()
195                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
196             let got = got
197                 .anyref()
198                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
199 
200             assert_eq!(new_val, got);
201         }
202     }
203     Ok(())
204 }
205 
206 #[test]
i31ref_global_ty() -> Result<()>207 fn i31ref_global_ty() -> Result<()> {
208     let mut config = Config::new();
209     config.wasm_function_references(true);
210     config.wasm_gc(true);
211 
212     let engine = Engine::new(&config)?;
213     let mut store = Store::new(&engine, ());
214 
215     for mutability in [Mutability::Const, Mutability::Var] {
216         for val in [
217             Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
218             None,
219         ] {
220             let expected_ty = GlobalType::new(ValType::I31REF, mutability);
221             let global = Global::new(&mut store, expected_ty.clone(), val.into())?;
222             let actual_ty = global.ty(&store);
223             assert_eq!(expected_ty.mutability(), actual_ty.mutability());
224             assert!(ValType::eq(expected_ty.content(), actual_ty.content()));
225         }
226     }
227     Ok(())
228 }
229 
230 #[test]
i31ref_as_anyref_global_new() -> Result<()>231 fn i31ref_as_anyref_global_new() -> Result<()> {
232     let mut config = Config::new();
233     config.wasm_function_references(true);
234     config.wasm_gc(true);
235 
236     let engine = Engine::new(&config)?;
237     let mut store = Store::new(&engine, ());
238 
239     for mutability in [Mutability::Const, Mutability::Var] {
240         for val in [
241             Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
242             None,
243         ] {
244             Global::new(
245                 &mut store,
246                 GlobalType::new(ValType::ANYREF, mutability),
247                 val.into(),
248             )?;
249         }
250     }
251     Ok(())
252 }
253 
254 #[test]
i31ref_as_anyref_global_get() -> Result<()>255 fn i31ref_as_anyref_global_get() -> Result<()> {
256     let mut config = Config::new();
257     config.wasm_function_references(true);
258     config.wasm_gc(true);
259 
260     let engine = Engine::new(&config)?;
261     let mut store = Store::new(&engine, ());
262 
263     for mutability in [Mutability::Const, Mutability::Var] {
264         for val in [
265             Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
266             None,
267         ] {
268             let val = Val::from(val);
269             let global = Global::new(
270                 &mut store,
271                 GlobalType::new(ValType::ANYREF, mutability),
272                 val,
273             )?;
274 
275             let got = global.get(&mut store);
276 
277             let val = val
278                 .anyref()
279                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
280             let got = got
281                 .anyref()
282                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
283 
284             assert_eq!(val, got);
285         }
286     }
287     Ok(())
288 }
289 
290 #[test]
i31ref_as_anyref_global_set() -> Result<()>291 fn i31ref_as_anyref_global_set() -> Result<()> {
292     let mut config = Config::new();
293     config.wasm_function_references(true);
294     config.wasm_gc(true);
295 
296     let engine = Engine::new(&config)?;
297     let mut store = Store::new(&engine, ());
298 
299     for init in [
300         Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
301         None,
302     ] {
303         for new_val in [
304             Some(AnyRef::from_i31(&mut store, I31::new_u32(36).unwrap())),
305             None,
306         ] {
307             let global = Global::new(
308                 &mut store,
309                 GlobalType::new(ValType::ANYREF, Mutability::Var),
310                 init.into(),
311             )?;
312 
313             let new_val = Val::from(new_val);
314             global.set(&mut store, new_val)?;
315             let got = global.get(&mut store);
316 
317             let new_val = new_val
318                 .anyref()
319                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
320             let got = got
321                 .anyref()
322                 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
323 
324             assert_eq!(new_val, got);
325         }
326     }
327     Ok(())
328 }
329 
330 #[test]
i31ref_as_anyref_global_ty() -> Result<()>331 fn i31ref_as_anyref_global_ty() -> Result<()> {
332     let mut config = Config::new();
333     config.wasm_function_references(true);
334     config.wasm_gc(true);
335 
336     let engine = Engine::new(&config)?;
337     let mut store = Store::new(&engine, ());
338 
339     for mutability in [Mutability::Const, Mutability::Var] {
340         for val in [
341             Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
342             None,
343         ] {
344             let expected_ty = GlobalType::new(ValType::ANYREF, mutability);
345             let global = Global::new(&mut store, expected_ty.clone(), val.into())?;
346             let actual_ty = global.ty(&store);
347             assert_eq!(expected_ty.mutability(), actual_ty.mutability());
348             assert!(ValType::eq(expected_ty.content(), actual_ty.content()));
349         }
350     }
351     Ok(())
352 }
353 
354 #[test]
355 #[cfg_attr(miri, ignore)]
instantiate_global_with_subtype() -> Result<()>356 fn instantiate_global_with_subtype() -> Result<()> {
357     let mut config = Config::new();
358     config.wasm_function_references(true);
359     config.wasm_gc(true);
360 
361     let engine = Engine::new(&config)?;
362     let module = Module::new(
363         &engine,
364         r#"
365             (module
366                 (type $func_ty (sub (func)))
367                 (import "" "" (global (ref null $func_ty)))
368             )
369         "#,
370     )?;
371 
372     {
373         let func_ty =
374             FuncType::with_finality_and_supertype(&engine, Finality::NonFinal, None, [], [])?;
375         let sub_func_ty = FuncType::with_finality_and_supertype(
376             &engine,
377             Finality::NonFinal,
378             Some(&func_ty),
379             [],
380             [],
381         )?;
382         let global_ty = GlobalType::new(
383             RefType::new(true, HeapType::ConcreteFunc(sub_func_ty.clone())).into(),
384             Mutability::Const,
385         );
386         assert!(
387             global_ty.content().matches(
388                 module
389                     .imports()
390                     .nth(0)
391                     .unwrap()
392                     .ty()
393                     .unwrap_global()
394                     .content()
395             )
396         );
397 
398         let mut store = Store::new(&engine, ());
399         let func = Func::new(&mut store, sub_func_ty, |_caller, _args, _rets| Ok(()));
400         let global = Global::new(&mut store, global_ty, func.into())?;
401 
402         // This instantiation should succeed: the given global's type is a subtype
403         // of the import's global type.
404         let _ = Instance::new(&mut store, &module, &[global.into()])?;
405     }
406 
407     {
408         let func_ty = FuncType::new(&engine, [], []);
409         let global_ty = GlobalType::new(
410             RefType::new(true, HeapType::ConcreteFunc(func_ty.clone())).into(),
411             Mutability::Const,
412         );
413         assert!(
414             !global_ty.content().matches(
415                 module
416                     .imports()
417                     .nth(0)
418                     .unwrap()
419                     .ty()
420                     .unwrap_global()
421                     .content()
422             )
423         );
424 
425         let mut store = Store::new(&engine, ());
426         let func = Func::new(&mut store, func_ty, |_caller, _args, _rets| Ok(()));
427         let global = Global::new(&mut store, global_ty, func.into())?;
428 
429         // This instantiation should fail: the given global's type is *not* a
430         // subtype of the import's global type.
431         assert!(Instance::new(&mut store, &module, &[global.into()]).is_err());
432     }
433 
434     Ok(())
435 }
436 
437 #[test]
host_globals_keep_type_registration() -> Result<()>438 fn host_globals_keep_type_registration() -> Result<()> {
439     let engine = Engine::default();
440     let mut store = Store::new(&engine, ());
441 
442     let ty = FuncType::new(&engine, [], []);
443 
444     let g = Global::new(
445         &mut store,
446         GlobalType::new(
447             RefType::new(true, HeapType::ConcreteFunc(ty)).into(),
448             Mutability::Const,
449         ),
450         Val::FuncRef(None),
451     )?;
452 
453     {
454         let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]);
455         let ty = g.ty(&store);
456         let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
457         assert!(fty.params().len() == 0);
458         assert!(fty.results().len() == 0);
459     }
460 
461     let ty = g.ty(&store);
462     let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
463     assert!(fty.params().len() == 0);
464     assert!(fty.results().len() == 0);
465 
466     Ok(())
467 }
468