From 66afc8921e4f5d3a41e407ab6d95ce7e4ec5383a Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 25 Aug 2019 14:35:44 +0200 Subject: Add `isInconsistent` property hook to all constructed types (#170) Added `isInconsistent` property to all constructed types. This property conceptually replaces `verifySizeSpec` method to serve a more general purpose e.g. ensuring all required fields are in a good shape. By default this check invokes subtype constraints verification and is run by codecs on value de/serialisation. --- tests/type/test_univ.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'tests') diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index 0092588..4cbfa01 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -1040,22 +1040,14 @@ class SequenceOf(BaseTestCase): else: pass - def testSizeSpec(self): + def testConsistency(self): s = self.s1.clone(sizeSpec=constraint.ConstraintsUnion( constraint.ValueSizeConstraint(1, 1) )) s.setComponentByPosition(0, univ.OctetString('abc')) - try: - s.verifySizeSpec() - except PyAsn1Error: - assert 0, 'size spec fails' + assert not s.isInconsistent, 'size spec fails' s.setComponentByPosition(1, univ.OctetString('abc')) - try: - s.verifySizeSpec() - except PyAsn1Error: - pass - else: - assert 0, 'size spec fails' + assert s.isInconsistent, 'size spec fails' def testGetComponentTagMap(self): assert self.s1.componentType.tagMap.presentTypes == { -- cgit v1.2.3 From 41ce2e5cfeef488f847c3f58ff3d9d0fceb9ded7 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 25 Aug 2019 15:17:38 +0200 Subject: Deprecate `sizeSpec` in favor of `subtypeSpec` (#172) This commit deprecates `subtypeSpec` attributes and keyword argument. It is now recommended to pass `ValueSizeConstraint`, as well as all other constraints, to `subtypeSpec`. By way of the change mentioned above, this commit fixes a design bug in a way of how the items assigned to constructed types are verified. Now if `Asn1Type`-based object is assigned, its compatibility is verified based on having all tags and constraint objects as the type in field definition. When a bare Python value is assigned, then field type object is cloned and initialized with the bare value (constraints verificaton would run at this moment). --- tests/type/test_univ.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index 4cbfa01..d9f921b 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -992,11 +992,13 @@ class SequenceOf(BaseTestCase): assert self.s1 == self.s2, '__cmp__() fails' def testSubtypeSpec(self): - s = self.s1.clone(subtypeSpec=constraint.ConstraintsUnion( - constraint.SingleValueConstraint(str2octs('abc')) - )) + s = self.s1.clone( + componentType=univ.OctetString().subtype( + subtypeSpec=constraint.SingleValueConstraint(str2octs('abc')))) try: - s.setComponentByPosition(0, univ.OctetString('abc')) + s.setComponentByPosition( + 0, univ.OctetString().subtype( + 'abc', subtypeSpec=constraint.SingleValueConstraint(str2octs('abc')))) except PyAsn1Error: assert 0, 'constraint fails' try: @@ -1006,7 +1008,7 @@ class SequenceOf(BaseTestCase): s.setComponentByPosition(1, univ.OctetString('Abc'), verifyConstraints=False) except PyAsn1Error: - assert 0, 'constraint failes with verifyConstraints=True' + assert 0, 'constraint fails with verifyConstraints=False' else: assert 0, 'constraint fails' @@ -1041,7 +1043,7 @@ class SequenceOf(BaseTestCase): pass def testConsistency(self): - s = self.s1.clone(sizeSpec=constraint.ConstraintsUnion( + s = self.s1.clone(subtypeSpec=constraint.ConstraintsUnion( constraint.ValueSizeConstraint(1, 1) )) s.setComponentByPosition(0, univ.OctetString('abc')) @@ -1057,15 +1059,13 @@ class SequenceOf(BaseTestCase): def testSubtype(self): subtype = self.s1.subtype( implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2), - subtypeSpec=constraint.SingleValueConstraint(1, 3), - sizeSpec=constraint.ValueSizeConstraint(0, 1) + subtypeSpec=constraint.ValueSizeConstraint(0, 1) ) subtype.clear() clone = self.s1.clone( tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2)), - subtypeSpec=constraint.ConstraintsIntersection(constraint.SingleValueConstraint(1, 3)), - sizeSpec=constraint.ValueSizeConstraint(0, 1) + subtypeSpec=constraint.ValueSizeConstraint(0, 1) ) clone.clear() assert clone == subtype -- cgit v1.2.3 From 7214dcae11f58b0c480bd30170da3eb4734ca707 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 27 Aug 2019 11:10:10 +0300 Subject: Fix for Python 4 (#173) --- tests/codec/ber/test_decoder.py | 6 +++--- tests/codec/ber/test_encoder.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py index 089f0f3..e3b74df 100644 --- a/tests/codec/ber/test_decoder.py +++ b/tests/codec/ber/test_decoder.py @@ -486,17 +486,17 @@ class RealDecoderTestCase(BaseTestCase): if sys.version_info[0:2] > (2, 5): class UniversalStringDecoderTestCase(BaseTestCase): def testDecoder(self): - assert decoder.decode(ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString(sys.version_info[0] == 3 and 'abc' or unicode('abc')), null) + assert decoder.decode(ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) class BMPStringDecoderTestCase(BaseTestCase): def testDecoder(self): - assert decoder.decode(ints2octs((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString(sys.version_info[0] == 3 and 'abc' or unicode('abc')), null) + assert decoder.decode(ints2octs((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) class UTF8StringDecoderTestCase(BaseTestCase): def testDecoder(self): - assert decoder.decode(ints2octs((12, 3, 97, 98, 99))) == (char.UTF8String(sys.version_info[0] == 3 and 'abc' or unicode('abc')), null) + assert decoder.decode(ints2octs((12, 3, 97, 98, 99))) == (char.UTF8String(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) class SequenceOfDecoderTestCase(BaseTestCase): diff --git a/tests/codec/ber/test_encoder.py b/tests/codec/ber/test_encoder.py index 38d75c0..df82e7b 100644 --- a/tests/codec/ber/test_encoder.py +++ b/tests/codec/ber/test_encoder.py @@ -436,40 +436,40 @@ class RealEncoderWithSchemaTestCase(BaseTestCase): if sys.version_info[0:2] > (2, 5): class UniversalStringEncoderTestCase(BaseTestCase): def testEncoding(self): - assert encoder.encode(char.UniversalString(sys.version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( + assert encoder.encode(char.UniversalString(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( (28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' class UniversalStringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( - sys.version_info[0] == 3 and 'abc' or unicode('abc'), asn1Spec=char.UniversalString() + sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.UniversalString() ) == ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' class BMPStringEncoderTestCase(BaseTestCase): def testEncoding(self): - assert encoder.encode(char.BMPString(sys.version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( + assert encoder.encode(char.BMPString(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( (30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' class BMPStringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( - sys.version_info[0] == 3 and 'abc' or unicode('abc'), asn1Spec=char.BMPString() + sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.BMPString() ) == ints2octs((30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' class UTF8StringEncoderTestCase(BaseTestCase): def testEncoding(self): - assert encoder.encode(char.UTF8String(sys.version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( + assert encoder.encode(char.UTF8String(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( (12, 3, 97, 98, 99)), 'Incorrect encoding' class UTF8StringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( - sys.version_info[0] == 3 and 'abc' or unicode('abc'), asn1Spec=char.UTF8String() + sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.UTF8String() ) == ints2octs((12, 3, 97, 98, 99)), 'Incorrect encoding' -- cgit v1.2.3 From d0b7f2ec8677eec8f9aa31103a66f5cab18e9308 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Tue, 27 Aug 2019 10:17:42 +0200 Subject: Add `SET ... WITH COMPONENTS ...` ASN.1 construct support (#171) Added `WithComponentsConstraint` along with related `ComponentPresentConstraint` and `ComponentAbsentConstraint` classes to be used with `Sequence`/`Set` types representing `SET ... WITH COMPONENTS ...` like ASN.1 constructs. --- tests/type/test_constraint.py | 63 ++++++++++++++++++++++++++ tests/type/test_univ.py | 102 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) (limited to 'tests') diff --git a/tests/type/test_constraint.py b/tests/type/test_constraint.py index b5276cd..0f49c78 100644 --- a/tests/type/test_constraint.py +++ b/tests/type/test_constraint.py @@ -128,6 +128,69 @@ class PermittedAlphabetConstraintTestCase(SingleValueConstraintTestCase): assert 0, 'constraint check fails' +class WithComponentsConstraintTestCase(BaseTestCase): + + def testGoodVal(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()), + ('B', constraint.ComponentAbsentConstraint())) + + try: + c({'A': 1}) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testGoodValWithExtraFields(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()), + ('B', constraint.ComponentAbsentConstraint()) + ) + + try: + c({'A': 1, 'C': 2}) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testEmptyConstraint(self): + c = constraint.WithComponentsConstraint() + + try: + c({'A': 1}) + + except error.ValueConstraintError: + assert 0, 'constraint check fails' + + def testBadVal(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()) + ) + + try: + c({'B': 2}) + + except error.ValueConstraintError: + pass + + else: + assert 0, 'constraint check fails' + + def testBadValExtraFields(self): + c = constraint.WithComponentsConstraint( + ('A', constraint.ComponentPresentConstraint()) + ) + + try: + c({'B': 2, 'C': 3}) + + except error.ValueConstraintError: + pass + + else: + assert 0, 'constraint check fails' + + class ConstraintsIntersectionTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index d9f921b..9762959 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -1249,6 +1249,37 @@ class SequenceOf(BaseTestCase): assert not s.isValue + def testIsInconsistentSizeConstraint(self): + + class SequenceOf(univ.SequenceOf): + componentType = univ.OctetString() + subtypeSpec = constraint.ValueSizeConstraint(0, 1) + + s = SequenceOf() + + assert s.isInconsistent + + s[0] = 'test' + + assert not s.isInconsistent + + s[0] = 'test' + s[1] = 'test' + + assert s.isInconsistent + + s.clear() + + assert not s.isInconsistent + + s.reset() + + assert s.isInconsistent + + s[1] = 'test' + + assert not s.isInconsistent + class SequenceOfPicklingTestCase(unittest.TestCase): @@ -1585,6 +1616,77 @@ class Sequence(BaseTestCase): assert not s.isValue + def testIsInconsistentWithComponentsConstraint(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(65)) + ) + subtypeSpec = constraint.WithComponentsConstraint( + ('name', constraint.ComponentPresentConstraint()), + ('age', constraint.ComponentAbsentConstraint()) + ) + + s = Sequence() + + assert s.isInconsistent + + s[0] = 'test' + + assert not s.isInconsistent + + s[0] = 'test' + s[1] = 23 + + assert s.isInconsistent + + s.clear() + + assert s.isInconsistent + + s.reset() + + assert s.isInconsistent + + s[1] = 23 + + assert s.isInconsistent + + def testIsInconsistentSizeConstraint(self): + + class Sequence(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.OptionalNamedType('name', univ.OctetString()), + namedtype.DefaultedNamedType('age', univ.Integer(65)) + ) + subtypeSpec = constraint.ValueSizeConstraint(0, 1) + + s = Sequence() + + assert not s.isInconsistent + + s[0] = 'test' + + assert not s.isInconsistent + + s[0] = 'test' + s[1] = 23 + + assert s.isInconsistent + + s.clear() + + assert not s.isInconsistent + + s.reset() + + assert s.isInconsistent + + s[1] = 23 + + assert not s.isInconsistent + class SequenceWithoutSchema(BaseTestCase): -- cgit v1.2.3