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

849 statements  

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

1import enum 

2import io 

3import unittest 

4import math 

5 

6 

7from test_object.api import CreatorEnum, CreatorBitmask, CreatorObject 

8 

9from zserio.bitbuffer import BitBuffer 

10from zserio.json import ( 

11 JsonWriter, 

12 JsonEncoder, 

13 JsonParser, 

14 JsonTokenizer, 

15 JsonToken, 

16 JsonParserException, 

17 JsonDecoder, 

18 JsonReader, 

19 JsonEnumerableFormat, 

20) 

21from zserio.typeinfo import ( 

22 TypeInfo, 

23 MemberInfo, 

24 ItemInfo, 

25 TypeAttribute, 

26 MemberAttribute, 

27) 

28from zserio.limits import INT64_MIN, UINT64_MAX 

29from zserio.exception import PythonRuntimeException 

30 

31 

32class JsonWriterTest(unittest.TestCase): 

33 

34 def test_empty(self): 

35 json_writer = JsonWriter() 

36 self.assertEqual("", json_writer.get_io().getvalue()) 

37 

38 def test_null_value(self): 

39 json_writer = JsonWriter() 

40 json_writer.visit_value(None, MemberInfo("text", TypeInfo("string", str))) 

41 # note that this is not valid JSON 

42 self.assertEqual('"text": null', json_writer.get_io().getvalue()) 

43 

44 def test_value(self): 

45 json_writer = JsonWriter() 

46 json_writer.visit_value("test", MemberInfo("text", TypeInfo("string", str))) 

47 # note that this is not valid JSON 

48 self.assertEqual('"text": "test"', json_writer.get_io().getvalue()) 

49 

50 def test_enum_value(self): 

51 class TestEnum(enum.Enum): 

52 ZERO = 0 

53 ONE = 1 

54 MINUS_ONE = -1 

55 NOT_IN_TYPE_INFO = 2 

56 

57 test_enum_type_info = TypeInfo( 

58 "TestEnum", 

59 TestEnum, 

60 attributes={ 

61 TypeAttribute.ENUM_ITEMS: [ 

62 ItemInfo("ZERO", TestEnum.ZERO, False, False), 

63 ItemInfo("One", TestEnum.ONE, False, False), 

64 ItemInfo("MINUS_ONE", TestEnum.MINUS_ONE, False, False), 

65 ] 

66 }, 

67 ) 

68 

69 test_enum_member_info = MemberInfo("enumField", test_enum_type_info) 

70 

71 json_writer = JsonWriter() 

72 json_writer.visit_value(TestEnum.ZERO, test_enum_member_info) 

73 json_writer.visit_value(TestEnum.ONE, test_enum_member_info) 

74 json_writer.visit_value(TestEnum.NOT_IN_TYPE_INFO, test_enum_member_info) 

75 json_writer.visit_value(TestEnum.MINUS_ONE, test_enum_member_info) 

76 # note that this is not valid JSON 

77 self.assertEqual( 

78 '"enumField": "ZERO", ' 

79 '"enumField": "One", ' 

80 '"enumField": "2 /* no match */", ' 

81 '"enumField": "MINUS_ONE"', 

82 json_writer.get_io().getvalue(), 

83 ) 

84 

85 json_writer = JsonWriter(enumerable_format=JsonEnumerableFormat.NUMBER) 

86 json_writer.visit_value(TestEnum.ZERO, test_enum_member_info) 

87 json_writer.visit_value(TestEnum.NOT_IN_TYPE_INFO, test_enum_member_info) 

88 json_writer.visit_value(TestEnum.MINUS_ONE, test_enum_member_info) 

89 # note that this is not valid JSON 

90 self.assertEqual( 

91 '"enumField": 0, "enumField": 2, "enumField": -1', 

92 json_writer.get_io().getvalue(), 

93 ) 

94 

95 def test_bitmask_value(self): 

96 class TestBitmask: 

97 def __init__(self, value): 

98 self._value = value 

99 

100 @property 

101 def value(self): 

102 return self._value 

103 

104 class Values: 

105 ZERO = None 

106 ONE = None 

107 TWO = None 

108 

109 TestBitmask.Values.ZERO = TestBitmask(0) 

110 TestBitmask.Values.ONE = TestBitmask(1) 

111 TestBitmask.Values.TWO = TestBitmask(2) 

112 

113 test_bitmask_type_info = TypeInfo( 

114 "TestBitmask", 

115 TestBitmask, 

116 attributes={ 

117 TypeAttribute.BITMASK_VALUES: [ 

118 ItemInfo("ZERO", TestBitmask.Values.ZERO, False, False), 

119 ItemInfo("One", TestBitmask.Values.ONE, False, False), 

120 ItemInfo("TWO", TestBitmask.Values.TWO, False, False), 

121 ] 

122 }, 

123 ) 

124 

125 test_bitmask_member_info = MemberInfo("bitmaskField", test_bitmask_type_info) 

126 

127 json_writer = JsonWriter() 

128 json_writer.visit_value(TestBitmask(0), test_bitmask_member_info) 

129 json_writer.visit_value(TestBitmask(2), test_bitmask_member_info) 

130 json_writer.visit_value(TestBitmask(3), test_bitmask_member_info) 

131 json_writer.visit_value(TestBitmask(4), test_bitmask_member_info) 

132 json_writer.visit_value(TestBitmask(7), test_bitmask_member_info) 

133 # note that this is not valid JSON 

134 self.assertEqual( 

135 '"bitmaskField": "ZERO", ' 

136 '"bitmaskField": "TWO", ' 

137 '"bitmaskField": "One | TWO", ' 

138 '"bitmaskField": "4 /* no match */", ' 

139 '"bitmaskField": "7 /* partial match: One | TWO */"', 

140 json_writer.get_io().getvalue(), 

141 ) 

142 

143 json_writer = JsonWriter(enumerable_format=JsonEnumerableFormat.NUMBER) 

144 json_writer.visit_value(TestBitmask(0), test_bitmask_member_info) 

145 json_writer.visit_value(TestBitmask(7), test_bitmask_member_info) 

146 # note that this is not valid JSON 

147 self.assertEqual('"bitmaskField": 0, "bitmaskField": 7', json_writer.get_io().getvalue()) 

148 

149 def test_compound(self): 

150 json_writer = JsonWriter() 

151 json_writer.begin_root(object()) 

152 json_writer.visit_value(13, MemberInfo("identifier", TypeInfo("uint32", int))) 

153 json_writer.visit_value("test", MemberInfo("text", TypeInfo("string", str))) 

154 json_writer.visit_value( 

155 BitBuffer(bytes([0xFF, 0x1F]), 13), 

156 MemberInfo("externData", TypeInfo("extern", BitBuffer)), 

157 ) 

158 json_writer.visit_value(bytes([0xCA, 0xFE]), MemberInfo("bytesData", TypeInfo("bytes", bytearray))) 

159 json_writer.end_root(object()) 

160 self.assertEqual( 

161 '{"identifier": 13, "text": "test", ' 

162 '"externData": {"buffer": [255, 31], "bitSize": 13}, ' 

163 '"bytesData": {"buffer": [202, 254]}}', 

164 json_writer.get_io().getvalue(), 

165 ) 

166 

167 def test_nested_compound(self): 

168 json_writer = JsonWriter() 

169 self._walk_nested(json_writer) 

170 self.assertEqual( 

171 '{"identifier": 13, "nested": {"text": "test"}}', 

172 json_writer.get_io().getvalue(), 

173 ) 

174 

175 def test_array(self): 

176 json_writer = JsonWriter() 

177 self._walk_array(json_writer) 

178 self.assertEqual('{"array": [1, 2]}', json_writer.get_io().getvalue()) 

179 

180 def test_array_with_indent(self): 

181 json_writer = JsonWriter(indent=2) 

182 self._walk_array(json_writer) 

183 self.assertEqual('{\n "array": [\n 1,\n 2\n ]\n}', json_writer.get_io().getvalue()) 

184 

185 def test_empty_indent(self): 

186 json_writer = JsonWriter(indent="") 

187 self._walk_nested(json_writer) 

188 self.assertEqual( 

189 '{\n"identifier": 13,\n"nested": {\n"text": "test"\n}\n}', 

190 json_writer.get_io().getvalue(), 

191 ) 

192 

193 def test_str_indent(self): 

194 json_writer = JsonWriter(indent=" ") 

195 self._walk_nested(json_writer) 

196 self.assertEqual( 

197 '{\n "identifier": 13,\n "nested": {\n "text": "test"\n }\n}', 

198 json_writer.get_io().getvalue(), 

199 ) 

