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

189 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.bitreader import BitStreamReader 

5from zserio.bitsizeof import INT64_MIN 

6from zserio.exception import PythonRuntimeException 

7 

8 

9class BitStreamReaderTest(unittest.TestCase): 

10 

11 def test_constructor(self): 

12 reader = BitStreamReader(bytes([0xAE, 0xEA, 0x80]), 17) 

13 self.assertEqual(0xAE, reader.read_bits(8)) 

14 self.assertEqual(0xEA, reader.read_bits(8)) 

15 self.assertEqual(0x01, reader.read_bits(1)) 

16 with self.assertRaises(PythonRuntimeException): 

17 reader.read_bits(1) # no more bits available 

18 

19 def test_constructor_wrong_bitsize(self): 

20 with self.assertRaises(PythonRuntimeException): 

21 BitStreamReader(bytes([0xAE]), 9) 

22 

23 def test_from_bitbuffer(self): 

24 bitbuffer = BitBuffer(bytes([0xAE, 0xEA, 0x80]), 17) 

25 reader = BitStreamReader.from_bitbuffer(bitbuffer) 

26 self.assertEqual(bitbuffer.bitsize, reader.buffer_bitsize) 

27 self.assertEqual(0xAEE, reader.read_bits(12)) 

28 self.assertEqual(0x0A, reader.read_bits(4)) 

29 self.assertEqual(0x01, reader.read_bits(1)) 

30 with self.assertRaises(PythonRuntimeException): 

31 reader.read_bits(1) 

32 

33 def test_from_bitbuffer_overflow(self): 

34 bitbuffer = BitBuffer(bytes([0xFF, 0xFF, 0xF0]), 19) 

35 reader = BitStreamReader.from_bitbuffer(bitbuffer) 

36 self.assertEqual(bitbuffer.bitsize, reader.buffer_bitsize) 

37 with self.assertRaises(PythonRuntimeException): 

38 reader.read_bits(20) 

39 

40 def test_read_unaligned_data(self): 

41 # number expected to read at offset 

42 test_value = 123 

43 

44 for offset in range(65): 

