]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - tests/test_pyderasn.py
Initial support for event generated mode
[pyderasn.git] / tests / test_pyderasn.py
index 309bc2290df05440bccc2b63d65a53547100e852..f160ba833b1933ace9c49871984ab2585982731b 100644 (file)
@@ -583,8 +583,9 @@ class TestBoolean(CommonMixin, TestCase):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
         for klass in (Boolean, BooleanInherited):
             _, _, _, default, optional, _decoded = values
             obj = klass(
@@ -639,6 +640,21 @@ class TestBoolean(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                hexdec(obj_expled_hex_encoded) + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj, obj_decoded)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
     @given(integers(min_value=2))
     def test_invalid_len(self, l):
         with self.assertRaises(InvalidLength):
@@ -656,14 +672,13 @@ class TestBoolean(CommonMixin, TestCase):
                 len_encode(1),
                 int2byte(value),
             )))
-        obj, _ = Boolean().decode(
-            b"".join((
-                Boolean.tag_default,
-                len_encode(1),
-                int2byte(value),
-            )),
-            ctx={"bered": True},
-        )
+        encoded = b"".join((
+            Boolean.tag_default,
+            len_encode(1),
+            int2byte(value),
+        ))
+        obj, _ = Boolean().decode(encoded, ctx={"bered": True})
+        list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
         self.assertTrue(bool(obj))
         self.assertTrue(obj.ber_encoded)
         self.assertFalse(obj.lenindef)
@@ -725,6 +740,7 @@ class TestBoolean(CommonMixin, TestCase):
         with self.assertRaises(LenIndefForm):
             SeqOf().decode(encoded)
         seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
