]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - tests/test_pyderasn.py
Strict default values existence validation option
[pyderasn.git] / tests / test_pyderasn.py
index 2fa22ab34daa594c3799b2ad12580ae124e86bd6..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
@@ -292,7 +295,6 @@ class CommonMixin(object):
     @given(binary())
     def test_impl_inherited(self, impl_tag):
         class Inherited(self.base_klass):
     @given(binary())
     def test_impl_inherited(self, impl_tag):
         class Inherited(self.base_klass):
-            __slots__ = ()
             impl = impl_tag
         obj = Inherited()
         self.assertSequenceEqual(obj.impl, impl_tag)
             impl = impl_tag
         obj = Inherited()
         self.assertSequenceEqual(obj.impl, impl_tag)
@@ -301,7 +303,6 @@ class CommonMixin(object):
     @given(binary())
     def test_expl_inherited(self, expl_tag):
         class Inherited(self.base_klass):
     @given(binary())
     def test_expl_inherited(self, expl_tag):
         class Inherited(self.base_klass):
-            __slots__ = ()
             expl = expl_tag
         obj = Inherited()
         self.assertSequenceEqual(obj.expl, expl_tag)
             expl = expl_tag
         obj = Inherited()
         self.assertSequenceEqual(obj.expl, expl_tag)
@@ -319,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
@@ -338,7 +339,7 @@ def boolean_values_strat(draw, do_expl=False):
 
 
 class BooleanInherited(Boolean):
 
 
 class BooleanInherited(Boolean):
-    __slots__ = ()
+    pass
 
 
 class TestBoolean(CommonMixin, TestCase):
 
 
 class TestBoolean(CommonMixin, TestCase):
