Coverage for tests/test_refs.py: 98%
107 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-12-01 19:40 +0000
« prev ^ index » next coverage.py v7.11.3, created at 2025-12-01 19:40 +0000
1import unittest
2from typing import cast
3import gc
5from wasmtime import *
8def ref_types_store():
9 config = Config()
10 config.wasm_reference_types = True
11 engine = Engine(config)
12 return Store(engine)
15def compile_and_instantiate(wat):
16 store = ref_types_store()
17 module = Module(store.engine, wat)
18 return (Instance(store, module, []), store)
21class SetHitOnDrop:
22 def __init__(self, obj):
23 obj['hit'] = False
24 self.obj = obj
26 def __del__(self):
27 self.obj['hit'] = True
30class TestExternRef(unittest.TestCase):
31 def test_smoke(self):
32 (instance, store) = compile_and_instantiate(
33 """
34 (module
35 (func (export "f") (param externref) (result externref)
36 local.get 0
37 )
38 (func (export "null_externref") (result externref)
39 ref.null extern
40 )
41 )
42 """
43 )
45 null_externref = instance.exports(store).get("null_externref")
46 self.assertEqual(null_externref(store), None)
48 f = instance.exports(store).get("f")
49 externs = [42, True, False, None, "Hello", {"x": 1}, [12, 13, 14], Config()]
51 for extern in externs:
52 # We can create an externref for the given extern data.
53 ref = Val.externref(extern)
55 # And the externref's value is our extern data.
56 self.assertEqual(ref.value, extern)
58 # And we can round trip the externref through Wasm and still get our
59 # extern data.
60 result = f(store, ref)
61 self.assertEqual(result, extern)
63 def test_int_to_externref(self):
64 wat = """
65 (module
66 (import "env" "int_to_ref" (func $int_to_ref (param $a externref) (result externref)))
67 (export "test" (func $int_to_ref))
68 )
69 """
70 config = Config()
71 config.wasm_reference_types = True
72 engine = Engine(config)
73 store = Store(engine)
74 module = Module(store.engine, wat)
75 linker = Linker(engine)
76 ftype = FuncType([ValType.externref()], [ValType.externref()])
77 linker.define_func("env", "int_to_ref", ftype, lambda x: x)
78 instance = linker.instantiate(store, module)
79 f: Func
80 f = cast(Func, instance.exports(store).get("test"))
81 f(store, 5)
82 f = cast(Func, instance.exports(store).get("test"))
83 f(store, 5.7)
85 def test_externref_tables(self):
86 store = ref_types_store()
87 ty = TableType(ValType.externref(), Limits(10, None))
88 table = Table(store, ty, "init")
90 for i in range(0, 10):
91 self.assertEqual(table.get(store, i), "init")
93 table.grow(store, 2, "grown")
95 for i in range(0, 10):
96 self.assertEqual(table.get(store, i), "init")
97 for i in range(10, 12):
98 self.assertEqual(table.get(store, i), "grown")
100 table.set(store, 7, "lucky")
102 for i in range(0, 7):
103 self.assertEqual(table.get(store, i), "init")
104 self.assertEqual(table.get(store, 7), "lucky")
105 for i in range(8, 10):
106 self.assertEqual(table.get(store, i), "init")
107 for i in range(10, 12):
108 self.assertEqual(table.get(store, i), "grown")
110 def test_externref_in_global(self):
111 store = ref_types_store()
112 ty = GlobalType(ValType.externref(), True)
113 g = Global(store, ty, Val.externref("hello"))
114 self.assertEqual(g.value(store), "hello")
115 g.set_value(store, "goodbye")
116 self.assertEqual(g.value(store), "goodbye")
118 def test_dtor_global(self):
119 obj = {} # type: ignore
120 store = ref_types_store()
121 ty = GlobalType(ValType.externref(), True)
122 g = Global(store, ty, Val.externref(SetHitOnDrop(obj)))
123 assert(not obj['hit'])
124 g.set_value(store, None)
125 store.gc()
126 gc.collect()
127 assert(obj['hit'])
129 def test_dtor_func(self):
130 (instance, store) = compile_and_instantiate(
131 """
132 (module
133 (func (export "f") (param externref))
134 )
135 """
136 )
138 f = instance.exports(store).get("f")
139 obj = {} # type: ignore
140 f(store, SetHitOnDrop(obj))
141 store.gc()
142 gc.collect()
143 assert(obj['hit'])
146class TestFuncRef(unittest.TestCase):
147 def test_smoke(self):
148 (instance, store) = compile_and_instantiate(
149 """
150 (module
151 (func (export \"f\") (param funcref) (result funcref)
152 local.get 0
153 )
154 (func (export "null_funcref") (result funcref)
155 ref.null func
156 )
157 )
158 """
159 )
161 null_funcref = instance.exports(store).get("null_funcref")
162 self.assertEqual(null_funcref(store), None)
164 f = instance.exports(store).get("f")
166 ty = FuncType([], [ValType.i32()])
167 g = Func(store, ty, lambda: 42)
169 # We can create a funcref.
170 ref_g_val = Val.funcref(g)
172 # And the funcref's points to `g`.
173 g2 = ref_g_val.as_funcref()
174 if isinstance(g2, Func):
175 self.assertEqual(g2(store), 42)
176 else:
177 self.fail("g2 is not a funcref: g2 = %r" % g2)
179 # And we can round trip the funcref through Wasm.
180 g3 = f(store, ref_g_val)
181 if isinstance(g3, Func):
182 self.assertEqual(g3(store), 42)
183 else:
184 self.fail("g3 is not a funcref: g3 = %r" % g3)