Coverage for /home/jenkins/workspace/NDS/Zserio/NDS_ZSERIO-linux-build/compiler/extensions/python/runtime/tests/test_array.py: 100%

547 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-12-13 15:12 +0000

1import unittest 

2 

3from test_object.api import ArrayObject, ArrayEnum, ArrayBitmask 

4 

5from zserio.array import (Array, BitFieldArrayTraits, SignedBitFieldArrayTraits, 

6 VarUInt16ArrayTraits, VarUInt32ArrayTraits, VarUInt64ArrayTraits, VarUIntArrayTraits, 

7 VarSizeArrayTraits, VarInt16ArrayTraits, VarInt32ArrayTraits, VarInt64ArrayTraits, 

8 VarIntArrayTraits, Float16ArrayTraits, Float32ArrayTraits, Float64ArrayTraits, 

9 BytesArrayTraits, StringArrayTraits, BoolArrayTraits, BitBufferArrayTraits, 

10 ObjectArrayTraits, DeltaContext) 

11from zserio.bitposition import alignto 

12from zserio.bitbuffer import BitBuffer 

13from zserio.bitreader import BitStreamReader 

14from zserio.bitsizeof import bitsizeof_varsize 

15from zserio.bitwriter import BitStreamWriter 

16from zserio import PythonRuntimeException 

17from zserio.limits import UINT64_MIN, UINT64_MAX, INT64_MIN, INT64_MAX, UINT8_MAX, INT16_MIN 

18 

19class ArrayTest(unittest.TestCase): 

20 

21 def test_bitfield_array(self): 

22 array_traits = BitFieldArrayTraits(5) 

23 array1_values = [1, 2] 

24 array1_bitsizeof = 2 * 5 

25 array1_aligned_bitsizeof = 5 + 3 + 5 

26 array2_values = [3, 4] 

27 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

28 

29 def test_signed_bitfield_array(self): 

30 array_traits = SignedBitFieldArrayTraits(5) 

31 array1_values = [-1, 1] 

32 array1_bitsizeof = 2 * 5 

33 array1_aligned_bitsizeof = 5 + 3 + 5 

34 array2_values = [-2, 2] 

35 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

36 

37 def test_varuint16_array(self): 

38 array_traits = VarUInt16ArrayTraits() 

39 array1_values = [1, 1024] 

40 array1_bitsizeof = 8 + 16 

41 array1_aligned_bitsizeof = array1_bitsizeof 

42 array2_values = [1, 8192] 

43 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

44 

45 def test_varuint32_array(self): 

46 array_traits = VarUInt32ArrayTraits() 

47 array1_values = [1, 16384] 

48 array1_bitsizeof = 8 + 24 

49 array1_aligned_bitsizeof = array1_bitsizeof 

50 array2_values = [1, 32768] 

51 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

52 

53 def test_varuint64_array(self): 

54 array_traits = VarUInt64ArrayTraits() 

55 array1_values = [1, 16384] 

56 array1_bitsizeof = 8 + 24 

57 array1_aligned_bitsizeof = array1_bitsizeof 

58 array2_values = [1, 65536] 

59 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

60 

61 def test_varuint_array(self): 

62 array_traits = VarUIntArrayTraits() 

63 array1_values = [1, 1024] 

64 array1_bitsizeof = 8 + 16 

65 array1_aligned_bitsizeof = array1_bitsizeof 

66 array2_values = [1, 8192] 

67 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

68 

69 def test_varsize_array(self): 

70 array_traits = VarSizeArrayTraits() 

71 array1_values = [1, 16384] 

72 array1_bitsizeof = 8 + 24 

73 array1_aligned_bitsizeof = array1_bitsizeof 

74 array2_values = [1, 32768] 

75 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

76 

77 def test_varint16_array(self): 

78 array_traits = VarInt16ArrayTraits() 

79 array1_values = [-1, 1024] 

80 array1_bitsizeof = 8 + 16 

81 array1_aligned_bitsizeof = array1_bitsizeof 

82 array2_values = [-1, 8192] 

83 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

84 

85 def test_varint32_array(self): 

86 array_traits = VarInt32ArrayTraits() 

87 array1_values = [-1, 16384] 

88 array1_bitsizeof = 8 + 24 

