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
« prev ^ index » next coverage.py v6.5.0, created at 2024-12-05 10:43 +0000
1import unittest
3from zserio.bitbuffer import BitBuffer
4from zserio.bitreader import BitStreamReader
5from zserio.bitsizeof import INT64_MIN
6from zserio.exception import PythonRuntimeException
9class BitStreamReaderTest(unittest.TestCase):
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
19 def test_constructor_wrong_bitsize(self):
20 with self.assertRaises(PythonRuntimeException):
21 BitStreamReader(bytes([0xAE]), 9)
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)
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)
40 def test_read_unaligned_data(self):
41 # number expected to read at offset
42 test_value = 123
44 for offset in range(65):
45 buffer = bytearray((8 + offset + 7) // 8)
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)
52 bitbuffer = BitBuffer(buffer, 8 + offset)
53 reader = BitStreamReader.from_bitbuffer(bitbuffer)
55 # read offset bits
56 if offset > 0:
57 self.assertEqual(0, reader.read_bits(offset))
59 # read magic number
60 self.assertEqual(test_value, reader.read_bits(8), msg="Offset: " + str(offset))
62 # check eof
63 with self.assertRaises(PythonRuntimeException):
64 reader.read_bits(1)
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))
72 for numbits in [-1, 0, 65]:
73 with self.assertRaises(PythonRuntimeException, msg=f"numbits={numbits}"):
74 reader.read_bits(numbits)
76 with self.assertRaises(PythonRuntimeException):
77 reader.read_bits(1) # no more bits available
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
88 for numbits in [-1, 0, 65]:
89 with self.assertRaises(PythonRuntimeException, msg=f"numbits={numbits}"):
90 reader.read_signed_bits(numbits)
92 with self.assertRaises(PythonRuntimeException):
93 reader.read_signed_bits(1) # no more bits available
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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)
219 with self.assertRaises(PythonRuntimeException):
220 reader.bitposition = 8
221 with self.assertRaises(PythonRuntimeException):
222 reader.bitposition = -1
224 reader.bitposition = 0
225 self.assertEqual(0, reader.bitposition)
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)