@@ -374,10 +375,12 @@ class TestBoolean(CommonMixin, TestCase):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == bool(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             self.assertEqual(obj1 == bool(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(data_strategy())
     def test_call(self, d):
 
     @given(data_strategy())
     def test_call(self, d):
@@ -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,
@@ -626,7 +629,7 @@ def integer_values_strat(draw, do_expl=False):
 
 
 class IntegerInherited(Integer):
 
 
 class IntegerInherited(Integer):
-    __slots__ = ()
+    pass
 
 
 class TestInteger(CommonMixin, TestCase):
 
 
 class TestInteger(CommonMixin, TestCase):
@@ -642,7 +645,6 @@ class TestInteger(CommonMixin, TestCase):
         missing = names_input.pop()
 
         class Int(Integer):
         missing = names_input.pop()
 
         class Int(Integer):
-            __slots__ = ()
             schema = [(n, 123) for n in names_input]
         with self.assertRaises(ObjUnknown) as err:
             Int(missing)
             schema = [(n, 123) for n in names_input]
         with self.assertRaises(ObjUnknown) as err:
             Int(missing)
@@ -651,7 +653,6 @@ class TestInteger(CommonMixin, TestCase):
     @given(sets(text_letters(), min_size=2))
     def test_known_name(self, names_input):
         class Int(Integer):
     @given(sets(text_letters(), min_size=2))
     def test_known_name(self, names_input):
         class Int(Integer):
-            __slots__ = ()
             schema = [(n, 123) for n in names_input]
         Int(names_input.pop())
 
             schema = [(n, 123) for n in names_input]
         Int(names_input.pop())
 
@@ -681,10 +682,12 @@ class TestInteger(CommonMixin, TestCase):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == int(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             self.assertEqual(obj1 == int(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(lists(integers()))
     def test_sorted_works(self, values):
 
     @given(lists(integers()))
     def test_sorted_works(self, values):
@@ -705,7 +708,6 @@ class TestInteger(CommonMixin, TestCase):
         names_input = dict(zip(names_input, values_input))
 
         class Int(Integer):
         names_input = dict(zip(names_input, values_input))
 
         class Int(Integer):
-            __slots__ = ()
             schema = names_input
         _int = Int(chosen_name)
         self.assertEqual(_int.named, chosen_name)
             schema = names_input
         _int = Int(chosen_name)
         self.assertEqual(_int.named, chosen_name)
@@ -739,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,
@@ -759,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 (
@@ -805,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)
@@ -898,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),
@@ -983,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()):
@@ -1029,7 +1031,7 @@ def bit_string_values_strat(draw, schema=None, value_required=False, do_expl=Fal
 
 
 class BitStringInherited(BitString):
 
 
 class BitStringInherited(BitString):
-    __slots__ = ()
+    pass
 
 
 class TestBitString(CommonMixin, TestCase):
 
 
 class TestBitString(CommonMixin, TestCase):
@@ -1063,7 +1065,6 @@ class TestBitString(CommonMixin, TestCase):
         self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
 
         class BS(BitString):
         self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
 
         class BS(BitString):
-            __slots__ = ()
             schema = (("whatever", 0),)
         obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
         self.assertEqual(obj.bit_len, leading_zeros + 1)
             schema = (("whatever", 0),)
         obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
         self.assertEqual(obj.bit_len, leading_zeros + 1)
@@ -1089,7 +1090,7 @@ class TestBitString(CommonMixin, TestCase):
             BitString(b"whatever")["whenever"]
         repr(err.exception)
 
             BitString(b"whatever")["whenever"]
         repr(err.exception)
 
-    def test_get_invalid_typ(self):
+    def test_get_invalid_type(self):
         with self.assertRaises(InvalidValueType) as err:
             BitString(b"whatever")[(1, 2, 3)]
         repr(err.exception)
         with self.assertRaises(InvalidValueType) as err:
             BitString(b"whatever")[(1, 2, 3)]
         repr(err.exception)
@@ -1100,7 +1101,6 @@ class TestBitString(CommonMixin, TestCase):
         missing = _schema.pop()
 
         class BS(BitString):
         missing = _schema.pop()
 
         class BS(BitString):
-            __slots__ = ()
             schema = [(n, i) for i, n in enumerate(_schema)]
         with self.assertRaises(ObjUnknown) as err:
             BS((missing,))
             schema = [(n, i) for i, n in enumerate(_schema)]
         with self.assertRaises(ObjUnknown) as err:
             BS((missing,))
@@ -1136,10 +1136,12 @@ class TestBitString(CommonMixin, TestCase):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(data_strategy())
     def test_call(self, d):
 
     @given(data_strategy())
     def test_call(self, d):
@@ -1152,10 +1154,9 @@ 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):
 
             class BS(klass):
-                __slots__ = ()
                 schema = schema_initial
             obj_initial = BS(
                 value=value_initial,
                 schema = schema_initial
             obj_initial = BS(
                 value=value_initial,
@@ -1173,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,
             ))
@@ -1194,13 +1195,12 @@ 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
 
             class BS(klass):
     def test_copy(self, values):
         for klass in (BitString, BitStringInherited):
             _schema, value, impl, expl, default, optional, _decoded = values
 
             class BS(klass):
-                __slots__ = ()
                 schema = _schema
             obj = BS(
                 value=value,
                 schema = _schema
             obj = BS(
                 value=value,
@@ -1278,12 +1278,11 @@ 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):
             class BS(klass):
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
         for klass in (BitString, BitStringInherited):
             class BS(klass):
-                __slots__ = ()
                 schema = _schema
             obj = BS(
                 value=value,
                 schema = _schema
             obj = BS(
                 value=value,
@@ -1375,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,
@@ -1408,7 +1407,7 @@ def octet_string_values_strat(draw, do_expl=False):
 
 
 class OctetStringInherited(OctetString):
 
 
 class OctetStringInherited(OctetString):
-    __slots__ = ()
+    pass
 
 
 class TestOctetString(CommonMixin, TestCase):
 
 
 class TestOctetString(CommonMixin, TestCase):
@@ -1444,10 +1443,19 @@ class TestOctetString(CommonMixin, TestCase):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == bytes(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             self.assertEqual(obj1 == bytes(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
+
+    @given(lists(binary()))
+    def test_sorted_works(self, values):
+        self.assertSequenceEqual(
+            [bytes(v) for v in sorted(OctetString(v) for v in values)],
+            sorted(values),
+        )
 
     @given(data_strategy())
     def test_bounds_satisfied(self, d):
 
     @given(data_strategy())
     def test_bounds_satisfied(self, d):
@@ -1480,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,
@@ -1498,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 (
@@ -1540,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)
@@ -1625,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),
@@ -1673,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:
@@ -1690,7 +1698,7 @@ def null_values_strat(draw, do_expl=False):
 
 
 class NullInherited(Null):
 
 
 class NullInherited(Null):
-    __slots__ = ()
+    pass
 
 
 class TestNull(CommonMixin, TestCase):
 
 
 class TestNull(CommonMixin, TestCase):
@@ -1708,6 +1716,7 @@ class TestNull(CommonMixin, TestCase):
             obj1 = klass(impl=tag1)
             obj2 = klass(impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             obj1 = klass(impl=tag1)
             obj2 = klass(impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
             self.assertNotEqual(obj1, tag2)
 
     @given(data_strategy())
             self.assertNotEqual(obj1, tag2)
 
     @given(data_strategy())
@@ -1718,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,
@@ -1730,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)
@@ -1738,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
@@ -1804,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),
     )
@@ -1864,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
@@ -1883,7 +1892,7 @@ def oid_values_strat(draw, do_expl=False):
 
 
 class ObjectIdentifierInherited(ObjectIdentifier):
 
 
 class ObjectIdentifierInherited(ObjectIdentifier):
-    __slots__ = ()
+    pass
 
 
 class TestObjectIdentifier(CommonMixin, TestCase):
 
 
 class TestObjectIdentifier(CommonMixin, TestCase):
@@ -1920,11 +1929,13 @@ class TestObjectIdentifier(CommonMixin, TestCase):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == tuple(obj2), value1 == value2)
             self.assertEqual(str(obj1) == str(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             self.assertEqual(obj1 == tuple(obj2), value1 == value2)
             self.assertEqual(str(obj1) == str(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(lists(oid_strategy()))
     def test_sorted_works(self, values):
 
     @given(lists(oid_strategy()))
     def test_sorted_works(self, values):
@@ -1943,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,
@@ -1959,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 = (
@@ -1981,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)
@@ -2100,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),
@@ -2184,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(
@@ -2212,7 +2244,6 @@ def enumerated_values_strat(draw, schema=None, do_expl=False):
 
 class TestEnumerated(CommonMixin, TestCase):
     class EWhatever(Enumerated):
 
 class TestEnumerated(CommonMixin, TestCase):
     class EWhatever(Enumerated):
-        __slots__ = ()
         schema = (("whatever", 0),)
 
     base_klass = EWhatever
         schema = (("whatever", 0),)
 
     base_klass = EWhatever
@@ -2231,7 +2262,6 @@ class TestEnumerated(CommonMixin, TestCase):
         missing = schema_input.pop()
 
         class E(Enumerated):
         missing = schema_input.pop()
 
         class E(Enumerated):
-            __slots__ = ()
             schema = [(n, 123) for n in schema_input]
         with self.assertRaises(ObjUnknown) as err:
             E(missing)
             schema = [(n, 123) for n in schema_input]
         with self.assertRaises(ObjUnknown) as err:
             E(missing)
@@ -2247,7 +2277,6 @@ class TestEnumerated(CommonMixin, TestCase):
         _input = list(zip(schema_input, values_input))
 
         class E(Enumerated):
         _input = list(zip(schema_input, values_input))
 
         class E(Enumerated):
-            __slots__ = ()
             schema = _input
         with self.assertRaises(DecodeError) as err:
             E(missing_value)
             schema = _input
         with self.assertRaises(DecodeError) as err:
             E(missing_value)
@@ -2274,22 +2303,23 @@ class TestEnumerated(CommonMixin, TestCase):
     @given(integers(), integers(), binary(), binary())
     def test_comparison(self, value1, value2, tag1, tag2):
         class E(Enumerated):
     @given(integers(), integers(), binary(), binary())
     def test_comparison(self, value1, value2, tag1, tag2):
         class E(Enumerated):
-            __slots__ = ()
             schema = (
                 ("whatever0", value1),
                 ("whatever1", value2),
             )
 
         class EInherited(E):
             schema = (
                 ("whatever0", value1),
                 ("whatever1", value2),
             )
 
         class EInherited(E):
-            __slots__ = ()
+            pass
         for klass in (E, EInherited):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
         for klass in (E, EInherited):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == int(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
             self.assertEqual(obj1 == int(obj2), value1 == value2)
             obj1 = klass(value1, impl=tag1)
             obj2 = klass(value1, impl=tag2)
             self.assertEqual(obj1 == obj2, tag1 == tag2)
+            self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(data_strategy())
     def test_call(self, d):
 
     @given(data_strategy())
     def test_call(self, d):
@@ -2301,10 +2331,9 @@ 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):
 
         class E(Enumerated):
-            __slots__ = ()
             schema = schema_initial
         obj_initial = E(
             value=value_initial,
             schema = schema_initial
         obj_initial = E(
             value=value_initial,
@@ -2322,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,
         ))
@@ -2357,12 +2386,11 @@ 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
 
         class E(Enumerated):
     def test_copy(self, values):
         schema_input, value, impl, expl, default, optional, _decoded = values
 
         class E(Enumerated):
-            __slots__ = ()
             schema = schema_input
         obj = E(
             value=value,
             schema = schema_input
         obj = E(
             value=value,
@@ -2380,14 +2408,13 @@ 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))
         value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
 
         class E(Enumerated):
         )
         tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
         offset = d.draw(integers(min_value=0))
         value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
 
         class E(Enumerated):
-            __slots__ = ()
             schema = schema_input
         obj = E(
             value=value,
             schema = schema_input
         obj = E(
             value=value,
@@ -2429,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,
@@ -2503,11 +2530,13 @@ class StringMixin(object):
         obj1 = self.base_klass(value1)
         obj2 = self.base_klass(value2)
         self.assertEqual(obj1 == obj2, value1 == value2)
         obj1 = self.base_klass(value1)
         obj2 = self.base_klass(value2)
         self.assertEqual(obj1 == obj2, value1 == value2)
+        self.assertEqual(obj1 != obj2, value1 != value2)
         self.assertEqual(obj1 == bytes(obj2), value1 == value2)
         self.assertEqual(obj1 == text_type(obj2), value1 == value2)
         obj1 = self.base_klass(value1, impl=tag1)
         obj2 = self.base_klass(value1, impl=tag2)
         self.assertEqual(obj1 == obj2, tag1 == tag2)
         self.assertEqual(obj1 == bytes(obj2), value1 == value2)
         self.assertEqual(obj1 == text_type(obj2), value1 == value2)
         obj1 = self.base_klass(value1, impl=tag1)
         obj2 = self.base_klass(value1, impl=tag2)
         self.assertEqual(obj1 == obj2, tag1 == tag2)
+        self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(data_strategy())
     def test_bounds_satisfied(self, d):
 
     @given(data_strategy())
     def test_bounds_satisfied(self, d):
@@ -2543,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,
@@ -2561,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,
         ))
@@ -2608,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)
@@ -2691,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))
@@ -2782,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,
@@ -2863,11 +2892,13 @@ class TimeMixin(object):
         obj1 = self.base_klass(value1)
         obj2 = self.base_klass(value2)
         self.assertEqual(obj1 == obj2, value1 == value2)
         obj1 = self.base_klass(value1)
         obj2 = self.base_klass(value2)
         self.assertEqual(obj1 == obj2, value1 == value2)
+        self.assertEqual(obj1 != obj2, value1 != value2)
         self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
         self.assertEqual(obj1 == bytes(obj2), value1 == value2)
         obj1 = self.base_klass(value1, impl=tag1)
         obj2 = self.base_klass(value1, impl=tag2)
         self.assertEqual(obj1 == obj2, tag1 == tag2)
         self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
         self.assertEqual(obj1 == bytes(obj2), value1 == value2)
         obj1 = self.base_klass(value1, impl=tag1)
         obj2 = self.base_klass(value1, impl=tag2)
         self.assertEqual(obj1 == obj2, tag1 == tag2)
+        self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(data_strategy())
     def test_call(self, d):
 
     @given(data_strategy())
     def test_call(self, d):
@@ -2878,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,
@@ -2898,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,
@@ -2933,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,
         ))
@@ -2967,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,
         ))
@@ -3122,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:
@@ -3137,7 +3168,7 @@ def any_values_strat(draw, do_expl=False):
 
 
 class AnyInherited(Any):
 
 
 class AnyInherited(Any):
-    __slots__ = ()
+    pass
 
 
 class TestAny(CommonMixin, TestCase):
 
 
 class TestAny(CommonMixin, TestCase):
@@ -3190,6 +3221,7 @@ class TestAny(CommonMixin, TestCase):
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
             obj1 = klass(value1)
             obj2 = klass(value2)
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == bytes(obj2), value1 == value2)
 
     @given(data_strategy())
             self.assertEqual(obj1 == bytes(obj2), value1 == value2)
 
     @given(data_strategy())
@@ -3200,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,
@@ -3212,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
@@ -3231,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)
@@ -3290,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),
@@ -3335,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(
@@ -3367,7 +3399,7 @@ def choice_values_strat(draw, value_required=False, schema=None, do_expl=False):
 
 
 class ChoiceInherited(Choice):
 
 
 class ChoiceInherited(Choice):
-    __slots__ = ()
+    pass
 
 
 class TestChoice(CommonMixin, TestCase):
 
 
 class TestChoice(CommonMixin, TestCase):
@@ -3424,11 +3456,12 @@ class TestChoice(CommonMixin, TestCase):
     @given(booleans(), booleans())
     def test_comparison(self, value1, value2):
         class WahlInherited(self.base_klass):
     @given(booleans(), booleans())
     def test_comparison(self, value1, value2):
         class WahlInherited(self.base_klass):
-            __slots__ = ()
+            pass
         for klass in (self.base_klass, WahlInherited):
             obj1 = klass(("whatever", Boolean(value1)))
             obj2 = klass(("whatever", Boolean(value2)))
             self.assertEqual(obj1 == obj2, value1 == value2)
         for klass in (self.base_klass, WahlInherited):
             obj1 = klass(("whatever", Boolean(value1)))
             obj2 = klass(("whatever", Boolean(value2)))
             self.assertEqual(obj1 == obj2, value1 == value2)
+            self.assertEqual(obj1 != obj2, value1 != value2)
             self.assertEqual(obj1 == obj2._value, value1 == value2)
             self.assertFalse(obj1 == obj2._value[1])
 
             self.assertEqual(obj1 == obj2._value, value1 == value2)
             self.assertFalse(obj1 == obj2._value[1])
 
@@ -3442,10 +3475,9 @@ 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):
 
             class Wahl(klass):
