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

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

641 

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) 

648 

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) 

652 

653 bitsize = array.bitsizeof(i) 

654 self.assertEqual(expected_bitsize, bitsize, i) 

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

656 

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) 

662 

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) 

667 

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) 

674 

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 ) 

683 

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) 

687 

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) 

693 

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) 

704 

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) 

715 

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 ) 

725 

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) 

729 

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) 

735 

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) 

746 

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) 

758 

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) 

762 

763 bitsize = array.bitsizeof(i) 

764 self.assertEqual(expected_bitsize, bitsize, i) 

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

766 

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) 

772 

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) 

782 

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) 

793 

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) 

797 

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) 

802 

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) 

808 

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) 

813 

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) 

820 

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) 

824 

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) 

829 

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) 

835 

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) 

840 

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) 

847 

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 ) 

856 

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) 

861 

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) 

867 

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) 

878 

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) 

889 

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 ) 

899 

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) 

904 

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) 

910 

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) 

921 

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) 

933 

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) 

937 

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) 

942 

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) 

948 

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) 

955 

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) 

958 

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 

963 

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 ) 

969 

970 PACKING_DESCRIPTOR_BITSIZE = 1 + 6