xref: /wasmtime-44.0.1/tests/all/table.rs (revision c6dddeaf)
1 use wasmtime::*;
2 
3 #[test]
get_none()4 fn get_none() {
5     let mut store = Store::<()>::default();
6     let ty = TableType::new(RefType::FUNCREF, 1, None);
7     let table = Table::new(&mut store, ty, Ref::Func(None)).unwrap();
8     match table.get(&mut store, 0) {
9         Some(Ref::Func(None)) => {}
10         _ => panic!(),
11     }
12     assert!(table.get(&mut store, 1).is_none());
13 }
14 
15 #[test]
fill_wrong()16 fn fill_wrong() {
17     let mut store = Store::<()>::default();
18     let ty = TableType::new(RefType::FUNCREF, 1, None);
19     let table = Table::new(&mut store, ty, Ref::Func(None)).unwrap();
20     assert_eq!(
21         table
22             .fill(&mut store, 0, Ref::Extern(None), 1)
23             .map_err(|e| e.to_string())
24             .unwrap_err(),
25         "type mismatch: value does not match table element type"
26     );
27 
28     let ty = TableType::new(RefType::EXTERNREF, 1, None);
29     let table = Table::new(&mut store, ty, Ref::Extern(None)).unwrap();
30     assert_eq!(
31         table
32             .fill(&mut store, 0, Ref::Func(None), 1)
33             .map_err(|e| e.to_string())
34             .unwrap_err(),
35         "type mismatch: value does not match table element type"
36     );
37 }
38 
39 #[test]
copy_wrong()40 fn copy_wrong() {
41     let mut store = Store::<()>::default();
42     let ty = TableType::new(RefType::FUNCREF, 1, None);
43     let table1 = Table::new(&mut store, ty, Ref::Func(None)).unwrap();
44     let ty = TableType::new(RefType::EXTERNREF, 1, None);
45     let table2 = Table::new(&mut store, ty, Ref::Extern(None)).unwrap();
46     assert_eq!(
47         Table::copy(&mut store, &table1, 0, &table2, 0, 1)
48             .map_err(|e| e.to_string())
49             .unwrap_err(),
50         "type mismatch: source table's element type does not match destination table's element type"
51     );
52 }
53 
54 #[test]
55 #[cfg_attr(miri, ignore)]
null_elem_segment_works_with_imported_table() -> Result<()>56 fn null_elem_segment_works_with_imported_table() -> Result<()> {
57     let mut store = Store::<()>::default();
58     let ty = TableType::new(RefType::FUNCREF, 1, None);
59     let table = Table::new(&mut store, ty, Ref::Func(None))?;
60     let module = Module::new(
61         store.engine(),
62         r#"
63 (module
64   (import "" "" (table (;0;) 1 funcref))
65   (func
66     i32.const 0
67     table.get 0
68     drop
69   )
70   (start 0)
71   (elem (;0;) (i32.const 0) funcref (ref.null func))
72 )
73 "#,
74     )?;
75     Instance::new(&mut store, &module, &[table.into()])?;
76     Ok(())
77 }
78 
79 #[test]
i31ref_table_new() -> Result<()>80 fn i31ref_table_new() -> Result<()> {
81     let mut config = Config::new();
82     config.wasm_function_references(true);
83     config.wasm_gc(true);
84 
85     let engine = Engine::new(&config)?;
86     let mut store = Store::new(&engine, ());
87 
88     for (elem_ty, inits) in [
89         (
90             RefType::I31REF,
91             vec![
92                 Ref::Any(None),
93                 AnyRef::from_i31(&mut store, I31::default()).into(),
94             ],
95         ),
96         (
97             RefType::new(false, HeapType::I31),
98             vec![AnyRef::from_i31(&mut store, I31::default()).into()],
99         ),
100     ] {
101         let table_ty = TableType::new(elem_ty, 10, None);
102         for init in inits {
103             Table::new(&mut store, table_ty.clone(), init)?;
104         }
105     }
106 
107     Ok(())
108 }
109 
110 #[test]
i31ref_table_get() -> Result<()>111 fn i31ref_table_get() -> Result<()> {
112     let mut config = Config::new();
113     config.wasm_function_references(true);
114     config.wasm_gc(true);
115 
116     let engine = Engine::new(&config)?;
117     let mut store = Store::new(&engine, ());
118 
119     for (elem_ty, inits) in [
120         (
121             RefType::I31REF,
122             vec![
123                 Ref::Any(None),
124                 AnyRef::from_i31(&mut store, I31::default()).into(),
125             ],
126         ),
127         (
128             RefType::new(false, HeapType::I31),
129             vec![AnyRef::from_i31(&mut store, I31::default()).into()],
130         ),
131     ] {
132         let table_ty = TableType::new(elem_ty, 10, None);
133         for init in inits {
134             let table = Table::new(&mut store, table_ty.clone(), init.clone())?;
135             for i in 0..10 {
136                 let val = table.get(&mut store, i).unwrap();
137                 assert_eq!(init.is_null(), val.is_null());
138                 assert_eq!(
139                     init.as_any()
140                         .expect("is anyref")
141                         .map(|a| a.as_i31(&store).expect("is in scope")),
142                     val.as_any()
143                         .expect("is anyref")
144                         .map(|a| a.as_i31(&store).expect("is in scope"))
145                 )
146             }
147         }
148     }
149 
150     Ok(())
151 }
152 
153 #[test]
i31ref_table_set() -> Result<()>154 fn i31ref_table_set() -> Result<()> {
155     let mut config = Config::new();
156     config.wasm_function_references(true);
157     config.wasm_gc(true);
158 
159     let engine = Engine::new(&config)?;
160     let mut store = Store::new(&engine, ());
161 
162     for (elem_ty, inits, vals) in [
163         (
164             RefType::I31REF,
165             vec![
166                 Ref::Any(None),
167                 AnyRef::from_i31(&mut store, I31::default()).into(),
168             ],
169             vec![
170                 Ref::Any(None),
171                 AnyRef::from_i31(&mut store, I31::wrapping_u32(42)).into(),
172             ],
173         ),
174         (
175             RefType::new(false, HeapType::I31),
176             vec![AnyRef::from_i31(&mut store, I31::default()).into()],
177             vec![AnyRef::from_i31(&mut store, I31::wrapping_u32(42)).into()],
178         ),
179     ] {
180         let table_ty = TableType::new(elem_ty, 10, None);
181         for init in inits {
182             for expected in vals.clone() {
183                 let table = Table::new(&mut store, table_ty.clone(), init.clone())?;
184                 for i in 0..10 {
185                     table.set(&mut store, i, expected.clone())?;
186                     let actual = table.get(&mut store, i).unwrap();
187                     assert_eq!(expected.is_null(), actual.is_null());
188                     assert_eq!(
189                         expected
190                             .as_any()
191                             .expect("is anyref")
192                             .map(|a| a.as_i31(&store).expect("is in scope")),
193                         actual
194                             .as_any()
195                             .expect("is anyref")
196                             .map(|a| a.as_i31(&store).expect("is in scope"))
197                     )
198                 }
199             }
200         }
201     }
202 
203     Ok(())
204 }
205 
206 #[test]
i31ref_table_grow() -> Result<()>207 fn i31ref_table_grow() -> 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 (elem_ty, init) in [
216         (RefType::I31REF, Ref::Any(None)),
217         (
218             RefType::new(false, HeapType::I31),
219             AnyRef::from_i31(&mut store, I31::default()).into(),
220         ),
221     ] {
222         let table_ty = TableType::new(elem_ty, 10, None);
223         let table = Table::new(&mut store, table_ty, init)?;
224         assert_eq!(table.size(&store), 10);
225         for i in 10..20 {
226             assert!(table.get(&mut store, i).is_none());
227         }
228         let expected = I31::wrapping_u32(42);
229         let grow_val = AnyRef::from_i31(&mut store, expected);
230         table.grow(&mut store, 10, grow_val.into())?;
231         for i in 10..20 {
232             let actual = table.get(&mut store, i).unwrap();
233             assert_eq!(
234                 actual
235                     .as_any()
236                     .expect("is anyref")
237                     .expect("is non null")
238                     .as_i31(&store)
239                     .expect("is in scope")
240                     .expect("is i31"),
241                 expected,
242             );
243         }
244         assert!(table.get(&mut store, 20).is_none());
245     }
246 
247     Ok(())
248 }
249 
250 #[test]
i31ref_table_fill() -> Result<()>251 fn i31ref_table_fill() -> Result<()> {
252     let mut config = Config::new();
253     config.wasm_function_references(true);
254     config.wasm_gc(true);
255 
256     let engine = Engine::new(&config)?;
257     let mut store = Store::new(&engine, ());
258 
259     let table_ty = TableType::new(RefType::I31REF, 10, None);
260     let table = Table::new(&mut store, table_ty, Ref::Any(None))?;
261 
262     let expected = I31::wrapping_u32(42);
263     let fill_val = AnyRef::from_i31(&mut store, expected);
264     let dst = 3;
265     let len = 4;
266     table.fill(&mut store, dst, fill_val.into(), len)?;
267 
268     for i in 0..dst {
269         let actual = table.get(&mut store, i).unwrap();
270         assert!(actual.as_any().expect("is anyref").is_none());
271     }
272     for i in dst..dst + len {
273         let actual = table.get(&mut store, i).unwrap();
274         assert_eq!(
275             actual
276                 .as_any()
277                 .expect("is anyref")
278                 .expect("is non null")
279                 .as_i31(&store)
280                 .expect("is in scope")
281                 .expect("is i31"),
282             expected,
283         );
284     }
285     for i in dst + len..10 {
286         let actual = table.get(&mut store, i).unwrap();
287         assert!(actual.as_any().expect("is anyref").is_none());
288     }
289 
290     Ok(())
291 }
292 
293 #[test]
i31ref_table_copy() -> Result<()>294 fn i31ref_table_copy() -> Result<()> {
295     let mut config = Config::new();
296     config.wasm_function_references(true);
297     config.wasm_gc(true);
298 
299     let engine = Engine::new(&config)?;
300     let mut store = Store::new(&engine, ());
301 
302     let table_ty = TableType::new(RefType::I31REF, 10, None);
303     let dst_table = Table::new(&mut store, table_ty.clone(), Ref::Any(None))?;
304 
305     let expected = I31::wrapping_u32(42);
306     let init_val = AnyRef::from_i31(&mut store, expected);
307     let src_table = Table::new(&mut store, table_ty, init_val.into())?;
308 
309     let dst_index = 1;
310     let src_index = 2;
311     let len = 3;
312     Table::copy(
313         &mut store, &dst_table, dst_index, &src_table, src_index, len,
314     )?;
315 
316     for i in 0..dst_index {
317         let actual = dst_table.get(&mut store, i).unwrap();
318         assert!(actual.as_any().expect("is anyref").is_none());
319     }
320     for i in dst_index..dst_index + len {
321         let actual = dst_table.get(&mut store, i).unwrap();
322         assert_eq!(
323             actual
324                 .as_any()
325                 .expect("is anyref")
326                 .expect("is non null")
327                 .as_i31(&store)
328                 .expect("is in scope")
329                 .expect("is i31"),
330             expected,
331         );
332     }
333     for i in dst_index + len..10 {
334         let actual = dst_table.get(&mut store, i).unwrap();
335         assert!(actual.as_any().expect("is anyref").is_none());
336     }
337 
338     Ok(())
339 }
340 
341 #[test]
host_table_keep_type_registration() -> Result<()>342 fn host_table_keep_type_registration() -> Result<()> {
343     let engine = Engine::default();
344     let mut store = Store::new(&engine, ());
345 
346     let ty = FuncType::new(&engine, [], []);
347 
348     let t = Table::new(
349         &mut store,
350         TableType::new(RefType::new(true, HeapType::ConcreteFunc(ty)), 1, None),
351         Ref::Func(None),
352     )?;
353 
354     {
355         let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]);
356         let ty = t.ty(&store);
357         let fty = ty.element().heap_type().unwrap_concrete_func();
358         assert!(fty.params().len() == 0);
359         assert!(fty.results().len() == 0);
360     }
361 
362     let ty = t.ty(&store);
363     let fty = ty.element().heap_type().unwrap_concrete_func();
364     assert!(fty.params().len() == 0);
365     assert!(fty.results().len() == 0);
366 
367     Ok(())
368 }
369 
370 #[test]
gc_store_with_table_initializers() -> Result<()>371 fn gc_store_with_table_initializers() -> Result<()> {
372     let mut config = Config::new();
373     config.wasm_gc(true);
374     config.wasm_function_references(true);
375     let engine = Engine::new(&config)?;
376 
377     let test = |wat: &str| -> Result<()> {
378         let module = Module::new(&engine, wat)?;
379         Instance::new(&mut Store::new(&engine, ()), &module, &[])?;
380         Ok(())
381     };
382 
383     test("(module (table 1 i31ref))")?;
384     test("(module (table 1 i31ref (ref.i31 (i32.const 1))))")?;
385     test("(module (table 1 i31ref (ref.null i31)))")?;
386 
387     Ok(())
388 }
389