-                __slots__ = ()
                 schema = schema_initial
             obj_initial = Wahl(
                 value=value_initial,
                 schema = schema_initial
             obj_initial = Wahl(
                 value=value_initial,
@@ -3461,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
@@ -3492,12 +3524,11 @@ 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
 
         class Wahl(self.base_klass):
     def test_copy(self, values):
         _schema, value, expl, default, optional, _decoded = values
 
         class Wahl(self.base_klass):
-            __slots__ = ()
             schema = _schema
         obj = Wahl(
             value=value,
             schema = _schema
         obj = Wahl(
             value=value,
@@ -3535,13 +3566,12 @@ 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))
 
         class Wahl(self.base_klass):
         )
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
         offset = d.draw(integers(min_value=0))
 
         class Wahl(self.base_klass):
-            __slots__ = ()
             schema = _schema
         obj = Wahl(
             value=value,
             schema = _schema
         obj = Wahl(
             value=value,
@@ -3623,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()
@@ -3673,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())),
@@ -3714,7 +3744,7 @@ def sequence_strat(draw, seq_klass):
     for i, (klass, value, default) in enumerate(inputs):
         schema.append((names[i], klass(default=default, **inits[i])))
     seq_name = draw(text_letters())
     for i, (klass, value, default) in enumerate(inputs):
         schema.append((names[i], klass(default=default, **inits[i])))
     seq_name = draw(text_letters())
-    Seq = type(seq_name, (seq_klass,), {"__slots__": (), "schema": tuple(schema)})
+    Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
     seq = Seq()
     expects = []
     for i, (klass, value, default) in enumerate(inputs):
     seq = Seq()
     expects = []
     for i, (klass, value, default) in enumerate(inputs):
@@ -3742,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)})
@@ -3765,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),
     ))