45 buffer = bytearray((8 + offset + 7) // 8) 

46 

47 # write test value at offset to data buffer 

48 buffer[offset // 8] = test_value >> (offset % 8) 

49 if offset % 8 != 0: # don't write behind the buffer 

50 buffer[offset // 8 + 1] = 0xFF & test_value << (8 - offset % 8) 

51 

52 bitbuffer = BitBuffer(buffer, 8 + offset) 

53 reader = BitStreamReader.from_bitbuffer(bitbuffer) 

54 

55 # read offset bits 

56 if offset > 0: 

57 self.assertEqual(0, reader.read_bits(offset)) 

58 

59 # read magic number 

60 self.assertEqual(test_value, reader.read_bits(8), msg="Offset: " + str(offset)) 

61 

62 # check eof 

63 with self.assertRaises(PythonRuntimeException): 

64 reader.read_bits(1) 

65 

66 def test_read_bits(self): 

67 data = [0, 1, 255, 128, 127] 

68 reader = BitStreamReader(bytes(data)) 

69 for byte in data: 

70 self.assertEqual(byte, reader.read_bits(8)) 

71 

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

73 with self.assertRaises(PythonRuntimeException, msg=f"numbits={numbits}"): 

74 reader.read_bits(numbits) 

75 

76 with self.assertRaises(PythonRuntimeException): 

77 reader.read_bits(1) # no more bits available 

78 

79 def test_read_signed_bits(self): 

80 data = [0, 0xFF, 1, 127, 0x80] 

81 reader = BitStreamReader(bytes(data)) 

82 self.assertEqual(0, reader.read_signed_bits(8)) 

83 self.assertEqual(-1, reader.read_signed_bits(8)) # 0xff == -1 

84 self.assertEqual(1, reader.read_signed_bits(8)) 

85 self.assertEqual(127, reader.read_signed_bits(8)) 

86 self.assertEqual(-128, reader.read_signed_bits(8)) # 0x80 == -128 

87 

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

89 with self.assertRaises(PythonRuntimeException, msg=f"numbits={numbits}"): 

90 reader.read_signed_bits(numbits) 

91 

92 with self.assertRaises(PythonRuntimeException): 

93 reader.read_signed_bits(1) # no more bits available 

94 

95 def test_read_varint16(self): 

96 reader = BitStreamReader(bytes(1)) 

97 self.assertEqual(0, reader.read_varint16()) 

98 self.assertEqual(8, reader.bitposition) 

99 with self.assertRaises(PythonRuntimeException): 

100 reader.read_varint16() 

101 

102 def test_read_varint32(self): 

103 reader = BitStreamReader(bytes(1)) 

104 self.assertEqual(0, reader.read_varint32()) 

105 self.assertEqual(8, reader.bitposition) 

106 with self.assertRaises(PythonRuntimeException): 

107 reader.read_varint32() 

108 

109 def test_read_varint64(self): 

110 reader = BitStreamReader(bytes(1)) 

111 self.assertEqual(0, reader.read_varint64()) 

112 self.assertEqual(8, reader.bitposition) 

113 with self.assertRaises(PythonRuntimeException): 

114 reader.read_varint64() 

115 

116 def test_read_varint(self): 

117 reader = BitStreamReader(b"\x00\x80") 

118 self.assertEqual(0, reader.read_varint()) 

119 self.assertEqual(8, reader.bitposition) 

120 self.assertEqual(INT64_MIN, reader.read_varint()) 

121 self.assertEqual(16, reader.bitposition) 

122 with self.assertRaises(PythonRuntimeException): 

123 reader.read_varint() 

124 

125 def test_read_varuint16(self): 

126 reader = BitStreamReader(bytes(1)) 

127 self.assertEqual(0, reader.read_varuint16()) 

128 self.assertEqual(8, reader.bitposition) 

129 with self.assertRaises(PythonRuntimeException): 

130 reader.read_varuint16() 

131 

132 def test_read_varuint32(self): 

133 reader = BitStreamReader(bytes(1)) 

134 self.assertEqual(0, reader.read_varuint32()) 

135 self.assertEqual(8, reader.bitposition) 

136 with self.assertRaises(PythonRuntimeException): 

137 reader.read_varuint32() 

138 

139 def test_read_varuint64(self): 

140 reader = BitStreamReader(bytes(1)) 

141 self.assertEqual(0, reader.read_varuint64()) 

142 self.assertEqual(8, reader.bitposition) 

143 with self.assertRaises(PythonRuntimeException): 

144 reader.read_varuint64() 

145 

146 def test_read_varuint(self): 

147 reader = BitStreamReader(bytes(1)) 

148 self.assertEqual(0, reader.read_varuint()) 

149 self.assertEqual(8, reader.bitposition) 

150 with self.assertRaises(PythonRuntimeException): 

151 reader.read_varuint() 

152 

153 def test_read_varsize(self): 

154 # overflow, 2^32 - 1 is too much (b'\x83\xFF\xFF\xFF\xFF') is the maximum) 

155 reader = BitStreamReader(b"\x87\xFF\xFF\xFF\xFF") 

156 with self.assertRaises(PythonRuntimeException): 

157 reader.read_varsize() 

158 

159 # overflow, 2^36 - 1 is too much (b'\x83\xFF\xFF\xFF\xFF') is the maximum) 

160 reader = BitStreamReader(b"\xFF\xFF\xFF\xFF\xFF") 

161 with self.assertRaises(PythonRuntimeException): 

162 reader.read_varsize() 

163 

164 def test_read_float16(self): 

165 reader = BitStreamReader(bytes(2)) 

166 self.assertEqual(0.0, reader.read_float16()) 

167 self.assertEqual(16, reader.bitposition) 

168 with self.assertRaises(PythonRuntimeException): 

169 reader.read_float16() 

170 

171 def test_read_float32(self): 

172 reader = BitStreamReader(bytes(4)) 

173 self.assertEqual(0.0, reader.read_float32()) 

174 self.assertEqual(32, reader.bitposition) 

175 with self.assertRaises(PythonRuntimeException): 

176 reader.read_float32() 

177 

178 def test_read_float64(self): 

179 reader = BitStreamReader(bytes(8)) 

180 self.assertEqual(0.0, reader.read_float64()) 

181 self.assertEqual(64, reader.bitposition) 

182 with self.assertRaises(PythonRuntimeException): 

183 reader.read_float64() 

184 

185 def test_read_string(self): 

186 reader = BitStreamReader(bytes(b"\x01\x41")) 

187 self.assertEqual("A", reader.read_string()) 

188 self.assertEqual(16, reader.bitposition) 

189 with self.assertRaises(PythonRuntimeException): 

190 reader.read_string() 

191 

192 def test_read_bool(self): 

193 reader = BitStreamReader(bytes(b"\xA8")) 

194 self.assertEqual(True, reader.read_bool()) 

195 self.assertEqual(False, reader.read_bool()) 

196 self.assertEqual(True, reader.read_bool()) 

197 self.assertEqual(False, reader.read_bool()) 

198 self.assertEqual(True, reader.read_bool()) 

199 self.assertEqual(False, reader.read_bool()) 

200 self.assertEqual(False, reader.read_bool()) 

201 self.assertEqual(False, reader.read_bool()) 

202 with self.assertRaises(PythonRuntimeException): 

203 reader.read_bool() 

204 

205 def test_read_bitbuffer(self): 

206 reader = BitStreamReader(bytes(b"\x0B\xAB\xE1\xE0\x1F\xC0")) 

207 self.assertEqual(BitBuffer(bytes([0xAB, 0xE0]), 11), reader.read_bitbuffer()) 

208 self.assertEqual(BitBuffer(bytes([0x00, 0xFE]), 15), reader.read_bitbuffer()) 

209 with self.assertRaises(PythonRuntimeException): 

210 reader.read_bitbuffer() 

211 

212 def test_bitposition(self): 

213 reader = BitStreamReader(bytes(1), 7) 

214 reader.bitposition = 0 

215 self.assertEqual(0, reader.bitposition) 

216 reader.bitposition = 7 

217 self.assertEqual(7, reader.bitposition) 

218 

219 with self.assertRaises(PythonRuntimeException): 

220 reader.bitposition = 8 

221 with self.assertRaises(PythonRuntimeException): 

222 reader.bitposition = -1 

223 

224 reader.bitposition = 0 

225 self.assertEqual(0, reader.bitposition) 

226 

227 def test_alignto(self): 

228 reader = BitStreamReader(bytes(1)) 

229 reader.alignto(1) 

230 self.assertEqual(0, reader.bitposition) 

231 reader.read_bits(1) 

232 self.assertEqual(1, reader.bitposition) 

233 reader.alignto(1) 

234 self.assertEqual(1, reader.bitposition) 

235 reader.alignto(4) 

236 self.assertEqual(4, reader.bitposition)