200 

201 def test_int_indent(self): 

202 json_writer = JsonWriter(indent=2) 

203 self._walk_nested(json_writer) 

204 self.assertEqual( 

205 '{\n "identifier": 13,\n "nested": {\n "text": "test"\n }\n}', 

206 json_writer.get_io().getvalue(), 

207 ) 

208 

209 def test_compact_separators(self): 

210 json_writer = JsonWriter(key_separator=":", item_separator=",") 

211 self._walk_nested(json_writer) 

212 self.assertEqual( 

213 '{"identifier":13,"nested":{"text":"test"}}', 

214 json_writer.get_io().getvalue(), 

215 ) 

216 

217 def test_multiple_objects(self): 

218 json_writer = JsonWriter() 

219 self._walk_nested(json_writer) 

220 self._walk_nested(json_writer) 

221 self.assertEqual( 

222 '{"identifier": 13, "nested": {"text": "test"}}{"identifier": 13, "nested": {"text": "test"}}', 

223 json_writer.get_io().getvalue(), 

224 ) 

225 

226 @staticmethod 

227 def _walk_nested(json_writer): 

228 creator_type_info = TypeInfo("Creator", object) 

229 

230 json_writer.begin_root(object()) 

231 json_writer.visit_value(13, MemberInfo("identifier", TypeInfo("uint32", int))) 

232 json_writer.begin_compound(object(), MemberInfo("nested", creator_type_info)) 

233 json_writer.visit_value("test", MemberInfo("text", TypeInfo("string", str))) 

234 json_writer.end_compound(object(), MemberInfo("nested", creator_type_info)) 

235 json_writer.end_root(object()) 

236 

237 @staticmethod 

238 def _walk_array(json_writer): 

239 array_member_info = MemberInfo( 

240 "array", 

241 TypeInfo("uint32", int), 

242 attributes={MemberAttribute.ARRAY_LENGTH: None}, 

243 ) 

244 

245 json_writer.begin_root(object()) 

246 json_writer.begin_array([1, 2], array_member_info) 

247 json_writer.visit_value(1, array_member_info, 0) 

248 json_writer.visit_value(2, array_member_info, 1) 

249 json_writer.end_array([1, 2], array_member_info) 

250 json_writer.end_root(object()) 

251 

252 

253class JsonEncoderTest(unittest.TestCase): 

254 

255 def test_encode_null(self): 

256 json_encoder = JsonEncoder() 

257 self.assertEqual("null", json_encoder.encode_value(None)) 

258 

259 def test_encode_bool(self): 

260 json_encoder = JsonEncoder() 

261 self.assertEqual("true", json_encoder.encode_value(True)) 

262 self.assertEqual("false", json_encoder.encode_value(False)) 

263 

264 def test_encode_integral(self): 

265 json_encoder = JsonEncoder() 

266 self.assertEqual("-9223372036854775808", json_encoder.encode_value(INT64_MIN)) 

267 self.assertEqual("-1000", json_encoder.encode_value(-1000)) 

268 self.assertEqual("0", json_encoder.encode_value(0)) 

269 self.assertEqual("1000", json_encoder.encode_value(1000)) 

270 self.assertEqual("18446744073709551615", json_encoder.encode_value(UINT64_MAX)) 

271 

272 def test_encode_floating_point(self): 

273 json_encoder = JsonEncoder() 

274 self.assertEqual("-1.0", json_encoder.encode_value(-1.0)) 

275 self.assertEqual("0.0", json_encoder.encode_value(0.0)) 

276 self.assertEqual("1.0", json_encoder.encode_value(1.0)) 

277 

278 self.assertEqual("3.5", json_encoder.encode_value(3.5)) 

279 self.assertEqual("9.875", json_encoder.encode_value(9.875)) 

280 self.assertEqual("0.6171875", json_encoder.encode_value(0.6171875)) 

281 

282 self.assertEqual("1e+20", json_encoder.encode_value(1e20)) 

283 

284 self.assertEqual("NaN", json_encoder.encode_value(float("nan"))) 

285 self.assertEqual("Infinity", json_encoder.encode_value(float("inf"))) 

286 self.assertEqual("-Infinity", json_encoder.encode_value(float("-inf"))) 

287 

288 def test_encode_string(self): 

289 json_encoder = JsonEncoder() 

290 self.assertEqual('""', json_encoder.encode_value("")) 

291 self.assertEqual('"test"', json_encoder.encode_value("test")) 

292 self.assertEqual('"München"', json_encoder.encode_value("München")) 

293 self.assertEqual('"€"', json_encoder.encode_value("€")) 

294 

295 # escapes 

296 self.assertEqual('"\\\\"', json_encoder.encode_value("\\")) 

297 self.assertEqual('"\\""', json_encoder.encode_value('"')) 

298 self.assertEqual('"\\b"', json_encoder.encode_value("\b")) 

299 self.assertEqual('"\\f"', json_encoder.encode_value("\f")) 

300 self.assertEqual('"\\n"', json_encoder.encode_value("\n")) 

301 self.assertEqual('"\\r"', json_encoder.encode_value("\r")) 

302 self.assertEqual('"\\t"', json_encoder.encode_value("\t")) 

303 