@@ -3777,7 +3807,7 @@ def sequences_strat(draw, seq_klass):
             seq(default=(seq if i in defaulted else None), **inits[i]),
         ))
     seq_name = draw(text_letters())
             seq(default=(seq if i in defaulted else None), **inits[i]),
         ))
     seq_name = draw(text_letters())
-    Seq = type(seq_name, (seq_klass,), {"__slots__": (), "schema": tuple(schema)})
+    Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
     seq_outer = Seq()
     expect_outers = []
     for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
     seq_outer = Seq()
     expect_outers = []
     for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
@@ -3801,7 +3831,6 @@ class SeqMixing(object):
 
     def test_invalid_value_type_set(self):
         class Seq(self.base_klass):
 
     def test_invalid_value_type_set(self):
         class Seq(self.base_klass):
-            __slots__ = ()
             schema = (("whatever", Boolean()),)
         seq = Seq()
         with self.assertRaises(InvalidValueType) as err:
             schema = (("whatever", Boolean()),)
         seq = Seq()
         with self.assertRaises(InvalidValueType) as err:
@@ -3836,7 +3865,6 @@ class SeqMixing(object):
             schema_input.append((name, Boolean()))
 
         class Seq(self.base_klass):
             schema_input.append((name, Boolean()))
 
         class Seq(self.base_klass):