+        list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
         self.assertSequenceEqual(tail, b"")
         self.assertSequenceEqual([bool(v) for v in seqof], values)
         self.assertSetEqual(
@@ -1081,8 +1097,9 @@ class TestInteger(CommonMixin, TestCase):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
         for klass in (Integer, IntegerInherited):
             _, _, _, _, default, optional, _, _decoded = values
             obj = klass(
@@ -1137,6 +1154,21 @@ class TestInteger(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                obj_expled_encoded + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj, obj_decoded)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
     def test_go_vectors_valid(self):
         for data, expect in ((
                 (b"\x00", 0),
@@ -1475,6 +1507,7 @@ class TestBitString(CommonMixin, TestCase):
         tail_junk = d.draw(binary(max_size=5))
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
+        decode_path = d.draw(decode_path_strat)
         for klass in (BitString, BitStringInherited):
             class BS(klass):
                 schema = _schema
@@ -1534,6 +1567,20 @@ class TestBitString(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                obj_expled_encoded + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
     @given(integers(min_value=1, max_value=255))
     def test_bad_zero_value(self, pad_size):
         with self.assertRaises(DecodeError):
@@ -1580,6 +1627,7 @@ class TestBitString(CommonMixin, TestCase):
         self.assertTrue(obj[9])
         self.assertFalse(obj[17])
 
+    @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
         integers(min_value=1, max_value=30),
         lists(
@@ -1596,8 +1644,9 @@ class TestBitString(CommonMixin, TestCase):
         ),
         lists(booleans(), min_size=1),
         binary(),
+        decode_path_strat,
     )
-    def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk):
+    def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
         def chunk_constructed(contents):
             return (
                 tag_encode(form=TagFormConstructed, num=3) +
@@ -1606,6 +1655,7 @@ class TestBitString(CommonMixin, TestCase):
                 EOC
             )
         chunks = []
+        chunks_len_expected = []
         payload_expected = b""
         bit_len_expected = 0
         for chunk_input in chunk_inputs:
@@ -1613,14 +1663,19 @@ class TestBitString(CommonMixin, TestCase):
                 chunks.append(BitString(chunk_input).encode())
                 payload_expected += chunk_input
                 bit_len_expected += len(chunk_input) * 8
+                chunks_len_expected.append(len(chunk_input) + 1)
             else:
                 chunks.append(chunk_constructed(chunk_input))
                 payload = b"".join(chunk_input)
                 payload_expected += payload
                 bit_len_expected += len(payload) * 8
+                for c in chunk_input:
+                    chunks_len_expected.append(len(c) + 1)
+                chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
         chunk_last = BitString("'%s'B" % "".join(
             "1" if bit else "0" for bit in chunk_last_bits
         ))
+        chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
         payload_expected += bytes(chunk_last)
         bit_len_expected += chunk_last.bit_len
         encoded_indefinite = (
@@ -1661,6 +1716,16 @@ class TestBitString(CommonMixin, TestCase):
             list(obj.pps())
             pprint(obj, big_blobs=True, with_decode_path=True)
 
+            evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
+                encoded,
+                decode_path=decode_path,
+                ctx={"bered": True},
+            ))
+            self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
+            for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
+                self.assertGreater(len(dp), len(decode_path))
+                self.assertEqual(obj.vlen, chunk_len_expected)
+
     @given(
         integers(min_value=0),
         decode_path_strat,
@@ -2072,8 +2137,9 @@ class TestOctetString(CommonMixin, TestCase):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
         for klass in (OctetString, OctetStringInherited):
             _, _, _, _, default, optional, _decoded = values
             obj = klass(
@@ -2128,6 +2194,21 @@ class TestOctetString(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                obj_expled_encoded + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
+    @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
         integers(min_value=1, max_value=30),
         lists(
@@ -2143,8 +2224,9 @@ class TestOctetString(CommonMixin, TestCase):
             max_size=3,
         ),
         binary(),
+        decode_path_strat,
     )
-    def test_constructed(self, impl, chunk_inputs, junk):
+    def test_constructed(self, impl, chunk_inputs, junk, decode_path):
         def chunk_constructed(contents):
             return (
                 tag_encode(form=TagFormConstructed, num=4) +
@@ -2153,15 +2235,20 @@ class TestOctetString(CommonMixin, TestCase):
                 EOC
             )
         chunks = []
+        chunks_len_expected = []
         payload_expected = b""
         for chunk_input in chunk_inputs:
             if isinstance(chunk_input, binary_type):
                 chunks.append(OctetString(chunk_input).encode())
                 payload_expected += chunk_input
+                chunks_len_expected.append(len(chunk_input))
             else:
                 chunks.append(chunk_constructed(chunk_input))
                 payload = b"".join(chunk_input)
                 payload_expected += payload
+                for c in chunk_input:
+                    chunks_len_expected.append(len(c))
+                chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
         encoded_indefinite = (
             tag_encode(form=TagFormConstructed, num=impl) +
             LENINDEF +
@@ -2197,6 +2284,16 @@ class TestOctetString(CommonMixin, TestCase):
             list(obj.pps())
             pprint(obj, big_blobs=True, with_decode_path=True)
 
+            evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
+                encoded,
+                decode_path=decode_path,
+                ctx={"bered": True},
+            ))
+            self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
+            for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
+                self.assertGreater(len(dp), len(decode_path))
+                self.assertEqual(obj.vlen, chunk_len_expected)
+
     @given(
         integers(min_value=0),
         decode_path_strat,
@@ -2390,8 +2487,9 @@ class TestNull(CommonMixin, TestCase):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
         for klass in (Null, NullInherited):
             _, _, optional, _decoded = values
             obj = klass(optional=optional, _decoded=_decoded)
@@ -2439,6 +2537,22 @@ class TestNull(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                obj_expled_encoded + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj, obj_decoded)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
+
     @given(integers(min_value=1))
     def test_invalid_len(self, l):
         with self.assertRaises(InvalidLength):
@@ -2727,8 +2841,9 @@ class TestObjectIdentifier(CommonMixin, TestCase):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
         for klass in (ObjectIdentifier, ObjectIdentifierInherited):
             _, _, _, default, optional, _decoded = values
             obj = klass(
@@ -2783,6 +2898,21 @@ class TestObjectIdentifier(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                obj_expled_encoded + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj, obj_decoded)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
     @given(
         oid_strategy().map(ObjectIdentifier),
         oid_strategy().map(ObjectIdentifier),
@@ -3100,6 +3230,7 @@ class TestEnumerated(CommonMixin, TestCase):
         offset = d.draw(integers(min_value=0))
         value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
         tail_junk = d.draw(binary(max_size=5))
+        decode_path = d.draw(decode_path_strat)
 
         class E(Enumerated):
             schema = schema_input
@@ -3155,6 +3286,21 @@ class TestEnumerated(CommonMixin, TestCase):
             tail_junk,
         )
 
+        evgens = list(obj_expled.decode_evgen(
+            obj_expled_encoded + tail_junk,
+            offset=offset,
+            decode_path=decode_path,
+            ctx=ctx_copied,
+        ))
+        self.assertEqual(len(evgens), 1)
+        _decode_path, obj, tail = evgens[0]
+        self.assertSequenceEqual(tail, tail_junk)
+        self.assertEqual(_decode_path, decode_path)
+        self.assertEqual(obj, obj_decoded)
+        self.assertEqual(obj.expl_offset, offset)
+        repr(obj)
+        list(obj.pps())
+
 
 @composite
 def string_values_strategy(draw, alphabet, do_expl=False):
@@ -3436,6 +3582,7 @@ class StringMixin(object):
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         tail_junk = d.draw(binary(max_size=5))
+        decode_path = d.draw(decode_path_strat)
         _, _, _, _, default, optional, _decoded = values
         obj = self.base_klass(
             value=value,
@@ -3491,6 +3638,22 @@ class StringMixin(object):
             tail_junk,
         )
 
+        evgens = list(obj_expled.decode_evgen(
+            obj_expled_encoded + tail_junk,
+            offset=offset,
+            decode_path=decode_path,
+            ctx=ctx_copied,
+        ))
+        self.assertEqual(len(evgens), 1)
+        _decode_path, obj, tail = evgens[0]
+        self.assertSequenceEqual(tail, tail_junk)
+        self.assertEqual(_decode_path, decode_path)
+        if not getattr(self, "evgen_mode_skip_value", True):
+            self.assertEqual(obj, obj_decoded)
+        self.assertEqual(obj.expl_offset, offset)
+        repr(obj)
+        list(obj.pps())
+
 
 class TestUTF8String(StringMixin, CommonMixin, TestCase):
     base_klass = UTF8String
@@ -3964,6 +4127,7 @@ class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
     omit_ms = False
     min_datetime = datetime(1900, 1, 1)
     max_datetime = datetime(9999, 12, 31)
+    evgen_mode_skip_value = False
 
     def additional_symmetric_check(self, value, obj_encoded):
         if value.microsecond > 0:
@@ -4348,6 +4512,7 @@ class TestUTCTime(TimeMixin, CommonMixin, TestCase):
     omit_ms = True
     min_datetime = datetime(2000, 1, 1)
     max_datetime = datetime(2049, 12, 31)
+    evgen_mode_skip_value = False
 
     def additional_symmetric_check(self, value, obj_encoded):
         pass
@@ -4859,8 +5024,9 @@ class TestAny(CommonMixin, TestCase):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
         for klass in (Any, AnyInherited):
             _, _, optional, _decoded = values
             obj = klass(value=value, optional=optional, _decoded=_decoded)
@@ -4916,6 +5082,20 @@ class TestAny(CommonMixin, TestCase):
                 tail_junk,
             )
 
+            evgens = list(obj_expled.decode_evgen(
+                obj_expled_encoded + tail_junk,
+                offset=offset,
+                decode_path=decode_path,
+                ctx=ctx_copied,
+            ))
+            self.assertEqual(len(evgens), 1)
+            _decode_path, obj, tail = evgens[0]
+            self.assertSequenceEqual(tail, tail_junk)
+            self.assertEqual(_decode_path, decode_path)
+            self.assertEqual(obj.expl_offset, offset)
+            repr(obj)
+            list(obj.pps())
+
     @given(
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0, max_value=3),
@@ -5225,6 +5405,7 @@ class TestChoice(CommonMixin, TestCase):
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         tail_junk = d.draw(binary(max_size=5))
+        decode_path = d.draw(decode_path_strat)
 
         class Wahl(self.base_klass):
             schema = _schema
@@ -5291,6 +5472,22 @@ class TestChoice(CommonMixin, TestCase):
             tail_junk,
         )
 
+        evgens = list(obj_expled.decode_evgen(
+            obj_expled_encoded + tail_junk,
+            offset=offset,
+            decode_path=decode_path,
+            ctx=ctx_copied,
+        ))
+        self.assertEqual(len(evgens), 2)
+        _decode_path, obj, tail = evgens[0]
+        self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
+        _decode_path, obj, tail = evgens[1]
+        self.assertSequenceEqual(tail, tail_junk)
+        self.assertEqual(_decode_path, decode_path)
+        self.assertEqual(obj.expl_offset, offset)
+        repr(obj)
+        list(obj.pps())
+
     @given(integers())
     def test_set_get(self, value):
         class Wahl(Choice):
@@ -5750,6 +5947,7 @@ class SeqMixing(object):
     def test_symmetric(self, d):
         seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
         tail_junk = d.draw(binary(max_size=5))
+        decode_path = d.draw(decode_path_strat)
         self.assertTrue(seq.ready)
         self.assertFalse(seq.decoded)
         self._assert_expects(seq, expects)
@@ -5813,6 +6011,21 @@ class SeqMixing(object):
                     obj.encode(),
                 )
 
+            evgens = list(seq.decode_evgen(
+                encoded + decoded_tail,
+                decode_path=decode_path,
+                ctx={"bered": True},
+            ))
+            self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
+            for _decode_path, obj, _ in evgens[:-1]:
+                self.assertEqual(_decode_path[:-1], decode_path)
+                repr(obj)
+                list(obj.pps())
+            _decode_path, obj, tail = evgens[-1]
+            self.assertEqual(_decode_path, decode_path)
+            repr(obj)
+            list(obj.pps())
+
         assert_exceeding_data(
             self,
             lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
@@ -6440,8 +6653,9 @@ class SeqOfMixing(object):
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(max_size=5),
+        decode_path_strat,
     )
-    def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
+    def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
         _, _, _, _, _, default, optional, _decoded = values
 
         class SeqOf(self.base_klass):
@@ -6523,6 +6737,21 @@ class SeqOfMixing(object):
         with self.assertRaises(DecodeError):
             obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
 
+        evgens = list(obj.decode_evgen(
+            obj_encoded_lenindef + tail_junk,
+            decode_path=decode_path,
+            ctx={"bered": True},
+        ))
+        self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
+        for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
+            self.assertEqual(_decode_path, decode_path + (str(i),))
+            repr(obj)
+            list(obj.pps())
+        _decode_path, obj, tail = evgens[-1]
+        self.assertEqual(_decode_path, decode_path)
+        repr(obj)
+        list(obj.pps())
+
         assert_exceeding_data(
             self,
             lambda: obj_expled.decod(obj_expled_encoded + tail_junk),