Coverage for /home/runner/work/zserio/zserio/compiler/extensions/python/runtime/tests/test_hashcode.py: 100%

148 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-07-18 11:41 +0000

1import enum 

2import unittest 

3 

4from zserio.array import Array, SignedBitFieldArrayTraits 

5from zserio.bitbuffer import BitBuffer 

6from zserio.hashcode import ( 

7 HASH_SEED, 

8 HASH_PRIME_NUMBER, 

9 calc_hashcode_bool, 

10 calc_hashcode_int32, 

11 calc_hashcode_int64, 

12 calc_hashcode_float32, 

13 calc_hashcode_float64, 

14 calc_hashcode_bytes, 

15 calc_hashcode_string, 

16 calc_hashcode_object, 

17 calc_hashcode_bool_array, 

18 calc_hashcode_int_array, 

19 calc_hashcode_float32_array, 

20 calc_hashcode_float64_array, 

21 calc_hashcode_bytes_array, 

22 calc_hashcode_string_array, 

23 calc_hashcode_object_array, 

24) 

25from zserio.float import float_to_uint32, float_to_uint64 

26 

27 

28class Color(enum.Enum): 

29 NONE = 0 

30 RED = 2 

31 BLUE = 3 

32 BLACK = 7 

33 

34 def __hash__(self): 

35 result = HASH_SEED 

36 result = calc_hashcode_int32(result, self.value) 

37 return result 

38 

39 

40class Permissions: 

41 def __init__(self, value): 

42 self._value = value 

43 

44 def __hash__(self): 

45 result = HASH_SEED 

46 result = calc_hashcode_int32(result, self.value) 

47 return result 

48 

49 @property 

50 def value(self): 

51 return self._value 

52 

53 class Values: 

54 READ = None 

55 WRITE = None 

56 CREATE = None 

57 

58 

59Permissions.Values.READ = Permissions(1) 

60Permissions.Values.WRITE = Permissions(2) 

61Permissions.Values.CREATE = Permissions(4) 

62 

63 

64class DummyObject: 

65 def __init__(self, hash_code): 

66 self._hash_code = hash_code 

67 

68 def __hash__(self): 

69 return self._hash_code 

70 

71 

72class HashCodeTest(unittest.TestCase): 

73 

74 def test_bool_type(self): 

75 hash_seed = 1 

76 bool_value = True 

77 self.assertEqual(HASH_PRIME_NUMBER + 1, calc_hashcode_bool(hash_seed, bool_value)) 

78 

79 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_bool(hash_seed, None)) 

80 

81 def test_int_type(self): 

82 hash_seed = 1 

83 int_value = 10 

84 self.assertEqual(HASH_PRIME_NUMBER + 10, calc_hashcode_int32(hash_seed, int_value)) 

85 

86 int_value = -1 

87 self.assertEqual(HASH_PRIME_NUMBER - 1, calc_hashcode_int32(hash_seed, int_value)) 

88 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_int64(hash_seed, int_value)) 

89 

90 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_int32(hash_seed, None)) 

91 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_int64(hash_seed, None)) 

92 

93 def test_float32_type(self): 

94 hash_seed = 1 

95 float_value = 10.0 

96 self.assertEqual( 

97 HASH_PRIME_NUMBER + float_to_uint32(float_value), 

98 calc_hashcode_float32(hash_seed, float_value), 

99 ) 

100 

101 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_float32(hash_seed, None)) 

102 

103 def test_float64_type(self): 

104 hash_seed = 1 

105 float_value = 10.0 

106 uint64_value = float_to_uint64(float_value) 

107 expected_hash_code = ( 

108 HASH_PRIME_NUMBER + ((uint64_value & 0xFFFFFFFF) ^ ((uint64_value & 0xFFFFFFFFFFFFFFFF) >> 32)) 

109 ) & 0xFFFFFFFF 

110 self.assertEqual(expected_hash_code, calc_hashcode_float64(hash_seed, float_value)) 

111 

112 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_float64(hash_seed, None)) 

113 

114 def test_bytes_type(self): 

115 hash_seed = 1 

116 bytes_value = bytearray([1]) 

117 self.assertEqual(HASH_PRIME_NUMBER + 1, calc_hashcode_bytes(hash_seed, bytes_value)) 

118 

119 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_bytes(hash_seed, None)) 

120 

121 def test_string_type(self): 

122 hash_seed = 1 

123 string_value = "0" 

124 self.assertEqual(HASH_PRIME_NUMBER + ord("0"), calc_hashcode_string(hash_seed, string_value)) 

125 

126 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_string(hash_seed, None)) 

127 

128 def test_bitbuffer_type(self): 

129 hash_seed = 1 

130 bitbuffer_value = BitBuffer(bytes()) 

131 self.assertEqual( 

132 HASH_PRIME_NUMBER + HASH_SEED, 

133 calc_hashcode_object(hash_seed, bitbuffer_value), 

134 ) 

135 

136 def test_enum_type(self): 

137 hash_seed = 1 

138 self.assertEqual( 

139 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Color.NONE.value), 

140 calc_hashcode_object(hash_seed, Color.NONE), 

141 ) 

142 self.assertEqual( 

143 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Color.RED.value), 

144 calc_hashcode_object(hash_seed, Color.RED), 

145 ) 

146 self.assertEqual( 

147 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Color.BLUE.value), 

148 calc_hashcode_object(hash_seed, Color.BLUE), 

149 ) 

150 self.assertEqual( 

151 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Color.BLACK.value), 

