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

555 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-12-05 10:43 +0000

1import unittest 

2 

3from test_object.api import ArrayObject, ArrayEnum, ArrayBitmask 

4 

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) 

42 

43 

44class ArrayTest(unittest.TestCase): 

45 

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 ) 

59 

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 ) 

73 

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 ) 

87 

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 ) 

101 

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 ) 

115 

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 ) 

129 

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 ) 

143 

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 ) 

157 

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 ) 

171 

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 ) 

185 

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 ) 

199 

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 ) 

213 

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 ) 

227 

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 ) 

241 

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 ) 

255 

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 ) 

269 

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 ) 

283 

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 ) 

303 

304 class ArrayEnumElementFactory: 

305 IS_OBJECT_PACKABLE = True 

306 

307 @staticmethod 

308 def create(reader, _index): 

309 return ArrayEnum.from_reader(reader) 

310 

311 @staticmethod 

312 def create_packing_context(): 

313 return DeltaContext() 

314 

315 @staticmethod 

316 def create_packed(context, reader, _index): 

317 return ArrayEnum.from_reader_packed(context, reader) 

318 

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 ) 

332 

333 class ArrayBitmaskElementFactory: 

334 IS_OBJECT_PACKABLE = True 

335 

336 @staticmethod 

337 def create(reader, _index): 

338 return ArrayBitmask.from_reader(reader) 

339 

340 @staticmethod 

341 def create_packing_context(): 

342 return DeltaContext() 

343 

344 @staticmethod 

345 def create_packed(context, reader, _index): 

346 return ArrayBitmask.from_reader_packed(context, reader) 

347 

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 ) 

369 

370 class ArrayObjectElementFactory: 

371 IS_OBJECT_PACKABLE = True 

372 

373 @staticmethod 

374 def create(reader, _index): 

375 return ArrayObject.from_reader(reader) 

376 

377 @staticmethod 

378 def create_packing_context(): 

379 return ArrayObject.ZserioPackingContext() 

380 

381 @staticmethod 

382 def create_packed(context, reader, _index): 

383 return ArrayObject.from_reader_packed(context, reader) 

384 

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 ) 

398 

399 def test_bitfield_packed_array(self): 

400 array_traits64 = BitFieldArrayTraits(64) 

401 

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) 

410 

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) 

416 

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) 

422 

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) 

428 

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]) 

432 

433 # will have maxBitNumber 62 bits 

434 self._test_packed_array(array_traits64, [0, INT64_MAX // 2, 100, 200, 300, 400, 500, 600, 700]) 

435 

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) 

449 

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) 

463 

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 

468 

469 self._test_packed_array(array_traits64, []) # empty 

470 self._test_packed_array(array_traits64, [-10]) # single element 

471 

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]) 

475 

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) 

490 

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]) 

495 

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) 

501 

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]) 

504 

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]) 

508 

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 ) 

519 

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)]) 

524 

525 @staticmethod 

526 def _set_offset_method(_index, _bitoffset): 

527 pass 

528 

529 @staticmethod 

530 def _check_offset_method(_index, _bitoffset): 

531 pass 

532 

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) 

547 

548 auto_bitsize = bitsizeof_varsize(len(array1_values)) 

549 

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) 

555 

556 def _test_packed_array( 

557 self, 

558 array_traits, 

559 array_values, 

560 array_bitsizeof=None, 

561 array_aligned_bitsizeof=None, 

562 ): 

563 

564 self._test_packed_array_normal(array_traits, array_values, array_bitsizeof) 

565 

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) 

569 

570 self._test_packed_array_aligned(array_traits, array_values, array_aligned_bitsizeof) 

571 

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) 

576 

577 self._test_packed_array_implicit(array_traits, array_values, array_bitsizeof) 

578 

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) 

586 

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)) 

593 

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)) 

598 

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) 

604 

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]) 

615 

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) 

622 

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) 

626 

627 bitsize = array.bitsizeof(i) 

628 self.assertEqual(expected_bitsize, bitsize) 

629 self.assertEqual(i + bitsize, array.initialize_offsets(i), i) 

630 

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) 

636 

637 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

638 if i > 0: 

639 self.assertEqual(0, from_reader.read_bits(i)) 

640 read_array_from_reader = Array.from_reader(array_traits, from_reader, len(array_values)) 

641 self.assertEqual(array, read_array_from_reader, i) 

642 

643 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

644 if i > 0: 

645 self.assertEqual(0, reader.read_bits(i)) 