304 self.assertEqual( 

305 '"\\n\\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\\\\"\'Hello World2"', 

306 json_encoder.encode_value("\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"'Hello World2"), 

307 ) 

308 

309 # <= 0x1F -> unicode escape 

310 self.assertEqual('"\\u001f"', json_encoder.encode_value("\x1f")) 

311 

312 

313class JsonParserTest(unittest.TestCase): 

314 

315 class DummyObserver(JsonParser.Observer): 

316 def __init__(self): 

317 self._report = [] 

318 

319 @property 

320 def report(self): 

321 return self._report 

322 

323 def begin_object(self): 

324 self._report.append("begin_object") 

325 

326 def end_object(self): 

327 self._report.append("end_object") 

328 

329 def begin_array(self): 

330 self._report.append("begin_array") 

331 

332 def end_array(self): 

333 self._report.append("end_array") 

334 

335 def visit_key(self, key): 

336 self._report.append(f"visit_key: {key}") 

337 

338 def visit_value(self, value): 

339 self._report.append(f"visit_value: {value}") 

340 

341 def test_json_parser_observer(self): 

342 observer = JsonParser.Observer() 

343 with self.assertRaises(NotImplementedError): 

344 observer.begin_object() 

345 with self.assertRaises(NotImplementedError): 

346 observer.end_object() 

347 with self.assertRaises(NotImplementedError): 

348 observer.begin_array() 

349 with self.assertRaises(NotImplementedError): 

350 observer.end_array() 

351 with self.assertRaises(NotImplementedError): 

352 observer.visit_key("key") 

353 with self.assertRaises(NotImplementedError): 

354 observer.visit_value(13) 

355 

356 def test_json_parser_tokenizer(self): 

357 text_io = io.StringIO('{"array":\n[\n{"key":\n10}]}') 

358 tokenizer = JsonTokenizer(text_io) 

359 token = tokenizer.next() 

360 tokens = [] 

361 while token not in [JsonToken.END_OF_FILE]: 

362 tokens.append((token, tokenizer.get_value())) 

363 token = tokenizer.next() 

364 

365 self.assertEqual( 

366 [ 

367 (JsonToken.BEGIN_OBJECT, "{"), 

368 (JsonToken.VALUE, "array"), 

369 (JsonToken.KEY_SEPARATOR, ":"), 

370 (JsonToken.BEGIN_ARRAY, "["), 

371 (JsonToken.BEGIN_OBJECT, "{"), 

372 (JsonToken.VALUE, "key"), 

373 (JsonToken.KEY_SEPARATOR, ":"), 

374 (JsonToken.VALUE, 10), 

375 (JsonToken.END_OBJECT, "}"), 

376 (JsonToken.END_ARRAY, "]"), 

377 (JsonToken.END_OBJECT, "}"), 

378 ], 

379 tokens, 

380 ) 

381 

382 def test_empty(self): 

383 text_io = io.StringIO("") 

384 observer = JsonParserTest.DummyObserver() 

385 json_parser = JsonParser(text_io, observer) 

386 self.assertTrue(json_parser.parse()) 

387 self.assertEqual([], observer.report) 

388 

389 def test_one_string(self): 

390 text_io = io.StringIO('"text"') 

391 observer = JsonParserTest.DummyObserver() 

392 json_parser = JsonParser(text_io, observer) 

393 self.assertTrue(json_parser.parse()) 

394 self.assertEqual(["visit_value: text"], observer.report) 

395 

396 def test_two_strings(self): 

397 text_io = io.StringIO('"text""second"') 

398 observer = JsonParserTest.DummyObserver() 

399 json_parser = JsonParser(text_io, observer) 

400 self.assertFalse(json_parser.parse()) 

401 self.assertEqual(["visit_value: text"], observer.report) 

402 self.assertTrue(json_parser.parse()) 

403 self.assertEqual(["visit_value: text", "visit_value: second"], observer.report) 

404 

405 def test_parse(self): 

406 text_io = io.StringIO('{"array":\n[\n{"key1":\n10, "key2":\n"text"}, {}]}') 

407 observer = JsonParserTest.DummyObserver() 

408 json_parser = JsonParser(text_io, observer) 

409 self.assertTrue(json_parser.parse()) 

410 

411 self.assertEqual( 

412 [ 

413 "begin_object", 

414 "visit_key: array", 

415 "begin_array", 

416 "begin_object", 

417 "visit_key: key1", 

418 "visit_value: 10", 

419 "visit_key: key2", 

420 "visit_value: text", 

421 "end_object", 

422 "begin_object", 

423 "end_object", 

424 "end_array", 

425 "end_object", 

426 ], 

427 observer.report, 

428 ) 

429 

430 def test_unexpected_object(self): 

431 text_io = io.StringIO("{\n\n{\n\n") 

432 observer = JsonParserTest.DummyObserver() 

433 json_parser = JsonParser(text_io, observer) 

434 with self.assertRaises(JsonParserException) as error: 

435 json_parser.parse() 

436 

437 self.assertEqual( 

438 "JsonParser:3:1: Unexpected token: JsonToken.BEGIN_OBJECT ('{'), " 

439 "expecting JsonToken.END_OBJECT!", 

440 str(error.exception), 

441 ) 

442 

443 self.assertEqual(["begin_object"], observer.report) 

444 

445 def test_unexpected_object_after_item_separator(self): 

446 text_io = io.StringIO('{\n "key": 10,\n {\n') 

447 observer = JsonParserTest.DummyObserver() 

448 json_parser = JsonParser(text_io, observer) 

449 with self.assertRaises(JsonParserException) as error: 

450 json_parser.parse() 

451 

452 self.assertEqual( 

453 "JsonParser:3:3: Unexpected token: JsonToken.BEGIN_OBJECT ('{'), expecting JsonToken.VALUE!", 

454 str(error.exception), 

455 ) 

456 

457 self.assertEqual(["begin_object", "visit_key: key", "visit_value: 10"], observer.report) 

458 

459 def test_missing_object_item_separator(self): 

460 text_io = io.StringIO('{\n"item1":"text"\n"item2":"text"\n}') 

461 observer = JsonParserTest.DummyObserver() 

462 json_parser = JsonParser(text_io, observer) 

463 with self.assertRaises(JsonParserException) as error: 

464 json_parser.parse() 

465 

466 self.assertEqual( 

467 "JsonParser:3:1: Unexpected token: JsonToken.VALUE ('item2'), expecting JsonToken.END_OBJECT!", 

468 str(error.exception), 

469 ) 

470 

471 self.assertEqual(["begin_object", "visit_key: item1", "visit_value: text"], observer.report) 

472 

473 def test_wrong_key_type(self): 

474 text_io = io.StringIO('{\n10:"text"\n}') 

475 observer = JsonParserTest.DummyObserver() 

476 json_parser = JsonParser(text_io, observer) 

477 with self.assertRaises(JsonParserException) as error: 

478 json_parser.parse() 

479 

480 self.assertEqual("JsonParser:2:1: Key must be a string value!", str(error.exception)) 

481 

482 self.assertEqual(["begin_object"], observer.report) 

483 

484 def test_unexpected_element_token(self): 

485 text_io = io.StringIO('{\n"item":}') 

486 observer = JsonParserTest.DummyObserver() 

487 json_parser = JsonParser(text_io, observer) 

488 with self.assertRaises(JsonParserException) as error: 

489 json_parser.parse() 

490 

491 self.assertEqual( 

492 "JsonParser:2:8: Unexpected token: JsonToken.END_OBJECT ('}'), " 

493 "expecting one of [JsonToken.BEGIN_OBJECT, JsonToken.BEGIN_ARRAY, JsonToken.VALUE]!", 

494 str(error.exception), 

495 ) 

496 

497 self.assertEqual(["begin_object", "visit_key: item"], observer.report) 

498 

499 def test_missing_array_element_separator(self): 

500 text_io = io.StringIO('{\n"array":\n[10\n20\n]}') 

501 observer = JsonParserTest.DummyObserver() 

502 json_parser = JsonParser(text_io, observer) 

503 with self.assertRaises(JsonParserException) as error: 

504 json_parser.parse() 

505 

506 self.assertEqual( 

507 "JsonParser:4:1: Unexpected token: JsonToken.VALUE ('20'), expecting JsonToken.END_ARRAY!", 

508 str(error.exception), 

509 ) 

510 

511 self.assertEqual( 

512 ["begin_object", "visit_key: array", "begin_array", "visit_value: 10"], 

513 observer.report, 

514 ) 

515 

516 

517class JsonDecoderTest(unittest.TestCase): 

518 

519 def test_decode_null(self): 

520 self._check_decoder_success("null", 0, 4, None) 

521 self._check_decoder_success("{ } null", 4, 4, None) 

522 self._check_decoder_success("null { }", 0, 4, None) 

523 self._check_decoder_failure("invalid", 0, 1) 

524 self._check_decoder_failure("invalid", 1, 4) 

525 self._check_decoder_failure("nul", 0, 3) 

526 

527 def test_decode_true(self): 

528 self._check_decoder_success("true", 0, 4, True) 

529 self._check_decoder_success("{ } true", 4, 4, True) 

530 self._check_decoder_success("true { }", 0, 4, True) 

531 self._check_decoder_failure("invalid", 0, 1) 

532 self._check_decoder_failure("stainless", 1, 4) 

533 self._check_decoder_failure("tru", 0, 3) 

534 

535 def test_decode_false(self): 

536 self._check_decoder_success("false", 0, 5, False) 

537 self._check_decoder_success("{ } false", 4, 5, False) 

538 self._check_decoder_success("false { }", 0, 5, False) 

539 self._check_decoder_failure("invalid", 0, 1) 

540 self._check_decoder_failure("affected", 1, 5) 

541 self._check_decoder_failure("fal", 0, 3) 

542 

543 def test_decode_nan(self): 

544 self._check_decoder_success("NaN", 0, 3, float("nan")) 

545 self._check_decoder_success("{ } NaN", 4, 3, float("nan")) 

546 self._check_decoder_success("NaN { }", 0, 3, float("nan")) 

547 self._check_decoder_failure("invalid", 0, 1) 

548 self._check_decoder_failure("iNactive", 1, 3) 

549 self._check_decoder_failure("Na", 0, 2) 

550 

551 def test_decode_positive_infinity(self): 

552 self._check_decoder_success("Infinity", 0, 8, float("inf")) 

553 self._check_decoder_success("{ } Infinity", 4, 8, float("inf")) 

554 self._check_decoder_success("Infinity { }", 0, 8, float("inf")) 

555 self._check_decoder_failure("invalid", 0, 1) 

556 self._check_decoder_failure("iInfinvalid", 1, 8) 

557 self._check_decoder_failure("Infin", 0, 5) 

558 

559 def test_decode_negative_infinity(self): 

560 self._check_decoder_success("-Infinity", 0, 9, float("-inf")) 

561 self._check_decoder_success("{ } -Infinity", 4, 9, float("-inf")) 

562 self._check_decoder_success("-Infinity { }", 0, 9, float("-inf")) 

563 self._check_decoder_failure("invalid", 0, 1) 

564 self._check_decoder_failure("i-Infinvalid", 1, 9) 

565 self._check_decoder_failure("-Infin", 0, 6) 

566 self._check_decoder_failure("-Infix", 0, 6) 

567 

568 def test_decode_signed_integral(self): 

569 self._check_decoder_success("-0", 0, 2, 0) 

570 self._check_decoder_success("{ } -0", 4, 2, 0) 

571 self._check_decoder_success("-0 { }", 0, 2, 0) 

572 self._check_decoder_success("-1", 0, 2, -1) 

573 self._check_decoder_success("-9223372036854775808", 0, 20, -9223372036854775808) 

574 

575 self._check_decoder_failure("--10", 0, 1) 

576 self._check_decoder_failure("-", 0, 1) 

577 

578 def test_decode_unsigned_integral(self): 

579 self._check_decoder_success("0", 0, 1, 0) 

580 self._check_decoder_success("{ } 0", 4, 1, 0) 

581 self._check_decoder_success("0 { }", 0, 1, 0) 

582 self._check_decoder_success("1", 0, 1, 1) 

583 self._check_decoder_success("9223372036854775807", 0, 19, 9223372036854775807) 

584 self._check_decoder_success("18446744073709551615", 0, 20, 18446744073709551615) 

585 

586 self._check_decoder_failure("+10", 0, 1) 

587 

588 def test_decode_double(self): 

589 self._check_decoder_success("0.0", 0, 3, 0.0) 

590 self._check_decoder_success("{ } 0.0", 4, 3, 0.0) 

591 self._check_decoder_success("0.0 { }", 0, 3, 0.0) 

592 self._check_decoder_success("-1.0", 0, 4, -1.0) 

593 self._check_decoder_success("1.0", 0, 3, 1.0) 

594 self._check_decoder_success("3.5", 0, 3, 3.5) 

595 self._check_decoder_success("9.875", 0, 5, 9.875) 

596 self._check_decoder_success("0.6171875", 0, 9, 0.6171875) 

597 

598 self._check_decoder_success("1e+20", 0, 5, 1e20) 

599 self._check_decoder_success("1E+20", 0, 5, 1e20) 

600 self._check_decoder_success("1e-20", 0, 5, 1e-20) 

601 self._check_decoder_success("1E-20", 0, 5, 1e-20) 

602 self._check_decoder_success("-1e+20", 0, 6, -1e20) 

603 self._check_decoder_success("-1E+20", 0, 6, -1e20) 

604 self._check_decoder_success("-1e-20", 0, 6, -1e-20) 

605 self._check_decoder_success("-1E-20", 0, 6, -1e-20) 

606 

607 self._check_decoder_success("1.0E-20", 0, 7, 1.0e-20) 

608 self._check_decoder_success("-1.0E-20", 0, 8, -1.0e-20) 

609 self._check_decoder_success("9.875E+3", 0, 8, 9.875e3) 

610 self._check_decoder_success("-9.875E-3", 0, 9, -9.875e-3) 

611 

612 self._check_decoder_failure("1EE20", 0, 2) 

613 self._check_decoder_failure("1E.E20", 0, 2) 

614 self._check_decoder_failure("1E++20", 0, 3) 

615 self._check_decoder_failure("1E--20", 0, 3) 

616 

617 self._check_decoder_failure("1e", 0, 2) 

618 self._check_decoder_failure("1e+", 0, 3) 

619 self._check_decoder_failure("1E-", 0, 3) 

620 

621 def test_decode_string(self): 

622 self._check_decoder_success('""', 0, 2, "") 

623 self._check_decoder_success('{ } ""', 4, 2, "") 

624 self._check_decoder_success('"" { }', 0, 2, "") 

625 

626 self._check_decoder_success('"test"', 0, 6, "test") 

627 self._check_decoder_success('"München"', 0, 9, "München") 

628 self._check_decoder_success('"€"', 0, 3, "€") 

629 

630 # escapes 

631 self._check_decoder_success('"\\\\"', 0, 4, "\\") 

632 self._check_decoder_success('"\\""', 0, 4, '"') 

633 self._check_decoder_success('"\\b"', 0, 4, "\b") 

634 self._check_decoder_success('"\\f"', 0, 4, "\f") 

635 self._check_decoder_success('"\\n"', 0, 4, "\n") 

636 self._check_decoder_success('"\\r"', 0, 4, "\r") 

637 self._check_decoder_success('"\\t"', 0, 4, "\t") 

638 

639 self._check_decoder_success( 

640 '"\\n\\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\\\\"\'Hello World2"', 

641 0, 

642 62, 

643 "\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"'Hello World2", 

644 ) 

645 

646 # <= 0x1F -> unicode escape 

647 self._check_decoder_success('"\\u001f"', 0, 8, "\u001f") 

648 

649 self._check_decoder_failure('"\\u001x"', 0, 7) 

650 self._check_decoder_failure('"unterminated', 0, 13) 

651 self._check_decoder_failure('"wrong escape \\', 0, 15) 

652 self._check_decoder_failure('"wrong unicode escape \\u0', 0, 25) 

653 self._check_decoder_failure('"unknown escape \\x', 0, 18) 

654 

655 def test_wrong_arguments(self): 

656 self._check_decoder_failure("", 1, 0) 

657 

658 def _check_decoder_success(self, content, pos, expected_num_read, expected_value): 

659 result = JsonDecoder.decode_value(content, pos) 

660 self.assertEqual(True, result.success) 

661 if isinstance(expected_value, float) and math.isnan(expected_value): 

662 self.assertTrue(math.isnan(result.value)) 

663 else: 

664 self.assertEqual(expected_value, result.value) 

665 self.assertEqual(expected_num_read, result.num_read_chars) 

666 

667 def _check_decoder_failure(self, content, pos, expected_num_read): 

668 result = JsonDecoder.decode_value(content, pos) 

669 self.assertEqual(False, result.success) 

670 self.assertEqual(None, result.value) 

671 self.assertEqual(expected_num_read, result.num_read_chars) 

672 

673 

674class JsonTokenizerTest(unittest.TestCase): 

675 

676 def test_tokens(self): 

677 text_io = io.StringIO('{"array":\n[\n{"key":\n10}]}') 

678 tokenizer = JsonTokenizer(text_io) 

679 

680 self.assertEqual(JsonToken.BEGIN_OBJECT, tokenizer.next()) 

681 self.assertEqual("{", tokenizer.get_value()) 

682 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

683 self.assertEqual("array", tokenizer.get_value()) 

684 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

685 self.assertEqual(":", tokenizer.get_value()) 

686 self.assertEqual(JsonToken.BEGIN_ARRAY, tokenizer.next()) 

687 self.assertEqual("[", tokenizer.get_value()) 

688 self.assertEqual(JsonToken.BEGIN_OBJECT, tokenizer.next()) 

689 self.assertEqual("{", tokenizer.get_value()) 

690 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

691 self.assertEqual("key", tokenizer.get_value()) 

692 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

693 self.assertEqual(":", tokenizer.get_value()) 

694 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

695 self.assertEqual(10, tokenizer.get_value()) 

696 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next()) 