152 calc_hashcode_object(hash_seed, Color.BLACK), 

153 ) 

154 

155 def test_bitmask_type(self): 

156 hash_seed = 1 

157 self.assertEqual( 

158 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Permissions.Values.READ.value), 

159 calc_hashcode_object(hash_seed, Permissions.Values.READ), 

160 ) 

161 self.assertEqual( 

162 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Permissions.Values.WRITE.value), 

163 calc_hashcode_object(hash_seed, Permissions.Values.WRITE), 

164 ) 

165 self.assertEqual( 

166 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Permissions.Values.CREATE.value), 

167 calc_hashcode_object(hash_seed, Permissions.Values.CREATE), 

168 ) 

169 

170 def test_object_type(self): 

171 hash_seed = 1 

172 object_value = DummyObject(10) 

173 self.assertEqual(HASH_PRIME_NUMBER + 10, calc_hashcode_object(hash_seed, object_value)) 

174 

175 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_object(hash_seed, None)) 

176 

177 def test_array_type(self): 

178 hash_seed = 1 

179 array_value = Array(SignedBitFieldArrayTraits(32), [3, 7]) 

180 

181 raw_array_hash_code = (HASH_PRIME_NUMBER * HASH_SEED + 3) * HASH_PRIME_NUMBER + 7 

182 self.assertEqual( 

183 HASH_PRIME_NUMBER + raw_array_hash_code, 

184 calc_hashcode_object(hash_seed, array_value), 

185 ) 

186 

187 def test_bool_array_type(self): 

188 hash_seed = 1 

189 bool_array_value = [False, True] 

190 self.assertEqual( 

191 (HASH_PRIME_NUMBER + 0) * HASH_PRIME_NUMBER + 1, 

192 calc_hashcode_bool_array(hash_seed, bool_array_value), 

193 ) 

194 

195 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_bool_array(hash_seed, None)) 

196 

197 def test_int_array_type(self): 

198 hash_seed = 1 

199 int_array_value = [3, 7] 

200 self.assertEqual( 

201 (HASH_PRIME_NUMBER + 3) * HASH_PRIME_NUMBER + 7, 

202 calc_hashcode_int_array(hash_seed, int_array_value), 

203 ) 

204 

205 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_int_array(hash_seed, None)) 

206 

207 def test_float32_array_type(self): 

208 hash_seed = 1 

209 float32_array_value = [10.0] 

210 self.assertEqual( 

211 HASH_PRIME_NUMBER + float_to_uint32(float32_array_value[0]), 

212 calc_hashcode_float32_array(hash_seed, float32_array_value), 

213 ) 

214 

215 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_float32_array(hash_seed, None)) 

216 

217 def test_float64_array_type(self): 

218 hash_seed = 1 

219 float64_array_value = [10.0] 

220 uint64_value = float_to_uint64(float64_array_value[0]) 

221 expected_hash_code = ( 

222 HASH_PRIME_NUMBER + ((uint64_value & 0xFFFFFFFF) ^ ((uint64_value & 0xFFFFFFFFFFFFFFFF) >> 32)) 

223 ) & 0xFFFFFFFF 

224 self.assertEqual( 

225 expected_hash_code, 

226 calc_hashcode_float64_array(hash_seed, float64_array_value), 

227 ) 

228 

229 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_float64_array(hash_seed, None)) 

230 

231 def test_bytes_array_type(self): 

232 hash_seed = 1 

233 bytes_value = [bytearray([1])] 

234 self.assertEqual(HASH_PRIME_NUMBER + 1, calc_hashcode_bytes_array(hash_seed, bytes_value)) 

235 

236 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_bytes_array(hash_seed, None)) 

237 

238 def test_str_array_type(self): 

239 hash_seed = 1 

240 str_array_value = ["0"] 

241 self.assertEqual( 

242 HASH_PRIME_NUMBER + ord(str_array_value[0]), 

243 calc_hashcode_string_array(hash_seed, str_array_value), 

244 ) 

245 

246 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_string_array(hash_seed, None)) 

247 

248 def test_bitbuffer_array_type(self): 

249 hash_seed = 1 

250 bitbuffer_array_value = [BitBuffer(bytes())] 

251 self.assertEqual( 

252 HASH_PRIME_NUMBER + HASH_SEED, 

253 calc_hashcode_object_array(hash_seed, bitbuffer_array_value), 

254 ) 

255 

256 def test_enum_array_type(self): 

257 hash_seed = 1 

258 enum_array_value = [Color.NONE] 

259 self.assertEqual( 

260 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Color.NONE.value), 

261 calc_hashcode_object_array(hash_seed, enum_array_value), 

262 ) 

263 

264 def test_bitmask_array_type(self): 

265 hash_seed = 1 

266 bitmask_array_value = [Permissions.Values.READ] 

267 self.assertEqual( 

268 HASH_PRIME_NUMBER + (HASH_PRIME_NUMBER * HASH_SEED + Permissions.Values.READ.value), 

269 calc_hashcode_object_array(hash_seed, bitmask_array_value), 

270 ) 

271 

272 def test_object_array_type(self): 

273 hash_seed = 1 

274 object_array_value = [DummyObject(3), DummyObject(7)] 

275 self.assertEqual( 

276 (HASH_PRIME_NUMBER + 3) * HASH_PRIME_NUMBER + 7, 

277 calc_hashcode_object_array(hash_seed, object_array_value), 

278 ) 

279 

280 self.assertEqual(HASH_PRIME_NUMBER, calc_hashcode_object_array(hash_seed, None))