646 read_array = Array(array_traits) 

647 read_array.read(reader, len(array_values)) 

648 self.assertEqual(array, read_array, i) 

649 

650 def _test_array_auto(self, array_traits, array_values, expected_bitsize): 

651 for i in range(8): 

652 array = Array(array_traits, array_values, is_auto=True) 

653 

654 bitsize = array.bitsizeof(i) 

655 self.assertEqual(expected_bitsize, bitsize, i) 

656 self.assertEqual(i + bitsize, array.initialize_offsets(i), i) 

657 

658 writer = BitStreamWriter() 

659 if i > 0: 

660 writer.write_bits(0, i) 

661 array.write(writer) 

662 self.assertEqual(i + bitsize, writer.bitposition, i) 

663 

664 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

665 if i > 0: 

666 self.assertEqual(0, from_reader.read_bits(i)) 

667 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_auto=True) 

668 self.assertEqual(array, read_array_from_reader, i) 

669 

670 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

671 if i > 0: 

672 self.assertEqual(0, reader.read_bits(i)) 

673 read_array = Array(array_traits, is_auto=True) 

674 read_array.read(reader) 

675 self.assertEqual(array, read_array, i) 

676 

677 def _test_array_aligned(self, array_traits, array_values, expected_bitsize): 

678 for i in range(8): 

679 array = Array( 

680 array_traits, 

681 array_values, 

682 set_offset_method=ArrayTest._set_offset_method, 

683 check_offset_method=ArrayTest._check_offset_method, 

684 ) 

685 

686 bitsize = array.bitsizeof(i) 

687 self.assertEqual(alignto(8, i) - i + expected_bitsize, bitsize, i) 

688 self.assertEqual(i + bitsize, array.initialize_offsets(i), i) 

689 

690 writer = BitStreamWriter() 

691 if i > 0: 

692 writer.write_bits(0, i) 

693 array.write(writer) 

694 self.assertEqual(i + bitsize, writer.bitposition, i) 

695 

696 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

697 if i > 0: 

698 self.assertEqual(0, from_reader.read_bits(i)) 

699 read_array_from_reader = Array.from_reader( 

700 array_traits, 

701 from_reader, 

702 len(array_values), 

703 set_offset_method=ArrayTest._set_offset_method, 

704 check_offset_method=ArrayTest._check_offset_method, 

705 ) 

706 self.assertEqual(array, read_array_from_reader, i) 

707 

708 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

709 if i > 0: 

710 self.assertEqual(0, reader.read_bits(i)) 

711 read_array = Array( 

712 array_traits, 

713 set_offset_method=ArrayTest._set_offset_method, 

714 check_offset_method=ArrayTest._check_offset_method, 

715 ) 

716 read_array.read(reader, len(array_values)) 

717 self.assertEqual(array, read_array, i) 

718 

719 def _test_array_aligned_auto(self, array_traits, array_values, expected_bitsize): 

720 for i in range(8): 

721 array = Array( 

722 array_traits, 

723 array_values, 

724 is_auto=True, 

725 set_offset_method=ArrayTest._set_offset_method, 

726 check_offset_method=ArrayTest._check_offset_method, 

727 ) 

728 

729 bitsize = array.bitsizeof(i) 

730 self.assertEqual(alignto(8, i) - i + expected_bitsize, bitsize, i) 

731 self.assertEqual(i + bitsize, array.initialize_offsets(i), i) 

732 

733 writer = BitStreamWriter() 

734 if i > 0: 

735 writer.write_bits(0, i) 

736 array.write(writer) 

737 self.assertEqual(i + bitsize, writer.bitposition, i) 

738 

739 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

740 if i > 0: 

741 self.assertEqual(0, from_reader.read_bits(i)) 

742 read_array_from_reader = Array.from_reader( 

743 array_traits, 

744 from_reader, 

745 is_auto=True, 

746 set_offset_method=ArrayTest._set_offset_method, 

747 check_offset_method=ArrayTest._check_offset_method, 

748 ) 

749 self.assertEqual(array, read_array_from_reader, i) 

750 

751 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

752 if i > 0: 

753 self.assertEqual(0, reader.read_bits(i)) 

754 read_array = Array( 

755 array_traits, 

756 is_auto=True, 

757 set_offset_method=ArrayTest._set_offset_method, 

758 check_offset_method=ArrayTest._check_offset_method, 

759 ) 

760 read_array.read(reader) 