697 self.assertEqual("}", tokenizer.get_value()) 

698 self.assertEqual(JsonToken.END_ARRAY, tokenizer.next()) 

699 self.assertEqual("]", tokenizer.get_value()) 

700 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next()) 

701 self.assertEqual("}", tokenizer.get_value()) 

702 self.assertEqual(JsonToken.END_OF_FILE, tokenizer.next()) 

703 

704 def test_line_column(self): 

705 text_io = io.StringIO('\n{\r "key" \n :\n10}\r') 

706 tokenizer = JsonTokenizer(text_io) 

707 

708 self.assertEqual(JsonToken.BEGIN_OBJECT, tokenizer.next()) 

709 self.assertEqual("{", tokenizer.get_value()) 

710 self.assertEqual(2, tokenizer.get_line()) 

711 self.assertEqual(1, tokenizer.get_column()) 

712 

713 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

714 self.assertEqual("key", tokenizer.get_value()) 

715 self.assertEqual(3, tokenizer.get_line()) 

716 self.assertEqual(4, tokenizer.get_column()) 

717 

718 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

719 self.assertEqual(":", tokenizer.get_value()) 

720 self.assertEqual(4, tokenizer.get_line()) 

721 self.assertEqual(2, tokenizer.get_column()) 

722 

723 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

724 self.assertEqual(10, tokenizer.get_value()) 

725 self.assertEqual(5, tokenizer.get_line()) 

726 self.assertEqual(1, tokenizer.get_column()) 

727 

728 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next()) 

729 self.assertEqual("}", tokenizer.get_value()) 

730 self.assertEqual(5, tokenizer.get_line()) 

731 self.assertEqual(3, tokenizer.get_column()) 

732 

733 self.assertEqual(JsonToken.END_OF_FILE, tokenizer.next()) 

734 self.assertEqual(5, tokenizer.get_line()) 

735 self.assertEqual(4, tokenizer.get_column()) 

736 

737 def test_long_input_split_in_number(self): 

738 json_string = "" 

739 json_string += "{\n" # 2 chars 

740 k = 4000 

741 for i in range(k): # 20 x 4000 > 65534 to check reading by chunks 

