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

204 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-04-30 09:38 +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 with self.assertRaises(PythonRuntimeException): 

71 writer.write_bits(1, 0) # zero bits! 

72 

73 with self.assertRaises(PythonRuntimeException): 

74 writer.write_bits(1, -1) # negative number of bits! 

75 

76 with self.assertRaises(PythonRuntimeException): 

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

78 

79 with self.assertRaises(PythonRuntimeException): 

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

81 

82 def test_write_signed_bits(self): 

83 writer = BitStreamWriter() 

84 writer.write_signed_bits(0, 1) 

85 writer.write_signed_bits(-1, 2) 

86 writer.write_signed_bits(-1, 5) 

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

88 self.assertEqual(8, writer.bitposition) 

89 writer.write_signed_bits(-1, 1) 

90 writer.write_signed_bits(-1, 7) 

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

92 self.assertEqual(16, writer.bitposition) 

93 

94 with self.assertRaises(PythonRuntimeException): 

95 writer.write_signed_bits(1, 0) # zero bits! 

96 

97 with self.assertRaises(PythonRuntimeException): 

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

99 

100 with self.assertRaises(PythonRuntimeException): 

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

102 

103 with self.assertRaises(PythonRuntimeException): 

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

105 

106 def test_write_varint16(self): 

107 writer = BitStreamWriter() 

108 writer.write_varint16(0) 

109 self.assertEqual(8, writer.bitposition) 

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

111 with self.assertRaises(PythonRuntimeException): 

112 writer.write_varint16(VARINT16_MIN - 1) 

113 with self.assertRaises(PythonRuntimeException): 

114 writer.write_varint16(VARINT16_MAX + 1) 

115 

116 def test_write_varint32(self): 

117 writer = BitStreamWriter() 

118 writer.write_varint32(0) 

119 self.assertEqual(8, writer.bitposition) 

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

121 with self.assertRaises(PythonRuntimeException): 

122 writer.write_varint32(VARINT32_MIN - 1) 

123 with self.assertRaises(PythonRuntimeException): 

124 writer.write_varint32(VARINT32_MAX + 1) 

125 

126 def test_write_varint64(self): 

127 writer = BitStreamWriter() 

128 writer.write_varint64(0) 

129 self.assertEqual(8, writer.bitposition) 

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

131 with self.assertRaises(PythonRuntimeException): 

132 writer.write_varint64(VARINT64_MIN - 1) 

133 with self.assertRaises(PythonRuntimeException): 

134 writer.write_varint64(VARINT64_MAX + 1) 

135 

136 def test_write_varint(self): 

137 writer = BitStreamWriter() 

138 writer.write_varint(0) 

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

140 self.assertEqual(8, writer.bitposition) 

141 writer.write_varint(VARINT_MIN) 

142 self.assertEqual(16, writer.bitposition) 

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

144 with self.assertRaises(PythonRuntimeException): 

145 writer.write_varint(VARINT_MIN - 1) 

146 with self.assertRaises(PythonRuntimeException): 

147 writer.write_varint(VARINT_MAX + 1) 

148 

149 def test_write_varuint16(self): 

150 writer = BitStreamWriter() 

151 writer.write_varuint16(0) 

152 self.assertEqual(8, writer.bitposition) 

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

154 with self.assertRaises(PythonRuntimeException): 

155 writer.write_varuint16(VARUINT16_MIN - 1) 

156 with self.assertRaises(PythonRuntimeException): 

157 writer.write_varuint16(VARUINT16_MAX + 1) 

158 

159 def test_write_varuint32(self): 

160 writer = BitStreamWriter() 

161 writer.write_varuint32(0) 

162 self.assertEqual(8, writer.bitposition) 

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

164 with self.assertRaises(PythonRuntimeException): 

165 writer.write_varuint32(VARUINT32_MIN - 1) 

166 with self.assertRaises(PythonRuntimeException): 

167 writer.write_varuint32(VARUINT32_MAX + 1) 

168 

169 def test_write_varuint64(self): 

170 writer = BitStreamWriter() 

171 writer.write_varuint64(0) 

172 self.assertEqual(8, writer.bitposition) 

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

174 with self.assertRaises(PythonRuntimeException): 

175 writer.write_varuint64(VARUINT64_MIN - 1) 

176 with self.assertRaises(PythonRuntimeException): 

177 writer.write_varuint64(VARUINT64_MAX + 1) 

178 

179 def test_write_varuint(self): 

180 writer = BitStreamWriter() 

181 writer.write_varuint(0) 

182 self.assertEqual(8, writer.bitposition) 

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

184 with self.assertRaises(PythonRuntimeException): 

185 writer.write_varuint(VARUINT_MIN - 1) 

186 with self.assertRaises(PythonRuntimeException): 

187 writer.write_varuint(VARUINT_MAX + 1) 

188 

189 def test_write_varsize(self): 

190 writer = BitStreamWriter() 

191 writer.write_varsize(0) 

192 self.assertEqual(8, writer.bitposition) 

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

194 with self.assertRaises(PythonRuntimeException): 

195 writer.write_varsize(VARSIZE_MIN - 1) 

196 with self.assertRaises(PythonRuntimeException): 

197 writer.write_varsize(VARSIZE_MAX + 1) 

198 

199 def test_write_float16(self): 

200 writer = BitStreamWriter() 

201 writer.write_float16(0) 

202 self.assertEqual(16, writer.bitposition) 

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

204 

205 def test_write_float32(self): 

206 writer = BitStreamWriter() 

207 writer.write_float32(0) 

208 self.assertEqual(32, writer.bitposition) 

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

210 

211 def test_write_float64(self): 

212 writer = BitStreamWriter() 

213 writer.write_float64(0) 

214 self.assertEqual(64, writer.bitposition) 

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

216 

217 def test_write_string(self): 

218 writer = BitStreamWriter() 

219 writer.write_string("") 

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

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

222 

223 def test_write_bool(self): 

224 writer = BitStreamWriter() 

225 writer.write_bool(True) 

226 writer.write_bool(False) 

227 writer.write_bool(True) 

228 writer.write_bool(False) 

229 writer.write_bool(True) 

230 writer.write_bool(False) 

231 self.assertEqual(6, writer.bitposition) 

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

233 

234 def test_write_bitbuffer(self): 

235 writer = BitStreamWriter() 

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

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

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

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

240 

241 def test_byte_array(self): 

242 writer = BitStreamWriter() 

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

244 

245 def test_bitposition(self): 

246 writer = BitStreamWriter() 

247 self.assertEqual(0, writer.bitposition) 

248 

249 def test_alignto(self): 

250 writer = BitStreamWriter() 

251 writer.alignto(8) 

252 self.assertEqual(0, writer.bitposition) 

253 writer.alignto(2) 

254 self.assertEqual(0, writer.bitposition) 

255 writer.write_bool(True) 

256 writer.alignto(8) 

257 self.assertEqual(8, writer.bitposition) 

258 writer.write_bool(True) 

259 writer.alignto(2) 

260 self.assertEqual(10, writer.bitposition)