761 self.assertEqual(array, read_array, i) 

762 

763 def _test_array_implicit(self, array_traits, array_values, expected_bitsize): 

764 for i in range(8): 

765 array = Array(array_traits, array_values, is_implicit=True) 

766 

767 bitsize = array.bitsizeof(i) 

768 self.assertEqual(expected_bitsize, bitsize, i) 

769 self.assertEqual(i + bitsize, array.initialize_offsets(i), i) 

770 

771 writer = BitStreamWriter() 

772 if i > 0: 

773 writer.write_bits(0, i) 

774 array.write(writer) 

775 self.assertEqual(i + bitsize, writer.bitposition, i) 

776 

777 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

778 if i > 0: 

779 self.assertEqual(0, from_reader.read_bits(i)) 

780 if array_traits.HAS_BITSIZEOF_CONSTANT: 

781 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_implicit=True) 

782 self.assertEqual(array, read_array_from_reader, i) 

783 else: 

784 with self.assertRaises(PythonRuntimeException): 

785 Array.from_reader(array_traits, from_reader, is_implicit=True) 

786 

787 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

788 if i > 0: 

789 self.assertEqual(0, reader.read_bits(i)) 

790 read_array = Array(array_traits, is_implicit=True) 

791 if array_traits.HAS_BITSIZEOF_CONSTANT: 

792 read_array.read(reader) 

793 self.assertEqual(array, read_array, i) 

794 else: 

795 with self.assertRaises(PythonRuntimeException): 

796 read_array.read(reader) 

797 

798 def _test_packed_array_normal(self, array_traits, array_values, expected_bitsize): 

799 for i in range(8): 

800 array = Array(array_traits, array_values) 

801 

802 bitsize = array.bitsizeof_packed(i) 

803 if expected_bitsize is not None: 

804 self.assertEqual(expected_bitsize, bitsize) 

805 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i) 

806 

807 writer = BitStreamWriter() 

808 if i > 0: 

809 writer.write_bits(0, i) 

810 array.write_packed(writer) 

811 self.assertEqual(i + bitsize, writer.bitposition, i) 

812 

813 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

814 if i > 0: 

815 self.assertEqual(0, from_reader.read_bits(i)) 

816 read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, len(array_values)) 

817 self.assertEqual(array, read_array_from_reader, i) 

818 

819 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

820 if i > 0: 

821 self.assertEqual(0, reader.read_bits(i)) 

822 read_array = Array(array_traits) 

823 read_array.read_packed(reader, len(array_values)) 

824 self.assertEqual(array, read_array, i) 

825 

826 def _test_packed_array_auto(self, array_traits, array_values, expected_bitsize): 

827 for i in range(8): 

828 array = Array(array_traits, array_values, is_auto=True) 

829 

830 bitsize = array.bitsizeof_packed(i) 

831 if expected_bitsize is not None: 

832 self.assertEqual(expected_bitsize, bitsize) 

833 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i) 

834 

835 writer = BitStreamWriter() 

836 if i > 0: 

837 writer.write_bits(0, i) 

838 array.write_packed(writer) 

839 self.assertEqual(i + bitsize, writer.bitposition, i) 

840 

841 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

842 if i > 0: 

843 self.assertEqual(0, from_reader.read_bits(i)) 

844 read_array_from_reader = Array.from_reader_packed(array_traits, from_reader, is_auto=True) 

845 self.assertEqual(array, read_array_from_reader, i) 

846 

847 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

848 if i > 0: 

849 self.assertEqual(0, reader.read_bits(i)) 

850 read_array = Array(array_traits, is_auto=True) 

851 read_array.read_packed(reader) 

852 self.assertEqual(array, read_array, i) 

853 

854 def _test_packed_array_aligned(self, array_traits, array_values, expected_bitsize): 

855 for i in range(8): 

856 array = Array( 

857 array_traits, 

858 array_values, 

859 set_offset_method=ArrayTest._set_offset_method, 

860 check_offset_method=ArrayTest._check_offset_method, 

861 ) 

862 

863 bitsize = array.bitsizeof_packed(i) 

864 if expected_bitsize is not None and i == 0: 

865 self.assertEqual(expected_bitsize, bitsize) 

866 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i) 

867 

868 writer = BitStreamWriter() 

869 if i > 0: 

870 writer.write_bits(0, i) 

871 array.write_packed(writer) 

872 self.assertEqual(i + bitsize, writer.bitposition, i) 

873 

874 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