742 # BUFFER_SIZE is 65536, thus 65534 % 20 gives position within the string below 

743 # where the buffer will be split => 14, which is somewhere in the middle of the number 

744 # |-> <-| 

745 json_string += ' "key": 100000000,\n' # 20 chars 

746 json_string += ' "key": 100000000\n' 

747 json_string += "}" 

748 

749 text_io = io.StringIO(json_string) 

750 tokenizer = JsonTokenizer(text_io) 

751 

752 self.assertEqual(JsonToken.BEGIN_OBJECT, tokenizer.next()) 

753 self.assertEqual("{", tokenizer.get_value()) 

754 self.assertEqual(1, tokenizer.get_line()) 

755 self.assertEqual(1, tokenizer.get_column()) 

756 

757 for i in range(k): 

758 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

759 self.assertEqual("key", tokenizer.get_value()) 

760 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

761 self.assertEqual(3, tokenizer.get_column()) 

762 

763 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

764 self.assertEqual(":", tokenizer.get_value()) 

765 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

766 self.assertEqual(8, tokenizer.get_column()) 

767 

768 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

769 self.assertEqual(100000000, tokenizer.get_value()) 

770 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

771 self.assertEqual(10, tokenizer.get_column()) 

772 

773 self.assertEqual(JsonToken.ITEM_SEPARATOR, tokenizer.next()) 

774 self.assertEqual(",", tokenizer.get_value()) 

775 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

776 self.assertEqual(19, tokenizer.get_column()) 

777 

778 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

779 self.assertEqual("key", tokenizer.get_value()) 

780 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

781 self.assertEqual(3, tokenizer.get_column()) 

782 

783 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

784 self.assertEqual(":", tokenizer.get_value()) 

785 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

786 self.assertEqual(8, tokenizer.get_column()) 

787 

788 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

789 self.assertEqual(100000000, tokenizer.get_value()) 

790 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

791 self.assertEqual(10, tokenizer.get_column()) 

792 

793 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next()) 

794 self.assertEqual(1 + k + 2, tokenizer.get_line()) 

795 self.assertEqual(1, tokenizer.get_column()) 

796 

797 def test_long_input_split_in_string(self): 

798 json_string = "" 

799 json_string += "{\n" # 2 chars 

800 k = 4000 

801 for i in range(k): # 20 x 4000 > 65534 to check reading by chunks 

802 # BUFFER_SIZE is 65536, thus 65534 % 20 gives position within the string below 

803 # where the buffer will be split => 14, which is somewhere in the middle of the number 

804 # |-> <-| 

805 json_string += ' "key": "1000000",\n' # 20 chars 

806 json_string += ' "key": "1000000"\n' 

807 json_string += "}" 

808 

809 text_io = io.StringIO(json_string) 

810 tokenizer = JsonTokenizer(text_io) 

811 

812 self.assertEqual(JsonToken.BEGIN_OBJECT, tokenizer.next()) 

813 self.assertEqual("{", tokenizer.get_value()) 

814 self.assertEqual(1, tokenizer.get_line()) 

815 self.assertEqual(1, tokenizer.get_column()) 

816 

817 for i in range(k): 

818 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

819 self.assertEqual("key", tokenizer.get_value()) 

820 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

821 self.assertEqual(3, tokenizer.get_column()) 

822 

823 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

824 self.assertEqual(":", tokenizer.get_value()) 

825 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

826 self.assertEqual(8, tokenizer.get_column()) 

827 

828 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

829 self.assertEqual("1000000", tokenizer.get_value()) 

830 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

831 self.assertEqual(10, tokenizer.get_column()) 

832 

833 self.assertEqual(JsonToken.ITEM_SEPARATOR, tokenizer.next()) 

834 self.assertEqual(",", tokenizer.get_value()) 

835 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

836 self.assertEqual(19, tokenizer.get_column()) 

837 

838 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

839 self.assertEqual("key", tokenizer.get_value()) 

840 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

841 self.assertEqual(3, tokenizer.get_column()) 

842 

843 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

844 self.assertEqual(":", tokenizer.get_value()) 

845 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

846 self.assertEqual(8, tokenizer.get_column()) 

847 

848 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

849 self.assertEqual("1000000", tokenizer.get_value()) 

850 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

851 self.assertEqual(10, tokenizer.get_column()) 

852 

853 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next()) 

854 self.assertEqual(1 + k + 2, tokenizer.get_line()) 

855 self.assertEqual(1, tokenizer.get_column()) 

856 

857 def test_long_input_split_in_double_after_e(self): 

858 json_string = "" 

859 json_string += "{\n" # 2 chars 

860 k = 4000 

861 for i in range(k): # 20 x 4000 > 65534 to check reading by chunks 

862 # BUFFER_SIZE is 65536, thus 65534 % 20 gives position within the string below 

863 # where the buffer will be split => 14, which is somewhere in the middle of the number 

864 # |-> <-| 

865 json_string += ' "key": 1e5 ,\n' # 20 chars 

866 json_string += ' "key": 1e5 \n' 

867 json_string += "}" 

868 

869 text_io = io.StringIO(json_string) 

870 tokenizer = JsonTokenizer(text_io) 

871 

872 self.assertEqual(JsonToken.BEGIN_OBJECT, tokenizer.next()) 

873 self.assertEqual("{", tokenizer.get_value()) 

874 self.assertEqual(1, tokenizer.get_line()) 

875 self.assertEqual(1, tokenizer.get_column()) 

876 

877 for i in range(k): 

878 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

879 self.assertEqual("key", tokenizer.get_value()) 

880 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

881 self.assertEqual(3, tokenizer.get_column()) 

882 

883 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

884 self.assertEqual(":", tokenizer.get_value()) 

885 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

886 self.assertEqual(8, tokenizer.get_column()) 

887 

888 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

889 self.assertEqual(1e5, tokenizer.get_value()) 

890 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

891 self.assertEqual(13, tokenizer.get_column()) 

892 

893 self.assertEqual(JsonToken.ITEM_SEPARATOR, tokenizer.next()) 

894 self.assertEqual(",", tokenizer.get_value()) 

895 self.assertEqual(1 + i + 1, tokenizer.get_line()) 

896 self.assertEqual(19, tokenizer.get_column()) 

897 

898 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

899 self.assertEqual("key", tokenizer.get_value()) 

900 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

901 self.assertEqual(3, tokenizer.get_column()) 

902 

903 self.assertEqual(JsonToken.KEY_SEPARATOR, tokenizer.next()) 

904 self.assertEqual(":", tokenizer.get_value()) 

905 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

906 self.assertEqual(8, tokenizer.get_column()) 

907 

908 self.assertEqual(JsonToken.VALUE, tokenizer.next()) 

909 self.assertEqual(1e5, tokenizer.get_value()) 

910 self.assertEqual(1 + k + 1, tokenizer.get_line()) 

911 self.assertEqual(13, tokenizer.get_column()) 

912 

913 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next()) 

914 self.assertEqual(1 + k + 2, tokenizer.get_line()) 

915 self.assertEqual(1, tokenizer.get_column()) 

916 

917 def test_unknown_token(self): 

918 text_io = io.StringIO("\\\n") 

919 tokenizer = JsonTokenizer(text_io) 

920 with self.assertRaises(JsonParserException) as error: 

921 tokenizer.next() 

922 self.assertEqual("JsonTokenizer:1:1: Unknown token!", str(error.exception)) 

923 

924 

925class JsonReaderTest(unittest.TestCase): 

926 

927 def test_json_reader_object_value_adapter(self): 

928 object_value_adapter = JsonReader._ObjectValueAdapter() 

929 with self.assertRaises(NotImplementedError): 

930 object_value_adapter.get() 

931 

932 def test_read_object(self): 

