Coverage for /home/runner/work/zserio/zserio/compiler/extensions/python/runtime/tests/test_array.py: 100%
547 statements
« prev ^ index » next coverage.py v6.5.0, created at 2024-04-30 09:38 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2024-04-30 09:38 +0000
1import unittest
3from test_object.api import ArrayObject, ArrayEnum, ArrayBitmask
5from zserio.array import (
6 Array,
7 BitFieldArrayTraits,
8 SignedBitFieldArrayTraits,
9 VarUInt16ArrayTraits,
10 VarUInt32ArrayTraits,
11 VarUInt64ArrayTraits,
12 VarUIntArrayTraits,
13 VarSizeArrayTraits,
14 VarInt16ArrayTraits,
15 VarInt32ArrayTraits,
16 VarInt64ArrayTraits,
17 VarIntArrayTraits,
18 Float16ArrayTraits,
19 Float32ArrayTraits,
20 Float64ArrayTraits,
21 BytesArrayTraits,
22 StringArrayTraits,
23 BoolArrayTraits,
24 BitBufferArrayTraits,
25 ObjectArrayTraits,
26 DeltaContext,
27)
28from zserio.bitposition import alignto
29from zserio.bitbuffer import BitBuffer
30from zserio.bitreader import BitStreamReader
31from zserio.bitsizeof import bitsizeof_varsize
32from zserio.bitwriter import BitStreamWriter
33from zserio import PythonRuntimeException
34from zserio.limits import (
35 UINT64_MIN,
36 UINT64_MAX,
37 INT64_MIN,
38 INT64_MAX,
39 UINT8_MAX,
40 INT16_MIN,
41)
44class ArrayTest(unittest.TestCase):
46 def test_bitfield_array(self):
47 array_traits = BitFieldArrayTraits(5)
48 array1_values = [1, 2]
49 array1_bitsizeof = 2 * 5
50 array1_aligned_bitsizeof = 5 + 3 + 5
51 array2_values = [3, 4]
52 self._test_array(
53 array_traits,
54 array1_values,
55 array1_bitsizeof,
56 array1_aligned_bitsizeof,
57 array2_values,
58 )
60 def test_signed_bitfield_array(self):
61 array_traits = SignedBitFieldArrayTraits(5)
62 array1_values = [-1, 1]
63 array1_bitsizeof = 2 * 5
64 array1_aligned_bitsizeof = 5 + 3 + 5
65 array2_values = [-2, 2]
66 self._test_array(
67 array_traits,
68 array1_values,
69 array1_bitsizeof,
70 array1_aligned_bitsizeof,
71 array2_values,
72 )
74 def test_varuint16_array(self):
75 array_traits = VarUInt16ArrayTraits()
76 array1_values = [1, 1024]
77 array1_bitsizeof = 8 + 16
78 array1_aligned_bitsizeof = array1_bitsizeof
79 array2_values = [1, 8192]
80 self._test_array(
81 array_traits,
82 array1_values,
83 array1_bitsizeof,
84 array1_aligned_bitsizeof,
85 array2_values,
86 )
88 def test_varuint32_array(self):
89 array_traits = VarUInt32ArrayTraits()
90 array1_values = [1, 16384]
91 array1_bitsizeof = 8 + 24
92 array1_aligned_bitsizeof = array1_bitsizeof
93 array2_values = [1, 32768]
94 self._test_array(
95 array_traits,
96 array1_values,
97 array1_bitsizeof,
98 array1_aligned_bitsizeof,
99 array2_values,
100 )
102 def test_varuint64_array(self):
103 array_traits = VarUInt64ArrayTraits()
104 array1_values = [1, 16384]
105 array1_bitsizeof = 8 + 24
106 array1_aligned_bitsizeof = array1_bitsizeof
107 array2_values = [1, 65536]
108 self._test_array(
109 array_traits,
110 array1_values,
111 array1_bitsizeof,
112 array1_aligned_bitsizeof,
113 array2_values,
114 )
116 def test_varuint_array(self):
117 array_traits = VarUIntArrayTraits()
118 array1_values = [1, 1024]
119 array1_bitsizeof = 8 + 16
120 array1_aligned_bitsizeof = array1_bitsizeof
121 array2_values = [1, 8192]
122 self._test_array(
123 array_traits,
124 array1_values,
125 array1_bitsizeof,
126 array1_aligned_bitsizeof,
127 array2_values,
128 )
130 def test_varsize_array(self):
131 array_traits = VarSizeArrayTraits()
132 array1_values = [1, 16384]
133 array1_bitsizeof = 8 + 24
134 array1_aligned_bitsizeof = array1_bitsizeof
135 array2_values = [1, 32768]
136 self._test_array(
137 array_traits,
138 array1_values,
139 array1_bitsizeof,
140 array1_aligned_bitsizeof,
141 array2_values,
142 )
144 def test_varint16_array(self):
145 array_traits = VarInt16ArrayTraits()
146 array1_values = [-1, 1024]
147 array1_bitsizeof = 8 + 16
148 array1_aligned_bitsizeof = array1_bitsizeof
149 array2_values = [-1, 8192]
150 self._test_array(
151 array_traits,
152 array1_values,
153 array1_bitsizeof,
154 array1_aligned_bitsizeof,
155 array2_values,
156 )
158 def test_varint32_array(self):
159 array_traits = VarInt32ArrayTraits()
160 array1_values = [-1, 16384]
161 array1_bitsizeof = 8 + 24
162 array1_aligned_bitsizeof = array1_bitsizeof
163 array2_values = [-1, 32768]
164 self._test_array(
165 array_traits,
166 array1_values,
167 array1_bitsizeof,
168 array1_aligned_bitsizeof,
169 array2_values,
170 )
172 def test_varint64_array(self):
173 array_traits = VarInt64ArrayTraits()
174 array1_values = [-1, 16384]
175 array1_bitsizeof = 8 + 24
176 array1_aligned_bitsizeof = array1_bitsizeof
177 array2_values = [-1, 65536]
178 self._test_array(
179 array_traits,
180 array1_values,
181 array1_bitsizeof,
182 array1_aligned_bitsizeof,
183 array2_values,
184 )
186 def test_varint_array(self):
187 array_traits = VarIntArrayTraits()
188 array1_values = [-1, 1024]
189 array1_bitsizeof = 8 + 16
190 array1_aligned_bitsizeof = array1_bitsizeof
191 array2_values = [-1, 8192]
192 self._test_array(
193 array_traits,
194 array1_values,
195 array1_bitsizeof,
196 array1_aligned_bitsizeof,
197 array2_values,
198 )
200 def test_float16_array(self):
201 array_traits = Float16ArrayTraits()
202 array1_values = [-1.0, 1.0]
203 array1_bitsizeof = 2 * 16
204 array1_aligned_bitsizeof = array1_bitsizeof
205 array2_values = [-3.5, 3.5]
206 self._test_array(
207 array_traits,
208 array1_values,
209 array1_bitsizeof,
210 array1_aligned_bitsizeof,
211 array2_values,
212 )
214 def test_float32_array(self):
215 array_traits = Float32ArrayTraits()
216 array1_values = [-1.0, 1.0]
217 array1_bitsizeof = 2 * 32
218 array1_aligned_bitsizeof = array1_bitsizeof
219 array2_values = [-3.5, 3.5]
220 self._test_array(
221 array_traits,
222 array1_values,
223 array1_bitsizeof,
224 array1_aligned_bitsizeof,
225 array2_values,
226 )
228 def test_float64_array(self):
229 array_traits = Float64ArrayTraits()
230 array1_values = [-1.0, 1.0]
231 array1_bitsizeof = 2 * 64
232 array1_aligned_bitsizeof = array1_bitsizeof
233 array2_values = [-3.5, 3.5]
234 self._test_array(
235 array_traits,
236 array1_values,
237 array1_bitsizeof,
238 array1_aligned_bitsizeof,
239 array2_values,
240 )
242 def test_bytes_array(self):
243 array_traits = BytesArrayTraits()
244 array1_values = [bytearray([1, 255]), bytearray([127, 128])]
245 array1_bitsizeof = 2 * (1 + 2) * 8
246 array1_aligned_bitsizeof = array1_bitsizeof
247 array2_values = [bytearray([0, 0]), bytearray([255, 255])]
248 self._test_array(
249 array_traits,
250 array1_values,
251 array1_bitsizeof,
252 array1_aligned_bitsizeof,
253 array2_values,
254 )
256 def test_string_array(self):
257 array_traits = StringArrayTraits()
258 array1_values = ["Text1", "Text2"]
259 array1_bitsizeof = 2 * (1 + len("TextN")) * 8
260 array1_aligned_bitsizeof = array1_bitsizeof
261 array2_values = ["Text3", "Text4"]
262 self._test_array(
263 array_traits,
264 array1_values,
265 array1_bitsizeof,
266 array1_aligned_bitsizeof,
267 array2_values,
268 )
270 def test_bool_array(self):
271 array_traits = BoolArrayTraits()
272 array1_values = [True, False]
273 array1_bitsizeof = 2 * 1
274 array1_aligned_bitsizeof = 1 + 7 + 1
275 array2_values = [True, True]
276 self._test_array(
277 array_traits,
278 array1_values,
279 array1_bitsizeof,
280 array1_aligned_bitsizeof,
281 array2_values,
282 )
284 def test_bitbuffer_array(self):
285 array_traits = BitBufferArrayTraits()
286 array1_values = [
287 BitBuffer(bytes([0xAB, 0xE0]), 11),
288 BitBuffer(bytes([0xAB, 0xCD, 0xFE]), 23),
289 ]
290 array1_bitsizeof = 8 + 11 + 8 + 23
291 array1_aligned_bitsizeof = 8 + 11 + 5 + 8 + 23
292 array2_values = [
293 BitBuffer(bytes([0xBA, 0xE0]), 11),
294 BitBuffer(bytes([0xBA, 0xDC, 0xFE]), 23),
295 ]
296 self._test_array(
297 array_traits,
298 array1_values,
299 array1_bitsizeof,
300 array1_aligned_bitsizeof,
301 array2_values,
302 )
304 class ArrayEnumElementFactory:
305 IS_OBJECT_PACKABLE = True
307 @staticmethod
308 def create(reader, _index):
309 return ArrayEnum.from_reader(reader)
311 @staticmethod
312 def create_packing_context():
313 return DeltaContext()
315 @staticmethod
316 def create_packed(context, reader, _index):
317 return ArrayEnum.from_reader_packed(context, reader)
319 def test_enum_array(self):
320 array_traits = ObjectArrayTraits(ArrayTest.ArrayEnumElementFactory)
321 array1_values = [ArrayEnum.VALUE1, ArrayEnum.VALUE2, ArrayEnum.VALUE3]
322 array1_bitsizeof = 3 * 8
323 array1_aligned_bitsizeof = array1_bitsizeof
324 array2_values = [ArrayEnum.VALUE1, ArrayEnum.VALUE1, ArrayEnum.VALUE1]
325 self._test_array(
326 array_traits,
327 array1_values,
328 array1_bitsizeof,
329 array1_aligned_bitsizeof,
330 array2_values,
331 )
333 class ArrayBitmaskElementFactory:
334 IS_OBJECT_PACKABLE = True
336 @staticmethod
337 def create(reader, _index):
338 return ArrayBitmask.from_reader(reader)
340 @staticmethod
341 def create_packing_context():
342 return DeltaContext()
344 @staticmethod
345 def create_packed(context, reader, _index):
346 return ArrayBitmask.from_reader_packed(context, reader)
348 def test_bitmask_array(self):
349 array_traits = ObjectArrayTraits(ArrayTest.ArrayBitmaskElementFactory)
350 array1_values = [
351 ArrayBitmask.Values.READ,
352 ArrayBitmask.Values.WRITE,
353 ArrayBitmask.Values.CREATE,
354 ]
355 array1_bitsizeof = 3 * 8
356 array1_aligned_bitsizeof = array1_bitsizeof
357 array2_values = [
358 ArrayBitmask.Values.READ,
359 ArrayBitmask.Values.READ,
360 ArrayBitmask.Values.READ,
361 ]
362 self._test_array(
363 array_traits,
364 array1_values,
365 array1_bitsizeof,
366 array1_aligned_bitsizeof,
367 array2_values,
368 )
370 class ArrayObjectElementFactory:
371 IS_OBJECT_PACKABLE = True
373 @staticmethod
374 def create(reader, _index):
375 return ArrayObject.from_reader(reader)
377 @staticmethod
378 def create_packing_context():
379 return ArrayObject.ZserioPackingContext()
381 @staticmethod
382 def create_packed(context, reader, _index):
383 return ArrayObject.from_reader_packed(context, reader)
385 def test_object_array(self):
386 array_traits = ObjectArrayTraits(ArrayTest.ArrayObjectElementFactory)
387 array1_values = [ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)]
388 array1_bitsizeof = 3 * 31
389 array1_aligned_bitsizeof = 31 + 1 + 31 + 1 + 31
390 array2_values = [ArrayObject(0x01), ArrayObject(0x02), ArrayObject(0x03)]
391 self._test_array(
392 array_traits,
393 array1_values,
394 array1_bitsizeof,
395 array1_aligned_bitsizeof,
396 array2_values,
397 )
399 def test_bitfield_packed_array(self):
400 array_traits64 = BitFieldArrayTraits(64)
402 # none-zero delta
403 array1_values = [10, 11, 12]
404 array1_max_delta_bit_size = 1
405 array1_bitsizeof = self._calc_packed_bit_size(64, len(array1_values), array1_max_delta_bit_size)
406 array1_aligned_bitsizeof = self._calc_aligned_packed_bit_size(
407 64, len(array1_values), array1_max_delta_bit_size
408 )
409 self._test_packed_array(array_traits64, array1_values, array1_bitsizeof, array1_aligned_bitsizeof)
411 # zero delta
412 array2_values = [10, 10, 10]
413 array2_bitsizeof = self.PACKING_DESCRIPTOR_BITSIZE + 64
414 array2_aligned_bitsizeof = self.PACKING_DESCRIPTOR_BITSIZE + 64 + 1
415 self._test_packed_array(array_traits64, array2_values, array2_bitsizeof, array2_aligned_bitsizeof)
417 # one-element array
418 array3_values = [10]
419 array3_bitsizeof = 1 + 64
420 array3_aligned_bitsizeof = 1 + 64
421 self._test_packed_array(array_traits64, array3_values, array3_bitsizeof, array3_aligned_bitsizeof)
423 # empty array
424 array4_values = []
425 array4_bitsizeof = 0
426 array4_aligned_bitsizeof = 0
427 self._test_packed_array(array_traits64, array4_values, array4_bitsizeof, array4_aligned_bitsizeof)
429 # packing not applied, delta is too big
430 self._test_packed_array(array_traits64, [UINT64_MIN, UINT64_MAX])
431 self._test_packed_array(array_traits64, [UINT64_MAX, UINT64_MAX // 2, UINT64_MIN])
433 # will have maxBitNumber 62 bits
434 self._test_packed_array(array_traits64, [0, INT64_MAX // 2, 100, 200, 300, 400, 500, 600, 700])
436 # will not be packed because unpacked 8bit values will be more efficient
437 array_traits8 = BitFieldArrayTraits(8)
438 array5_values = [
439 UINT8_MAX,
440 0,
441 10,
442 20,
443 30,
444 40,
445 ] # max_bit_number 8, delta needs 9 bits
446 array5_bitsizeof = 1 + 6 * 8
447 array5_aligned_bitsizeof = 1 + 8 + 7 + 5 * 8
448 self._test_packed_array(array_traits8, array5_values, array5_bitsizeof, array5_aligned_bitsizeof)
450 # will not be packed because unpacked 8bit values will be more efficient
451 # (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
452 array6_values = [
453 UINT8_MAX,
454 UINT8_MAX // 2 + 1,
455 10,
456 20,
457 30,
458 40,
459 ] # max_bit_number 7, delta needs 8 bits
460 array6_bitsizeof = 1 + 6 * 8
461 array6_aligned_bitsizeof = 1 + 8 + 7 + 5 * 8
462 self._test_packed_array(array_traits8, array6_values, array6_bitsizeof, array6_aligned_bitsizeof)
464 def test_signed_bitfield_packed_array(self):
465 array_traits64 = SignedBitFieldArrayTraits(64)
466 self._test_packed_array(array_traits64, [-10, 11, -12])
467 self._test_packed_array(array_traits64, [-10, -10, -10]) # zero delta
469 self._test_packed_array(array_traits64, []) # empty
470 self._test_packed_array(array_traits64, [-10]) # single element
472 # packing not applied, delta is too big
473 self._test_packed_array(array_traits64, [INT64_MIN, INT64_MAX])
474 self._test_packed_array(array_traits64, [INT64_MIN, 0, INT64_MAX])
476 # will not be packed because unpacked 16bit values will be more efficient
477 # (6 bits more are needed to store max_bit_number in descriptor if packing was enabled)
478 array_traits16 = SignedBitFieldArrayTraits(16)
479 array16_values = [
480 INT16_MIN,
481 -1,
482 10,
483 20,
484 30,
485 40,
486 ] # max_bit_number 15, delta needs 16 bits
487 array16_bitsizeof = 1 + 6 * 16
488 array16_aligned_bitsizeof = 1 + 16 + 7 + 5 * 16
489 self._test_packed_array(array_traits16, array16_values, array16_bitsizeof, array16_aligned_bitsizeof)
491 def test_varuint_packed_array(self):
492 array_traits = VarUIntArrayTraits()
493 self._test_packed_array(array_traits, [100, 200, 300])
494 self._test_packed_array(array_traits, [300, 200, 100])
496 # won't be packed because unpacked varuint values will be more efficient
497 unpacked_array = [5000000, 0, 0, 0, 0, 0, 0]
498 unpacked_bitsizeof = 1 + 32 + 6 * 8
499 unpacked_aligned_bitsizeof = 1 + 32 + 7 + 6 * 8
500 self._test_packed_array(array_traits, unpacked_array, unpacked_bitsizeof, unpacked_aligned_bitsizeof)
502 self._test_packed_array(array_traits, [UINT64_MIN, UINT64_MAX])
503 self._test_packed_array(array_traits, [UINT64_MAX, UINT64_MAX // 2, UINT64_MIN])
505 def test_enum_packed_array(self):
506 array_traits = ObjectArrayTraits(ArrayTest.ArrayEnumElementFactory)
507 self._test_packed_array(array_traits, [ArrayEnum.VALUE1, ArrayEnum.VALUE2, ArrayEnum.VALUE3])
509 def test_bitmask_packed_array(self):
510 array_traits = ObjectArrayTraits(ArrayTest.ArrayBitmaskElementFactory)
511 self._test_packed_array(
512 array_traits,
513 [
514 ArrayBitmask.Values.READ,
515 ArrayBitmask.Values.WRITE,
516 ArrayBitmask.Values.CREATE,
517 ],
518 )
520 def test_object_packed_array(self):
521 array_traits = ObjectArrayTraits(ArrayTest.ArrayObjectElementFactory)
522 self._test_packed_array(array_traits, [ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)])
523 self._test_packed_array(array_traits, [ArrayObject(0x01), ArrayObject(0x02), ArrayObject(0x03)])
525 @staticmethod
526 def _set_offset_method(_index, _bitoffset):
527 pass
529 @staticmethod
530 def _check_offset_method(_index, _bitoffset):
531 pass
533 def _test_array(
534 self,
535 array_traits,
536 array1_values,
537 array1_bitsizeof,
538 array1_aligned_bitsizeof,
539 array2_values,
540 ):
541 self._test_eq(array_traits, array1_values, array2_values)
542 self._test_hashcode(array_traits, array1_values, array2_values)
543 self._test_len(array_traits, array1_values)
544 self._test_get_item(array_traits, array1_values)
545 self._test_set_item(array_traits, array1_values)
546 self._test_raw_array(array_traits, array1_values, array2_values)
548 auto_bitsize = bitsizeof_varsize(len(array1_values))
550 self._test_array_normal(array_traits, array1_values, array1_bitsizeof)
551 self._test_array_auto(array_traits, array1_values, auto_bitsize + array1_bitsizeof)
552 self._test_array_aligned(array_traits, array1_values, array1_aligned_bitsizeof)
553 self._test_array_aligned_auto(array_traits, array1_values, auto_bitsize + array1_aligned_bitsizeof)
554 self._test_array_implicit(array_traits, array1_values, array1_bitsizeof)
556 def _test_packed_array(
557 self,
558 array_traits,
559 array_values,
560 array_bitsizeof=None,
561 array_aligned_bitsizeof=None,
562 ):
564 self._test_packed_array_normal(array_traits, array_values, array_bitsizeof)
566 auto_size_bitsize = bitsizeof_varsize(len(array_values))
567 auto_bitsize = auto_size_bitsize + array_bitsizeof if array_bitsizeof is not None else None
568 self._test_packed_array_auto(array_traits, array_values, auto_bitsize)
570 self._test_packed_array_aligned(array_traits, array_values, array_aligned_bitsizeof)
572 auto_aligned_bitsize = (
573 auto_size_bitsize + array_aligned_bitsizeof if array_aligned_bitsizeof is not None else None
574 )
575 self._test_packed_array_aligned_auto(array_traits, array_values, auto_aligned_bitsize)
577 self._test_packed_array_implicit(array_traits, array_values, array_bitsizeof)
579 def _test_eq(self, array_traits, array1_values, array2_values):
580 array1 = Array(array_traits, array1_values)
581 array2 = Array(array_traits, array2_values)
582 array3 = Array(array_traits, array1_values)
583 self.assertNotEqual(array1, None)
584 self.assertNotEqual(array1, array2)
585 self.assertEqual(array1, array3)
587 def _test_hashcode(self, array_traits, array1_values, array2_values):
588 array1 = Array(array_traits, array1_values)
589 array2 = Array(array_traits, array2_values)
590 array3 = Array(array_traits, array1_values)
591 self.assertNotEqual(hash(array1), hash(array2))
592 self.assertEqual(hash(array1), hash(array3))
594 def _test_len(self, array_traits, array_values):
595 array = Array(array_traits, array_values)
596 raw_array = array.raw_array
597 self.assertEqual(len(raw_array), len(array))
599 def _test_get_item(self, array_traits, array_values):
600 array = Array(array_traits, array_values)
601 raw_array = array.raw_array
602 for value, raw_value in zip(array, raw_array):
603 self.assertEqual(value, raw_value)
605 def _test_set_item(self, array_traits, array_values):
606 array = Array(array_traits, array_values)
607 raw_array = array.raw_array
608 self.assertTrue(len(array) > 1)
609 first_value = array[0]
610 second_value = array[1]
611 array[0] = second_value
612 self.assertEqual(array[0], raw_array[0])
613 raw_array[0] = first_value # return the original value for other tests
614 self.assertEqual(array[0], raw_array[0])
616 def _test_raw_array(self, array_traits, array1_values, array2_values):
617 array1 = Array(array_traits, array1_values)
618 array2 = Array(array_traits, array2_values)
619 array3 = Array(array_traits, array1_values)
620 self.assertNotEqual(array1.raw_array, array2.raw_array)
621 self.assertEqual(array1.raw_array, array3.raw_array)
623 def _test_array_normal(self, array_traits, array_values, expected_bitsize):
624 for i in range(8):
625 array = Array(array_traits, array_values)
627 bitsize = array.bitsizeof(i)
628 self.assertEqual(expected_bitsize, bitsize)
629 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
631 writer = BitStreamWriter()
632 if i > 0:
633 writer.write_bits(0, i)
634 array.write(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(array_traits, from_reader, len(array_values))
640 self.assertEqual(array, read_array_from_reader, i)
642 reader = BitStreamReader(writer.byte_array, writer.bitposition)
643 if i > 0:
644 self.assertEqual(0, reader.read_bits(i))
645 read_array = Array(array_traits)
646 read_array.read(reader, len(array_values))
647 self.assertEqual(array, read_array, i)
649 def _test_array_auto(self, array_traits, array_values, expected_bitsize):
650 for i in range(8):
651 array = Array(array_traits, array_values, is_auto=True)
653 bitsize = array.bitsizeof(i)
654 self.assertEqual(expected_bitsize, bitsize, i)
655 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
657 writer = BitStreamWriter()
658 if i > 0:
659 writer.write_bits(0, i)
660 array.write(writer)
661 self.assertEqual(i + bitsize, writer.bitposition, i)
663 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
664 self.assertEqual(0, from_reader.read_bits(i))
665 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_auto=True)
666 self.assertEqual(array, read_array_from_reader, i)
668 reader = BitStreamReader(writer.byte_array, writer.bitposition)
669 if i > 0:
670 self.assertEqual(0, reader.read_bits(i))
671 read_array = Array(array_traits, is_auto=True)
672 read_array.read(reader)
673 self.assertEqual(array, read_array, i)
675 def _test_array_aligned(self, array_traits, array_values, expected_bitsize):
676 for i in range(8):
677 array = Array(
678 array_traits,
679 array_values,
680 set_offset_method=ArrayTest._set_offset_method,
681 check_offset_method=ArrayTest._check_offset_method,
682 )
684 bitsize = array.bitsizeof(i)
685 self.assertEqual(alignto(8, i) - i + expected_bitsize, bitsize, i)
686 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
688 writer = BitStreamWriter()
689 if i > 0:
690 writer.write_bits(0, i)
691 array.write(writer)
692 self.assertEqual(i + bitsize, writer.bitposition, i)
694 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
695 self.assertEqual(0, from_reader.read_bits(i))
696 read_array_from_reader = Array.from_reader(
697 array_traits,
698 from_reader,
699 len(array_values),
700 set_offset_method=ArrayTest._set_offset_method,
701 check_offset_method=ArrayTest._check_offset_method,
702 )
703 self.assertEqual(array, read_array_from_reader, i)
705 reader = BitStreamReader(writer.byte_array, writer.bitposition)
706 if i > 0:
707 self.assertEqual(0, reader.read_bits(i))
708 read_array = Array(
709 array_traits,
710 set_offset_method=ArrayTest._set_offset_method,
711 check_offset_method=ArrayTest._check_offset_method,
712 )
713 read_array.read(reader, len(array_values))
714 self.assertEqual(array, read_array, i)
716 def _test_array_aligned_auto(self, array_traits, array_values, expected_bitsize):
717 for i in range(8):
718 array = Array(
719 array_traits,
720 array_values,
721 is_auto=True,
722 set_offset_method=ArrayTest._set_offset_method,
723 check_offset_method=ArrayTest._check_offset_method,
724 )
726 bitsize = array.bitsizeof(i)
727 self.assertEqual(alignto(8, i) - i + expected_bitsize, bitsize, i)
728 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
730 writer = BitStreamWriter()
731 if i > 0:
732 writer.write_bits(0, i)
733 array.write(writer)
734 self.assertEqual(i + bitsize, writer.bitposition, i)
736 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
737 self.assertEqual(0, from_reader.read_bits(i))
738 read_array_from_reader = Array.from_reader(
739 array_traits,
740 from_reader,
741 is_auto=True,
742 set_offset_method=ArrayTest._set_offset_method,
743 check_offset_method=ArrayTest._check_offset_method,
744 )
745 self.assertEqual(array, read_array_from_reader, i)
747 reader = BitStreamReader(writer.byte_array, writer.bitposition)
748 if i > 0:
749 self.assertEqual(0, reader.read_bits(i))
750 read_array = Array(
751 array_traits,
752 is_auto=True,
753 set_offset_method=ArrayTest._set_offset_method,
754 check_offset_method=ArrayTest._check_offset_method,
755 )
756 read_array.read(reader)
757 self.assertEqual(array, read_array, i)
759 def _test_array_implicit(self, array_traits, array_values, expected_bitsize):
760 for i in range(8):
761 array = Array(array_traits, array_values, is_implicit=True)
763 bitsize = array.bitsizeof(i)
764 self.assertEqual(expected_bitsize, bitsize, i)
765 self.assertEqual(i + bitsize, array.initialize_offsets(i), i)
767 writer = BitStreamWriter()
768 if i > 0:
769 writer.write_bits(0, i)
770 array.write(writer)
771 self.assertEqual(i + bitsize, writer.bitposition, i)
773 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
774 if i > 0:
775 self.assertEqual(0, from_reader.read_bits(i))
776 if array_traits.HAS_BITSIZEOF_CONSTANT:
777 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_implicit=True)
778 self.assertEqual(array, read_array_from_reader, i)
779 else:
780 with self.assertRaises(PythonRuntimeException):
781 Array.from_reader(array_traits, from_reader, is_implicit=True)
783 reader = BitStreamReader(writer.byte_array, writer.bitposition)
784 if i > 0:
785 self.assertEqual(0, reader.read_bits(i))
786 read_array = Array(array_traits, is_implicit=True)
787 if array_traits.HAS_BITSIZEOF_CONSTANT:
788 read_array.read(reader)
789 self.assertEqual(array, read_array, i)
790 else:
791 with self.assertRaises(PythonRuntimeException):
792 read_array.read(reader)
794 def _test_packed_array_normal(self, array_traits, array_values, expected_bitsize):
795 for i in range(8):
796 array = Array(array_traits, array_values)
798 bitsize = array.bitsizeof_packed(i)
799 if expected_bitsize is not None:
800 self.assertEqual(expected_bitsize, bitsize)
801 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
803 writer = BitStreamWriter()
804 if i > 0:
805 writer.write_bits(0, i)
806 array.write_packed(writer)
807 self.assertEqual(i + bitsize, writer.bitposition, i)
809 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
810 self.assertEqual(0, from_reader.read_bits(i))
811 read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, len(array_values))
812 self.assertEqual(array, read_array_from_reader, i)
814 reader = BitStreamReader(writer.byte_array, writer.bitposition)
815 if i > 0:
816 self.assertEqual(0, reader.read_bits(i))
817 read_array = Array(array_traits)
818 read_array.read_packed(reader, len(array_values))
819 self.assertEqual(array, read_array, i)
821 def _test_packed_array_auto(self, array_traits, array_values, expected_bitsize):
822 for i in range(8):
823 array = Array(array_traits, array_values, is_auto=True)
825 bitsize = array.bitsizeof_packed(i)
826 if expected_bitsize is not None:
827 self.assertEqual(expected_bitsize, bitsize)
828 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
830 writer = BitStreamWriter()
831 if i > 0:
832 writer.write_bits(0, i)
833 array.write_packed(writer)
834 self.assertEqual(i + bitsize, writer.bitposition, i)
836 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
837 self.assertEqual(0, from_reader.read_bits(i))
838 read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, is_auto=True)
839 self.assertEqual(array, read_array_from_reader, i)
841 reader = BitStreamReader(writer.byte_array, writer.bitposition)
842 if i > 0:
843 self.assertEqual(0, reader.read_bits(i))
844 read_array = Array(array_traits, is_auto=True)
845 read_array.read_packed(reader)
846 self.assertEqual(array, read_array, i)
848 def _test_packed_array_aligned(self, array_traits, array_values, expected_bitsize):
849 for i in range(8):
850 array = Array(
851 array_traits,
852 array_values,
853 set_offset_method=ArrayTest._set_offset_method,
854 check_offset_method=ArrayTest._check_offset_method,
855 )
857 bitsize = array.bitsizeof_packed(i)
858 if expected_bitsize is not None and i == 0:
859 self.assertEqual(expected_bitsize, bitsize)
860 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
862 writer = BitStreamWriter()
863 if i > 0:
864 writer.write_bits(0, i)
865 array.write_packed(writer)
866 self.assertEqual(i + bitsize, writer.bitposition, i)
868 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
869 self.assertEqual(0, from_reader.read_bits(i))
870 read_array_from_reader = Array.from_reader_packed(
871 array_traits,
872 from_reader,
873 len(array_values),
874 set_offset_method=ArrayTest._set_offset_method,
875 check_offset_method=ArrayTest._check_offset_method,
876 )
877 self.assertEqual(array, read_array_from_reader, i)
879 reader = BitStreamReader(writer.byte_array, writer.bitposition)
880 if i > 0:
881 self.assertEqual(0, reader.read_bits(i))
882 read_array = Array(
883 array_traits,
884 set_offset_method=ArrayTest._set_offset_method,
885 check_offset_method=ArrayTest._check_offset_method,
886 )
887 read_array.read_packed(reader, len(array_values))
888 self.assertEqual(array, read_array, i)
890 def _test_packed_array_aligned_auto(self, array_traits, array_values, expected_bitsize):
891 for i in range(8):
892 array = Array(
893 array_traits,
894 array_values,
895 is_auto=True,
896 set_offset_method=ArrayTest._set_offset_method,
897 check_offset_method=ArrayTest._check_offset_method,
898 )
900 bitsize = array.bitsizeof_packed(i)
901 if expected_bitsize is not None and i == 0:
902 self.assertEqual(expected_bitsize, bitsize)
903 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
905 writer = BitStreamWriter()
906 if i > 0:
907 writer.write_bits(0, i)
908 array.write_packed(writer)
909 self.assertEqual(i + bitsize, writer.bitposition, i)
911 from_reader = BitStreamReader(writer.byte_array, writer.bitposition)
912 self.assertEqual(0, from_reader.read_bits(i))
913 read_array_from_reader = Array.from_reader_packed(
914 array_traits,
915 from_reader,
916 is_auto=True,
917 set_offset_method=ArrayTest._set_offset_method,
918 check_offset_method=ArrayTest._check_offset_method,
919 )
920 self.assertEqual(array, read_array_from_reader, i)
922 reader = BitStreamReader(writer.byte_array, writer.bitposition)
923 if i > 0:
924 self.assertEqual(0, reader.read_bits(i))
925 read_array = Array(
926 array_traits,
927 is_auto=True,
928 set_offset_method=ArrayTest._set_offset_method,
929 check_offset_method=ArrayTest._check_offset_method,
930 )
931 read_array.read_packed(reader)
932 self.assertEqual(array, read_array, i)
934 def _test_packed_array_implicit(self, array_traits, array_values, expected_bitsize):
935 for i in range(8):
936 array = Array(array_traits, array_values, is_implicit=True)
938 bitsize = array.bitsizeof_packed(i)
939 if expected_bitsize is not None:
940 self.assertEqual(expected_bitsize, bitsize)
941 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i)
943 writer = BitStreamWriter()
944 if i > 0:
945 writer.write_bits(0, i)
946 array.write_packed(writer)
947 self.assertEqual(i + bitsize, writer.bitposition, i)
949 reader = BitStreamReader(writer.byte_array, writer.bitposition)
950 if i > 0:
951 self.assertEqual(0, reader.read_bits(i))
952 read_array = Array(array_traits, is_implicit=True)
953 with self.assertRaises(PythonRuntimeException):
954 read_array.read_packed(reader)
956 def _calc_packed_bit_size(self, element_bit_size, array_size, max_delta_bit_size):
957 return self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size + (array_size - 1) * (max_delta_bit_size + 1)
959 def _calc_aligned_packed_bit_size(self, element_bit_size, array_size, max_delta_bit_size):
960 first_element_with_descriptor_bit_size = self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size
961 aligned_first_element_with_descriptor_bit_size = (first_element_with_descriptor_bit_size + 7) // 8 * 8
962 aligned_max_delta_bit_size = (max_delta_bit_size + 1 + 7) // 8 * 8
964 return (
965 aligned_first_element_with_descriptor_bit_size
966 + (array_size - 2) * aligned_max_delta_bit_size
967 + (max_delta_bit_size + 1)
968 )
970 PACKING_DESCRIPTOR_BITSIZE = 1 + 6