]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - tests/test_pyderasn.py
Strict default values existence validation option
[pyderasn.git] / tests / test_pyderasn.py
index 7bce6b49bcfdb7d237e6353e0677d6da0efa3acb..5b98ea60cf1012c829ef6b9d396ac245e858343b 100644 (file)
@@ -1,6 +1,6 @@
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER codec with abstract structures
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER codec with abstract structures
-# Copyright (C) 2017 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2018 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
@@ -50,12 +50,14 @@ from six import PY2
 from six import text_type
 
 from pyderasn import _pp
 from six import text_type
 
 from pyderasn import _pp
+from pyderasn import abs_decode_path
 from pyderasn import Any
 from pyderasn import BitString
 from pyderasn import BMPString
 from pyderasn import Boolean
 from pyderasn import BoundsError
 from pyderasn import Choice
 from pyderasn import Any
 from pyderasn import BitString
 from pyderasn import BMPString
 from pyderasn import Boolean
 from pyderasn import BoundsError
 from pyderasn import Choice
+from pyderasn import decode_path_defby
 from pyderasn import DecodeError
 from pyderasn import Enumerated
 from pyderasn import GeneralizedTime
 from pyderasn import DecodeError
 from pyderasn import Enumerated
 from pyderasn import GeneralizedTime
@@ -85,6 +87,7 @@ from pyderasn import SequenceOf
 from pyderasn import Set
 from pyderasn import SetOf
 from pyderasn import tag_ctxc
 from pyderasn import Set
 from pyderasn import SetOf
 from pyderasn import tag_ctxc
+from pyderasn import tag_ctxp
 from pyderasn import tag_decode
 from pyderasn import tag_encode
 from pyderasn import tag_strip
 from pyderasn import tag_decode
 from pyderasn import tag_encode
 from pyderasn import tag_strip
@@ -317,7 +320,7 @@ class CommonMixin(object):
 
 
 @composite
 
 
 @composite
-def boolean_values_strat(draw, do_expl=False):
+def boolean_values_strategy(draw, do_expl=False):
     value = draw(one_of(none(), booleans()))
     impl = None
     expl = None
     value = draw(one_of(none(), booleans()))
     impl = None
     expl = None
@@ -389,7 +392,7 @@ class TestBoolean(CommonMixin, TestCase):
                 default_initial,
                 optional_initial,
                 _decoded_initial,
                 default_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(boolean_values_strat())