-            __slots__ = ()
             schema = tuple(schema_input)
         seq = Seq()
         for name in ready.keys():
             schema = tuple(schema_input)
         seq = Seq()
         for name in ready.keys():
@@ -3862,7 +3890,7 @@ class SeqMixing(object):
     @given(data_strategy())
     def test_call(self, d):
         class SeqInherited(self.base_klass):
     @given(data_strategy())
     def test_call(self, d):
         class SeqInherited(self.base_klass):
-            __slots__ = ()
+            pass
         for klass in (self.base_klass, SeqInherited):
             (
                 value_initial,
         for klass in (self.base_klass, SeqInherited):
             (
                 value_initial,
@@ -3872,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,
@@ -3890,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,
             ))
@@ -3918,9 +3946,9 @@ class SeqMixing(object):
     @given(data_strategy())
     def test_copy(self, d):
         class SeqInherited(self.base_klass):
     @given(data_strategy())
     def test_copy(self, d):
         class SeqInherited(self.base_klass):
-            __slots__ = ()
+            pass
         for klass in (self.base_klass, SeqInherited):
         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)
@@ -3933,7 +3961,6 @@ class SeqMixing(object):
         tag_impl = tag_encode(d.draw(integers(min_value=1)))
 
         class Seq(self.base_klass):
         tag_impl = tag_encode(d.draw(integers(min_value=1)))
 
         class Seq(self.base_klass):
-            __slots__ = ()
             impl = tag_impl
             schema = (("whatever", Integer()),)
         seq = Seq()
             impl = tag_impl
             schema = (("whatever", Integer()),)
         seq = Seq()
@@ -3947,7 +3974,6 @@ class SeqMixing(object):
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
 
         class Seq(self.base_klass):
         tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
 
         class Seq(self.base_klass):
-            __slots__ = ()
             expl = tag_expl
             schema = (("whatever", Integer()),)
         seq = Seq()
             expl = tag_expl
             schema = (("whatever", Integer()),)
         seq = Seq()
@@ -3966,7 +3992,6 @@ class SeqMixing(object):
             assume(False)
 
         class Seq(self.base_klass):
             assume(False)
 
         class Seq(self.base_klass):