933 text_io = io.StringIO( 

934 "{\n" 

935 + ' "value": 13,\n' 

936 + ' "nested": {\n' 

937 + ' "value": 10,\n' 

938 + ' "text": "nested",\n' 

939 + ' "externData": {\n' 

940 + ' "buffer": [\n' 

941 + " 203,\n" 

942 + " 240\n" 

943 + " ],\n" 

944 + ' "bitSize": 12\n' 

945 + " },\n" 

946 + ' "bytesData": {\n' 

947 + ' "buffer": [\n' 

948 + " 202,\n" 

949 + " 254\n" 

950 + " ]\n" 

951 + " },\n" 

952 + ' "creatorEnum": 0,\n' 

953 + ' "creatorBitmask": 1\n' 

954 + " },\n" 

955 + ' "text": "test",\n' 

956 + ' "nestedArray": [\n' 

957 + " {\n" 

958 + ' "value": 5,\n' 

959 + ' "text": "nestedArray",\n' 

960 + ' "externData": {\n' 

961 + ' "buffer": [\n' 

962 + " 202,\n" 

963 + " 254\n" 

964 + " ]," 

965 + ' "bitSize": 15\n' 

966 + " },\n" 

967 + ' "bytesData": {\n' 

968 ' "buffer": [\n' 

969 " 203,\n" 

970 " 240\n" 

971 " ]\n" 

972 " },\n" 

973 ' "creatorEnum": 1,\n' 

974 + ' "creatorBitmask": 2\n' 

975 + " }\n" 

976 + " ],\n" 

977 + ' "textArray": [\n' 

978 + ' "this",\n' 

979 + ' "is",\n' 

980 + ' "text",\n' 

981 + ' "array"\n' 

982 + " ],\n" 

983 + ' "externArray": [\n' 

984 + " {\n" 

985 + ' "buffer": [\n' 

986 + " 222,\n" 

987 + " 209\n" 

988 + " ]," 

989 + ' "bitSize": 13\n' 

990 + " }\n" 

991 + " ],\n" 

992 + ' "bytesArray": [\n' 

993 + " {\n" 

994 + ' "buffer": [\n' 

995 + " 0\n" 

996 + " ]\n" 

997 + " }\n" 

998 + " ],\n" 

999 + ' "optionalBool": null\n' 

1000 + "}" 

1001 ) 

1002 

1003 json_reader = JsonReader(text_io) 

1004 creator_object = json_reader.read(CreatorObject.type_info()) 

1005 self.assertTrue(creator_object is not None) 

1006 self.assertTrue(isinstance(creator_object, CreatorObject)) 

1007 

1008 self.assertEqual(13, creator_object.value) 

1009 self.assertEqual(13, creator_object.nested.param) 

1010 self.assertEqual(10, creator_object.nested.value) 

1011 self.assertEqual("nested", creator_object.nested.text) 

1012 self.assertEqual(BitBuffer(bytes([0xCB, 0xF0]), 12), creator_object.nested.extern_data) 

1013 self.assertEqual(bytes([0xCA, 0xFE]), creator_object.nested.bytes_data) 

1014 self.assertEqual(CreatorEnum.ONE, creator_object.nested.creator_enum) 

1015 self.assertEqual(CreatorBitmask.Values.READ, creator_object.nested.creator_bitmask) 

1016 self.assertEqual("test", creator_object.text) 

1017 self.assertEqual(1, len(creator_object.nested_array)) 

1018 self.assertEqual(5, creator_object.nested_array[0].value) 

1019 self.assertEqual("nestedArray", creator_object.nested_array[0].text) 

1020 self.assertEqual( 

1021 BitBuffer(bytes([0xCA, 0xFE]), 15), 

1022 creator_object.nested_array[0].extern_data, 

1023 ) 

1024 self.assertEqual(bytes([0xCB, 0xF0]), creator_object.nested_array[0].bytes_data) 

1025 self.assertEqual(CreatorEnum.TWO, creator_object.nested_array[0].creator_enum) 

1026 self.assertEqual(CreatorBitmask.Values.WRITE, creator_object.nested_array[0].creator_bitmask) 

1027 self.assertEqual(4, len(creator_object.text_array)) 

1028 self.assertEqual("this", creator_object.text_array[0]) 

1029 self.assertEqual("is", creator_object.text_array[1]) 

1030 self.assertEqual("text", creator_object.text_array[2]) 

1031 self.assertEqual("array", creator_object.text_array[3]) 

1032 self.assertEqual(1, len(creator_object.extern_array)) 

1033 self.assertEqual(BitBuffer(bytes([0xDE, 0xD1]), 13), creator_object.extern_array[0]) 

1034 self.assertEqual(1, len(creator_object.bytes_array)) 

1035 self.assertEqual(bytes([0]), creator_object.bytes_array[0]) 

1036 self.assertEqual(None, creator_object.optional_bool) 

1037 self.assertEqual(None, creator_object.optional_nested) # not present in json 

1038 

1039 def test_read_two_objects(self): 

1040 text_io = io.StringIO('{"value": 13}\n' + '{"value": 42, "text": "test"}\n') 

1041 

1042 json_reader = JsonReader(text_io) 

1043 creator_object1 = json_reader.read(CreatorObject.type_info()) 

1044 self.assertTrue(creator_object1 is not None) 

1045 self.assertTrue(isinstance(creator_object1, CreatorObject)) 

1046 

1047 self.assertEqual(13, creator_object1.value) 

1048 self.assertEqual("", creator_object1.text) 

1049 

1050 creator_object2 = json_reader.read(CreatorObject.type_info()) 

1051 self.assertTrue(creator_object2 is not None) 

1052 self.assertTrue(isinstance(creator_object2, CreatorObject)) 

1053 

1054 self.assertEqual(42, creator_object2.value) 

1055 self.assertEqual("test", creator_object2.text) 

1056 

1057 def test_read_unordered_bit_buffer(self): 

1058 text_io = io.StringIO( 

1059 "{\n" 

1060 + ' "value": 13,\n' 

1061 + ' "nested": {\n' 

1062 + ' "value": 10,\n' 

1063 + ' "text": "nested",\n' 

1064 + ' "externData": {\n' 

1065 + ' "bitSize": 12,\n' 

1066 + ' "buffer": [\n' 

1067 + " 203,\n" 

1068 + " 240\n" 

1069 + " ]\n" 

1070 + " },\n" 

1071 + ' "bytesData": {\n' 

1072 + ' "buffer": [\n' 

1073 + " 202,\n" 

1074 + " 254\n" 

1075 + " ]\n" 

1076 + " },\n" 

1077 + ' "creatorEnum": 0,\n' 

1078 + ' "creatorBitmask": 1\n' 

1079 + " }\n" 

1080 + "}" 

1081 ) 

1082 

1083 json_reader = JsonReader(text_io) 

1084 creator_object = json_reader.read(CreatorObject.type_info()) 

1085 self.assertTrue(creator_object is not None) 

1086 self.assertTrue(isinstance(creator_object, CreatorObject)) 

1087 

1088 self.assertEqual(13, creator_object.value) 

1089 self.assertEqual(13, creator_object.nested.param) 

1090 self.assertEqual(10, creator_object.nested.value) 

1091 self.assertEqual("nested", creator_object.nested.text) 

1092 self.assertEqual(BitBuffer(bytes([0xCB, 0xF0]), 12), creator_object.nested.extern_data) 

1093 self.assertEqual(bytes([0xCA, 0xFE]), creator_object.nested.bytes_data) 

1094 self.assertEqual(CreatorEnum.ONE, creator_object.nested.creator_enum) 

1095 self.assertEqual(CreatorBitmask.Values.READ, creator_object.nested.creator_bitmask) 

1096 

1097 def test_read_empty_bit_buffer(self): 

1098 text_io = io.StringIO( 

1099 "{\n" 

1100 + ' "value": 13,\n' 

1101 + ' "nested": {\n' 

1102 + ' "value": 10,\n' 

1103 + ' "text": "nested",\n' 

1104 + ' "externData": {\n' 

1105 + ' "buffer": [\n' 

1106 + " ],\n" 

1107 + ' "bitSize": 0\n' 

1108 + " },\n" 

1109 + ' "bytesData": {\n' 

1110 + ' "buffer": [\n' 

1111 + " 202,\n" 

1112 + " 254\n" 

1113 + " ]\n" 

1114 + " },\n" 

1115 + ' "creatorEnum": 0,\n' 

1116 + ' "creatorBitmask": 1\n' 

1117 + " }\n" 

1118 + "}" 

1119 ) 

1120 

1121 json_reader = JsonReader(text_io) 

1122 creator_object = json_reader.read(CreatorObject.type_info()) 

1123 self.assertTrue(creator_object is not None) 

1124 self.assertTrue(isinstance(creator_object, CreatorObject)) 

1125 

1126 self.assertEqual(13, creator_object.value) 

1127 self.assertEqual(13, creator_object.nested.param) 

1128 self.assertEqual(10, creator_object.nested.value) 

1129 self.assertEqual("nested", creator_object.nested.text) 

1130 self.assertEqual(BitBuffer(bytes()), creator_object.nested.extern_data) 

1131 self.assertEqual(bytes([0xCA, 0xFE]), creator_object.nested.bytes_data) 

1132 self.assertEqual(CreatorEnum.ONE, creator_object.nested.creator_enum) 