875 if i > 0: 

876 self.assertEqual(0, from_reader.read_bits(i)) 

877 read_array_from_reader = Array.from_reader_packed( 

878 array_traits, 

879 from_reader, 

880 len(array_values), 

881 set_offset_method=ArrayTest._set_offset_method, 

882 check_offset_method=ArrayTest._check_offset_method, 

883 ) 

884 self.assertEqual(array, read_array_from_reader, i) 

885 

886 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

887 if i > 0: 

888 self.assertEqual(0, reader.read_bits(i)) 

889 read_array = Array( 

890 array_traits, 

891 set_offset_method=ArrayTest._set_offset_method, 

892 check_offset_method=ArrayTest._check_offset_method, 

893 ) 

894 read_array.read_packed(reader, len(array_values)) 

895 self.assertEqual(array, read_array, i) 

896 

897 def _test_packed_array_aligned_auto(self, array_traits, array_values, expected_bitsize): 

898 for i in range(8): 

899 array = Array( 

900 array_traits, 

901 array_values, 

902 is_auto=True, 

903 set_offset_method=ArrayTest._set_offset_method, 

904 check_offset_method=ArrayTest._check_offset_method, 

905 ) 

906 

907 bitsize = array.bitsizeof_packed(i) 

908 if expected_bitsize is not None and i == 0: 

909 self.assertEqual(expected_bitsize, bitsize) 

910 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i) 

911 

912 writer = BitStreamWriter() 

913 if i > 0: 

914 writer.write_bits(0, i) 

915 array.write_packed(writer) 

916 self.assertEqual(i + bitsize, writer.bitposition, i) 

917 

918 from_reader = BitStreamReader(writer.byte_array, writer.bitposition) 

919 if i > 0: 

920 self.assertEqual(0, from_reader.read_bits(i)) 

921 read_array_from_reader = Array.from_reader_packed( 

922 array_traits, 

923 from_reader, 

924 is_auto=True, 

925 set_offset_method=ArrayTest._set_offset_method, 

926 check_offset_method=ArrayTest._check_offset_method, 

927 ) 

928 self.assertEqual(array, read_array_from_reader, i) 

929 

930 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

931 if i > 0: 

932 self.assertEqual(0, reader.read_bits(i)) 

933 read_array = Array( 

934 array_traits, 

935 is_auto=True, 

936 set_offset_method=ArrayTest._set_offset_method, 

937 check_offset_method=ArrayTest._check_offset_method, 

938 ) 

939 read_array.read_packed(reader) 

940 self.assertEqual(array, read_array, i) 

941 

942 def _test_packed_array_implicit(self, array_traits, array_values, expected_bitsize): 

943 for i in range(8): 

944 array = Array(array_traits, array_values, is_implicit=True) 

945 

946 bitsize = array.bitsizeof_packed(i) 

947 if expected_bitsize is not None: 

948 self.assertEqual(expected_bitsize, bitsize) 

949 self.assertEqual(i + bitsize, array.initialize_offsets_packed(i), i) 

950 

951 writer = BitStreamWriter() 

952 if i > 0: 

953 writer.write_bits(0, i) 

954 array.write_packed(writer) 

955 self.assertEqual(i + bitsize, writer.bitposition, i) 

956 

957 reader = BitStreamReader(writer.byte_array, writer.bitposition) 

958 if i > 0: 

959 self.assertEqual(0, reader.read_bits(i)) 

960 read_array = Array(array_traits, is_implicit=True) 

961 with self.assertRaises(PythonRuntimeException): 

962 read_array.read_packed(reader) 

963 

964 def _calc_packed_bit_size(self, element_bit_size, array_size, max_delta_bit_size): 

965 return self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size + (array_size - 1) * (max_delta_bit_size + 1) 

966 

967 def _calc_aligned_packed_bit_size(self, element_bit_size, array_size, max_delta_bit_size): 

968 first_element_with_descriptor_bit_size = self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size 

969 aligned_first_element_with_descriptor_bit_size = (first_element_with_descriptor_bit_size + 7) // 8 * 8 

970 aligned_max_delta_bit_size = (max_delta_bit_size + 1 + 7) // 8 * 8 

971 

972 return ( 

973 aligned_first_element_with_descriptor_bit_size 

974 + (array_size - 2) * aligned_max_delta_bit_size 

975 + (max_delta_bit_size + 1) 

976 ) 

977 

978 PACKING_DESCRIPTOR_BITSIZE = 1 + 6