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

208 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-12-05 10:43 +0000

1import unittest 

2 

3from zserio.bitbuffer import BitBuffer 

4from zserio.bitwriter import BitStreamWriter 

5from zserio.exception import PythonRuntimeException 

6from zserio.limits import ( 

7 VARINT16_MIN, 

8 VARINT16_MAX, 

9 VARINT32_MIN, 

10 VARINT32_MAX, 

11 VARINT64_MIN, 

12 VARINT64_MAX, 

13 VARINT_MIN, 

14 VARINT_MAX, 

15 VARUINT16_MIN, 

16 VARUINT16_MAX, 

17 VARUINT32_MIN, 

18 VARUINT32_MAX, 

19 VARUINT64_MIN, 

20 VARUINT64_MAX, 

21 VARUINT_MIN, 

22 VARUINT_MAX, 

23 VARSIZE_MIN, 

24 VARSIZE_MAX, 

25) 

26 

27 

28class BitStreamWriterTest(unittest.TestCase): 

29 

30 def test_write_unaligned_data(self): 

31 # number expected to be written at offset 

32 test_value = 123 

33 

34 for offset in range(65): 

35 writer = BitStreamWriter() 

36 

37 if offset != 0: 

38 writer.write_bits(0, offset) 

39 writer.write_bits(test_value, 8) 

40 

41 # check written value 

42 buffer = writer.byte_array 