89 array1_aligned_bitsizeof = array1_bitsizeof 

90 array2_values = [-1, 32768] 

91 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

92 

93 def test_varint64_array(self): 

94 array_traits = VarInt64ArrayTraits() 

95 array1_values = [-1, 16384] 

96 array1_bitsizeof = 8 + 24 

97 array1_aligned_bitsizeof = array1_bitsizeof 

98 array2_values = [-1, 65536] 

99 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

100 

101 def test_varint_array(self): 

102 array_traits = VarIntArrayTraits() 

103 array1_values = [-1, 1024] 

104 array1_bitsizeof = 8 + 16 

105 array1_aligned_bitsizeof = array1_bitsizeof 

106 array2_values = [-1, 8192] 

107 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

108 

109 def test_float16_array(self): 

110 array_traits = Float16ArrayTraits() 

111 array1_values = [-1.0, 1.0] 

112 array1_bitsizeof = 2 * 16 

113 array1_aligned_bitsizeof = array1_bitsizeof 

114 array2_values = [-3.5, 3.5] 

115 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

116 

117 def test_float32_array(self): 

118 array_traits = Float32ArrayTraits() 

119 array1_values = [-1.0, 1.0] 

120 array1_bitsizeof = 2 * 32 

121 array1_aligned_bitsizeof = array1_bitsizeof 

122 array2_values = [-3.5, 3.5] 

123 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

124 

125 def test_float64_array(self): 

126 array_traits = Float64ArrayTraits() 

127 array1_values = [-1.0, 1.0] 

128 array1_bitsizeof = 2 * 64 

129 array1_aligned_bitsizeof = array1_bitsizeof 

130 array2_values = [-3.5, 3.5] 

131 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

132 

133 def test_bytes_array(self): 

134 array_traits = BytesArrayTraits() 

135 array1_values = [bytearray([1, 255]), bytearray([127, 128])] 

136 array1_bitsizeof = 2 * (1 + 2) * 8 

137 array1_aligned_bitsizeof = array1_bitsizeof 

138 array2_values = [bytearray([0, 0]), bytearray([255, 255])] 

139 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

140 

141 def test_string_array(self): 

142 array_traits = StringArrayTraits() 

143 array1_values = ["Text1", "Text2"] 

144 array1_bitsizeof = 2 * (1 + len("TextN")) * 8 

145 array1_aligned_bitsizeof = array1_bitsizeof 

146 array2_values = ["Text3", "Text4"] 

147 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

148 

149 def test_bool_array(self): 

150 array_traits = BoolArrayTraits() 

151 array1_values = [True, False] 

152 array1_bitsizeof = 2 * 1 

153 array1_aligned_bitsizeof = 1 + 7 + 1 

154 array2_values = [True, True] 

155 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

156 

157 def test_bitbuffer_array(self): 

158 array_traits = BitBufferArrayTraits() 

159 array1_values = [BitBuffer(bytes([0xAB, 0xE0]), 11), BitBuffer(bytes([0xAB, 0xCD, 0xFE]), 23)] 

160 array1_bitsizeof = 8 + 11 + 8 + 23 

161 array1_aligned_bitsizeof = 8 + 11 + 5 + 8 + 23 

162 array2_values = [BitBuffer(bytes([0xBA, 0xE0]), 11), BitBuffer(bytes([0xBA, 0xDC, 0xFE]), 23)] 

163 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

164 

165 class ArrayEnumElementFactory: 

166 IS_OBJECT_PACKABLE = True 

167 

168 @staticmethod 

169 def create(reader, _index): 

170 return ArrayEnum.from_reader(reader) 

171 

172 @staticmethod 

173 def create_packing_context(): 

174 return DeltaContext() 

175 

176 @staticmethod 

177 def create_packed(context, reader, _index): 

178 return ArrayEnum.from_reader_packed(context, reader) 

179 

180 def test_enum_array(self): 

181 array_traits = ObjectArrayTraits(ArrayTest.ArrayEnumElementFactory) 

182 array1_values = [ArrayEnum.VALUE1, ArrayEnum.VALUE2, ArrayEnum.VALUE3] 

183 array1_bitsizeof = 3 * 8 

184 array1_aligned_bitsizeof = array1_bitsizeof 

185 array2_values = [ArrayEnum.VALUE1, ArrayEnum.VALUE1, ArrayEnum.VALUE1] 

