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