1133 self.assertEqual(CreatorBitmask.Values.READ, creator_object.nested.creator_bitmask) 

1134 

1135 def test_read_empty_bytes(self): 

1136 text_io = io.StringIO( 

1137 "{\n" 

1138 + ' "value": 13,\n' 

1139 + ' "nested": {\n' 

1140 + ' "value": 10,\n' 

1141 + ' "text": "nested",\n' 

1142 + ' "externData": {\n' 

1143 + ' "bitSize": 0,\n' 

1144 + ' "buffer": [\n' 

1145 + " ]\n" 

1146 + " },\n" 

1147 + ' "bytesData": {\n' 

1148 + ' "buffer": [\n' 

1149 + " ]\n" 

1150 + " },\n" 

1151 + ' "creatorEnum": 0,\n' 

1152 + ' "creatorBitmask": 1\n' 

1153 + " }\n" 

1154 + "}" 

1155 ) 

1156 

1157 json_reader = JsonReader(text_io) 

1158 creator_object = json_reader.read(CreatorObject.type_info()) 

1159 self.assertTrue(creator_object is not None) 

1160 self.assertTrue(isinstance(creator_object, CreatorObject)) 

1161 

1162 self.assertEqual(13, creator_object.value) 

1163 self.assertEqual(13, creator_object.nested.param) 

1164 self.assertEqual(10, creator_object.nested.value) 

1165 self.assertEqual("nested", creator_object.nested.text) 

1166 self.assertEqual(BitBuffer(bytes()), creator_object.nested.extern_data) 

1167 self.assertEqual(bytes(), creator_object.nested.bytes_data) 

1168 self.assertEqual(CreatorEnum.ONE, creator_object.nested.creator_enum) 

1169 self.assertEqual(CreatorBitmask.Values.READ, creator_object.nested.creator_bitmask) 

1170 

1171 def test_read_stringified_enum(self): 

1172 self._check_read_stringified_enum("ONE", CreatorEnum.ONE) 

1173 self._check_read_stringified_enum("MinusOne", CreatorEnum.MINUS_ONE) 

1174 self._check_read_stringified_enum_raises( 

1175 "NONEXISTING", 

1176 "JsonReader: Cannot create enum 'test_object.CreatorEnum' " 

1177 "from string value 'NONEXISTING'! (JsonParser:3:24)", 

1178 ) 

1179 self._check_read_stringified_enum_raises( 

1180 "***", 

1181 "JsonReader: Cannot create enum 'test_object.CreatorEnum' " 

1182 "from string value '***'! (JsonParser:3:24)", 

1183 ) 

1184 self._check_read_stringified_enum_raises( 

1185 "10 /* no match */", 

1186 "JsonReader: Cannot create enum 'test_object.CreatorEnum' " 

1187 "from string value '10 /* no match */'! (JsonParser:3:24)", 

1188 ) 

1189 self._check_read_stringified_enum_raises( 

1190 "-10 /* no match */", 

1191 "JsonReader: Cannot create enum 'test_object.CreatorEnum' " 

1192 "from string value '-10 /* no match */'! (JsonParser:3:24)", 

1193 ) 

1194 self._check_read_stringified_enum_raises( 

1195 "", 

1196 "JsonReader: Cannot create enum 'test_object.CreatorEnum' " 

1197 "from string value ''! (JsonParser:3:24)", 

1198 ) 

1199 

1200 def test_read_stringified_bitmask(self): 

1201 self._check_read_stringified_bitmask("READ", CreatorBitmask.Values.READ) 

1202 self._check_read_stringified_bitmask( 

1203 "READ | WRITE", CreatorBitmask.Values.READ | CreatorBitmask.Values.WRITE 

1204 ) 

1205 self._check_read_stringified_bitmask_raises( 

1206 "NONEXISTING", 

1207 "JsonReader: Cannot create bitmask 'test_object.CreatorBitmask' " 

1208 + "from string value 'NONEXISTING'! (JsonParser:3:27)", 

1209 ) 

1210 self._check_read_stringified_bitmask_raises( 

1211 "READ | NONEXISTING", 

1212 "JsonReader: Cannot create bitmask 'test_object.CreatorBitmask' " 

1213 + "from string value 'READ | NONEXISTING'! (JsonParser:3:27)", 

1214 ) 

1215 self._check_read_stringified_bitmask_raises( 

1216 "READ * NONEXISTING", 

1217 "JsonReader: Cannot create bitmask 'test_object.CreatorBitmask' " 

1218 + "from string value 'READ * NONEXISTING'! (JsonParser:3:27)", 

1219 ) 

1220 self._check_read_stringified_bitmask("7 /* READ | WRITE */", CreatorBitmask.from_value(7)) 

1221 self._check_read_stringified_bitmask("15 /* READ | WRITE */", CreatorBitmask.from_value(15)) 

1222 self._check_read_stringified_bitmask("4 /* no match */", CreatorBitmask.from_value(4)) 

1223 self._check_read_stringified_bitmask_raises( 

1224 "", 

1225 "JsonReader: Cannot create bitmask 'test_object.CreatorBitmask' " 

1226 + "from string value ''! (JsonParser:3:27)", 

1227 ) 

1228 self._check_read_stringified_bitmask_raises( 

1229 " ", 

1230 "JsonReader: Cannot create bitmask 'test_object.CreatorBitmask' " 

1231 + "from string value ' '! (JsonParser:3:27)", 

1232 ) 

1233 self._check_read_stringified_bitmask_raises( 

1234 " | ", 

1235 "JsonReader: Cannot create bitmask 'test_object.CreatorBitmask' " 

1236 + "from string value ' | '! (JsonParser:3:27)", 

1237 ) 

1238 

1239 def test_json_parser_exception(self): 

1240 text_io = io.StringIO('{"value"\n"value"') 

1241 

1242 json_reader = JsonReader(text_io) 

1243 with self.assertRaises(JsonParserException) as error: 

1244 json_reader.read(CreatorObject.type_info()) 

1245 self.assertEqual( 

1246 "JsonParser:2:1: Unexpected token: JsonToken.VALUE ('value'), " 

1247 + "expecting JsonToken.KEY_SEPARATOR!", 

1248 str(error.exception), 

1249 ) 

1250 

1251 def test_wrong_key_exception(self): 

1252 text_io = io.StringIO('{"value": 13,\n"nonexisting": 10}') 

1253 

1254 json_reader = JsonReader(text_io) 

1255 with self.assertRaises(PythonRuntimeException) as error: 

1256 json_reader.read(CreatorObject.type_info()) 

1257 self.assertEqual( 

1258 "ZserioTreeCreator: Field 'nonexisting' not found in " 

1259 + "'test_object.CreatorObject'! (JsonParser:2:16)", 

1260 str(error.exception), 

1261 ) 

1262 

1263 def test_wrong_value_type_exception(self): 

1264 text_io = io.StringIO('{\n "value": "13"\n}') 

1265 

1266 json_reader = JsonReader(text_io) 

1267 with self.assertRaises(PythonRuntimeException) as error: 

1268 json_reader.read(CreatorObject.type_info()) 

1269 self.assertEqual( 

1270 "ZserioTreeCreator: Unexpected value type '<class 'str'>', " 

1271 + "expecting '<class 'int'>'! (JsonParser:2:12)", 

1272 str(error.exception), 

1273 ) 

1274 

1275 def test_wrong_bit_buffer_exception(self): 

1276 text_io = io.StringIO( 

1277 "{\n" 

1278 + ' "value": 13,\n' 

1279 + ' "nested": {\n' 

1280 + ' "value": 10,\n' 

1281 + ' "text": "nested",\n' 

1282 + ' "externData": {\n' 

1283 + ' "buffer": [\n' 

1284 + " 203,\n" 

1285 + " 240\n" 

1286 + " ],\n" 

1287 + ' "bitSize": {\n' 

1288 + " }\n" 

1289 + " }\n" 

1290 + " }\n" 

1291 + "}" 

1292 ) 

1293 

1294 json_reader = JsonReader(text_io) 

1295 with self.assertRaises(PythonRuntimeException) as error: 

1296 json_reader.read(CreatorObject.type_info()) 

1297 self.assertEqual( 

1298 "JsonReader: Unexpected begin object in Bit Buffer! (JsonParser:11:25)", 

1299 str(error.exception), 

1300 ) 

1301 

1302 def test_partial_bit_buffer_exception(self): 