186 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

187 

188 class ArrayBitmaskElementFactory: 

189 IS_OBJECT_PACKABLE = True 

190 

191 @staticmethod 

192 def create(reader, _index): 

193 return ArrayBitmask.from_reader(reader) 

194 

195 @staticmethod 

196 def create_packing_context(): 

197 return DeltaContext() 

198 

199 @staticmethod 

200 def create_packed(context, reader, _index): 

201 return ArrayBitmask.from_reader_packed(context, reader) 

202 

203 def test_bitmask_array(self): 

204 array_traits = ObjectArrayTraits(ArrayTest.ArrayBitmaskElementFactory) 

205 array1_values = [ArrayBitmask.Values.READ, ArrayBitmask.Values.WRITE, ArrayBitmask.Values.CREATE] 

206 array1_bitsizeof = 3 * 8 

207 array1_aligned_bitsizeof = array1_bitsizeof 

208 array2_values = [ArrayBitmask.Values.READ, ArrayBitmask.Values.READ, ArrayBitmask.Values.READ] 

209 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

210 

211 class ArrayObjectElementFactory: 

212 IS_OBJECT_PACKABLE = True 

213 

214 @staticmethod 

215 def create(reader, _index): 

216 return ArrayObject.from_reader(reader) 

217 

218 @staticmethod 

219 def create_packing_context(): 

220 return ArrayObject.ZserioPackingContext() 

221 

222 @staticmethod 

223 def create_packed(context, reader, _index): 

224 return ArrayObject.from_reader_packed(context, reader) 

225 

226 def test_object_array(self): 

227 array_traits = ObjectArrayTraits(ArrayTest.ArrayObjectElementFactory) 

228 array1_values = [ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)] 

229 array1_bitsizeof = 3 * 31 

230 array1_aligned_bitsizeof = 31 + 1 + 31 + 1 + 31 

231 array2_values = [ArrayObject(0x01), ArrayObject(0x02), ArrayObject(0x03)] 

232 self._test_array(array_traits, array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values) 

233 

234 def test_bitfield_packed_array(self): 

235 array_traits64 = BitFieldArrayTraits(64) 

236 

237 # none-zero delta 

238 array1_values = [10, 11, 12] 

239 array1_max_delta_bit_size = 1 

240 array1_bitsizeof = self._calc_packed_bit_size(64, len(array1_values), array1_max_delta_bit_size) 

241 array1_aligned_bitsizeof = self._calc_aligned_packed_bit_size(64, len(array1_values), 

242 array1_max_delta_bit_size) 

243 self._test_packed_array(array_traits64, array1_values, array1_bitsizeof, array1_aligned_bitsizeof) 

244 

245 # zero delta 

246 array2_values = [10, 10, 10] 

247 array2_bitsizeof = self.PACKING_DESCRIPTOR_BITSIZE + 64 

248 array2_aligned_bitsizeof = self.PACKING_DESCRIPTOR_BITSIZE + 64 + 1 

249 self._test_packed_array(array_traits64, array2_values, array2_bitsizeof, array2_aligned_bitsizeof) 

250 

251 # one-element array 

252 array3_values = [10] 

253 array3_bitsizeof = 1 + 64 

254 array3_aligned_bitsizeof = 1 + 64 

255 self._test_packed_array(array_traits64, array3_values, array3_bitsizeof, array3_aligned_bitsizeof) 

256 

257 # empty array 

258 array4_values = [] 

259 array4_bitsizeof = 0 

260 array4_aligned_bitsizeof = 0 

261 self._test_packed_array(array_traits64, array4_values, array4_bitsizeof, array4_aligned_bitsizeof) 

262 

263 # packing not applied, delta is too big 

264 self._test_packed_array(array_traits64, [UINT64_MIN, UINT64_MAX]) 