-            __slots__ = ()
             schema = (
                 ("whatever", Integer()),
                 ("junk", Any()),
             schema = (
                 ("whatever", Integer()),
                 ("junk", Any()),
@@ -4031,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)
@@ -4061,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)
@@ -4093,7 +4118,6 @@ class SeqMixing(object):
         )).items())
 
         class Seq(self.base_klass):
         )).items())
 
         class Seq(self.base_klass):
-            __slots__ = ()
             schema = [
                 (n, Integer(default=d))
                 for n, (_, d) in _schema
             schema = [
                 (n, Integer(default=d))
                 for n, (_, d) in _schema
@@ -4123,7 +4147,6 @@ class SeqMixing(object):
         ))]
 
         class SeqWithoutDefault(self.base_klass):
         ))]
 
         class SeqWithoutDefault(self.base_klass):
-            __slots__ = ()
             schema = [
                 (n, Integer(impl=t))
                 for (n, _), t in zip(_schema, tags)
             schema = [
                 (n, Integer(impl=t))
                 for (n, _), t in zip(_schema, tags)
@@ -4134,7 +4157,6 @@ class SeqMixing(object):
         seq_encoded = seq_without_default.encode()
 
         class SeqWithDefault(self.base_klass):
         seq_encoded = seq_without_default.encode()
 
         class SeqWithDefault(self.base_klass):
-            __slots__ = ()
             schema = [
                 (n, Integer(default=v, impl=t))
                 for (n, v), t in zip(_schema, tags)
             schema = [
                 (n, Integer(default=v, impl=t))
                 for (n, v), t in zip(_schema, tags)
@@ -4156,7 +4178,6 @@ class SeqMixing(object):
         names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
 
         class SeqFull(self.base_klass):
         names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
 
         class SeqFull(self.base_klass):
-            __slots__ = ()
             schema = [(n, Integer(impl=t)) for n, t in names_tags]
         seq_full = SeqFull()
         for i, name in enumerate(names):
             schema = [(n, Integer(impl=t)) for n, t in names_tags]
         seq_full = SeqFull()
         for i, name in enumerate(names):
@@ -4165,7 +4186,6 @@ class SeqMixing(object):
         altered = names_tags[:-2] + names_tags[-1:]
 
         class SeqMissing(self.base_klass):
         altered = names_tags[:-2] + names_tags[-1:]
 
         class SeqMissing(self.base_klass):
-            __slots__ = ()
             schema = [(n, Integer(impl=t)) for n, t in altered]
         seq_missing = SeqMissing()
         with self.assertRaises(TagMismatch):
             schema = [(n, Integer(impl=t)) for n, t in altered]
         seq_missing = SeqMissing()
         with self.assertRaises(TagMismatch):
@@ -4181,7 +4201,6 @@ class TestSequence(SeqMixing, CommonMixin, TestCase):
     )
     def test_remaining(self, value, junk):
         class Seq(Sequence):
     )
     def test_remaining(self, value, junk):
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("whatever", Integer()),
             )
             schema = (
                 ("whatever", Integer()),
             )
@@ -4199,7 +4218,6 @@ class TestSequence(SeqMixing, CommonMixin, TestCase):
         missing = names.pop()
 
         class Seq(Sequence):
         missing = names.pop()
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = [(n, Boolean()) for n in names]
         seq = Seq()
         with self.assertRaises(ObjUnknown) as err:
             schema = [(n, Boolean()) for n in names]
         seq = Seq()
         with self.assertRaises(ObjUnknown) as err:
@@ -4222,7 +4240,6 @@ class TestSet(SeqMixing, CommonMixin, TestCase):
         ]
 
         class Seq(Set):
         ]
 
         class Seq(Set):
-            __slots__ = ()
             schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
         seq = Seq()
         for name, _ in Seq.schema:
             schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
         seq = Seq()
         for name, _ in Seq.schema:
