Coverage for tests/test_func.py: 100%

115 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-20 16:25 +0000

1import unittest 

2 

3from wasmtime import * 

4 

5 

6class TestFunc(unittest.TestCase): 

7 def test_smoke(self): 

8 store = Store() 

9 ty = FuncType([], []) 

10 func = Func(store, ty, lambda: None) 

11 func(store) 

12 self.assertTrue(isinstance(func.type(store), FuncType)) 

13 

14 def test_add(self): 

15 store = Store() 

16 ty = FuncType([ValType.i32(), ValType.i32()], [ValType.i32()]) 

17 func = Func(store, ty, lambda a, b: a + b) 

18 self.assertEqual(func(store, 1, 2), 3) 

19 

20 def test_calls(self): 

21 store = Store() 

22 ty = FuncType([ValType.i32()], []) 

23 func = Func(store, ty, lambda a: self.assertEqual(a, 1)) 

24 func(store, 1) 

25 

26 ty = FuncType([ValType.i64()], []) 

27 func = Func(store, ty, lambda a: self.assertEqual(a, 2)) 

28 func(store, Val.i64(2)) 

29 

30 ty = FuncType([ValType.f32()], []) 

31 func = Func(store, ty, lambda a: self.assertEqual(a, 3.0)) 

32 func(store, 3.0) 

33 

34 ty = FuncType([ValType.f64()], []) 

35 func = Func(store, ty, lambda a: self.assertEqual(a, 4.0)) 

36 func(store, 4.0) 

37 

38 def test_multi_return(self): 

39 store = Store() 

40 ty = FuncType([], [ValType.i32(), ValType.i32()]) 

41 func = Func(store, ty, lambda: [1, 2]) 

42 self.assertEqual(func(store), [1, 2]) 

43 

44 def test_errors(self): 

45 store = Store() 

46 ty = FuncType([], []) 

47 with self.assertRaises(TypeError): 

48 Func(1, ty, lambda: None) # type: ignore 

49 with self.assertRaises(TypeError): 

50 Func(store, 1, lambda: None) # type: ignore 

51 func = Func(store, ty, lambda: None) 

52 with self.assertRaises(WasmtimeError): 

53 func(store, 2) 

54 

55 ty = FuncType([ValType.i32()], []) 

56 func = Func(store, ty, lambda: None) 

57 with self.assertRaises(TypeError): 

58 func(store, 3.0) 

59 with self.assertRaises(TypeError): 

60 func(store, Val.i64(3)) 

61 ty = FuncType([ValType.i32()], []) 

62 

63 func = Func(store, ty, lambda x: x) 

64 with self.assertRaises(WasmtimeError, msg="produced results"): 

65 func(store, 1) 

66 

67 def test_produce_wrong(self): 

68 store = Store() 

69 ty = FuncType([], [ValType.i32(), ValType.i32()]) 

70 func = Func(store, ty, lambda: 1) 

71 with self.assertRaises(TypeError, msg="has no len"): 

72 func(store) 

73 func = Func(store, ty, lambda: [1, 2, 3]) 

74 with self.assertRaises(WasmtimeError, msg="wrong number of results"): 

75 func(store) 

76 

77 def test_host_exception(self): 

78 store = Store() 

79 ty = FuncType([], []) 

80 

81 def do_raise(): 

82 raise Exception("hello") 

83 

84 func = Func(store, ty, do_raise) 

85 with self.assertRaises(Exception, msg="hello"): 

86 func(store) 

87 

88 def test_type(self): 

89 store = Store() 

90 i32 = ValType.i32() 

91 i64 = ValType.i64() 

92 f32 = ValType.f32() 

93 f64 = ValType.f64() 

94 ty = FuncType([i32, i64, f32, f64], [f64, f32, i64, i32]) 

95 

96 def rev(*args): 

97 ret = list(args) 

98 ret.reverse() 

99 return ret 

100 

101 func = Func(store, ty, rev) 

102 self.assertEqual(func(store, 1, 2, 3.0, 4.0), [4.0, 3.0, 2, 1]) 

103 

104 def test_access_caller(self): 

105 # Test that we get *something* 

106 store = Store() 

107 

108 def runtest(caller): 

109 self.assertEqual(caller.get(''), None) 

110 self.assertEqual(caller.get('x'), None) 

111 self.assertEqual(caller.get('y'), None) 

112 

113 Func(store, FuncType([], []), runtest, access_caller=True)(store) 

114 

115 hit = {} 

116 

117 # Test that `Caller` works and that it's invalidated 

118 def runtest2(caller): 

119 hit['yes'] = True 

120 hit['caller'] = caller 

121 

122 self.assertTrue(caller.get('bar') is None) 

123 mem = caller.get('foo') 

124 self.assertTrue(isinstance(mem, Memory)) 

125 

126 self.assertEqual(mem.data_ptr(caller)[0], ord('f')) 

127 self.assertEqual(mem.data_ptr(caller)[1], ord('o')) 

128 self.assertEqual(mem.data_ptr(caller)[2], ord('o')) 

129 self.assertEqual(mem.data_ptr(caller)[3], 0) 

130 

131 module = Module(store.engine, """ 

132 (module 

133 (import "" "" (func)) 

134 (memory (export "foo") 1) 

135 (start 0) 

136 (data (i32.const 0) "foo") 

137 ) 

138 """) 

139 func = Func(store, FuncType([], []), runtest2, access_caller=True) 

140 Instance(store, module, [func]) 

141 self.assertTrue(hit['yes']) 

142 self.assertTrue(hit['caller'].get('foo') is None) # type: ignore 

143 

144 # Test that `Caller` is invalidated even on exceptions 

145 hit2 = {} 

146 

147 def runtest3(caller): 

148 hit2['caller'] = caller 

149 self.assertTrue(caller['foo'] is not None) 

150 raise WasmtimeError('foo') 

151 

152 func = Func(store, FuncType([], []), runtest3, access_caller=True) 

153 with self.assertRaises(WasmtimeError, msg='foo'): 

154 Instance(store, module, [func]) 

155 self.assertTrue(hit2['caller'].get('foo') is None)