265 self._test_packed_array(array_traits64, [UINT64_MAX, UINT64_MAX // 2, UINT64_MIN]) 

266 

267 # will have maxBitNumber 62 bits 

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

269 

270 # will not be packed because unpacked 8bit values will be more efficient 

271 array_traits8 = BitFieldArrayTraits(8) 

272 array5_values = [UINT8_MAX, 0, 10, 20, 30, 40] # max_bit_number 8, delta needs 9 bits 

273 array5_bitsizeof = 1 + 6 * 8 

274 array5_aligned_bitsizeof = 1 + 8 + 7 + 5 * 8 

275 self._test_packed_array(array_traits8, array5_values, array5_bitsizeof, array5_aligned_bitsizeof) 

276 

277 # will not be packed because unpacked 8bit values will be more efficient 

278 # (6 bits more are needed to store max_bit_number in descriptor if packing was enabled) 

279 array6_values = [UINT8_MAX, UINT8_MAX // 2 + 1, 10, 20, 30, 40] # max_bit_number 7, delta needs 8 bits 

280 array6_bitsizeof = 1 + 6 * 8 

281 array6_aligned_bitsizeof = 1 + 8 + 7 + 5 * 8 

282 self._test_packed_array(array_traits8, array6_values, array6_bitsizeof, array6_aligned_bitsizeof) 

283 

284 def test_signed_bitfield_packed_array(self): 

285 array_traits64 = SignedBitFieldArrayTraits(64) 

286 self._test_packed_array(array_traits64, [-10, 11, -12]) 

287 self._test_packed_array(array_traits64, [-10, -10, -10]) # zero delta 

288 

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

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

291 

292 # packing not applied, delta is too big 

293 self._test_packed_array(array_traits64, [INT64_MIN, INT64_MAX]) 

294 self._test_packed_array(array_traits64, [INT64_MIN, 0, INT64_MAX]) 

295 

296 # will not be packed because unpacked 16bit values will be more efficient 

297 # (6 bits more are needed to store max_bit_number in descriptor if packing was enabled) 

298 array_traits16 = SignedBitFieldArrayTraits(16) 

299 array16_values = [INT16_MIN, -1, 10, 20, 30, 40] # max_bit_number 15, delta needs 16 bits 

300 array16_bitsizeof = 1 + 6 * 16 

301 array16_aligned_bitsizeof = 1 + 16 + 7 + 5 * 16 

302 self._test_packed_array(array_traits16, array16_values, array16_bitsizeof, array16_aligned_bitsizeof) 

303 

304 def test_varuint_packed_array(self): 

305 array_traits = VarUIntArrayTraits() 

306 self._test_packed_array(array_traits, [100, 200, 300]) 

307 self._test_packed_array(array_traits, [300, 200, 100]) 

308 

309 # won't be packed because unpacked varuint values will be more efficient 

310 unpacked_array = [5000000, 0, 0, 0, 0, 0, 0] 

311 unpacked_bitsizeof = 1 + 32 + 6 * 8 

312 unpacked_aligned_bitsizeof = 1 + 32 + 7 + 6 * 8 

313 self._test_packed_array(array_traits, unpacked_array, unpacked_bitsizeof, unpacked_aligned_bitsizeof) 

314 

315 self._test_packed_array(array_traits, [UINT64_MIN, UINT64_MAX]) 

316 self._test_packed_array(array_traits, [UINT64_MAX, UINT64_MAX // 2, UINT64_MIN]) 

317 

318 def test_enum_packed_array(self): 

319 array_traits = ObjectArrayTraits(ArrayTest.ArrayEnumElementFactory) 

320 self._test_packed_array(array_traits, [ArrayEnum.VALUE1, ArrayEnum.VALUE2, ArrayEnum.VALUE3]) 

321 

322 def test_bitmask_packed_array(self): 

323 array_traits = ObjectArrayTraits(ArrayTest.ArrayBitmaskElementFactory) 

324 self._test_packed_array(array_traits, [ 

325 ArrayBitmask.Values.READ, ArrayBitmask.Values.WRITE, ArrayBitmask.Values.CREATE 

326 ]) 

327 

328 def test_object_packed_array(self): 

329 array_traits = ObjectArrayTraits(ArrayTest.ArrayObjectElementFactory) 

330 self._test_packed_array(array_traits, [ArrayObject(0xAB), ArrayObject(0xCD), ArrayObject(0xEF)]) 

331 self._test_packed_array(array_traits, [ArrayObject(0x01), ArrayObject(0x02), ArrayObject(0x03)]) 

332 

333 @staticmethod 

334 def _set_offset_method(_index, _bitoffset): 

335 pass 

336 

337 @staticmethod 

338 def _check_offset_method(_index, _bitoffset): 

339 pass 

340 

341 def _test_array(self, array_traits, 

342 array1_values, array1_bitsizeof, array1_aligned_bitsizeof, array2_values): 

343 self._test_eq(array_traits, array1_values, array2_values) 

344 self._test_hashcode(array_traits, array1_values, array2_values) 

345 self._test_len(array_traits, array1_values) 

346 self._test_get_item(array_traits, array1_values) 

347 self._test_set_item(array_traits, array1_values) 

348 self._test_raw_array(array_traits, array1_values, array2_values) 

349 

350 auto_bitsize = bitsizeof_varsize(len(array1_values)) 

351 

352 self._test_array_normal(array_traits, array1_values, array1_bitsizeof) 

353 self._test_array_auto(array_traits, array1_values, auto_bitsize + array1_bitsizeof) 

354 self._test_array_aligned(array_traits, array1_values, array1_aligned_bitsizeof) 

355 self._test_array_aligned_auto(array_traits, array1_values, auto_bitsize + array1_aligned_bitsizeof) 

356 self._test_array_implicit(array_traits, array1_values, array1_bitsizeof) 

357 

358 def _test_packed_array(self, array_traits, array_values, array_bitsizeof=None, 

359 array_aligned_bitsizeof=None): 

360 

361 self._test_packed_array_normal(array_traits, array_values, array_bitsizeof) 

362 

363 auto_size_bitsize = bitsizeof_varsize(len(array_values)) 

364 auto_bitsize = auto_size_bitsize + array_bitsizeof if array_bitsizeof is not None else None 

365 self._test_packed_array_auto(array_traits, array_values, auto_bitsize) 

366 

367 self._test_packed_array_aligned(array_traits, array_values, array_aligned_bitsizeof) 

368 

369 auto_aligned_bitsize = (auto_size_bitsize + array_aligned_bitsizeof 

370 if array_aligned_bitsizeof is not None else None) 

371 self._test_packed_array_aligned_auto(array_traits, array_values, auto_aligned_bitsize) 

372 

373 self._test_packed_array_implicit(array_traits, array_values, array_bitsizeof) 

374 

375 def _test_eq(self, array_traits, array1_values, array2_values): 

376 array1 = Array(array_traits, array1_values) 

377 array2 = Array(array_traits, array2_values) 

378 array3 = Array(array_traits, array1_values) 

379 self.assertNotEqual(array1, None) 

380 self.assertNotEqual(array1, array2) 

381 self.assertEqual(array1, array3) 

382 

383 def _test_hashcode(self, array_traits, array1_values, array2_values): 

384 array1 = Array(array_traits, array1_values) 

385 array2 = Array(array_traits, array2_values) 

386 array3 = Array(array_traits, array1_values) 

387 self.assertNotEqual(hash(array1), hash(array2)) 

388 self.assertEqual(hash(array1), hash(array3)) 

389 

390 def _test_len(self, array_traits, array_values): 

391 array = Array(array_traits, array_values) 

392 raw_array = array.raw_array 

393 self.assertEqual(len(raw_array), len(array)) 

394 

395 def _test_get_item(self, array_traits, array_values): 

396 array = Array(array_traits, array_values) 

397 raw_array = array.raw_array 

398 for value, raw_value in zip(array, raw_array): 

399 self.assertEqual(value, raw_value) 

400 

401 def _test_set_item(self, array_traits, array_values): 

402 array = Array(array_traits, array_values) 

403 raw_array = array.raw_array 

404 self.assertTrue(len(array) > 1) 

405 first_value = array[0] 

406 second_value = array[1] 

407 array[0] = second_value 

408 self.assertEqual(array[0], raw_array[0]) 

409 raw_array[0] = first_value # return the original value for other tests 

410 self.assertEqual(array[0], raw_array[0]) 

411 

412 def _test_raw_array(self, array_traits, array1_values, array2_values): 

413 array1 = Array(array_traits, array1_values) 

414 array2 = Array(array_traits, array2_values) 

415 array3 = Array(array_traits, array1_values) 

416 self.assertNotEqual(array1.raw_array, array2.raw_array) 

417 self.assertEqual(array1.raw_array, array3.raw_array) 

418 

419 def _test_array_normal(self, array_traits, array_values, expected_bitsize): 

420 for i in range(8): 

421 array = Array(array_traits, array_values) 

422 

423 bitsize = array.bitsizeof(i) 

424 self.assertEqual(expected_bitsize, bitsize) 

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

426 

427 writer = BitStreamWriter() 

428 if i > 0: 

429 writer.write_bits(0, i) 

430 array.write(writer) 

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

432 

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

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

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

436 self.assertEqual(array, read_array_from_reader, i) 

437 

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

439 if i > 0: 

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

441 read_array = Array(array_traits) 

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

443 self.assertEqual(array, read_array, i) 

444 

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

446 for i in range(8): 

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

448 

449 bitsize = array.bitsizeof(i) 

450 self.assertEqual(expected_bitsize, bitsize, i) 

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

452 

453 writer = BitStreamWriter() 

454 if i > 0: 

455 writer.write_bits(0, i) 

456 array.write(writer) 

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

458 

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

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

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

462 self.assertEqual(array, read_array_from_reader, i) 

463 

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

465 if i > 0: 

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

467 read_array = Array(array_traits, is_auto=True) 

468 read_array.read(reader) 

469 self.assertEqual(array, read_array, i) 

470 

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

472 for i in range(8): 

473 array = Array(array_traits, array_values, set_offset_method=ArrayTest._set_offset_method, 

474 check_offset_method=ArrayTest._check_offset_method) 

475 

476 bitsize = array.bitsizeof(i) 

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

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

479 

480 writer = BitStreamWriter() 

481 if i > 0: 

482 writer.write_bits(0, i) 

483 array.write(writer) 

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

485 

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

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

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

489 set_offset_method=ArrayTest._set_offset_method, 

490 check_offset_method=ArrayTest._check_offset_method) 

491 self.assertEqual(array, read_array_from_reader, i) 

492 

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

494 if i > 0: 

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

496 read_array = Array(array_traits, set_offset_method=ArrayTest._set_offset_method, 

497 check_offset_method=ArrayTest._check_offset_method) 

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

499 self.assertEqual(array, read_array, i) 

500 

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

502 for i in range(8): 

503 array = Array(array_traits, array_values, is_auto=True, 

504 set_offset_method=ArrayTest._set_offset_method, 

505 check_offset_method=ArrayTest._check_offset_method) 

506 

507 bitsize = array.bitsizeof(i) 

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

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

510 

511 writer = BitStreamWriter() 

512 if i > 0: 

513 writer.write_bits(0, i) 

514 array.write(writer) 

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

516 

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

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

519 read_array_from_reader = Array.from_reader(array_traits, from_reader, is_auto=True, 

520 set_offset_method=ArrayTest._set_offset_method, 

521 check_offset_method=ArrayTest._check_offset_method) 

522 self.assertEqual(array, read_array_from_reader, i) 

523 

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

525 if i > 0: 

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

527 read_array = Array(array_traits, is_auto=True, set_offset_method=ArrayTest._set_offset_method, 

528 check_offset_method=ArrayTest._check_offset_method) 

529 read_array.read(reader) 

530 self.assertEqual(array, read_array, i) 

531 

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

533 for i in range(8): 

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

535 

536 bitsize = array.bitsizeof(i) 

537 self.assertEqual(expected_bitsize, bitsize, i) 

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

539 

540 writer = BitStreamWriter() 

541 if i > 0: 

542 writer.write_bits(0, i) 

543 array.write(writer) 

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

545 

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

547 if i > 0: 

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

549 if array_traits.HAS_BITSIZEOF_CONSTANT: 

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

551 self.assertEqual(array, read_array_from_reader, i) 

552 else: 

553 with self.assertRaises(PythonRuntimeException): 

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

555 

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

557 if i > 0: 

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

559 read_array = Array(array_traits, is_implicit=True) 

560 if array_traits.HAS_BITSIZEOF_CONSTANT: 

561 read_array.read(reader) 

562 self.assertEqual(array, read_array, i) 

563 else: 

564 with self.assertRaises(PythonRuntimeException): 

565 read_array.read(reader) 

566 

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

568 for i in range(8): 

569 array = Array(array_traits, array_values) 

570 

571 bitsize = array.bitsizeof_packed(i) 

572 if expected_bitsize is not None: 

573 self.assertEqual(expected_bitsize, bitsize) 

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

575 

576 writer = BitStreamWriter() 

577 if i > 0: 

578 writer.write_bits(0, i) 

579 array.write_packed(writer) 

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

581 

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

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

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

585 self.assertEqual(array, read_array_from_reader, i) 

586 

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

588 if i > 0: 

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

590 read_array = Array(array_traits) 

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

592 self.assertEqual(array, read_array, i) 

593 

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

595 for i in range(8): 

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

597 

598 bitsize = array.bitsizeof_packed(i) 

599 if expected_bitsize is not None: 

600 self.assertEqual(expected_bitsize, bitsize) 

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

602 

603 writer = BitStreamWriter() 

604 if i > 0: 

605 writer.write_bits(0, i) 

606 array.write_packed(writer) 

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

608 

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

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

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

612 self.assertEqual(array, read_array_from_reader, i) 

613 

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

615 if i > 0: 

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

617 read_array = Array(array_traits, is_auto=True) 

618 read_array.read_packed(reader) 

619 self.assertEqual(array, read_array, i) 

620 

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

622 for i in range(8): 

623 array = Array(array_traits, array_values, set_offset_method=ArrayTest._set_offset_method, 

624 check_offset_method=ArrayTest._check_offset_method) 

625 

626 bitsize = array.bitsizeof_packed(i) 

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

628 self.assertEqual(expected_bitsize, bitsize) 

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

630 

631 writer = BitStreamWriter() 

632 if i > 0: 

633 writer.write_bits(0, i) 

634 array.write_packed(writer) 

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

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_packed( 

640 array_traits, from_reader, len(array_values), 

641 set_offset_method=ArrayTest._set_offset_method, 

642 check_offset_method=ArrayTest._check_offset_method) 

643 self.assertEqual(array, read_array_from_reader, i) 

644 

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

646 if i > 0: 

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

648 read_array = Array(array_traits, set_offset_method=ArrayTest._set_offset_method, 

649 check_offset_method=ArrayTest._check_offset_method) 

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

651 self.assertEqual(array, read_array, i) 

652 

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

654 for i in range(8): 

655 array = Array(array_traits, array_values, is_auto=True, 

656 set_offset_method=ArrayTest._set_offset_method, 

657 check_offset_method=ArrayTest._check_offset_method) 

658 

659 bitsize = array.bitsizeof_packed(i) 

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

661 self.assertEqual(expected_bitsize, bitsize) 

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

663 

664 writer = BitStreamWriter() 

665 if i > 0: 

666 writer.write_bits(0, i) 

667 array.write_packed(writer) 

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

669 

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

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

672 read_array_from_reader = Array.from_reader_packed( 

673 array_traits, from_reader, is_auto=True, 

674 set_offset_method=ArrayTest._set_offset_method, 

675 check_offset_method=ArrayTest._check_offset_method 

676 ) 

677 self.assertEqual(array, read_array_from_reader, i) 

678 

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

680 if i > 0: 

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

682 read_array = Array(array_traits, is_auto=True, set_offset_method=ArrayTest._set_offset_method, 

683 check_offset_method=ArrayTest._check_offset_method) 

684 read_array.read_packed(reader) 

685 self.assertEqual(array, read_array, i) 

686 

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

688 for i in range(8): 

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

690 

691 bitsize = array.bitsizeof_packed(i) 

692 if expected_bitsize is not None: 

693 self.assertEqual(expected_bitsize, bitsize) 

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

695 

696 writer = BitStreamWriter() 

697 if i > 0: 

698 writer.write_bits(0, i) 

699 array.write_packed(writer) 

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

701 

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

703 if i > 0: 

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

705 read_array = Array(array_traits, is_implicit=True) 

706 with self.assertRaises(PythonRuntimeException): 

707 read_array.read_packed(reader) 

708 

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

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

711 

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

713 first_element_with_descriptor_bit_size = self.PACKING_DESCRIPTOR_BITSIZE + element_bit_size 

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

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

716 

717 return (aligned_first_element_with_descriptor_bit_size + 

718 (array_size - 2) * aligned_max_delta_bit_size + (max_delta_bit_size + 1)) 

719 

720 PACKING_DESCRIPTOR_BITSIZE = 1 + 6