Coverage for /home/jenkins/workspace/NDS/Zserio/NDS_ZSERIO-linux-build/compiler/extensions/python/runtime/tests/test_array.py: 100%
547 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-12-13 15:12 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-12-13 15:12 +0000
1import unittest
3from test_object.api import ArrayObject, ArrayEnum, ArrayBitmask
5from zserio.array import (Array, BitFieldArrayTraits, SignedBitFieldArrayTraits,
6 VarUInt16ArrayTraits, VarUInt32ArrayTraits, VarUInt64ArrayTraits, VarUIntArrayTraits,
7 VarSizeArrayTraits, VarInt16ArrayTraits, VarInt32ArrayTraits, VarInt64ArrayTraits,
8 VarIntArrayTraits, Float16ArrayTraits, Float32ArrayTraits, Float64ArrayTraits,
9 BytesArrayTraits, StringArrayTraits, BoolArrayTraits, BitBufferArrayTraits,
10 ObjectArrayTraits, DeltaContext)
11from zserio.bitposition import alignto
12from zserio.bitbuffer import BitBuffer
13from zserio.bitreader import BitStreamReader
14from zserio.bitsizeof import bitsizeof_varsize
15from zserio.bitwriter import BitStreamWriter
16from zserio import PythonRuntimeException
17from zserio.limits import UINT64_MIN, UINT64_MAX, INT64_MIN, INT64_MAX, UINT8_MAX, INT16_MIN
19class ArrayTest(unittest.TestCase):
21 def test_bitfield_array(self):
22 array_traits = BitFieldArrayTraits(5)
23 array1_values = [1, 2]
24 array1_bitsizeof = 2 * 5
25 array1_aligned_bitsizeof = 5 + 3 + 5
26 array2_values = [3, 4]
27 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
29 def test_signed_bitfield_array(self):
30 array_traits = SignedBitFieldArrayTraits(5)
31 array1_values = [-1, 1]
32 array1_bitsizeof = 2 * 5
33 array1_aligned_bitsizeof = 5 + 3 + 5
34 array2_values = [-2, 2]
35 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
37 def test_varuint16_array(self):
38 array_traits = VarUInt16ArrayTraits()
39 array1_values = [1, 1024]
40 array1_bitsizeof = 8 + 16
41 array1_aligned_bitsizeof = array1_bitsizeof
42 array2_values = [1, 8192]
43 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
45 def test_varuint32_array(self):
46 array_traits = VarUInt32ArrayTraits()
47 array1_values = [1, 16384]
48 array1_bitsizeof = 8 + 24
49 array1_aligned_bitsizeof = array1_bitsizeof
50 array2_values = [1, 32768]
51 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
53 def test_varuint64_array(self):
54 array_traits = VarUInt64ArrayTraits()
55 array1_values = [1, 16384]
56 array1_bitsizeof = 8 + 24
57 array1_aligned_bitsizeof = array1_bitsizeof
58 array2_values = [1, 65536]
59 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
61 def test_varuint_array(self):
62 array_traits = VarUIntArrayTraits()
63 array1_values = [1, 1024]
64 array1_bitsizeof = 8 + 16
65 array1_aligned_bitsizeof = array1_bitsizeof
66 array2_values = [1, 8192]
67 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
69 def test_varsize_array(self):
70 array_traits = VarSizeArrayTraits()
71 array1_values = [1, 16384]
72 array1_bitsizeof = 8 + 24
73 array1_aligned_bitsizeof = array1_bitsizeof
74 array2_values = [1, 32768]
75 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
77 def test_varint16_array(self):
78 array_traits = VarInt16ArrayTraits()
79 array1_values = [-1, 1024]
80 array1_bitsizeof = 8 + 16
81 array1_aligned_bitsizeof = array1_bitsizeof
82 array2_values = [-1, 8192]
83 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
85 def test_varint32_array(self):
86 array_traits = VarInt32ArrayTraits()
87 array1_values = [-1, 16384]
88 array1_bitsizeof = 8 + 24
89 array1_aligned_bitsizeof = array1_bitsizeof
90 array2_values = [-1, 32768]
91 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
93 def test_varint64_array(self):
94 array_traits = VarInt64ArrayTraits()
95 array1_values = [-1, 16384]
96 array1_bitsizeof = 8 + 24
97 array1_aligned_bitsizeof = array1_bitsizeof
98 array2_values = [-1, 65536]
99 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
101 def test_varint_array(self):
102 array_traits = VarIntArrayTraits()
103 array1_values = [-1, 1024]
104 array1_bitsizeof = 8 + 16
105 array1_aligned_bitsizeof = array1_bitsizeof
106 array2_values = [-1, 8192]
107 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
109 def test_float16_array(self):
110 array_traits = Float16ArrayTraits()
111 array1_values = [-1.0, 1.0]
112 array1_bitsizeof = 2 * 16
113 array1_aligned_bitsizeof = array1_bitsizeof
114 array2_values = [-3.5, 3.5]
115 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
117 def test_float32_array(self):
118 array_traits = Float32ArrayTraits()
119 array1_values = [-1.0, 1.0]
120 array1_bitsizeof = 2 * 32
121 array1_aligned_bitsizeof = array1_bitsizeof
122 array2_values = [-3.5, 3.5]
123 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
125 def test_float64_array(self):
126 array_traits = Float64ArrayTraits()
127 array1_values = [-1.0, 1.0]
128 array1_bitsizeof = 2 * 64
129 array1_aligned_bitsizeof = array1_bitsizeof
130 array2_values = [-3.5, 3.5]
131 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
133 def test_bytes_array(self):
134 array_traits = BytesArrayTraits()
135 array1_values = [bytearray([1, 255]), bytearray([127, 128])]
136 array1_bitsizeof = 2 * (1 + 2) * 8
137 array1_aligned_bitsizeof = array1_bitsizeof
138 array2_values = [bytearray([0, 0]), bytearray([255, 255])]
139 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
141 def test_string_array(self):
142 array_traits = StringArrayTraits()
143 array1_values = ["Text1", "Text2"]
144 array1_bitsizeof = 2 * (1 + len("TextN")) * 8
145 array1_aligned_bitsizeof = array1_bitsizeof
146 array2_values = ["Text3", "Text4"]
147 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
149 def test_bool_array(self):
150 array_traits = BoolArrayTraits()
151 array1_values = [True, False]
152 array1_bitsizeof = 2 * 1
153 array1_aligned_bitsizeof = 1 + 7 + 1
154 array2_values = [True, True]
155 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
157 def test_bitbuffer_array(self):
158 array_traits = BitBufferArrayTraits()
159 array1_values = [BitBuffer(bytes([0xAB, 0xE0]), 11), BitBuffer(bytes([0xAB, 0xCD, 0xFE]), 23)]
160 array1_bitsizeof = 8 + 11 + 8 + 23
161 array1_aligned_bitsizeof = 8 + 11 + 5 + 8 + 23
162 array2_values = [BitBuffer(bytes([0xBA, 0xE0]), 11), BitBuffer(bytes([0xBA, 0xDC, 0xFE]), 23)]
163 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
165 class ArrayEnumElementFactory:
166 IS_OBJECT_PACKABLE = True
168 @staticmethod
169 def create(reader, _index):
170 return ArrayEnum.from_reader(reader)
172 @staticmethod
173 def create_packing_context():
174 return DeltaContext()
176 @staticmethod
177 def create_packed(context, reader, _index):
178 return ArrayEnum.from_reader_packed(context, reader)
180 def test_enum_array(self):
181 array_traits = ObjectArrayTraits(ArrayTest.ArrayEnumElementFactory)
182 array1_values = [ArrayEnum.VALUE1, ArrayEnum.VALUE2, ArrayEnum.VALUE3]
183 array1_bitsizeof = 3 * 8
184 array1_aligned_bitsizeof = array1_bitsizeof
185 array2_values = [ArrayEnum.VALUE1, ArrayEnum.VALUE1, ArrayEnum.VALUE1]
186 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
188 class ArrayBitmaskElementFactory:
189 IS_OBJECT_PACKABLE = True
191 @staticmethod
192 def create(reader, _index):
193 return ArrayBitmask.from_reader(reader)
195 @staticmethod
196 def create_packing_context():
197 return DeltaContext()
199 @staticmethod
200 def create_packed(context, reader, _index):
201 return ArrayBitmask.from_reader_packed(context, reader)
203 def test_bitmask_array(self):
204 array_traits = ObjectArrayTraits(ArrayTest.ArrayBitmaskElementFactory)
205 array1_values = [ArrayBitmask.Values.READ, ArrayBitmask.Values.WRITE, ArrayBitmask.Values.CREATE]
206 array1_bitsizeof = 3 * 8
207 array1_aligned_bitsizeof = array1_bitsizeof
208 array2_values = [ArrayBitmask.Values.READ, ArrayBitmask.Values.READ, ArrayBitmask.Values.READ]
209 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
211 class ArrayObjectElementFactory:
212 IS_OBJECT_PACKABLE = True
214 @staticmethod
215 def create(reader, _index):
216 return ArrayObject.from_reader(reader)
218 @staticmethod
219 def create_packing_context():
220 return ArrayObject.ZserioPackingContext()
222 @staticmethod
223 def create_packed(context, reader, _index):
224 return ArrayObject.from_reader_packed(context, reader)
226 def test_object_array(self):
227 array_traits = ObjectArrayTraits(ArrayTest.ArrayObjectElementFactory)
228 array1_values = [ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)]
229 array1_bitsizeof = 3 * 31
230 array1_aligned_bitsizeof = 31 + 1 + 31 + 1 + 31
231 array2_values = [ArrayObject(0x01), ArrayObject(0x02), ArrayObject(0x03)]
232 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values)
234 def test_bitfield_packed_array(self):
235 array_traits64 = BitFieldArrayTraits(64)
237 # none-zero delta
238 array1_values = [10, 11, 12]
239 array1_max_delta_bit_size = 1
240 array1_bitsizeof = self._calc_packed_bit_size(64, len(array1_values), array1_max_delta_bit_size)
241 array1_aligned_bitsizeof = self._calc_aligned_packed_bit_size(64, len(array1_values),
242 array1_max_delta_bit_size)
243 self._test_packed_array(array_traits64, array1_values, array1_bitsizeof, array1_aligned_bitsizeof)
245 # zero delta
246 array2_values = [10, 10, 10]
247 array2_bitsizeof = self.PACKING_DESCRIPTOR_BITSIZE + 64
248 array2_aligned_bitsizeof = self.PACKING_DESCRIPTOR_BITSIZE + 64 + 1
249 self._test_packed_array(array_traits64, array2_values, array2_bitsizeof, array2_aligned_bitsizeof)
251 # one-element array
252 array3_values = [10]
253 array3_bitsizeof = 1 + 64
254 array3_aligned_bitsizeof = 1 + 64
255 self._test_packed_array(array_traits64, array3_values, array3_bitsizeof, array3_aligned_bitsizeof)
257 # empty array
258 array4_values = []
259 array4_bitsizeof = 0
260 array4_aligned_bitsizeof = 0
261 self._test_packed_array(array_traits64, array4_values, array4_bitsizeof, array4_aligned_bitsizeof)
263 # packing not applied, delta is too big
264 self._test_packed_array(array_traits64, [UINT64_MIN, UINT64_MAX])
265 self._test_packed_array(array_traits64, [UINT64_MAX, UINT64_MAX // 2, UINT64_MIN])
267 # will have maxBitNumber 62 bits
268 self._test_packed_array(array_traits64, [0, INT64_MAX // 2, 100, 200, 300, 400, 500, 600, 700])
270 # will not be packed because unpacked 8bit values will be more efficient
271 array_traits8 = BitFieldArrayTraits(8)
272 array5_values = [UINT8_MAX, 0, 10, 20, 30, 40] # max_bit_number 8, delta needs 9 bits
273 array5_bitsizeof = 1 + 6 * 8
274 array5_aligned_bitsizeof = 1 + 8 + 7 + 5 * 8
275 self._test_packed_array(array_traits8, array5_values, array5_bitsizeof, array5_aligned_bitsizeof)
277 # will not be packed because unpacked 8bit values will be more efficient
278 # (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
279 array6_values = [UINT8_MAX, UINT8_MAX // 2 + 1, 10, 20, 30, 40] # max_bit_number 7, delta needs 8 bits
280 array6_bitsizeof = 1 + 6 * 8
281 array6_aligned_bitsizeof = 1 + 8 + 7 + 5 * 8
282 self._test_packed_array(array_traits8, array6_values, array6_bitsizeof, array6_aligned_bitsizeof)
284 def test_signed_bitfield_packed_array(self):
285 array_traits64 = SignedBitFieldArrayTraits(64)
286 self._test_packed_array(array_traits64, [-10, 11, -12])
287 self._test_packed_array(array_traits64, [-10, -10, -10]) # zero delta
289 self._test_packed_array(array_traits64, []) # empty
290 self._test_packed_array(array_traits64, [-10]) # single element
292 # packing not applied, delta is too big
293 self._test_packed_array(array_traits64, [INT64_MIN, INT64_MAX])
294 self._test_packed_array(array_traits64, [INT64_MIN, 0, INT64_MAX])
296 # will not be packed because unpacked 16bit values will be more efficient
297 # (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
298 array_traits16 = SignedBitFieldArrayTraits(16)
299 array16_values = [INT16_MIN, -1, 10, 20, 30, 40] # max_bit_number 15, delta needs 16 bits
300 array16_bitsizeof = 1 + 6 * 16
301 array16_aligned_bitsizeof = 1 + 16 + 7 + 5 * 16
302 self._test_packed_array(array_traits16, array16_values, array16_bitsizeof, array16_aligned_bitsizeof)
304 def test_varuint_packed_array(self):
305 array_traits = VarUIntArrayTraits()
306 self._test_packed_array(array_traits, [100, 200, 300])
307 self._test_packed_array(array_traits, [300, 200, 100])
309 # won't be packed because unpacked varuint values will be more efficient
310 unpacked_array = [5000000, 0, 0, 0, 0, 0, 0]
311 unpacked_bitsizeof = 1 + 32 + 6 * 8
312 unpacked_aligned_bitsizeof = 1 + 32 + 7 + 6 * 8
313 self._test_packed_array(array_traits, unpacked_array, unpacked_bitsizeof, unpacked_aligned_bitsizeof)
315 self._test_packed_array(array_traits, [UINT64_MIN, UINT64_MAX])
316 self._test_packed_array(array_traits, [UINT64_MAX, UINT64_MAX // 2, UINT64_MIN])
318 def test_enum_packed_array(self):
319 array_traits = ObjectArrayTraits(ArrayTest.ArrayEnumElementFactory)
320 self._test_packed_array(array_traits, [ArrayEnum.VALUE1, ArrayEnum.VALUE2, ArrayEnum.VALUE3])
322 def test_bitmask_packed_array(self):
323 array_traits = ObjectArrayTraits(ArrayTest.ArrayBitmaskElementFactory)
324 self._test_packed_array(array_traits, [
325 ArrayBitmask.Values.READ, ArrayBitmask.Values.WRITE, ArrayBitmask.Values.CREATE
326 ])
328 def test_object_packed_array(self):
329 array_traits = ObjectArrayTraits(ArrayTest.ArrayObjectElementFactory)
330 self._test_packed_array(array_traits, [ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)])
331 self._test_packed_array(array_traits, [ArrayObject(0x01), ArrayObject(0x02), ArrayObject(0x03)])
333 @staticmethod
334 def _set_offset_method(_index, _bitoffset):
335 pass
337 @staticmethod
338 def _check_offset_method(_index, _bitoffset):
339 pass
341 def _test_array(self, array_traits,
342 array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values):
343 self._test_eq(array_traits, array1_values, array2_values)
344 self._test_hashcode(array_traits, array1_values, array2_values)
345 self._test_len(array_traits, array1_values)
346 self._test_get_item(array_traits, array1_values)
347 self._test_set_item(array_traits, array1_values)
348 self._test_raw_array(array_traits, array1_values, array2_values)
350 auto_bitsize = bitsizeof_varsize(len(array1_values))
352 self._test_array_normal(array_traits, array1_values, array1_bitsizeof)
353 self._test_array_auto(array_traits, array1_values, auto_bitsize + array1_bitsizeof)
354 self._test_array_aligned(array_traits, array1_values, array1_aligned_bitsizeof)
355 self._test_array_aligned_auto(array_traits, array1_values, auto_bitsize + array1_aligned_bitsizeof)
356 self._test_array_implicit(array_traits, array1_values, array1_bitsizeof)
358 def _test_packed_array(self, array_traits, array_values, array_bitsizeof=None,
359 array_aligned_bitsizeof=None):
361 self._test_packed_array_normal(array_traits, array_values, array_bitsizeof)
363 auto_size_bitsize = bitsizeof_varsize(len(array_values))
364 auto_bitsize = auto_size_bitsize + array_bitsizeof if array_bitsizeof is not None else None
365 self._test_packed_array_auto(array_traits, array_values, auto_bitsize)
367 self._test_packed_array_aligned(array_traits, array_values, array_aligned_bitsizeof)
369 auto_aligned_bitsize = (auto_size_bitsize + array_aligned_bitsizeof
370 if array_aligned_bitsizeof is not None else None)
371 self._test_packed_array_aligned_auto(array_traits, array_values, auto_aligned_bitsize)
373 self._test_packed_array_implicit(array_traits, array_values, array_bitsizeof)
375 def _test_eq(self, array_traits, array1_values, array2_values):
376 array1 = Array(array_traits, array1_values)
377 array2 = Array(array_traits, array2_values)
378 array3 = Array(array_traits, array1_values)
379 self.assertNotEqual(array1, None)
380 self.assertNotEqual(array1, array2)
381 self.assertEqual(array1, array3)
383 def _test_hashcode(self, array_traits, array1_values, array2_values):
384 array1 = Array(array_traits, array1_values)
385 array2 = Array(array_traits, array2_values)
386 array3 = Array(array_traits, array1_values)
387 self.assertNotEqual(hash(array1), hash(array2))
388 self.assertEqual(hash(array1), hash(array3))
390 def _test_len(self, array_traits, array_values):
391 array = Array(array_traits, array_values)
392 raw_array = array.raw_array
393 self.assertEqual(len(raw_array), len(array))
395 def _test_get_item(self, array_traits, array_values):
396 array = Array(array_traits, array_values)
397 raw_array = array.raw_array
398 for value, raw_value in zip(array, raw_array):
399 self.assertEqual(value, raw_value)
401 def _test_set_item(self, array_traits, array_values):
402 array = Array(array_traits, array_values)
403 raw_array = array.raw_array
404 self.assertTrue(len(array) > 1)
405 first_value = array[0]
406 second_value = array[1]
407 array[0] = second_value
408 self.assertEqual(array[0], raw_array[0])
409 raw_array[0] = first_value # return the original value for other tests
410 self.assertEqual(array[0], raw_array[0])
412 def _test_raw_array(self, array_traits, array1_values, array2_values):
413 array1 = Array(array_traits, array1_values)
414 array2 = Array(array_traits, array2_values)
415 array3 = Array(array_traits, array1_values)
416 self.assertNotEqual(array1.raw_array, array2.raw_array)
417 self.assertEqual(array1.raw_array, array3.raw_array)
419 def _test_array_normal(self, array_traits, array_values, expected_bitsize):
420 for i in range(8):
421 array = Array(array_traits, array_values)
423 bitsize = array.bitsizeof(i)
424 self.assertEqual(expected_bitsize, bitsize)
425 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
427 writer = BitStreamWriter()
428 if i > 0:
429 writer.write_bits(0, i)
430 array.write(writer)
431 self.assertEqual(i + bitsize, writer.bitposition, i)
433 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
434 self.assertEqual(0, from_reader.read_bits(i))
435 read_array_from_reader = Array.from_reader(array_traits, from_reader, len(array_values))
436 self.assertEqual(array, read_array_from_reader, i)
438 reader = BitStreamReader(writer.byte_array, writer.bitposition)
439 if i > 0:
440 self.assertEqual(0, reader.read_bits(i))
441 read_array = Array(array_traits)
442 read_array.read(reader, len(array_values))
443 self.assertEqual(array, read_array, i)
445 def _test_array_auto(self, array_traits, array_values, expected_bitsize):
446 for i in range(8):
447 array = Array(array_traits, array_values, is_auto=True)
449 bitsize = array.bitsizeof(i)
450 self.assertEqual(expected_bitsize, bitsize, i)
451 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
453 writer = BitStreamWriter()
454 if i > 0:
455 writer.write_bits(0, i)
456 array.write(writer)
457 self.assertEqual(i + bitsize, writer.bitposition, i)
459 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
460 self.assertEqual(0, from_reader.read_bits(i))
461 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_auto=True)
462 self.assertEqual(array, read_array_from_reader, i)
464 reader = BitStreamReader(writer.byte_array, writer.bitposition)
465 if i > 0:
466 self.assertEqual(0, reader.read_bits(i))
467 read_array = Array(array_traits, is_auto=True)
468 read_array.read(reader)
469 self.assertEqual(array, read_array, i)
471 def _test_array_aligned(self, array_traits, array_values, expected_bitsize):
472 for i in range(8):
473 array = Array(array_traits, array_values, set_offset_method=ArrayTest._set_offset_method,
474 check_offset_method=ArrayTest._check_offset_method)
476 bitsize = array.bitsizeof(i)
477 self.assertEqual(alignto(8, i) - i + expected_bitsize, bitsize, i)
478 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
480 writer = BitStreamWriter()
481 if i > 0:
482 writer.write_bits(0, i)
483 array.write(writer)
484 self.assertEqual(i + bitsize, writer.bitposition, i)
486 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
487 self.assertEqual(0, from_reader.read_bits(i))
488 read_array_from_reader = Array.from_reader(array_traits, from_reader, len(array_values),
489 set_offset_method=ArrayTest._set_offset_method,
490 check_offset_method=ArrayTest._check_offset_method)
491 self.assertEqual(array, read_array_from_reader, i)
493 reader = BitStreamReader(writer.byte_array, writer.bitposition)
494 if i > 0:
495 self.assertEqual(0, reader.read_bits(i))
496 read_array = Array(array_traits, set_offset_method=ArrayTest._set_offset_method,
497 check_offset_method=ArrayTest._check_offset_method)
498 read_array.read(reader, len(array_values))
499 self.assertEqual(array, read_array, i)
501 def _test_array_aligned_auto(self, array_traits, array_values, expected_bitsize):
502 for i in range(8):
503 array = Array(array_traits, array_values, is_auto=True,
504 set_offset_method=ArrayTest._set_offset_method,
505 check_offset_method=ArrayTest._check_offset_method)
507 bitsize = array.bitsizeof(i)
508 self.assertEqual(alignto(8, i) - i + expected_bitsize, bitsize, i)
509 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
511 writer = BitStreamWriter()
512 if i > 0:
513 writer.write_bits(0, i)
514 array.write(writer)
515 self.assertEqual(i + bitsize, writer.bitposition, i)
517 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
518 self.assertEqual(0, from_reader.read_bits(i))
519 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_auto=True,
520 set_offset_method=ArrayTest._set_offset_method,
521 check_offset_method=ArrayTest._check_offset_method)
522 self.assertEqual(array, read_array_from_reader, i)
524 reader = BitStreamReader(writer.byte_array, writer.bitposition)
525 if i > 0:
526 self.assertEqual(0, reader.read_bits(i))
527 read_array = Array(array_traits, is_auto=True, set_offset_method=ArrayTest._set_offset_method,
528 check_offset_method=ArrayTest._check_offset_method)
529 read_array.read(reader)
530 self.assertEqual(array, read_array, i)
532 def _test_array_implicit(self, array_traits, array_values, expected_bitsize):
533 for i in range(8):
534 array = Array(array_traits, array_values, is_implicit=True)
536 bitsize = array.bitsizeof(i)
537 self.assertEqual(expected_bitsize, bitsize, i)
538 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
540 writer = BitStreamWriter()
541 if i > 0:
542 writer.write_bits(0, i)
543 array.write(writer)
544 self.assertEqual(i + bitsize, writer.bitposition, i)
546 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
547 if i > 0:
548 self.assertEqual(0, from_reader.read_bits(i))
549 if array_traits.HAS_BITSIZEOF_CONSTANT:
550 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_implicit=True)
551 self.assertEqual(array, read_array_from_reader, i)
552 else:
553 with self.assertRaises(PythonRuntimeException):
554 Array.from_reader(array_traits, from_reader, is_implicit=True)
556 reader = BitStreamReader(writer.byte_array, writer.bitposition)
557 if i > 0:
558 self.assertEqual(0, reader.read_bits(i))
559 read_array = Array(array_traits, is_implicit=True)
560 if array_traits.HAS_BITSIZEOF_CONSTANT:
561 read_array.read(reader)
562 self.assertEqual(array, read_array, i)
563 else:
564 with self.assertRaises(PythonRuntimeException):
565 read_array.read(reader)
567 def _test_packed_array_normal(self, array_traits, array_values, expected_bitsize):
568 for i in range(8):
569 array = Array(array_traits, array_values)
571 bitsize = array.bitsizeof_packed(i)
572 if expected_bitsize is not None:
573 self.assertEqual(expected_bitsize, bitsize)
574 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
576 writer = BitStreamWriter()
577 if i > 0:
578 writer.write_bits(0, i)
579 array.write_packed(writer)
580 self.assertEqual(i + bitsize, writer.bitposition, i)
582 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
583 self.assertEqual(0, from_reader.read_bits(i))
584 read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, len(array_values))
585 self.assertEqual(array, read_array_from_reader, i)
587 reader = BitStreamReader(writer.byte_array, writer.bitposition)
588 if i > 0:
589 self.assertEqual(0, reader.read_bits(i))
590 read_array = Array(array_traits)
591 read_array.read_packed(reader, len(array_values))
592 self.assertEqual(array, read_array, i)
594 def _test_packed_array_auto(self, array_traits, array_values, expected_bitsize):
595 for i in range(8):
596 array = Array(array_traits, array_values, is_auto=True)
598 bitsize = array.bitsizeof_packed(i)
599 if expected_bitsize is not None:
600 self.assertEqual(expected_bitsize, bitsize)
601 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
603 writer = BitStreamWriter()
604 if i > 0:
605 writer.write_bits(0, i)
606 array.write_packed(writer)
607 self.assertEqual(i + bitsize, writer.bitposition, i)
609 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
610 self.assertEqual(0, from_reader.read_bits(i))
611 read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, is_auto=True)
612 self.assertEqual(array, read_array_from_reader, i)
614 reader = BitStreamReader(writer.byte_array, writer.bitposition)
615 if i > 0:
616 self.assertEqual(0, reader.read_bits(i))
617 read_array = Array(array_traits, is_auto=True)
618 read_array.read_packed(reader)
619 self.assertEqual(array, read_array, i)
621 def _test_packed_array_aligned(self, array_traits, array_values, expected_bitsize):
622 for i in range(8):
623 array = Array(array_traits, array_values, set_offset_method=ArrayTest._set_offset_method,
624 check_offset_method=ArrayTest._check_offset_method)
626 bitsize = array.bitsizeof_packed(i)
627 if expected_bitsize is not None and i == 0:
628 self.assertEqual(expected_bitsize, bitsize)
629 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
631 writer = BitStreamWriter()
632 if i > 0:
633 writer.write_bits(0, i)
634 array.write_packed(writer)
635 self.assertEqual(i + bitsize, writer.bitposition, i)
637 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
638 self.assertEqual(0, from_reader.read_bits(i))
639 read_array_from_reader = Array.from_reader_packed(
640 array_traits, from_reader, len(array_values),
641 set_offset_method=ArrayTest._set_offset_method,
642 check_offset_method=ArrayTest._check_offset_method)
643 self.assertEqual(array, read_array_from_reader, i)
645 reader = BitStreamReader(writer.byte_array, writer.bitposition)
646 if i > 0:
647 self.assertEqual(0, reader.read_bits(i))
648 read_array = Array(array_traits, set_offset_method=ArrayTest._set_offset_method,
649 check_offset_method=ArrayTest._check_offset_method)
650 read_array.read_packed(reader, len(array_values))
651 self.assertEqual(array, read_array, i)
653 def _test_packed_array_aligned_auto(self, array_traits, array_values, expected_bitsize):
654 for i in range(8):
655 array = Array(array_traits, array_values, is_auto=True,
656 set_offset_method=ArrayTest._set_offset_method,
657 check_offset_method=ArrayTest._check_offset_method)
659 bitsize = array.bitsizeof_packed(i)
660 if expected_bitsize is not None and i == 0:
661 self.assertEqual(expected_bitsize, bitsize)
662 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
664 writer = BitStreamWriter()
665 if i > 0:
666 writer.write_bits(0, i)
667 array.write_packed(writer)
668 self.assertEqual(i + bitsize, writer.bitposition, i)
670 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
671 self.assertEqual(0, from_reader.read_bits(i))
672 read_array_from_reader = Array.from_reader_packed(
673 array_traits, from_reader, is_auto=True,
674 set_offset_method=ArrayTest._set_offset_method,
675 check_offset_method=ArrayTest._check_offset_method
676 )
677 self.assertEqual(array, read_array_from_reader, i)
679 reader = BitStreamReader(writer.byte_array, writer.bitposition)
680 if i > 0:
681 self.assertEqual(0, reader.read_bits(i))
682 read_array = Array(array_traits, is_auto=True, set_offset_method=ArrayTest._set_offset_method,
683 check_offset_method=ArrayTest._check_offset_method)
684 read_array.read_packed(reader)
685 self.assertEqual(array, read_array, i)
687 def _test_packed_array_implicit(self, array_traits, array_values, expected_bitsize):
688 for i in range(8):
689 array = Array(array_traits, array_values, is_implicit=True)
691 bitsize = array.bitsizeof_packed(i)
692 if expected_bitsize is not None:
693 self.assertEqual(expected_bitsize, bitsize)
694 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
696 writer = BitStreamWriter()
697 if i > 0:
698 writer.write_bits(0, i)
699 array.write_packed(writer)
700 self.assertEqual(i + bitsize, writer.bitposition, i)
702 reader = BitStreamReader(writer.byte_array, writer.bitposition)
703 if i > 0:
704 self.assertEqual(0, reader.read_bits(i))
705 read_array = Array(array_traits, is_implicit=True)
706 with self.assertRaises(PythonRuntimeException):
707 read_array.read_packed(reader)
709 def _calc_packed_bit_size(self, element_bit_size, array_size, max_delta_bit_size):
710 return self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size + (array_size - 1) * (max_delta_bit_size + 1)
712 def _calc_aligned_packed_bit_size(self, element_bit_size, array_size, max_delta_bit_size):
713 first_element_with_descriptor_bit_size = self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size
714 aligned_first_element_with_descriptor_bit_size = (first_element_with_descriptor_bit_size + 7) // 8 * 8
715 aligned_max_delta_bit_size = (max_delta_bit_size + 1 + 7) // 8 * 8
717 return (aligned_first_element_with_descriptor_bit_size +
718 (array_size - 2) * aligned_max_delta_bit_size + (max_delta_bit_size + 1))
720 PACKING_DESCRIPTOR_BITSIZE = 1 + 6