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
« prev ^ index » next coverage.py v6.5.0, created at 2024-12-05 10:43 +0000
1import enum
2import io
3import unittest
4import math
7from test_object.api import CreatorEnum, CreatorBitmask, CreatorObject
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
32class JsonWriterTest(unittest.TestCase):
34 def test_empty(self):
35 json_writer = JsonWriter()
36 self.assertEqual("", json_writer.get_io().getvalue())
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())
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())
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
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 )
69 test_enum_member_info = MemberInfo("enumField", test_enum_type_info)
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 )
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 )
95 def test_bitmask_value(self):
96 class TestBitmask:
97 def __init__(self, value):
98 self._value = value
100 @property
101 def value(self):
102 return self._value
104 class Values:
105 ZERO = None
106 ONE = None
107 TWO = None
109 TestBitmask.Values.ZERO = TestBitmask(0)
110 TestBitmask.Values.ONE = TestBitmask(1)
111 TestBitmask.Values.TWO = TestBitmask(2)
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 )
125 test_bitmask_member_info = MemberInfo("bitmaskField", test_bitmask_type_info)
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 )
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())
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 )
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 )
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())
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())
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 )
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 )
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 )
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 )
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 )
226 @staticmethod
227 def _walk_nested(json_writer):
228 creator_type_info = TypeInfo("Creator", object)
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())
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 )
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())
253class JsonEncoderTest(unittest.TestCase):
255 def test_encode_null(self):
256 json_encoder = JsonEncoder()
257 self.assertEqual("null", json_encoder.encode_value(None))
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))
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))
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))
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))
282 self.assertEqual("1e+20", json_encoder.encode_value(1e20))
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")))
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("€"))
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"))
304 self.assertEqual(
305 '"\\n\\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\\\\"\'Hello World2"',
306 json_encoder.encode_value("\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"'Hello World2"),
307 )
309 # <= 0x1F -> unicode escape
310 self.assertEqual('"\\u001f"', json_encoder.encode_value("\x1f"))
313class JsonParserTest(unittest.TestCase):
315 class DummyObserver(JsonParser.Observer):
316 def __init__(self):
317 self._report = []
319 @property
320 def report(self):
321 return self._report
323 def begin_object(self):
324 self._report.append("begin_object")
326 def end_object(self):
327 self._report.append("end_object")
329 def begin_array(self):
330 self._report.append("begin_array")
332 def end_array(self):
333 self._report.append("end_array")
335 def visit_key(self, key):
336 self._report.append(f"visit_key: {key}")
338 def visit_value(self, value):
339 self._report.append(f"visit_value: {value}")
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)
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()
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 )
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)
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)
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)
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())
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 )
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()
437 self.assertEqual(
438 "JsonParser:3:1: Unexpected token: JsonToken.BEGIN_OBJECT ('{'), "
439 "expecting JsonToken.END_OBJECT!",
440 str(error.exception),
441 )
443 self.assertEqual(["begin_object"], observer.report)
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()
452 self.assertEqual(
453 "JsonParser:3:3: Unexpected token: JsonToken.BEGIN_OBJECT ('{'), expecting JsonToken.VALUE!",
454 str(error.exception),
455 )
457 self.assertEqual(["begin_object", "visit_key: key", "visit_value: 10"], observer.report)
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()
466 self.assertEqual(
467 "JsonParser:3:1: Unexpected token: JsonToken.VALUE ('item2'), expecting JsonToken.END_OBJECT!",
468 str(error.exception),
469 )
471 self.assertEqual(["begin_object", "visit_key: item1", "visit_value: text"], observer.report)
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()
480 self.assertEqual("JsonParser:2:1: Key must be a string value!", str(error.exception))
482 self.assertEqual(["begin_object"], observer.report)
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()
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 )
497 self.assertEqual(["begin_object", "visit_key: item"], observer.report)
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()
506 self.assertEqual(
507 "JsonParser:4:1: Unexpected token: JsonToken.VALUE ('20'), expecting JsonToken.END_ARRAY!",
508 str(error.exception),
509 )
511 self.assertEqual(
512 ["begin_object", "visit_key: array", "begin_array", "visit_value: 10"],
513 observer.report,
514 )
517class JsonDecoderTest(unittest.TestCase):
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)
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)
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)
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)
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)
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)
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)
575 self._check_decoder_failure("--10", 0, 1)
576 self._check_decoder_failure("-", 0, 1)
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)
586 self._check_decoder_failure("+10", 0, 1)
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)
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)
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)
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)
617 self._check_decoder_failure("1e", 0, 2)
618 self._check_decoder_failure("1e+", 0, 3)
619 self._check_decoder_failure("1E-", 0, 3)
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, "")
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, "€")
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")
639 self._check_decoder_success(
640 '"\\n\\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\\\\"\'Hello World2"',
641 0,
642 62,
643 "\n\t%^@(*aAzZ01234569$%^!?<>[]](){}-=+~:;/|\\\"'Hello World2",
644 )
646 # <= 0x1F -> unicode escape
647 self._check_decoder_success('"\\u001f"', 0, 8, "\u001f")
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)
655 def test_wrong_arguments(self):
656 self._check_decoder_failure("", 1, 0)
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)
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)
674class JsonTokenizerTest(unittest.TestCase):
676 def test_tokens(self):
677 text_io = io.StringIO('{"array":\n[\n{"key":\n10}]}')
678 tokenizer = JsonTokenizer(text_io)
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())
704 def test_line_column(self):
705 text_io = io.StringIO('\n{\r "key" \n :\n10}\r')
706 tokenizer = JsonTokenizer(text_io)
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())
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())
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())
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())
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())
733 self.assertEqual(JsonToken.END_OF_FILE, tokenizer.next())
734 self.assertEqual(5, tokenizer.get_line())
735 self.assertEqual(4, tokenizer.get_column())
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 += "}"
749 text_io = io.StringIO(json_string)
750 tokenizer = JsonTokenizer(text_io)
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())
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())
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())
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())
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())
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())
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())
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())
793 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next())
794 self.assertEqual(1 + k + 2, tokenizer.get_line())
795 self.assertEqual(1, tokenizer.get_column())
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 += "}"
809 text_io = io.StringIO(json_string)
810 tokenizer = JsonTokenizer(text_io)
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())
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())
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())
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())
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())
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())
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())
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())
853 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next())
854 self.assertEqual(1 + k + 2, tokenizer.get_line())
855 self.assertEqual(1, tokenizer.get_column())
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 += "}"
869 text_io = io.StringIO(json_string)
870 tokenizer = JsonTokenizer(text_io)
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())
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())
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())
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())
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())
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())
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())
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())
913 self.assertEqual(JsonToken.END_OBJECT, tokenizer.next())
914 self.assertEqual(1 + k + 2, tokenizer.get_line())
915 self.assertEqual(1, tokenizer.get_column())
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))
925class JsonReaderTest(unittest.TestCase):
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()
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 )
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))
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
1039 def test_read_two_objects(self):
1040 text_io = io.StringIO('{"value": 13}\n' + '{"value": 42, "text": "test"}\n')
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))
1047 self.assertEqual(13, creator_object1.value)
1048 self.assertEqual("", creator_object1.text)
1050 creator_object2 = json_reader.read(CreatorObject.type_info())
1051 self.assertTrue(creator_object2 is not None)
1052 self.assertTrue(isinstance(creator_object2, CreatorObject))
1054 self.assertEqual(42, creator_object2.value)
1055 self.assertEqual("test", creator_object2.text)
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 )
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))
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)
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 )
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))
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)
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 )
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))
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)
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 )
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 )
1239 def test_json_parser_exception(self):
1240 text_io = io.StringIO('{"value"\n"value"')
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 )
1251 def test_wrong_key_exception(self):
1252 text_io = io.StringIO('{"value": 13,\n"nonexisting": 10}')
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 )
1263 def test_wrong_value_type_exception(self):
1264 text_io = io.StringIO('{\n "value": "13"\n}')
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
1374 def test_json_array_exception(self):
1375 text_io = io.StringIO("[1, 2]")
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 )
1385 def test_json_value_exception(self):
1386 text_io = io.StringIO('"text"')
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 )
1396 def test_bitbuffer_adapter_uninitialized_calls(self):
1397 bitbuffer_adapter = JsonReader._BitBufferAdapter()
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")
1415 def test_bytes_adapter_uninitialized_calls(self):
1416 bytes_adapter = JsonReader._BytesAdapter()
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")
1434 def test_creator_adapter_uninitialized_calls(self):
1435 creator_adapter = JsonReader._CreatorAdapter()
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)
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 )
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))
1462 self.assertEqual(expected_value, creator_object.nested.creator_enum)
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 )
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))
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 )
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))
1484 self.assertEqual(expected_value, creator_object.nested.creator_bitmask)
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 )
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))