@@ -4236,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(
@@ -4287,7 +4304,6 @@ class SeqOfMixing(object):
 
     def test_invalid_values_type(self):
         class SeqOf(self.base_klass):
 
     def test_invalid_values_type(self):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Integer()
         with self.assertRaises(InvalidValueType) as err:
             SeqOf([Integer(123), Boolean(False), Integer(234)])
             schema = Integer()
         with self.assertRaises(InvalidValueType) as err:
             SeqOf([Integer(123), Boolean(False), Integer(234)])
@@ -4300,21 +4316,21 @@ class SeqOfMixing(object):
     @given(booleans(), booleans(), binary(), binary())
     def test_comparison(self, value1, value2, tag1, tag2):
         class SeqOf(self.base_klass):
     @given(booleans(), booleans(), binary(), binary())
     def test_comparison(self, value1, value2, tag1, tag2):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Boolean()
         obj1 = SeqOf([Boolean(value1)])
         obj2 = SeqOf([Boolean(value2)])
         self.assertEqual(obj1 == obj2, value1 == value2)
             schema = Boolean()
         obj1 = SeqOf([Boolean(value1)])
         obj2 = SeqOf([Boolean(value2)])
         self.assertEqual(obj1 == obj2, value1 == value2)
+        self.assertEqual(obj1 != obj2, value1 != value2)
         self.assertEqual(obj1 == list(obj2), value1 == value2)
         self.assertEqual(obj1 == tuple(obj2), value1 == value2)
         obj1 = SeqOf([Boolean(value1)], impl=tag1)
         obj2 = SeqOf([Boolean(value1)], impl=tag2)
         self.assertEqual(obj1 == obj2, tag1 == tag2)
         self.assertEqual(obj1 == list(obj2), value1 == value2)
         self.assertEqual(obj1 == tuple(obj2), value1 == value2)
         obj1 = SeqOf([Boolean(value1)], impl=tag1)
         obj2 = SeqOf([Boolean(value1)], impl=tag2)
         self.assertEqual(obj1 == obj2, tag1 == tag2)
+        self.assertEqual(obj1 != obj2, tag1 != tag2)
 
     @given(lists(booleans()))
     def test_iter(self, values):
         class SeqOf(self.base_klass):
 
     @given(lists(booleans()))
     def test_iter(self, values):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Boolean()
         obj = SeqOf([Boolean(value) for value in values])
         self.assertEqual(len(obj), len(values))
             schema = Boolean()
         obj = SeqOf([Boolean(value) for value in values])
         self.assertEqual(len(obj), len(values))
@@ -4334,7 +4350,6 @@ class SeqOfMixing(object):
         ]
 
         class SeqOf(self.base_klass):
         ]
 
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Integer()
         values = d.draw(permutations(ready + non_ready))
         seqof = SeqOf()
             schema = Integer()
         values = d.draw(permutations(ready + non_ready))
         seqof = SeqOf()
@@ -4356,7 +4371,6 @@ class SeqOfMixing(object):
 
     def test_spec_mismatch(self):
         class SeqOf(self.base_klass):
 
     def test_spec_mismatch(self):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Integer()
         seqof = SeqOf()
         seqof.append(Integer(123))
             schema = Integer()
         seqof = SeqOf()
         seqof.append(Integer(123))
@@ -4368,7 +4382,6 @@ class SeqOfMixing(object):
     @given(data_strategy())
     def test_bounds_satisfied(self, d):
         class SeqOf(self.base_klass):
     @given(data_strategy())
     def test_bounds_satisfied(self, d):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Boolean()
         bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
         bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
             schema = Boolean()
         bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
         bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
@@ -4378,7 +4391,6 @@ class SeqOfMixing(object):
     @given(data_strategy())
     def test_bounds_unsatisfied(self, d):
         class SeqOf(self.base_klass):
     @given(data_strategy())
     def test_bounds_unsatisfied(self, d):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Boolean()
         bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
         bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
             schema = Boolean()
         bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
         bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
@@ -4397,7 +4409,6 @@ class SeqOfMixing(object):
     @given(integers(min_value=1, max_value=10))
     def test_out_of_bounds(self, bound_max):
         class SeqOf(self.base_klass):
     @given(integers(min_value=1, max_value=10))
     def test_out_of_bounds(self, bound_max):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Integer()
             bounds = (0, bound_max)
         seqof = SeqOf()
             schema = Integer()
             bounds = (0, bound_max)
         seqof = SeqOf()
@@ -4417,10 +4428,9 @@ 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):
 
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = schema_initial
         obj_initial = SeqOf(
             value=value_initial,
             schema = schema_initial
         obj_initial = SeqOf(
             value=value_initial,
@@ -4440,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,
         ))
@@ -4493,12 +4503,11 @@ 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
 
         class SeqOf(self.base_klass):
     def test_copy(self, values):
         _schema, value, bounds, impl, expl, default, optional, _decoded = values
 
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = _schema
         obj = SeqOf(
             value=value,
             schema = _schema
         obj = SeqOf(
             value=value,
@@ -4521,7 +4530,6 @@ class SeqOfMixing(object):
     )
     def test_stripped(self, values, tag_impl):
         class SeqOf(self.base_klass):
     )
     def test_stripped(self, values, tag_impl):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = OctetString()
         obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
         with self.assertRaises(NotEnoughData):
             schema = OctetString()
         obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
         with self.assertRaises(NotEnoughData):
@@ -4533,7 +4541,6 @@ class SeqOfMixing(object):
     )
     def test_stripped_expl(self, values, tag_expl):
         class SeqOf(self.base_klass):
     )
     def test_stripped_expl(self, values, tag_expl):
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = OctetString()
         obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
         with self.assertRaises(NotEnoughData):
             schema = OctetString()
         obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
         with self.assertRaises(NotEnoughData):