1303 text_io = io.StringIO( 

1304 "{\n" 

1305 + ' "value": 13,\n' 

1306 + ' "nested": {\n' 

1307 + ' "value": 10,\n' 

1308 + ' "text": "nested",\n' 

1309 + ' "externData": {\n' 

1310 + ' "buffer": [\n' 

1311 + " 203,\n" 

1312 + " 240\n" 

1313 + " ]\n" 

1314 + " }\n" 

1315 + " }\n" 

1316 + "}" 

1317 ) 

1318 

1319 json_reader = JsonReader(text_io) 

1320 with self.assertRaises(PythonRuntimeException) as error: 

1321 json_reader.read(CreatorObject.type_info()) 

1322 self.assertEqual( 

1323 "JsonReader: Unexpected end in Bit Buffer! (JsonParser:12:5)", 

1324 str(error.exception), 

1325 ) 

1326 

1327 def test_wrong_bytes_exception(self): 

1328 text_io = io.StringIO( 

1329 "{\n" 

1330 + ' "value": 13,\n' 

1331 + ' "nested": {\n' 

1332 + ' "value": 10,\n' 

1333 + ' "text": "nested",\n' 

1334 + ' "externData": {\n' 

1335 + ' "buffer": [\n' 

1336 + " 203,\n" 

1337 + " 240\n" 

1338 + " ],\n" 

1339 + ' "bitSize": 12\n' 

1340 + " },\n" 

1341 + ' "bytesData": {\n' 

1342 + ' "buffer": {}\n' 

1343 + " }\n" 

1344 + " }\n" 

1345 + "}" 

1346 ) 

1347 

1348 json_reader = JsonReader(text_io) 

1349 with self.assertRaises(PythonRuntimeException) as error: 

1350 json_reader.read(CreatorObject.type_info()) 

1351 self.assertEqual( 

1352 "JsonReader: Unexpected begin object in bytes! (JsonParser:14:23)", 

1353 str(error.exception), 

1354 ) 

1355 

1356 def test_partial_bytes_exception(self): 

1357 text_io = io.StringIO( 

1358 "{\n" 

1359 + ' "value": 13,\n' 

1360 + ' "nested": {\n' 

1361 + ' "bytesData": {\n' 

1362 + " }\n" 

1363 + "}" 

1364 ) 

1365 

1366 json_reader = JsonReader(text_io) 

1367 with self.assertRaises(PythonRuntimeException) as error: 

1368 json_reader.read(CreatorObject.type_info()) 

1369 self.assertEqual( 

1370 "JsonReader: Unexpected end in bytes! (JsonParser:6:1)", 

1371 str(error.exception), 

1372 ) 

1373 

1374 def test_json_array_exception(self): 

1375 text_io = io.StringIO("[1, 2]") 

1376 

1377 json_reader = JsonReader(text_io) 

1378 with self.assertRaises(PythonRuntimeException) as error: 

1379 json_reader.read(CreatorObject.type_info()) 

1380 self.assertEqual( 

1381 "JsonReader: ZserioTreeCreator expects json object! (JsonParser:1:1)", 

1382 str(error.exception), 

1383 ) 

1384 

1385 def test_json_value_exception(self): 

1386 text_io = io.StringIO('"text"') 

1387 

1388 json_reader = JsonReader(text_io) 

1389 with self.assertRaises(PythonRuntimeException) as error: 

1390 json_reader.read(CreatorObject.type_info()) 

1391 self.assertEqual( 

1392 "JsonReader: ZserioTreeCreator expects json object! (JsonParser:1:1)", 

1393 str(error.exception), 

1394 ) 

1395 

1396 def test_bitbuffer_adapter_uninitialized_calls(self): 

1397 bitbuffer_adapter = JsonReader._BitBufferAdapter() 

1398 

1399 with self.assertRaises(PythonRuntimeException): 

1400 bitbuffer_adapter.begin_object() 

1401 with self.assertRaises(PythonRuntimeException): 

1402 bitbuffer_adapter.end_object() 

1403 with self.assertRaises(PythonRuntimeException): 

1404 bitbuffer_adapter.begin_array() 

1405 with self.assertRaises(PythonRuntimeException): 

1406 bitbuffer_adapter.end_array() 

1407 with self.assertRaises(PythonRuntimeException): 

1408 bitbuffer_adapter.visit_key("nonexisting") 

1409 bitbuffer_adapter.visit_key("buffer") 

1410 with self.assertRaises(PythonRuntimeException): 

1411 bitbuffer_adapter.visit_key("nonexisting") 

1412 with self.assertRaises(PythonRuntimeException): 

1413 bitbuffer_adapter.visit_value("BadValue") 

1414 

1415 def test_bytes_adapter_uninitialized_calls(self): 

1416 bytes_adapter = JsonReader._BytesAdapter() 

1417 

1418 with self.assertRaises(PythonRuntimeException): 

1419 bytes_adapter.begin_object() 

1420 with self.assertRaises(PythonRuntimeException): 

1421 bytes_adapter.end_object() 

1422 with self.assertRaises(PythonRuntimeException): 

1423 bytes_adapter.begin_array() 

1424 with self.assertRaises(PythonRuntimeException): 

1425 bytes_adapter.end_array() 

1426 with self.assertRaises(PythonRuntimeException): 

1427 bytes_adapter.visit_key("nonexisting") 

1428 bytes_adapter.visit_key("buffer") 

1429 with self.assertRaises(PythonRuntimeException): 

1430 bytes_adapter.visit_key("nonexisting") 

1431 with self.assertRaises(PythonRuntimeException): 

1432 bytes_adapter.visit_value("BadValue") 

1433 

1434 def test_creator_adapter_uninitialized_calls(self): 

1435 creator_adapter = JsonReader._CreatorAdapter() 

1436 

1437 with self.assertRaises(PythonRuntimeException): 

1438 creator_adapter.get() 

1439 with self.assertRaises(PythonRuntimeException): 

1440 creator_adapter.begin_object() 

1441 with self.assertRaises(PythonRuntimeException): 

1442 creator_adapter.end_object() 

1443 with self.assertRaises(PythonRuntimeException): 

1444 creator_adapter.begin_array() 

1445 with self.assertRaises(PythonRuntimeException): 

1446 creator_adapter.end_array() 

1447 with self.assertRaises(PythonRuntimeException): 

1448 creator_adapter.visit_key("key") 

1449 with self.assertRaises(PythonRuntimeException): 

1450 creator_adapter.visit_value(None) 

1451 

1452 def _check_read_stringified_enum(self, string_value, expected_value): 

1453 text_io = io.StringIO( 

1454 "{\n" ' "nested": {\n' ' "creatorEnum": "' + string_value + '"\n' " }\n" "}" 

1455 ) 

1456 

1457 json_reader = JsonReader(text_io) 

1458 creator_object = json_reader.read(CreatorObject.type_info()) 

1459 self.assertTrue(creator_object is not None) 

1460 self.assertTrue(isinstance(creator_object, CreatorObject)) 

1461 

1462 self.assertEqual(expected_value, creator_object.nested.creator_enum) 

1463 

1464 def _check_read_stringified_enum_raises(self, string_value, expected_message): 

1465 text_io = io.StringIO( 

1466 "{\n" ' "nested": {\n' ' "creatorEnum": "' + string_value + '"\n' " }\n" "}" 

1467 ) 

1468 

1469 json_reader = JsonReader(text_io) 

1470 with self.assertRaises(PythonRuntimeException) as error: 

1471 json_reader.read(CreatorObject.type_info()) 

1472 self.assertEqual(expected_message, str(error.exception)) 

1473 

1474 def _check_read_stringified_bitmask(self, string_value, expected_value): 

1475 text_io = io.StringIO( 

1476 "{\n" ' "nested": {\n' ' "creatorBitmask": "' + string_value + '"\n' " }\n" "}" 

1477 ) 

1478 

1479 json_reader = JsonReader(text_io) 

1480 creator_object = json_reader.read(CreatorObject.type_info()) 

1481 self.assertTrue(creator_object is not None) 

1482 self.assertTrue(isinstance(creator_object, CreatorObject)) 

1483 

1484 self.assertEqual(expected_value, creator_object.nested.creator_bitmask) 

1485 

1486 def _check_read_stringified_bitmask_raises(self, string_value, expected_message): 

1487 text_io = io.StringIO( 

1488 "{\n" ' "nested": {\n' ' "creatorBitmask": "' + string_value + '"\n' " }\n" "}" 

1489 ) 

1490 

1491 json_reader = JsonReader(text_io) 

1492 with self.assertRaises(PythonRuntimeException) as error: 

1493 json_reader.read(CreatorObject.type_info()) 

1494 self.assertEqual(expected_message, str(error.exception))