43 written_test_value = buffer[offset // 8] << (offset % 8) 

44 if offset % 8 != 0: 

45 written_test_value |= buffer[offset // 8 + 1] >> (8 - (offset % 8)) 

46 self.assertEqual(test_value, written_test_value, msg="Offset: " + str(offset)) 

47 

48 def test_write_bits(self): 

49 writer = BitStreamWriter() 

50 writer.write_bits(0, 8) 

51 writer.write_bits(255, 8) 

52 writer.write_bits(1, 1) 

53 writer.write_bits(0x3F, 6) 

54 writer.write_bits(1, 1) 

55 self.assertEqual(b"\x00\xff\xff", writer.byte_array) 

56 self.assertEqual(3 * 8, writer.bitposition) 

57 writer.write_bits(0xFF, 8) 

58 self.assertEqual(b"\x00\xff\xff\xff", writer.byte_array) 

59 self.assertEqual(4 * 8, writer.bitposition) 

60 writer.write_bits(0, 4) 

61 self.assertEqual(b"\x00\xff\xff\xff\x00", writer.byte_array) 

62 self.assertEqual(4 * 8 + 4, writer.bitposition) 

63 writer.write_bits(0x0F, 4) 

64 self.assertEqual(b"\x00\xff\xff\xff\x0f", writer.byte_array) 

65 self.assertEqual(5 * 8, writer.bitposition) 

66 writer.write_bits(0x80, 8) 

67 self.assertEqual(b"\x00\xff\xff\xff\x0f\x80", writer.byte_array) 

68 self.assertEqual(6 * 8, writer.bitposition) 

69 

70 for numbits in [-1, 0, 65]: 

71 with self.assertRaises(PythonRuntimeException): 

72 writer.write_bits(0, numbits) 

73 

74 with self.assertRaises(PythonRuntimeException): 

75 writer.write_bits(1, numbits) 

76 

77 with self.assertRaises(PythonRuntimeException): 

78 writer.write_bits(256, 8) # above the upper bound 

79 

80 with self.assertRaises(PythonRuntimeException): 

81 writer.write_bits(-1, 8) # below the lower bound 

82 

83 def test_write_signed_bits(self): 

84 writer = BitStreamWriter() 

85 writer.write_signed_bits(0, 1) 

86 writer.write_signed_bits(-1, 2) 

87 writer.write_signed_bits(-1, 5) 

88 self.assertEqual(b"\x7f", writer.byte_array) 

89 self.assertEqual(8, writer.bitposition) 

90 writer.write_signed_bits(-1, 1) 

91 writer.write_signed_bits(-1, 7) 

92 self.assertEqual(b"\x7f\xff", writer.byte_array) 

93 self.assertEqual(16, writer.bitposition) 

94 

95 for numbits in [-1, 0, 65]: 

96 with self.assertRaises(PythonRuntimeException): 

97 writer.write_signed_bits(0, numbits) 

98 

99 with self.assertRaises(PythonRuntimeException): 

100 writer.write_signed_bits(1, numbits) 

101 

102 with self.assertRaises(PythonRuntimeException): 

103 writer.write_signed_bits(1, 1) # above the upper bound 

104 

105 with self.assertRaises(PythonRuntimeException): 

106 writer.write_signed_bits(128, 8) # above the upper bound 

107 

108 with self.assertRaises(PythonRuntimeException): 

109 writer.write_signed_bits(-129, 8) # below the lower bound 

110 

111 def test_write_varint16(self): 

112 writer = BitStreamWriter() 

113 writer.write_varint16(0) 

114 self.assertEqual(8, writer.bitposition) 

115 self.assertEqual(b"\x00", writer.byte_array) 

116 with self.assertRaises(PythonRuntimeException): 

117 writer.write_varint16(VARINT16_MIN - 1) 

118 with self.assertRaises(PythonRuntimeException): 

119 writer.write_varint16(VARINT16_MAX + 1) 

120 

121 def test_write_varint32(self): 

122 writer = BitStreamWriter() 

123 writer.write_varint32(0) 

124 self.assertEqual(8, writer.bitposition) 

125 self.assertEqual(b"\x00", writer.byte_array) 

126 with self.assertRaises(PythonRuntimeException): 

127 writer.write_varint32(VARINT32_MIN - 1) 

128 with self.assertRaises(PythonRuntimeException): 

129 writer.write_varint32(VARINT32_MAX + 1) 

130 

131 def test_write_varint64(self): 

132 writer = BitStreamWriter() 

133 writer.write_varint64(0) 

134 self.assertEqual(8, writer.bitposition) 

135 self.assertEqual(b"\x00", writer.byte_array) 

136 with self.assertRaises(PythonRuntimeException): 

137 writer.write_varint64(VARINT64_MIN - 1) 

138 with self.assertRaises(PythonRuntimeException): 

139 writer.write_varint64(VARINT64_MAX + 1) 

140 

141 def test_write_varint(self): 

142 writer = BitStreamWriter() 

143 writer.write_varint(0) 

144 self.assertEqual(b"\x00", writer.byte_array) 

145 self.assertEqual(8, writer.bitposition) 

146 writer.write_varint(VARINT_MIN) 

147 self.assertEqual(16, writer.bitposition) 

148 self.assertEqual(b"\x00\x80", writer.byte_array) # INT64_MIN is encoded as -0 

149 with self.assertRaises(PythonRuntimeException): 

150 writer.write_varint(VARINT_MIN - 1) 

151 with self.assertRaises(PythonRuntimeException): 

152 writer.write_varint(VARINT_MAX + 1) 

153 

154 def test_write_varuint16(self): 

155 writer = BitStreamWriter() 

156 writer.write_varuint16(0) 

157 self.assertEqual(8, writer.bitposition) 

158 self.assertEqual(b"\x00", writer.byte_array) 

159 with self.assertRaises(PythonRuntimeException): 

160 writer.write_varuint16(VARUINT16_MIN - 1) 

161 with self.assertRaises(PythonRuntimeException): 

162 writer.write_varuint16(VARUINT16_MAX + 1) 

163 

164 def test_write_varuint32(self): 

165 writer = BitStreamWriter() 

166 writer.write_varuint32(0) 

167 self.assertEqual(8, writer.bitposition) 

168 self.assertEqual(b"\x00", writer.byte_array) 

169 with self.assertRaises(PythonRuntimeException): 

170 writer.write_varuint32(VARUINT32_MIN - 1) 

171 with self.assertRaises(PythonRuntimeException): 

172 writer.write_varuint32(VARUINT32_MAX + 1) 

173 

174 def test_write_varuint64(self): 

175 writer = BitStreamWriter() 

176 writer.write_varuint64(0) 

177 self.assertEqual(8, writer.bitposition) 

178 self.assertEqual(b"\x00", writer.byte_array) 

179 with self.assertRaises(PythonRuntimeException): 

180 writer.write_varuint64(VARUINT64_MIN - 1) 

181 with self.assertRaises(PythonRuntimeException): 

182 writer.write_varuint64(VARUINT64_MAX + 1) 

183 

184 def test_write_varuint(self): 

185 writer = BitStreamWriter() 

186 writer.write_varuint(0) 

187 self.assertEqual(8, writer.bitposition) 

188 self.assertEqual(b"\x00", writer.byte_array) 

189 with self.assertRaises(PythonRuntimeException): 

190 writer.write_varuint(VARUINT_MIN - 1) 

191 with self.assertRaises(PythonRuntimeException): 

192 writer.write_varuint(VARUINT_MAX + 1) 

193 

194 def test_write_varsize(self): 

195 writer = BitStreamWriter() 

196 writer.write_varsize(0) 

197 self.assertEqual(8, writer.bitposition) 

198 self.assertEqual(b"\x00", writer.byte_array) 

199 with self.assertRaises(PythonRuntimeException): 

200 writer.write_varsize(VARSIZE_MIN - 1) 

201 with self.assertRaises(PythonRuntimeException): 

202 writer.write_varsize(VARSIZE_MAX + 1) 

203 

204 def test_write_float16(self): 

205 writer = BitStreamWriter() 

206 writer.write_float16(0) 

207 self.assertEqual(16, writer.bitposition) 

208 self.assertEqual(b"\x00\x00", writer.byte_array) 

209 

210 def test_write_float32(self): 

211 writer = BitStreamWriter() 

212 writer.write_float32(0) 

213 self.assertEqual(32, writer.bitposition) 

214 self.assertEqual(b"\x00\x00\x00\x00", writer.byte_array) 

215 

216 def test_write_float64(self): 

217 writer = BitStreamWriter() 

218 writer.write_float64(0) 

219 self.assertEqual(64, writer.bitposition) 

220 self.assertEqual(b"\x00\x00\x00\x00\x00\x00\x00\x00", writer.byte_array) 

221 

222 def test_write_string(self): 

223 writer = BitStreamWriter() 

224 writer.write_string("") 

225 self.assertEqual(8, writer.bitposition) # length 0 

226 self.assertEqual(b"\x00", writer.byte_array) 

227 

228 def test_write_bool(self): 

229 writer = BitStreamWriter() 

230 writer.write_bool(True) 

231 writer.write_bool(False) 

232 writer.write_bool(True) 

233 writer.write_bool(False) 

234 writer.write_bool(True) 

235 writer.write_bool(False) 

236 self.assertEqual(6, writer.bitposition) 

237 self.assertEqual(b"\xA8", writer.byte_array) 

238 

239 def test_write_bitbuffer(self): 

240 writer = BitStreamWriter() 

241 writer.write_bitbuffer(BitBuffer(bytes([0xAB, 0xE0]), 11)) 

242 writer.write_bitbuffer(BitBuffer(bytes([0x00, 0xFE]), 15)) 

243 self.assertEqual(8 + 11 + 8 + 15, writer.bitposition) 

244 self.assertEqual(b"\x0B\xAB\xE1\xE0\x1F\xC0", writer.byte_array) 

245 

246 def test_byte_array(self): 

247 writer = BitStreamWriter() 

248 self.assertEqual(b"", writer.byte_array) 

249 

250 def test_bitposition(self): 

251 writer = BitStreamWriter() 

252 self.assertEqual(0, writer.bitposition) 

253 

254 def test_alignto(self): 

255 writer = BitStreamWriter() 

256 writer.alignto(8) 

257 self.assertEqual(0, writer.bitposition) 

258 writer.alignto(2) 

259 self.assertEqual(0, writer.bitposition) 

260 writer.write_bool(True) 

261 writer.alignto(8) 

262 self.assertEqual(8, writer.bitposition) 

263 writer.write_bool(True) 

264 writer.alignto(2) 

265 self.assertEqual(10, writer.bitposition)