+            ) = d.draw(boolean_values_strategy())
             obj_initial = klass(
                 value_initial,
                 impl_initial,
             obj_initial = klass(
                 value_initial,
                 impl_initial,
@@ -405,7 +408,7 @@ class TestBoolean(CommonMixin, TestCase):
                 default,
                 optional,
                 _decoded,
                 default,
                 optional,
                 _decoded,
-            ) = d.draw(boolean_values_strat(do_expl=impl_initial is None))
+            ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
             obj = obj_initial(value, impl, expl, default, optional)
             if obj.ready:
                 value_expected = default if value is None else value
             obj = obj_initial(value, impl, expl, default, optional)
             if obj.ready:
                 value_expected = default if value is None else value
@@ -427,7 +430,7 @@ class TestBoolean(CommonMixin, TestCase):
                 optional = True
             self.assertEqual(obj.optional, optional)
 
                 optional = True
             self.assertEqual(obj.optional, optional)
 
-    @given(boolean_values_strat())
+    @given(boolean_values_strategy())
     def test_copy(self, values):
         for klass in (Boolean, BooleanInherited):
             obj = klass(*values)
     def test_copy(self, values):
         for klass in (Boolean, BooleanInherited):
             obj = klass(*values)
@@ -522,7 +525,7 @@ class TestBoolean(CommonMixin, TestCase):
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
-        boolean_values_strat(),
+        boolean_values_strategy(),
         booleans(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         booleans(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
@@ -588,7 +591,7 @@ class TestBoolean(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def integer_values_strat(draw, do_expl=False):
+def integer_values_strategy(draw, do_expl=False):
     bound_min, value, default, bound_max = sorted(draw(sets(
         integers(),
         min_size=4,
     bound_min, value, default, bound_max = sorted(draw(sets(
         integers(),
         min_size=4,
@@ -738,7 +741,7 @@ class TestInteger(CommonMixin, TestCase):
                 optional_initial,
                 _specs_initial,
                 _decoded_initial,
                 optional_initial,
                 _specs_initial,
                 _decoded_initial,
-            ) = d.draw(integer_values_strat())
+            ) = d.draw(integer_values_strategy())
             obj_initial = klass(
                 value_initial,
                 bounds_initial,
             obj_initial = klass(
                 value_initial,
                 bounds_initial,
@@ -758,7 +761,7 @@ class TestInteger(CommonMixin, TestCase):
                 optional,
                 _,
                 _decoded,
                 optional,
                 _,
                 _decoded,
-            ) = d.draw(integer_values_strat(do_expl=impl_initial is None))
+            ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
             if (default is None) and (obj_initial.default is not None):
                 bounds = None
             if (
             if (default is None) and (obj_initial.default is not None):
                 bounds = None
             if (
@@ -804,7 +807,7 @@ class TestInteger(CommonMixin, TestCase):
                 {} if _specs_initial is None else dict(_specs_initial),
             )
 
                 {} if _specs_initial is None else dict(_specs_initial),
             )
 
-    @given(integer_values_strat())
+    @given(integer_values_strategy())
     def test_copy(self, values):
         for klass in (Integer, IntegerInherited):
             obj = klass(*values)
     def test_copy(self, values):
         for klass in (Integer, IntegerInherited):
             obj = klass(*values)
@@ -897,7 +900,7 @@ class TestInteger(CommonMixin, TestCase):
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
-        integer_values_strat(),
+        integer_values_strategy(),
         integers(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         integers(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
@@ -982,7 +985,7 @@ class TestInteger(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def bit_string_values_strat(draw, schema=None, value_required=False, do_expl=False):
+def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
     if schema is None:
         schema = ()
         if draw(booleans()):
     if schema is None:
         schema = ()
         if draw(booleans()):
@@ -1151,7 +1154,7 @@ class TestBitString(CommonMixin, TestCase):
                 default_initial,
                 optional_initial,
                 _decoded_initial,
                 default_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(bit_string_values_strat())
+            ) = d.draw(bit_string_values_strategy())
 
             class BS(klass):
                 schema = schema_initial
 
             class BS(klass):
                 schema = schema_initial
@@ -1171,7 +1174,7 @@ class TestBitString(CommonMixin, TestCase):
                 default,
                 optional,
                 _decoded,
                 default,
                 optional,
                 _decoded,
-            ) = d.draw(bit_string_values_strat(
+            ) = d.draw(bit_string_values_strategy(
                 schema=schema_initial,
                 do_expl=impl_initial is None,
             ))
                 schema=schema_initial,
                 do_expl=impl_initial is None,
             ))
@@ -1192,7 +1195,7 @@ class TestBitString(CommonMixin, TestCase):
             self.assertEqual(obj.optional, optional)
             self.assertEqual(obj.specs, obj_initial.specs)
 
             self.assertEqual(obj.optional, optional)
             self.assertEqual(obj.specs, obj_initial.specs)
 
-    @given(bit_string_values_strat())
+    @given(bit_string_values_strategy())
     def test_copy(self, values):
         for klass in (BitString, BitStringInherited):
             _schema, value, impl, expl, default, optional, _decoded = values
     def test_copy(self, values):
         for klass in (BitString, BitStringInherited):
             _schema, value, impl, expl, default, optional, _decoded = values
@@ -1275,7 +1278,7 @@ class TestBitString(CommonMixin, TestCase):
             default,
             optional,
             _decoded,
             default,
             optional,
             _decoded,
-        ) = d.draw(bit_string_values_strat(value_required=True))
+        ) = d.draw(bit_string_values_strategy(value_required=True))
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         for klass in (BitString, BitStringInherited):
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         for klass in (BitString, BitStringInherited):
@@ -1371,7 +1374,7 @@ class TestBitString(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def octet_string_values_strat(draw, do_expl=False):
+def octet_string_values_strategy(draw, do_expl=False):
     bound_min, bound_max = sorted(draw(sets(
         integers(min_value=0, max_value=1 << 7),
         min_size=2,
     bound_min, bound_max = sorted(draw(sets(
         integers(min_value=0, max_value=1 << 7),
         min_size=2,
@@ -1485,7 +1488,7 @@ class TestOctetString(CommonMixin, TestCase):
                 default_initial,
                 optional_initial,
                 _decoded_initial,
                 default_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(octet_string_values_strat())
+            ) = d.draw(octet_string_values_strategy())
             obj_initial = klass(
                 value_initial,
                 bounds_initial,
             obj_initial = klass(
                 value_initial,
                 bounds_initial,
@@ -1503,7 +1506,7 @@ class TestOctetString(CommonMixin, TestCase):
                 default,
                 optional,
                 _decoded,
                 default,
                 optional,
                 _decoded,
-            ) = d.draw(octet_string_values_strat(do_expl=impl_initial is None))
+            ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
             if (default is None) and (obj_initial.default is not None):
                 bounds = None
             if (
             if (default is None) and (obj_initial.default is not None):
                 bounds = None
             if (
@@ -1545,7 +1548,7 @@ class TestOctetString(CommonMixin, TestCase):
                 bounds or bounds_initial or (0, float("+inf")),
             )
 
                 bounds or bounds_initial or (0, float("+inf")),
             )
 
-    @given(octet_string_values_strat())
+    @given(octet_string_values_strategy())
     def test_copy(self, values):
         for klass in (OctetString, OctetStringInherited):
             obj = klass(*values)
     def test_copy(self, values):
         for klass in (OctetString, OctetStringInherited):
             obj = klass(*values)
@@ -1630,7 +1633,7 @@ class TestOctetString(CommonMixin, TestCase):
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
-        octet_string_values_strat(),
+        octet_string_values_strategy(),
         binary(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         binary(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
@@ -1678,7 +1681,7 @@ class TestOctetString(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def null_values_strat(draw, do_expl=False):
+def null_values_strategy(draw, do_expl=False):
     impl = None
     expl = None
     if do_expl:
     impl = None
     expl = None
     if do_expl:
@@ -1724,7 +1727,7 @@ class TestNull(CommonMixin, TestCase):
                 expl_initial,
                 optional_initial,
                 _decoded_initial,
                 expl_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(null_values_strat())
+            ) = d.draw(null_values_strategy())
             obj_initial = klass(
                 impl=impl_initial,
                 expl=expl_initial,
             obj_initial = klass(
                 impl=impl_initial,
                 expl=expl_initial,
@@ -1736,7 +1739,7 @@ class TestNull(CommonMixin, TestCase):
                 expl,
                 optional,
                 _decoded,
                 expl,
                 optional,
                 _decoded,
-            ) = d.draw(null_values_strat(do_expl=impl_initial is None))
+            ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
             obj = obj_initial(impl=impl, expl=expl, optional=optional)
             self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
             self.assertEqual(obj.expl_tag, expl or expl_initial)
             obj = obj_initial(impl=impl, expl=expl, optional=optional)
             self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
             self.assertEqual(obj.expl_tag, expl or expl_initial)
@@ -1744,7 +1747,7 @@ class TestNull(CommonMixin, TestCase):
             optional = False if optional is None else optional
             self.assertEqual(obj.optional, optional)
 
             optional = False if optional is None else optional
             self.assertEqual(obj.optional, optional)
 
-    @given(null_values_strat())
+    @given(null_values_strategy())
     def test_copy(self, values):
         for klass in (Null, NullInherited):
             impl, expl, optional, _decoded = values
     def test_copy(self, values):
         for klass in (Null, NullInherited):
             impl, expl, optional, _decoded = values
@@ -1810,7 +1813,7 @@ class TestNull(CommonMixin, TestCase):
             Null(impl=impl).decode(Null().encode())
 
     @given(
             Null(impl=impl).decode(Null().encode())
 
     @given(
-        null_values_strat(),
+        null_values_strategy(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
     )
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
     )
@@ -1870,7 +1873,7 @@ def oid_strategy(draw):
 
 
 @composite
 
 
 @composite
-def oid_values_strat(draw, do_expl=False):
+def oid_values_strategy(draw, do_expl=False):
     value = draw(one_of(none(), oid_strategy()))
     impl = None
     expl = None
     value = draw(one_of(none(), oid_strategy()))
     impl = None
     expl = None
@@ -1951,14 +1954,14 @@ class TestObjectIdentifier(CommonMixin, TestCase):
                 default_initial,
                 optional_initial,
                 _decoded_initial,
                 default_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(oid_values_strat())
+            ) = d.draw(oid_values_strategy())
             obj_initial = klass(
             obj_initial = klass(
-                value_initial,
-                impl_initial,
-                expl_initial,
-                default_initial,
-                optional_initial or False,
-                _decoded_initial,
+                value=value_initial,
+                impl=impl_initial,
+                expl=expl_initial,
+                default=default_initial,
+                optional=optional_initial or False,
+                _decoded=_decoded_initial,
             )
             (
                 value,
             )
             (
                 value,
@@ -1967,8 +1970,14 @@ class TestObjectIdentifier(CommonMixin, TestCase):
                 default,
                 optional,
                 _decoded,
                 default,
                 optional,
                 _decoded,
-            ) = d.draw(oid_values_strat(do_expl=impl_initial is None))
-            obj = obj_initial(value, impl, expl, default, optional)
+            ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
+            obj = obj_initial(
+                value=value,
+                impl=impl,
+                expl=expl,
+                default=default,
+                optional=optional,
+            )
             if obj.ready:
                 value_expected = default if value is None else value
                 value_expected = (
             if obj.ready:
                 value_expected = default if value is None else value
                 value_expected = (
@@ -1989,10 +1998,25 @@ class TestObjectIdentifier(CommonMixin, TestCase):
                 optional = True
             self.assertEqual(obj.optional, optional)
 
                 optional = True
             self.assertEqual(obj.optional, optional)
 
-    @given(oid_values_strat())
+    @given(oid_values_strategy())
     def test_copy(self, values):
         for klass in (ObjectIdentifier, ObjectIdentifierInherited):
     def test_copy(self, values):
         for klass in (ObjectIdentifier, ObjectIdentifierInherited):
-            obj = klass(*values)
+            (
+                value,
+                impl,
+                expl,
+                default,
+                optional,
+                _decoded,
+            ) = values
+            obj = klass(
+                value=value,
+                impl=impl,
+                expl=expl,
+                default=default,
+                optional=optional,
+                _decoded=_decoded,
+            )
             obj_copied = obj.copy()
             self.assert_copied_basic_fields(obj, obj_copied)
             self.assertEqual(obj._value, obj_copied._value)
             obj_copied = obj.copy()
             self.assert_copied_basic_fields(obj, obj_copied)
             self.assertEqual(obj._value, obj_copied._value)
@@ -2108,7 +2132,7 @@ class TestObjectIdentifier(CommonMixin, TestCase):
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
-        oid_values_strat(),
+        oid_values_strategy(),
         oid_strategy(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         oid_strategy(),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
@@ -2192,7 +2216,7 @@ class TestObjectIdentifier(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def enumerated_values_strat(draw, schema=None, do_expl=False):
+def enumerated_values_strategy(draw, schema=None, do_expl=False):
     if schema is None:
         schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
         values = list(draw(sets(
     if schema is None:
         schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
         values = list(draw(sets(
@@ -2307,7 +2331,7 @@ class TestEnumerated(CommonMixin, TestCase):
             default_initial,
             optional_initial,
             _decoded_initial,
             default_initial,
             optional_initial,
             _decoded_initial,
-        ) = d.draw(enumerated_values_strat())
+        ) = d.draw(enumerated_values_strategy())
 
         class E(Enumerated):
             schema = schema_initial
 
         class E(Enumerated):
             schema = schema_initial
@@ -2327,7 +2351,7 @@ class TestEnumerated(CommonMixin, TestCase):
             default,
             optional,
             _decoded,
             default,
             optional,
             _decoded,
-        ) = d.draw(enumerated_values_strat(
+        ) = d.draw(enumerated_values_strategy(
             schema=schema_initial,
             do_expl=impl_initial is None,
         ))
             schema=schema_initial,
             do_expl=impl_initial is None,
         ))
@@ -2362,7 +2386,7 @@ class TestEnumerated(CommonMixin, TestCase):
         self.assertEqual(obj.optional, optional)
         self.assertEqual(obj.specs, dict(schema_initial))
 
         self.assertEqual(obj.optional, optional)
         self.assertEqual(obj.specs, dict(schema_initial))
 
-    @given(enumerated_values_strat())
+    @given(enumerated_values_strategy())
     def test_copy(self, values):
         schema_input, value, impl, expl, default, optional, _decoded = values
 
     def test_copy(self, values):
         schema_input, value, impl, expl, default, optional, _decoded = values
 
@@ -2384,7 +2408,7 @@ class TestEnumerated(CommonMixin, TestCase):
     @given(data_strategy())
     def test_symmetric(self, d):
         schema_input, _, _, _, default, optional, _decoded = d.draw(
     @given(data_strategy())
     def test_symmetric(self, d):
         schema_input, _, _, _, default, optional, _decoded = d.draw(
-            enumerated_values_strat(),
+            enumerated_values_strategy(),
         )
         tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
         offset = d.draw(integers(min_value=0))
         )
         tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
         offset = d.draw(integers(min_value=0))
@@ -2432,7 +2456,7 @@ class TestEnumerated(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def string_values_strat(draw, alphabet, do_expl=False):
+def string_values_strategy(draw, alphabet, do_expl=False):
     bound_min, bound_max = sorted(draw(sets(
         integers(min_value=0, max_value=1 << 7),
         min_size=2,
     bound_min, bound_max = sorted(draw(sets(
         integers(min_value=0, max_value=1 << 7),
         min_size=2,
@@ -2548,7 +2572,7 @@ class StringMixin(object):
             default_initial,
             optional_initial,
             _decoded_initial,
             default_initial,
             optional_initial,
             _decoded_initial,
-        ) = d.draw(string_values_strat(self.text_alphabet()))
+        ) = d.draw(string_values_strategy(self.text_alphabet()))
         obj_initial = self.base_klass(
             value_initial,
             bounds_initial,
         obj_initial = self.base_klass(
             value_initial,
             bounds_initial,
@@ -2566,7 +2590,7 @@ class StringMixin(object):
             default,
             optional,
             _decoded,
             default,
             optional,
             _decoded,
-        ) = d.draw(string_values_strat(
+        ) = d.draw(string_values_strategy(
             self.text_alphabet(),
             do_expl=impl_initial is None,
         ))
             self.text_alphabet(),
             do_expl=impl_initial is None,
         ))
@@ -2613,7 +2637,7 @@ class StringMixin(object):
 
     @given(data_strategy())
     def test_copy(self, d):
 
     @given(data_strategy())
     def test_copy(self, d):
-        values = d.draw(string_values_strat(self.text_alphabet()))
+        values = d.draw(string_values_strategy(self.text_alphabet()))
         obj = self.base_klass(*values)
         obj_copied = obj.copy()
         self.assert_copied_basic_fields(obj, obj_copied)
         obj = self.base_klass(*values)
         obj_copied = obj.copy()
         self.assert_copied_basic_fields(obj, obj_copied)
@@ -2696,7 +2720,7 @@ class StringMixin(object):
 
     @given(data_strategy())
     def test_symmetric(self, d):
 
     @given(data_strategy())
     def test_symmetric(self, d):
-        values = d.draw(string_values_strat(self.text_alphabet()))
+        values = d.draw(string_values_strategy(self.text_alphabet()))
         value = d.draw(text(alphabet=self.text_alphabet()))
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         value = d.draw(text(alphabet=self.text_alphabet()))
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
@@ -2787,7 +2811,7 @@ class TestBMPString(StringMixin, CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def generalized_time_values_strat(
+def generalized_time_values_strategy(
         draw,
         min_datetime,
         max_datetime,
         draw,
         min_datetime,
         max_datetime,
@@ -2885,7 +2909,7 @@ class TimeMixin(object):
             default_initial,
             optional_initial,
             _decoded_initial,
             default_initial,
             optional_initial,
             _decoded_initial,
-        ) = d.draw(generalized_time_values_strat(
+        ) = d.draw(generalized_time_values_strategy(
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
             omit_ms=self.omit_ms,
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
             omit_ms=self.omit_ms,
@@ -2905,7 +2929,7 @@ class TimeMixin(object):
             default,
             optional,
             _decoded,
             default,
             optional,
             _decoded,
-        ) = d.draw(generalized_time_values_strat(
+        ) = d.draw(generalized_time_values_strategy(
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
             omit_ms=self.omit_ms,
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
             omit_ms=self.omit_ms,
@@ -2940,7 +2964,7 @@ class TimeMixin(object):
 
     @given(data_strategy())
     def test_copy(self, d):
 
     @given(data_strategy())
     def test_copy(self, d):
-        values = d.draw(generalized_time_values_strat(
+        values = d.draw(generalized_time_values_strategy(
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
         ))
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
         ))
@@ -2974,7 +2998,7 @@ class TimeMixin(object):
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(data_strategy())
     def test_symmetric(self, d):
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(data_strategy())
     def test_symmetric(self, d):
-        values = d.draw(generalized_time_values_strat(
+        values = d.draw(generalized_time_values_strategy(
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
         ))
             min_datetime=self.min_datetime,
             max_datetime=self.max_datetime,
         ))
@@ -3129,7 +3153,7 @@ class TestUTCTime(TimeMixin, CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def any_values_strat(draw, do_expl=False):
+def any_values_strategy(draw, do_expl=False):
     value = draw(one_of(none(), binary()))
     expl = None
     if do_expl:
     value = draw(one_of(none(), binary()))
     expl = None
     if do_expl:
@@ -3208,7 +3232,7 @@ class TestAny(CommonMixin, TestCase):
                 expl_initial,
                 optional_initial,
                 _decoded_initial,
                 expl_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(any_values_strat())
+            ) = d.draw(any_values_strategy())
             obj_initial = klass(
                 value_initial,
                 expl_initial,
             obj_initial = klass(
                 value_initial,
                 expl_initial,
@@ -3220,7 +3244,7 @@ class TestAny(CommonMixin, TestCase):
                 expl,
                 optional,
                 _decoded,
                 expl,
                 optional,
                 _decoded,
-            ) = d.draw(any_values_strat(do_expl=True))
+            ) = d.draw(any_values_strategy(do_expl=True))
             obj = obj_initial(value, expl, optional)
             if obj.ready:
                 value_expected = None if value is None else value
             obj = obj_initial(value, expl, optional)
             if obj.ready:
                 value_expected = None if value is None else value
@@ -3239,7 +3263,7 @@ class TestAny(CommonMixin, TestCase):
         # override it, as Any does not have implicit tag
         pass
 
         # override it, as Any does not have implicit tag
         pass
 
-    @given(any_values_strat())
+    @given(any_values_strategy())
     def test_copy(self, values):
         for klass in (Any, AnyInherited):
             obj = klass(*values)
     def test_copy(self, values):
         for klass in (Any, AnyInherited):
             obj = klass(*values)
@@ -3298,7 +3322,7 @@ class TestAny(CommonMixin, TestCase):
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
-        any_values_strat(),
+        any_values_strategy(),
         integers().map(lambda x: Integer(x).encode()),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         integers().map(lambda x: Integer(x).encode()),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
@@ -3343,7 +3367,7 @@ class TestAny(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def choice_values_strat(draw, value_required=False, schema=None, do_expl=False):
+def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
     if schema is None:
         names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
         tags = [tag_encode(tag) for tag in draw(sets(
     if schema is None:
         names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
         tags = [tag_encode(tag) for tag in draw(sets(
@@ -3451,7 +3475,7 @@ class TestChoice(CommonMixin, TestCase):
                 default_initial,
                 optional_initial,
                 _decoded_initial,
                 default_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(choice_values_strat())
+            ) = d.draw(choice_values_strategy())
 
             class Wahl(klass):
                 schema = schema_initial
 
             class Wahl(klass):
                 schema = schema_initial
@@ -3469,7 +3493,7 @@ class TestChoice(CommonMixin, TestCase):
                 default,
                 optional,
                 _decoded,
                 default,
                 optional,
                 _decoded,
-            ) = d.draw(choice_values_strat(schema=schema_initial, do_expl=True))
+            ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
             obj = obj_initial(value, expl, default, optional)
             if obj.ready:
                 value_expected = default if value is None else value
             obj = obj_initial(value, expl, default, optional)
             if obj.ready:
                 value_expected = default if value is None else value
@@ -3500,7 +3524,7 @@ class TestChoice(CommonMixin, TestCase):
         # override it, as Any does not have implicit tag
         pass
 
         # override it, as Any does not have implicit tag
         pass
 
-    @given(choice_values_strat())
+    @given(choice_values_strategy())
     def test_copy(self, values):
         _schema, value, expl, default, optional, _decoded = values
 
     def test_copy(self, values):
         _schema, value, expl, default, optional, _decoded = values
 
@@ -3542,7 +3566,7 @@ class TestChoice(CommonMixin, TestCase):
     @given(data_strategy())
     def test_symmetric(self, d):
         _schema, value, _, default, optional, _decoded = d.draw(
     @given(data_strategy())
     def test_symmetric(self, d):
         _schema, value, _, default, optional, _decoded = d.draw(
-            choice_values_strat(value_required=True)
+            choice_values_strategy(value_required=True)
         )
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         )
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
@@ -3629,7 +3653,7 @@ class TestChoice(CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def seq_values_strat(draw, seq_klass, do_expl=False):
+def seq_values_strategy(draw, seq_klass, do_expl=False):
     value = None
     if draw(booleans()):
         value = seq_klass()
     value = None
     if draw(booleans()):
         value = seq_klass()
@@ -3679,7 +3703,7 @@ def seq_values_strat(draw, seq_klass, do_expl=False):
 
 
 @composite
 
 
 @composite
-def sequence_strat(draw, seq_klass):
+def sequence_strategy(draw, seq_klass):
     inputs = draw(lists(
         one_of(
             tuples(just(Boolean), booleans(), one_of(none(), booleans())),
     inputs = draw(lists(
         one_of(
             tuples(just(Boolean), booleans(), one_of(none(), booleans())),
@@ -3748,7 +3772,7 @@ def sequence_strat(draw, seq_klass):
 
 
 @composite
 
 
 @composite
-def sequences_strat(draw, seq_klass):
+def sequences_strategy(draw, seq_klass):
     tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
     inits = [
         ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
     tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
     inits = [
         ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
@@ -3771,7 +3795,7 @@ def sequences_strat(draw, seq_klass):
         max_size=len(tags),
     )))
     seq_expectses = draw(lists(
         max_size=len(tags),
     )))
     seq_expectses = draw(lists(
-        sequence_strat(seq_klass=seq_klass),
+        sequence_strategy(seq_klass=seq_klass),
         min_size=len(tags),
         max_size=len(tags),
     ))
         min_size=len(tags),
         max_size=len(tags),
     ))
@@ -3876,7 +3900,7 @@ class SeqMixing(object):
                 default_initial,
                 optional_initial,
                 _decoded_initial,
                 default_initial,
                 optional_initial,
                 _decoded_initial,
-            ) = d.draw(seq_values_strat(seq_klass=klass))
+            ) = d.draw(seq_values_strategy(seq_klass=klass))
             obj_initial = klass(
                 value_initial,
                 schema_initial,
             obj_initial = klass(
                 value_initial,
                 schema_initial,
@@ -3894,7 +3918,7 @@ class SeqMixing(object):
                 default,
                 optional,
                 _decoded,
                 default,
                 optional,
                 _decoded,
-            ) = d.draw(seq_values_strat(
+            ) = d.draw(seq_values_strategy(
                 seq_klass=klass,
                 do_expl=impl_initial is None,
             ))
                 seq_klass=klass,
                 do_expl=impl_initial is None,
             ))
@@ -3924,7 +3948,7 @@ class SeqMixing(object):
         class SeqInherited(self.base_klass):
             pass
         for klass in (self.base_klass, SeqInherited):
         class SeqInherited(self.base_klass):
             pass
         for klass in (self.base_klass, SeqInherited):
-            values = d.draw(seq_values_strat(seq_klass=klass))
+            values = d.draw(seq_values_strategy(seq_klass=klass))
             obj = klass(*values)
             obj_copied = obj.copy()
             self.assert_copied_basic_fields(obj, obj_copied)
             obj = klass(*values)
             obj_copied = obj.copy()
             self.assert_copied_basic_fields(obj, obj_copied)
@@ -4032,7 +4056,7 @@ class SeqMixing(object):
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(data_strategy())
     def test_symmetric(self, d):
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(data_strategy())
     def test_symmetric(self, d):
-        seq, expects = d.draw(sequence_strat(seq_klass=self.base_klass))
+        seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
         self.assertTrue(seq.ready)
         self.assertFalse(seq.decoded)
         self._assert_expects(seq, expects)
         self.assertTrue(seq.ready)
         self.assertFalse(seq.decoded)
         self._assert_expects(seq, expects)
@@ -4062,7 +4086,7 @@ class SeqMixing(object):
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(data_strategy())
     def test_symmetric_with_seq(self, d):
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(data_strategy())
     def test_symmetric_with_seq(self, d):
-        seq, expect_outers = d.draw(sequences_strat(seq_klass=self.base_klass))
+        seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
         self.assertTrue(seq.ready)
         seq_encoded = seq.encode()
         seq_decoded, tail = seq.decode(seq_encoded)
         self.assertTrue(seq.ready)
         seq_encoded = seq.encode()
         seq_decoded, tail = seq.decode(seq_encoded)
@@ -4229,7 +4253,7 @@ class TestSet(SeqMixing, CommonMixin, TestCase):
 
 
 @composite
 
 
 @composite
-def seqof_values_strat(draw, schema=None, do_expl=False):
+def seqof_values_strategy(draw, schema=None, do_expl=False):
     if schema is None:
         schema = draw(sampled_from((Boolean(), Integer())))
     bound_min, bound_max = sorted(draw(sets(
     if schema is None:
         schema = draw(sampled_from((Boolean(), Integer())))
     bound_min, bound_max = sorted(draw(sets(
@@ -4404,7 +4428,7 @@ class SeqOfMixing(object):
             default_initial,
             optional_initial,
             _decoded_initial,
             default_initial,
             optional_initial,
             _decoded_initial,
-        ) = d.draw(seqof_values_strat())
+        ) = d.draw(seqof_values_strategy())
 
         class SeqOf(self.base_klass):
             schema = schema_initial
 
         class SeqOf(self.base_klass):
             schema = schema_initial
@@ -4426,7 +4450,7 @@ class SeqOfMixing(object):
             default,
             optional,
             _decoded,
             default,
             optional,
             _decoded,
-        ) = d.draw(seqof_values_strat(
+        ) = d.draw(seqof_values_strategy(
             schema=schema_initial,
             do_expl=impl_initial is None,
         ))
             schema=schema_initial,
             do_expl=impl_initial is None,
         ))
@@ -4479,7 +4503,7 @@ class SeqOfMixing(object):
             bounds or bounds_initial or (0, float("+inf")),
         )
 
             bounds or bounds_initial or (0, float("+inf")),
         )
 
-    @given(seqof_values_strat())
+    @given(seqof_values_strategy())
     def test_copy(self, values):
         _schema, value, bounds, impl, expl, default, optional, _decoded = values
 
     def test_copy(self, values):
         _schema, value, bounds, impl, expl, default, optional, _decoded = values
 
@@ -4564,7 +4588,7 @@ class SeqOfMixing(object):
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
 
     @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
     @given(
-        seqof_values_strat(schema=Integer()),
+        seqof_values_strategy(schema=Integer()),
         lists(integers().map(Integer)),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
         lists(integers().map(Integer)),
         integers(min_value=1).map(tag_ctxc),
         integers(min_value=0),
@@ -4861,3 +4885,253 @@ class TestAutoAddSlots(TestCase):
         with self.assertRaises(AttributeError):
             inher = Inher()
             inher.unexistent = "whatever"
         with self.assertRaises(AttributeError):
             inher = Inher()
             inher.unexistent = "whatever"
+
+
+class TestOIDDefines(TestCase):
+    @given(data_strategy())
+    def runTest(self, d):
+        value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
+        value_name_chosen = d.draw(sampled_from(value_names))
+        oids = [
+            ObjectIdentifier(oid)
+            for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
+        ]
+        oid_chosen = d.draw(sampled_from(oids))
+        values = d.draw(lists(
+            integers(),
+            min_size=len(value_names),
+            max_size=len(value_names),
+        ))
+        _schema = [
+            ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
+                oid: Integer() for oid in oids[:-1]
+            }),))),
+        ]
+        for i, value_name in enumerate(value_names):
+            _schema.append((value_name, Any(expl=tag_ctxp(i))))
+
+        class Seq(Sequence):
+            schema = _schema
+        seq = Seq()
+        for value_name, value in zip(value_names, values):
+            seq[value_name] = Any(Integer(value).encode())
+        seq["type"] = oid_chosen
+        seq, _ = Seq().decode(seq.encode())
+        for value_name in value_names:
+            if value_name == value_name_chosen:
+                continue
+            self.assertIsNone(seq[value_name].defined)
+        if value_name_chosen in oids[:-1]:
+            self.assertIsNotNone(seq[value_name_chosen].defined)
+            self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
+            self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
+
+
+class TestDefinesByPath(TestCase):
+    def test_generated(self):
+        class Seq(Sequence):
+            schema = (
+                ("type", ObjectIdentifier()),
+                ("value", OctetString(expl=tag_ctxc(123))),
+            )
+
+        class SeqInner(Sequence):
+            schema = (
+                ("typeInner", ObjectIdentifier()),
+                ("valueInner", Any()),
+            )
+
+        class PairValue(SetOf):
+            schema = Any()
+
+        class Pair(Sequence):
+            schema = (
+                ("type", ObjectIdentifier()),
+                ("value", PairValue()),
+            )
+
+        class Pairs(SequenceOf):
+            schema = Pair()
+
+        (
+            type_integered,
+            type_sequenced,
+            type_innered,
+            type_octet_stringed,
+        ) = [
+            ObjectIdentifier(oid)
+            for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
+        ]
+        seq_integered = Seq()
+        seq_integered["type"] = type_integered
+        seq_integered["value"] = OctetString(Integer(123).encode())
+        seq_integered_raw = seq_integered.encode()
+
+        pairs = Pairs()
+        pairs_input = (
+            (type_octet_stringed, OctetString(b"whatever")),
+            (type_integered, Integer(123)),
+            (type_octet_stringed, OctetString(b"whenever")),
+            (type_integered, Integer(234)),
+        )
+        for t, v in pairs_input:
+            pair = Pair()
+            pair["type"] = t
+            pair["value"] = PairValue((Any(v),))
+            pairs.append(pair)
+        seq_inner = SeqInner()
+        seq_inner["typeInner"] = type_innered
+        seq_inner["valueInner"] = Any(pairs)
+        seq_sequenced = Seq()
+        seq_sequenced["type"] = type_sequenced
+        seq_sequenced["value"] = OctetString(seq_inner.encode())
+        seq_sequenced_raw = seq_sequenced.encode()
+
+        defines_by_path = []
+        seq_integered, _ = Seq().decode(seq_integered_raw)
+        self.assertIsNone(seq_integered["value"].defined)
+        defines_by_path.append(
+            (("type",), ((("value",), {
+                type_integered: Integer(),
+                type_sequenced: SeqInner(),
+            }),))
+        )
+        seq_integered, _ = Seq().decode(
+            seq_integered_raw,
+            ctx={"defines_by_path": defines_by_path},
+        )
+        self.assertIsNotNone(seq_integered["value"].defined)
+        self.assertEqual(seq_integered["value"].defined[0], type_integered)
+        self.assertEqual(seq_integered["value"].defined[1], Integer(123))
+
+        seq_sequenced, _ = Seq().decode(
+            seq_sequenced_raw,
+            ctx={"defines_by_path": defines_by_path},
+        )
+        self.assertIsNotNone(seq_sequenced["value"].defined)
+        self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
+        seq_inner = seq_sequenced["value"].defined[1]
+        self.assertIsNone(seq_inner["valueInner"].defined)
+
+        defines_by_path.append((
+            ("value", decode_path_defby(type_sequenced), "typeInner"),
+            ((("valueInner",), {type_innered: Pairs()}),),
+        ))
+        seq_sequenced, _ = Seq().decode(
+            seq_sequenced_raw,
+            ctx={"defines_by_path": defines_by_path},
+        )
+        self.assertIsNotNone(seq_sequenced["value"].defined)
+        self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
+        seq_inner = seq_sequenced["value"].defined[1]
+        self.assertIsNotNone(seq_inner["valueInner"].defined)
+        self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
+        pairs = seq_inner["valueInner"].defined[1]
+        for pair in pairs:
+            self.assertIsNone(pair["value"][0].defined)
+
+        defines_by_path.append((
+            (
+                "value",
+                decode_path_defby(type_sequenced),
+                "valueInner",
+                decode_path_defby(type_innered),
+                any,
+                "type",
+            ),
+            ((("value",), {
+                type_integered: Integer(),
+                type_octet_stringed: OctetString(),
+            }),),
+        ))
+        seq_sequenced, _ = Seq().decode(
+            seq_sequenced_raw,
+            ctx={"defines_by_path": defines_by_path},
+        )
+        self.assertIsNotNone(seq_sequenced["value"].defined)
+        self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
+        seq_inner = seq_sequenced["value"].defined[1]
+        self.assertIsNotNone(seq_inner["valueInner"].defined)
+        self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
+        pairs_got = seq_inner["valueInner"].defined[1]
+        for pair_input, pair_got in zip(pairs_input, pairs_got):
+            self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
+            self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
+
+    @given(oid_strategy(), integers())
+    def test_simple(self, oid, tgt):
+        class Inner(Sequence):
+            schema = (
+                ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
+                    ObjectIdentifier(oid): Integer(),
+                }),))),
+            )
+
+        class Outer(Sequence):
+            schema = (
+                ("inner", Inner()),
+                ("tgt", OctetString()),
+            )
+
+        inner = Inner()
+        inner["oid"] = ObjectIdentifier(oid)
+        outer = Outer()
+        outer["inner"] = inner
+        outer["tgt"] = OctetString(Integer(tgt).encode())
+        decoded, _ = Outer().decode(outer.encode())
+        self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
+
+class TestAbsDecodePath(TestCase):
+    @given(
+        lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
+        lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
+    )
+    def test_concat(self, decode_path, rel_path):
+        self.assertSequenceEqual(
+            abs_decode_path(decode_path, rel_path),
+            decode_path + rel_path,
+        )
+
+    @given(
+        lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
+        lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
+    )
+    def test_abs(self, decode_path, rel_path):
+        self.assertSequenceEqual(
+            abs_decode_path(decode_path, ("/",) + rel_path),
+            rel_path,
+        )
+
+    @given(
+        lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
+        integers(min_value=1, max_value=3),
+        lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
+    )
+    def test_dots(self, decode_path, number_of_dots, rel_path):
+        self.assertSequenceEqual(
+            abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
+            decode_path[:-number_of_dots] + rel_path,
+        )
+
+
+class TestStrictDefaultExistence(TestCase):
+    @given(data_strategy())
+    def runTest(self, d):
+        count = d.draw(integers(min_value=1, max_value=10))
+        chosen = d.draw(integers(min_value=0, max_value=count - 1))
+        _schema = [
+            ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
+            for i in range(count)
+        ]
+
+        class Seq(Sequence):
+            schema = _schema
+        seq = Seq()
+        for i in range(count):
+            seq["int%d" % i] = Integer(123)
+        raw = seq.encode()
+        chosen = "int%d" % chosen
+        seq.specs[chosen] = seq.specs[chosen](default=123)
+        seq.decode(raw)
+        with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
+            seq.decode(raw, ctx={"strict_default_existence": True})