X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=tests%2Ftest_pyderasn.py;h=8fe0502eb0d7028ca591abd5fb5d6ec181823bde;hb=2aaa384be26f265bf37579a0d23145cb30b6753c;hp=f655d973dcb39cd7b3c80e68b1876daeacb8af98;hpb=eb67733960022e82168120c03b5c0e81272ddb2b;p=pyderasn.git diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index f655d97..8fe0502 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -18,6 +18,7 @@ from datetime import datetime from string import ascii_letters +from string import digits from string import printable from string import whitespace from unittest import TestCase @@ -48,6 +49,7 @@ from six import int2byte from six import iterbytes from six import PY2 from six import text_type +from six import unichr as six_unichr from pyderasn import _pp from pyderasn import abs_decode_path @@ -106,11 +108,11 @@ from pyderasn import VideotexString from pyderasn import VisibleString -settings.register_profile('local', settings( +settings.register_profile("local", settings( deadline=5000, perform_health_check=False, )) -settings.load_profile('local') +settings.load_profile("local") LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4 tag_classes = sampled_from(( @@ -283,7 +285,7 @@ class CommonMixin(object): with self.assertRaises(ValueError): self.base_klass(impl=b"whatever", expl=b"whenever") - @given(binary(), integers(), integers(), integers()) + @given(binary(min_size=1), integers(), integers(), integers()) def test_decoded(self, impl, offset, llen, vlen): obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen)) self.assertEqual(obj.offset, offset) @@ -292,7 +294,7 @@ class CommonMixin(object): self.assertEqual(obj.tlen, len(impl)) self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen) - @given(binary()) + @given(binary(min_size=1)) def test_impl_inherited(self, impl_tag): class Inherited(self.base_klass): impl = impl_tag @@ -1136,8 +1138,8 @@ class TestBitString(CommonMixin, TestCase): @given( tuples(integers(min_value=0), binary()), tuples(integers(min_value=0), binary()), - binary(), - binary(), + binary(min_size=1), + binary(min_size=1), ) def test_comparison(self, value1, value2, tag1, tag2): for klass in (BitString, BitStringInherited): @@ -1449,7 +1451,7 @@ class TestOctetString(CommonMixin, TestCase): repr(obj) pprint(obj) - @given(binary(), binary(), binary(), binary()) + @given(binary(), binary(), binary(min_size=1), binary(min_size=1)) def test_comparison(self, value1, value2, tag1, tag2): for klass in (OctetString, OctetStringInherited): obj1 = klass(value1) @@ -2238,6 +2240,12 @@ class TestObjectIdentifier(CommonMixin, TestCase): data, ))) + def test_x690_vector(self): + self.assertEqual( + ObjectIdentifier().decode(hexdec("0603883703"))[0], + ObjectIdentifier((2, 999, 3)), + ) + @composite def enumerated_values_strategy(draw, schema=None, do_expl=False): @@ -2553,8 +2561,8 @@ class StringMixin(object): def test_comparison(self, d): value1 = d.draw(text(alphabet=self.text_alphabet())) value2 = d.draw(text(alphabet=self.text_alphabet())) - tag1 = d.draw(binary()) - tag2 = d.draw(binary()) + tag1 = d.draw(binary(min_size=1)) + tag2 = d.draw(binary(min_size=1)) obj1 = self.base_klass(value1) obj2 = self.base_klass(value2) self.assertEqual(obj1 == obj2, value1 == value2) @@ -2802,35 +2810,130 @@ class TestUTF8String(StringMixin, CommonMixin, TestCase): base_klass = UTF8String +class UnicodeDecodeErrorMixin(object): + @given(text( + alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))), + min_size=1, + max_size=5, + )) + def test_unicode_decode_error(self, cyrillic_text): + with self.assertRaises(DecodeError): + self.base_klass(cyrillic_text) + + class TestNumericString(StringMixin, CommonMixin, TestCase): base_klass = NumericString + def text_alphabet(self): + return digits -class TestPrintableString(StringMixin, CommonMixin, TestCase): + @given(text(alphabet=ascii_letters, min_size=1, max_size=5)) + def test_non_numeric(self, cyrillic_text): + with assertRaisesRegex(self, DecodeError, "non-numeric"): + self.base_klass(cyrillic_text) + + @given( + sets(integers(min_value=0, max_value=10), min_size=2, max_size=2), + integers(min_value=0), + lists(integers()), + ) + def test_invalid_bounds_while_decoding(self, ints, offset, decode_path): + decode_path = tuple(str(i) for i in decode_path) + value, bound_min = list(sorted(ints)) + + class String(self.base_klass): + bounds = (bound_min, bound_min) + with self.assertRaises(DecodeError) as err: + String().decode( + self.base_klass(b"1" * value).encode(), + offset=offset, + decode_path=decode_path, + ) + repr(err.exception) + self.assertEqual(err.exception.offset, offset) + self.assertEqual(err.exception.decode_path, decode_path) + + +class TestPrintableString( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = PrintableString -class TestTeletexString(StringMixin, CommonMixin, TestCase): +class TestTeletexString( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = TeletexString -class TestVideotexString(StringMixin, CommonMixin, TestCase): +class TestVideotexString( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = VideotexString -class TestIA5String(StringMixin, CommonMixin, TestCase): +class TestIA5String( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = IA5String -class TestGraphicString(StringMixin, CommonMixin, TestCase): +class TestGraphicString( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = GraphicString -class TestVisibleString(StringMixin, CommonMixin, TestCase): +class TestVisibleString( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = VisibleString + def test_x690_vector(self): + self.assertEqual( + str(VisibleString().decode(hexdec("1A054A6F6E6573"))[0]), + "Jones", + ) + self.assertEqual( + str(VisibleString().decode( + hexdec("3A0904034A6F6E04026573"), + ctx={"bered": True}, + )[0]), + "Jones", + ) + self.assertEqual( + str(VisibleString().decode( + hexdec("3A8004034A6F6E040265730000"), + ctx={"bered": True}, + )[0]), + "Jones", + ) + -class TestGeneralString(StringMixin, CommonMixin, TestCase): +class TestGeneralString( + UnicodeDecodeErrorMixin, + StringMixin, + CommonMixin, + TestCase, +): base_klass = GeneralString @@ -2916,8 +3019,8 @@ class TimeMixin(object): min_value=self.min_datetime, max_value=self.max_datetime, )) - tag1 = d.draw(binary()) - tag2 = d.draw(binary()) + tag1 = d.draw(binary(min_size=1)) + tag2 = d.draw(binary(min_size=1)) if self.omit_ms: value1 = value1.replace(microsecond=0) value2 = value2.replace(microsecond=0) @@ -3695,6 +3798,26 @@ class TestChoice(CommonMixin, TestCase): with self.assertRaises(TagMismatch): obj.decode(int_encoded) + def test_tag_mismatch_underlying(self): + class SeqOfBoolean(SequenceOf): + schema = Boolean() + + class SeqOfInteger(SequenceOf): + schema = Integer() + + class Wahl(Choice): + schema = ( + ("erste", SeqOfBoolean()), + ) + + int_encoded = SeqOfInteger((Integer(123),)).encode() + bool_encoded = SeqOfBoolean((Boolean(False),)).encode() + obj = Wahl() + obj.decode(bool_encoded) + with self.assertRaises(TagMismatch) as err: + obj.decode(int_encoded) + self.assertEqual(err.exception.decode_path, ("erste", "0")) + @composite def seq_values_strategy(draw, seq_klass, do_expl=False): @@ -3870,7 +3993,7 @@ def sequences_strategy(draw, seq_klass): class SeqMixing(object): def test_invalid_value_type(self): with self.assertRaises(InvalidValueType) as err: - self.base_klass((1, 2, 3)) + self.base_klass(123) repr(err.exception) def test_invalid_value_type_set(self): @@ -4272,6 +4395,16 @@ class TestSequence(SeqMixing, CommonMixin, TestCase): seq[missing] = Boolean() repr(err.exception) + def test_x690_vector(self): + class Seq(Sequence): + schema = ( + ("name", IA5String()), + ("ok", Boolean()), + ) + seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0] + self.assertEqual(seq["name"], "Smith") + self.assertEqual(seq["ok"], True) + class TestSet(SeqMixing, CommonMixin, TestCase): base_klass = Set @@ -5188,3 +5321,42 @@ class TestStrictDefaultExistence(TestCase): seq.decode(raw) with assertRaisesRegex(self, DecodeError, "DEFAULT value met"): seq.decode(raw, ctx={"strict_default_existence": True}) + + +class TestX690PrefixedType(TestCase): + def runTest(self): + self.assertSequenceEqual( + VisibleString("Jones").encode(), + hexdec("1A054A6F6E6573"), + ) + self.assertSequenceEqual( + VisibleString( + "Jones", + impl=tag_encode(3, klass=TagClassApplication), + ).encode(), + hexdec("43054A6F6E6573"), + ) + self.assertSequenceEqual( + Any( + VisibleString( + "Jones", + impl=tag_encode(3, klass=TagClassApplication), + ), + expl=tag_ctxc(2), + ).encode(), + hexdec("A20743054A6F6E6573"), + ) + self.assertSequenceEqual( + OctetString( + VisibleString( + "Jones", + impl=tag_encode(3, klass=TagClassApplication), + ).encode(), + impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication), + ).encode(), + hexdec("670743054A6F6E6573"), + ) + self.assertSequenceEqual( + VisibleString("Jones", impl=tag_ctxp(2)).encode(), + hexdec("82054A6F6E6573"), + )