@@ -4581,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),
@@ -4590,7 +4597,6 @@ class SeqOfMixing(object):
         _, _, _, _, _, default, optional, _decoded = values
 
         class SeqOf(self.base_klass):
         _, _, _, _, _, default, optional, _decoded = values
 
         class SeqOf(self.base_klass):
-            __slots__ = ()
             schema = Integer()
         obj = SeqOf(
             value=value,
             schema = Integer()
         obj = SeqOf(
             value=value,
@@ -4639,7 +4645,6 @@ class SeqOfMixing(object):
 
 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
     class SeqOf(SequenceOf):
 
 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
     class SeqOf(SequenceOf):
-        __slots__ = ()
         schema = "whatever"
     base_klass = SeqOf
 
         schema = "whatever"
     base_klass = SeqOf
 
@@ -4650,7 +4655,6 @@ class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
 
 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
     class SeqOf(SetOf):
 
 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
     class SeqOf(SetOf):
-        __slots__ = ()
         schema = "whatever"
     base_klass = SeqOf
 
         schema = "whatever"
     base_klass = SeqOf
 
@@ -4666,7 +4670,6 @@ class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
         values = [OctetString(v) for v in d.draw(lists(binary()))]
 
         class Seq(SetOf):
         values = [OctetString(v) for v in d.draw(lists(binary()))]
 
         class Seq(SetOf):
-            __slots__ = ()
             schema = OctetString()
         seq = Seq(values)
         seq_encoded = seq.encode()
             schema = OctetString()
         seq = Seq(values)
         seq_encoded = seq.encode()
@@ -4686,7 +4689,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", Integer()),
                 ("zweite", Integer(optional=True))
             schema = (
                 ("erste", Integer()),
                 ("zweite", Integer(optional=True))
@@ -4701,7 +4703,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
 
         class NestedSeq(Sequence):
         self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
 
         class NestedSeq(Sequence):
-            __slots__ = ()
             schema = (
                 ("nest", Seq()),
             )
             schema = (
                 ("nest", Seq()),
             )
@@ -4717,7 +4718,6 @@ class TestGoMarshalVectors(TestCase):
         )
 
         class Seq(Sequence):
         )
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
             )
             schema = (
                 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
             )
@@ -4726,7 +4726,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", Integer(expl=tag_ctxc(5))),
             )
             schema = (
                 ("erste", Integer(expl=tag_ctxc(5))),
             )
@@ -4735,7 +4734,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", Null(
                     impl=tag_encode(0, klass=TagClassContext),
             schema = (
                 ("erste", Null(
                     impl=tag_encode(0, klass=TagClassContext),
@@ -4762,7 +4760,6 @@ class TestGoMarshalVectors(TestCase):
         )
 
         class Seq(Sequence):
         )
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", GeneralizedTime()),
             )
             schema = (
                 ("erste", GeneralizedTime()),
             )
@@ -4810,7 +4807,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", IA5String()),
             )
             schema = (
                 ("erste", IA5String()),
             )
@@ -4819,7 +4815,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", PrintableString()),
             )
             schema = (
                 ("erste", PrintableString()),
             )
@@ -4830,7 +4825,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", Any(optional=True)),
                 ("zweite", Integer()),
             schema = (
                 ("erste", Any(optional=True)),
                 ("zweite", Integer()),
@@ -4840,18 +4834,15 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
 
         class Seq(SetOf):
         self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
 
         class Seq(SetOf):
-            __slots__ = ()
             schema = Integer()
         seq = Seq()
         seq.append(Integer(10))
         self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
 
         class _SeqOf(SequenceOf):
             schema = Integer()
         seq = Seq()
         seq.append(Integer(10))
         self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
 
         class _SeqOf(SequenceOf):
-            __slots__ = ()
             schema = PrintableString()
 
         class SeqOf(SequenceOf):
             schema = PrintableString()
 
         class SeqOf(SequenceOf):
-            __slots__ = ()
             schema = _SeqOf()
         _seqof = _SeqOf()
         _seqof.append(PrintableString("1"))
             schema = _SeqOf()
         _seqof = _SeqOf()
         _seqof.append(PrintableString("1"))
@@ -4860,7 +4851,6 @@ class TestGoMarshalVectors(TestCase):
         self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
 
         class Seq(Sequence):
         self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
 
         class Seq(Sequence):
-            __slots__ = ()
             schema = (
                 ("erste", Integer(default=1)),
             )
             schema = (
                 ("erste", Integer(default=1)),
             )
@@ -4885,3 +4875,263 @@ class TestPP(TestCase):
         pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
         self.assertNotIn(chosen_id, pp_console_row(pp))
         self.assertIn(chosen_id, pp_console_row(pp, oids=oids))
         pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
         self.assertNotIn(chosen_id, pp_console_row(pp))
         self.assertIn(chosen_id, pp_console_row(pp, oids=oids))
+
+
+class TestAutoAddSlots(TestCase):
+    def runTest(self):
+        class Inher(Integer):
+            pass
+
+        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})