2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2020 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this program. If not, see
16 # <http://www.gnu.org/licenses/>.
19 from copy import deepcopy
20 from datetime import datetime
21 from datetime import timedelta
22 from importlib import import_module
23 from io import BytesIO
24 from operator import attrgetter
25 from os import environ
26 from os import urandom
27 from random import random
28 from string import ascii_letters
29 from string import digits
30 from string import printable
31 from string import whitespace
32 from time import mktime
34 from unittest import TestCase
36 from hypothesis import assume
37 from hypothesis import given
38 from hypothesis import settings
39 from hypothesis.strategies import binary
40 from hypothesis.strategies import booleans
41 from hypothesis.strategies import composite
42 from hypothesis.strategies import data as data_strategy
43 from hypothesis.strategies import datetimes
44 from hypothesis.strategies import dictionaries
45 from hypothesis.strategies import integers
46 from hypothesis.strategies import just
47 from hypothesis.strategies import lists
48 from hypothesis.strategies import none
49 from hypothesis.strategies import one_of
50 from hypothesis.strategies import permutations
51 from hypothesis.strategies import sampled_from
52 from hypothesis.strategies import sets
53 from hypothesis.strategies import text
54 from hypothesis.strategies import tuples
55 from six import assertRaisesRegex
56 from six import binary_type
57 from six import byte2int
58 from six import indexbytes
59 from six import int2byte
60 from six import iterbytes
62 from six import text_type
63 from six import unichr as six_unichr
64 from six.moves import xrange as six_xrange
65 from six.moves.cPickle import dumps as pickle_dumps
66 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
67 from six.moves.cPickle import loads as pickle_loads
69 from pyderasn import _pp
70 from pyderasn import abs_decode_path
71 from pyderasn import Any
72 from pyderasn import BitString
73 from pyderasn import BMPString
74 from pyderasn import Boolean
75 from pyderasn import BoundsError
76 from pyderasn import Choice
77 from pyderasn import DecodeError
78 from pyderasn import DecodePathDefBy
79 from pyderasn import encode2pass
80 from pyderasn import encode_cer
81 from pyderasn import Enumerated
82 from pyderasn import EOC
83 from pyderasn import EOC_LEN
84 from pyderasn import ExceedingData
85 from pyderasn import GeneralizedTime
86 from pyderasn import GeneralString
87 from pyderasn import GraphicString
88 from pyderasn import hexdec
89 from pyderasn import hexenc
90 from pyderasn import IA5String
91 from pyderasn import Integer
92 from pyderasn import InvalidLength
93 from pyderasn import InvalidOID
94 from pyderasn import InvalidValueType
95 from pyderasn import len_decode
96 from pyderasn import len_encode
97 from pyderasn import LEN_YYMMDDHHMMSSZ
98 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
99 from pyderasn import LEN_YYYYMMDDHHMMSSZ
100 from pyderasn import LENINDEF
101 from pyderasn import LenIndefForm
102 from pyderasn import NotEnoughData
103 from pyderasn import Null
104 from pyderasn import NumericString
105 from pyderasn import ObjectIdentifier
106 from pyderasn import ObjNotReady
107 from pyderasn import ObjUnknown
108 from pyderasn import OctetString
109 from pyderasn import pp_console_row
110 from pyderasn import pprint
111 from pyderasn import PrintableString
112 from pyderasn import Sequence
113 from pyderasn import SequenceOf
114 from pyderasn import Set
115 from pyderasn import SetOf
116 from pyderasn import tag_ctxc
117 from pyderasn import tag_ctxp
118 from pyderasn import tag_decode
119 from pyderasn import tag_encode
120 from pyderasn import tag_strip
121 from pyderasn import TagClassApplication
122 from pyderasn import TagClassContext
123 from pyderasn import TagClassPrivate
124 from pyderasn import TagClassUniversal
125 from pyderasn import TagFormConstructed
126 from pyderasn import TagFormPrimitive
127 from pyderasn import TagMismatch
128 from pyderasn import TeletexString
129 from pyderasn import UniversalString
130 from pyderasn import UTCTime
131 from pyderasn import UTF8String
132 from pyderasn import VideotexString
133 from pyderasn import VisibleString
136 max_examples = environ.get("MAX_EXAMPLES")
137 settings.register_profile("local", settings(
139 **({"max_examples": int(max_examples)} if max_examples else {})
141 settings.load_profile("local")
142 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
144 tag_classes = sampled_from((
150 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
151 decode_path_strat = lists(integers(), max_size=3).map(
152 lambda decode_path: tuple(str(dp) for dp in decode_path)
154 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
157 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
159 self_module = import_module(__name__)
162 def register_class(klass):
163 klassname = klass.__name__ + str(time()).replace(".", "")
164 klass.__name__ = klassname
165 klass.__qualname__ = klassname
166 setattr(self_module, klassname, klass)
169 def assert_exceeding_data(self, call, junk):
172 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
177 class TestHex(TestCase):
179 def test_symmetric(self, data):
180 self.assertEqual(hexdec(hexenc(data)), data)
183 class TestTagCoder(TestCase):
184 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
188 integers(min_value=0, max_value=30),
191 def test_short(self, klass, form, num, junk):
192 raw = tag_encode(klass=klass, form=form, num=num)
193 self.assertEqual(tag_decode(raw), (klass, form, num))
194 self.assertEqual(len(raw), 1)
196 byte2int(tag_encode(klass=klass, form=form, num=0)),
197 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
199 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
200 self.assertSequenceEqual(stripped.tobytes(), raw)
201 self.assertEqual(tlen, len(raw))
202 self.assertSequenceEqual(tail, junk)
204 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
208 integers(min_value=31),
211 def test_long(self, klass, form, num, junk):
212 raw = tag_encode(klass=klass, form=form, num=num)
213 self.assertEqual(tag_decode(raw), (klass, form, num))
214 self.assertGreater(len(raw), 1)
216 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
219 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
220 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
221 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
222 self.assertSequenceEqual(stripped.tobytes(), raw)
223 self.assertEqual(tlen, len(raw))
224 self.assertSequenceEqual(tail, junk)
226 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
227 @given(integers(min_value=31))
228 def test_unfinished_tag(self, num):
229 raw = bytearray(tag_encode(num=num))
230 for i in range(1, len(raw)):
232 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
233 tag_strip(bytes(raw))
235 def test_go_vectors_valid(self):
236 for data, (eklass, etag, elen, eform) in (
237 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
238 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
239 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
240 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
241 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
242 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
243 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
244 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
245 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
246 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
248 tag, _, len_encoded = tag_strip(memoryview(data))
249 klass, form, num = tag_decode(tag)
250 _len, _, tail = len_decode(len_encoded)
251 self.assertSequenceEqual(tail, b"")
252 self.assertEqual(klass, eklass)
253 self.assertEqual(num, etag)
254 self.assertEqual(_len, elen)
255 self.assertEqual(form, eform)
257 def test_go_vectors_invalid(self):
265 with self.assertRaises(DecodeError):
266 _, _, len_encoded = tag_strip(memoryview(data))
267 len_decode(len_encoded)
270 integers(min_value=0, max_value=127),
271 integers(min_value=0, max_value=2),
273 def test_long_instead_of_short(self, l, dummy_num):
274 octets = (b"\x00" * dummy_num) + int2byte(l)
275 octets = int2byte((dummy_num + 1) | 0x80) + octets
276 with self.assertRaises(DecodeError):
279 @given(tag_classes, tag_forms, integers(min_value=31))
280 def test_leading_zero_byte(self, klass, form, num):
281 raw = tag_encode(klass=klass, form=form, num=num)
282 raw = b"".join((raw[:1], b"\x80", raw[1:]))
283 with assertRaisesRegex(self, DecodeError, "leading zero byte"):
286 @given(tag_classes, tag_forms, integers(max_value=30, min_value=0))
287 def test_unexpected_long_form(self, klass, form, num):
288 raw = int2byte(klass | form | 31) + int2byte(num)
289 with assertRaisesRegex(self, DecodeError, "unexpected long form"):
293 class TestLenCoder(TestCase):
294 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
296 integers(min_value=0, max_value=127),
299 def test_short(self, l, junk):
300 raw = len_encode(l) + junk
301 decoded, llen, tail = len_decode(memoryview(raw))
302 self.assertEqual(decoded, l)
303 self.assertEqual(llen, 1)
304 self.assertEqual(len(raw), 1 + len(junk))
305 self.assertEqual(tail.tobytes(), junk)
307 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
309 integers(min_value=128),
312 def test_long(self, l, junk):
313 raw = len_encode(l) + junk
314 decoded, llen, tail = len_decode(memoryview(raw))
315 self.assertEqual(decoded, l)
316 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
317 self.assertEqual(llen, len(raw) - len(junk))
318 self.assertNotEqual(indexbytes(raw, 1), 0)
319 self.assertSequenceEqual(tail.tobytes(), junk)
321 def test_empty(self):
322 with self.assertRaises(NotEnoughData):
325 @given(integers(min_value=128))
326 def test_stripped(self, _len):
327 with self.assertRaises(NotEnoughData):
328 len_decode(len_encode(_len)[:-1])
331 text_printable = text(alphabet=printable, min_size=1)
335 def text_letters(draw):
336 result = draw(text(alphabet=ascii_letters, min_size=1))
338 result = result.encode("ascii")
342 class CommonMixin(object):
343 def test_tag_default(self):
344 obj = self.base_klass()
345 self.assertEqual(obj.tag, obj.tag_default)
347 def test_simultaneous_impl_expl(self):
348 with self.assertRaises(ValueError):
349 self.base_klass(impl=b"whatever", expl=b"whenever")
351 @given(binary(min_size=1), integers(), integers(), integers())
352 def test_decoded(self, impl, offset, llen, vlen):
353 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
354 self.assertEqual(obj.offset, offset)
355 self.assertEqual(obj.llen, llen)
356 self.assertEqual(obj.vlen, vlen)
357 self.assertEqual(obj.tlen, len(impl))
358 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
360 @given(binary(min_size=1))
361 def test_impl_inherited(self, impl_tag):
362 class Inherited(self.base_klass):
365 self.assertSequenceEqual(obj.impl, impl_tag)
366 self.assertFalse(obj.expled)
368 tag_class, _, tag_num = tag_decode(impl_tag)
369 self.assertEqual(obj.tag_order, (tag_class, tag_num))
371 @given(binary(min_size=1))
372 def test_expl_inherited(self, expl_tag):
373 class Inherited(self.base_klass):
376 self.assertSequenceEqual(obj.expl, expl_tag)
377 self.assertTrue(obj.expled)
379 tag_class, _, tag_num = tag_decode(expl_tag)
380 self.assertEqual(obj.tag_order, (tag_class, tag_num))
382 def assert_copied_basic_fields(self, obj, obj_copied):
383 self.assertEqual(obj, obj_copied)
384 self.assertSequenceEqual(obj.tag, obj_copied.tag)
385 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
386 self.assertEqual(obj.default, obj_copied.default)
387 self.assertEqual(obj.optional, obj_copied.optional)
388 self.assertEqual(obj.offset, obj_copied.offset)
389 self.assertEqual(obj.llen, obj_copied.llen)
390 self.assertEqual(obj.vlen, obj_copied.vlen)
392 self.assertEqual(obj.tag_order, obj_copied.tag_order)
396 def boolean_values_strategy(draw, do_expl=False):
397 value = draw(one_of(none(), booleans()))
401 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
403 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
404 default = draw(one_of(none(), booleans()))
405 optional = draw(one_of(none(), booleans()))
407 draw(integers(min_value=0)),
408 draw(integers(min_value=0)),
409 draw(integers(min_value=0)),
411 return (value, impl, expl, default, optional, _decoded)
414 class BooleanInherited(Boolean):
418 class TestBoolean(CommonMixin, TestCase):
421 def test_invalid_value_type(self):
422 with self.assertRaises(InvalidValueType) as err:
427 def test_optional(self, optional):
428 obj = Boolean(default=Boolean(False), optional=optional)
429 self.assertTrue(obj.optional)
432 def test_ready(self, value):
434 self.assertFalse(obj.ready)
437 pprint(obj, big_blobs=True, with_decode_path=True)
438 with self.assertRaises(ObjNotReady) as err:
440 with self.assertRaises(ObjNotReady) as err:
444 self.assertTrue(obj.ready)
447 pprint(obj, big_blobs=True, with_decode_path=True)
449 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
450 def test_comparison(self, value1, value2, tag1, tag2):
451 for klass in (Boolean, BooleanInherited):
454 self.assertEqual(obj1 == obj2, value1 == value2)
455 self.assertEqual(obj1 != obj2, value1 != value2)
456 self.assertEqual(obj1 == bool(obj2), value1 == value2)
457 obj1 = klass(value1, impl=tag1)
458 obj2 = klass(value1, impl=tag2)
459 self.assertEqual(obj1 == obj2, tag1 == tag2)
460 self.assertEqual(obj1 != obj2, tag1 != tag2)
462 @given(data_strategy())
463 def test_call(self, d):
464 for klass in (Boolean, BooleanInherited):
472 ) = d.draw(boolean_values_strategy())
478 optional_initial or False,
488 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
489 obj = obj_initial(value, impl, expl, default, optional)
491 value_expected = default if value is None else value
493 default_initial if value_expected is None
496 self.assertEqual(obj, value_expected)
497 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
498 self.assertEqual(obj.expl_tag, expl or expl_initial)
501 default_initial if default is None else default,
503 if obj.default is None:
504 optional = optional_initial if optional is None else optional
505 optional = False if optional is None else optional
508 self.assertEqual(obj.optional, optional)
510 @given(boolean_values_strategy())
511 def test_copy(self, values):
512 for klass in (Boolean, BooleanInherited):
514 for copy_func in copy_funcs:
515 obj_copied = copy_func(obj)
516 self.assert_copied_basic_fields(obj, obj_copied)
520 integers(min_value=1).map(tag_encode),
522 def test_stripped(self, value, tag_impl):
523 obj = Boolean(value, impl=tag_impl)
524 with self.assertRaises(NotEnoughData):
525 obj.decode(obj.encode()[:-1])
526 with self.assertRaises(NotEnoughData):
527 obj.decode(encode2pass(obj)[:-1])
531 integers(min_value=1).map(tag_ctxc),
533 def test_stripped_expl(self, value, tag_expl):
534 obj = Boolean(value, expl=tag_expl)
535 with self.assertRaises(NotEnoughData):
536 obj.decode(obj.encode()[:-1])
537 with self.assertRaises(NotEnoughData):
538 obj.decode(encode2pass(obj)[:-1])
541 integers(min_value=31),
542 integers(min_value=0),
545 def test_bad_tag(self, tag, offset, decode_path):
546 with self.assertRaises(DecodeError) as err:
548 tag_encode(tag)[:-1],
550 decode_path=decode_path,
553 self.assertEqual(err.exception.offset, offset)
554 self.assertEqual(err.exception.decode_path, decode_path)
557 integers(min_value=31),
558 integers(min_value=0),
561 def test_bad_expl_tag(self, tag, offset, decode_path):
562 with self.assertRaises(DecodeError) as err:
563 Boolean(expl=Boolean.tag_default).decode(
564 tag_encode(tag)[:-1],
566 decode_path=decode_path,
569 self.assertEqual(err.exception.offset, offset)
570 self.assertEqual(err.exception.decode_path, decode_path)
573 integers(min_value=128),
574 integers(min_value=0),
577 def test_bad_len(self, l, offset, decode_path):
578 with self.assertRaises(DecodeError) as err:
580 Boolean.tag_default + len_encode(l)[:-1],
582 decode_path=decode_path,
585 self.assertEqual(err.exception.offset, offset)
586 self.assertEqual(err.exception.decode_path, decode_path)
589 integers(min_value=128),
590 integers(min_value=0),
593 def test_bad_expl_len(self, l, offset, decode_path):
594 with self.assertRaises(DecodeError) as err:
595 Boolean(expl=Boolean.tag_default).decode(
596 Boolean.tag_default + len_encode(l)[:-1],
598 decode_path=decode_path,
601 self.assertEqual(err.exception.offset, offset)
602 self.assertEqual(err.exception.decode_path, decode_path)
604 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
606 boolean_values_strategy(),
608 integers(min_value=1).map(tag_ctxc),
609 integers(min_value=0),
613 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
614 for klass in (Boolean, BooleanInherited):
615 _, _, _, default, optional, _decoded = values
624 pprint(obj, big_blobs=True, with_decode_path=True)
625 self.assertFalse(obj.expled)
626 obj_encoded = obj.encode()
627 self.assertEqual(encode2pass(obj), obj_encoded)
628 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
629 obj_expled = obj(value, expl=tag_expl)
630 self.assertTrue(obj_expled.expled)
632 list(obj_expled.pps())
633 pprint(obj_expled, big_blobs=True, with_decode_path=True)
634 obj_expled_cer = encode_cer(obj_expled)
635 self.assertNotEqual(obj_expled_cer, obj_encoded)
636 self.assertSequenceEqual(
637 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
640 obj_expled_hex_encoded = obj_expled.hexencode()
641 ctx_copied = deepcopy(ctx_dummy)
642 obj_decoded, tail = obj_expled.hexdecode(
643 obj_expled_hex_encoded + hexenc(tail_junk),
647 self.assertDictEqual(ctx_copied, ctx_dummy)
649 list(obj_decoded.pps())
650 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
651 self.assertEqual(tail, tail_junk)
652 self.assertEqual(obj_decoded, obj_expled)
653 self.assertNotEqual(obj_decoded, obj)
654 self.assertEqual(bool(obj_decoded), bool(obj_expled))
655 self.assertEqual(bool(obj_decoded), bool(obj))
656 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
657 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
658 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
660 obj_decoded.expl_llen,
661 len(len_encode(len(obj_encoded))),
663 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
664 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
667 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
669 self.assertEqual(obj_decoded.expl_offset, offset)
670 assert_exceeding_data(
672 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
676 evgens = list(obj_expled.decode_evgen(
677 hexdec(obj_expled_hex_encoded) + tail_junk,
679 decode_path=decode_path,
682 self.assertEqual(len(evgens), 1)
683 _decode_path, obj, tail = evgens[0]
684 self.assertSequenceEqual(tail, tail_junk)
685 self.assertEqual(_decode_path, decode_path)
686 self.assertEqual(obj, obj_decoded)
687 self.assertEqual(obj.expl_offset, offset)
691 @given(integers(min_value=2))
692 def test_invalid_len(self, l):
693 with self.assertRaises(InvalidLength):
694 Boolean().decode(b"".join((
700 @given(integers(min_value=0 + 1, max_value=255 - 1))
701 def test_ber_value(self, value):
702 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
703 Boolean().decode(b"".join((
713 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
714 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
715 self.assertTrue(bool(obj))
716 self.assertTrue(obj.ber_encoded)
717 self.assertFalse(obj.lenindef)
718 self.assertTrue(obj.bered)
720 self.assertTrue(obj.ber_encoded)
721 self.assertFalse(obj.lenindef)
722 self.assertTrue(obj.bered)
725 integers(min_value=1).map(tag_ctxc),
726 binary().filter(lambda x: not x.startswith(EOC)),
728 def test_ber_expl_no_eoc(self, expl, junk):
729 encoded = expl + LENINDEF + Boolean(False).encode()
730 with self.assertRaises(LenIndefForm):
731 Boolean(expl=expl).decode(encoded + junk)
732 with assertRaisesRegex(self, DecodeError, "no EOC"):
733 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
734 obj, tail = Boolean(expl=expl).decode(
735 encoded + EOC + junk,
738 self.assertTrue(obj.expl_lenindef)
739 self.assertFalse(obj.lenindef)
740 self.assertFalse(obj.ber_encoded)
741 self.assertTrue(obj.bered)
743 self.assertTrue(obj.expl_lenindef)
744 self.assertFalse(obj.lenindef)
745 self.assertFalse(obj.ber_encoded)
746 self.assertTrue(obj.bered)
747 self.assertSequenceEqual(tail, junk)
750 pprint(obj, big_blobs=True, with_decode_path=True)
753 integers(min_value=1).map(tag_ctxc),
760 def test_ber_expl(self, expl, values):
766 Boolean(value).encode() +
769 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
771 class SeqOf(SequenceOf):
772 schema = Boolean(expl=expl)
773 with self.assertRaises(LenIndefForm):
774 SeqOf().decode(encoded)
775 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
776 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
777 self.assertSequenceEqual(tail, b"")
778 self.assertSequenceEqual([bool(v) for v in seqof], values)
794 len(expl) + 1 + 3 + EOC_LEN,
805 pprint(seqof, big_blobs=True, with_decode_path=True)
809 def integer_values_strategy(draw, do_expl=False):
810 bound_min, value, default, bound_max = sorted(draw(sets(
819 _specs = draw(sets(text_letters()))
822 min_size=len(_specs),
823 max_size=len(_specs),
825 _specs = list(zip(_specs, values))
828 bounds = (bound_min, bound_max)
832 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
834 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
837 optional = draw(one_of(none(), booleans()))
839 draw(integers(min_value=0)),
840 draw(integers(min_value=0)),
841 draw(integers(min_value=0)),
843 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
846 class IntegerInherited(Integer):
850 class TestInteger(CommonMixin, TestCase):
853 def test_invalid_value_type(self):
854 with self.assertRaises(InvalidValueType) as err:
858 @given(sets(text_letters(), min_size=2))
859 def test_unknown_name(self, names_input):
860 missing = names_input.pop()
863 schema = [(n, 123) for n in names_input]
864 with self.assertRaises(ObjUnknown) as err:
868 @given(sets(text_letters(), min_size=2))
869 def test_known_name(self, names_input):
871 schema = [(n, 123) for n in names_input]
872 Int(names_input.pop())
875 def test_optional(self, optional):
876 obj = Integer(default=Integer(0), optional=optional)
877 self.assertTrue(obj.optional)
880 def test_ready(self, value):
882 self.assertFalse(obj.ready)
885 pprint(obj, big_blobs=True, with_decode_path=True)
886 with self.assertRaises(ObjNotReady) as err:
888 with self.assertRaises(ObjNotReady) as err:
892 self.assertTrue(obj.ready)
895 pprint(obj, big_blobs=True, with_decode_path=True)
898 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
899 def test_comparison(self, value1, value2, tag1, tag2):
900 for klass in (Integer, IntegerInherited):
903 self.assertEqual(obj1 == obj2, value1 == value2)
904 self.assertEqual(obj1 != obj2, value1 != value2)
905 self.assertEqual(obj1 == int(obj2), value1 == value2)
906 obj1 = klass(value1, impl=tag1)
907 obj2 = klass(value1, impl=tag2)
908 self.assertEqual(obj1 == obj2, tag1 == tag2)
909 self.assertEqual(obj1 != obj2, tag1 != tag2)
911 @given(lists(integers()))
912 def test_sorted_works(self, values):
913 self.assertSequenceEqual(
914 [int(v) for v in sorted(Integer(v) for v in values)],
918 @given(data_strategy())
919 def test_named(self, d):
920 names_input = list(d.draw(sets(text_letters(), min_size=1)))
921 values_input = list(d.draw(sets(
923 min_size=len(names_input),
924 max_size=len(names_input),
926 chosen_name = d.draw(sampled_from(names_input))
927 names_input = dict(zip(names_input, values_input))
931 _int = Int(chosen_name)
932 self.assertEqual(_int.named, chosen_name)
933 self.assertEqual(int(_int), names_input[chosen_name])
935 @given(integers(), integers(min_value=0), integers(min_value=0))
936 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
937 value = bound_min + value_delta
938 bound_max = value + bound_delta
939 Integer(value=value, bounds=(bound_min, bound_max))
941 @given(sets(integers(), min_size=3, max_size=3))
942 def test_bounds_unsatisfied(self, values):
943 values = sorted(values)
944 with self.assertRaises(BoundsError) as err:
945 Integer(value=values[0], bounds=(values[1], values[2]))
947 with assertRaisesRegex(self, DecodeError, "bounds") as err:
948 Integer(bounds=(values[1], values[2])).decode(
949 Integer(values[0]).encode()
952 with assertRaisesRegex(self, DecodeError, "bounds") as err:
953 Integer(bounds=(values[1], values[2])).decode(
954 encode2pass(Integer(values[0]))
956 with self.assertRaises(BoundsError) as err:
957 Integer(value=values[2], bounds=(values[0], values[1]))
959 with assertRaisesRegex(self, DecodeError, "bounds") as err:
960 Integer(bounds=(values[0], values[1])).decode(
961 Integer(values[2]).encode()
964 with assertRaisesRegex(self, DecodeError, "bounds") as err:
965 Integer(bounds=(values[0], values[1])).decode(
966 encode2pass(Integer(values[2]))
969 @given(data_strategy())
970 def test_call(self, d):
971 for klass in (Integer, IntegerInherited):
981 ) = d.draw(integer_values_strategy())
988 optional_initial or False,
1001 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
1002 if (default is None) and (obj_initial.default is not None):
1005 (bounds is None) and
1006 (value is not None) and
1007 (bounds_initial is not None) and
1008 not (bounds_initial[0] <= value <= bounds_initial[1])
1012 (bounds is None) and
1013 (default is not None) and
1014 (bounds_initial is not None) and
1015 not (bounds_initial[0] <= default <= bounds_initial[1])
1018 obj = obj_initial(value, bounds, impl, expl, default, optional)
1020 value_expected = default if value is None else value
1022 default_initial if value_expected is None
1025 self.assertEqual(obj, value_expected)
1026 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1027 self.assertEqual(obj.expl_tag, expl or expl_initial)
1030 default_initial if default is None else default,
1032 if obj.default is None:
1033 optional = optional_initial if optional is None else optional
1034 optional = False if optional is None else optional
1037 self.assertEqual(obj.optional, optional)
1039 (obj._bound_min, obj._bound_max),
1040 bounds or bounds_initial or (float("-inf"), float("+inf")),
1044 {} if _specs_initial is None else dict(_specs_initial),
1047 @given(integer_values_strategy())
1048 def test_copy(self, values):
1049 for klass in (Integer, IntegerInherited):
1050 obj = klass(*values)
1051 for copy_func in copy_funcs:
1052 obj_copied = copy_func(obj)
1053 self.assert_copied_basic_fields(obj, obj_copied)
1054 self.assertEqual(obj.specs, obj_copied.specs)
1055 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1056 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1057 self.assertEqual(obj._value, obj_copied._value)
1061 integers(min_value=1).map(tag_encode),
1063 def test_stripped(self, value, tag_impl):
1064 obj = Integer(value, impl=tag_impl)
1065 with self.assertRaises(NotEnoughData):
1066 obj.decode(obj.encode()[:-1])
1070 integers(min_value=1).map(tag_ctxc),
1072 def test_stripped_expl(self, value, tag_expl):
1073 obj = Integer(value, expl=tag_expl)
1074 with self.assertRaises(NotEnoughData):
1075 obj.decode(obj.encode()[:-1])
1077 def test_zero_len(self):
1078 with self.assertRaises(NotEnoughData):
1079 Integer().decode(b"".join((
1080 Integer.tag_default,
1085 integers(min_value=31),
1086 integers(min_value=0),
1089 def test_bad_tag(self, tag, offset, decode_path):
1090 with self.assertRaises(DecodeError) as err:
1092 tag_encode(tag)[:-1],
1094 decode_path=decode_path,
1097 self.assertEqual(err.exception.offset, offset)
1098 self.assertEqual(err.exception.decode_path, decode_path)
1101 integers(min_value=128),
1102 integers(min_value=0),
1105 def test_bad_len(self, l, offset, decode_path):
1106 with self.assertRaises(DecodeError) as err:
1108 Integer.tag_default + len_encode(l)[:-1],
1110 decode_path=decode_path,
1113 self.assertEqual(err.exception.offset, offset)
1114 self.assertEqual(err.exception.decode_path, decode_path)
1117 sets(integers(), min_size=2, max_size=2),
1118 integers(min_value=0),
1121 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1122 value, bound_min = list(sorted(ints))
1125 bounds = (bound_min, bound_min)
1126 with self.assertRaises(DecodeError) as err:
1128 Integer(value).encode(),
1130 decode_path=decode_path,
1133 self.assertEqual(err.exception.offset, offset)
1134 self.assertEqual(err.exception.decode_path, decode_path)
1136 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1138 integer_values_strategy(),
1140 integers(min_value=1).map(tag_ctxc),
1141 integers(min_value=0),
1145 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1146 for klass in (Integer, IntegerInherited):
1147 _, _, _, _, default, optional, _, _decoded = values
1156 pprint(obj, big_blobs=True, with_decode_path=True)
1157 self.assertFalse(obj.expled)
1158 obj_encoded = obj.encode()
1159 self.assertEqual(encode2pass(obj), obj_encoded)
1160 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1161 obj_expled = obj(value, expl=tag_expl)
1162 self.assertTrue(obj_expled.expled)
1164 list(obj_expled.pps())
1165 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1166 obj_expled_encoded = obj_expled.encode()
1167 obj_expled_cer = encode_cer(obj_expled)
1168 self.assertNotEqual(obj_expled_cer, obj_encoded)
1169 self.assertSequenceEqual(
1170 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1173 ctx_copied = deepcopy(ctx_dummy)
1174 obj_decoded, tail = obj_expled.decode(
1175 obj_expled_encoded + tail_junk,
1179 self.assertDictEqual(ctx_copied, ctx_dummy)
1181 list(obj_decoded.pps())
1182 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1183 self.assertEqual(tail, tail_junk)
1184 self.assertEqual(obj_decoded, obj_expled)
1185 self.assertNotEqual(obj_decoded, obj)
1186 self.assertEqual(int(obj_decoded), int(obj_expled))
1187 self.assertEqual(int(obj_decoded), int(obj))
1188 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1189 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1190 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1192 obj_decoded.expl_llen,
1193 len(len_encode(len(obj_encoded))),
1195 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1196 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1199 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1201 self.assertEqual(obj_decoded.expl_offset, offset)
1202 assert_exceeding_data(
1204 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1208 evgens = list(obj_expled.decode_evgen(
1209 obj_expled_encoded + tail_junk,
1211 decode_path=decode_path,
1214 self.assertEqual(len(evgens), 1)
1215 _decode_path, obj, tail = evgens[0]
1216 self.assertSequenceEqual(tail, tail_junk)
1217 self.assertEqual(_decode_path, decode_path)
1218 self.assertEqual(obj, obj_decoded)
1219 self.assertEqual(obj.expl_offset, offset)
1223 def test_go_vectors_valid(self):
1224 for data, expect in ((
1228 (b"\xff\x7f", -129),
1232 (b"\xff\x00", -256),
1236 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1237 (b"\x80\x00\x00\x00", -2147483648),
1240 Integer().decode(b"".join((
1241 Integer.tag_default,
1242 len_encode(len(data)),
1248 def test_go_vectors_invalid(self):
1253 with self.assertRaises(DecodeError):
1254 Integer().decode(b"".join((
1255 Integer.tag_default,
1256 len_encode(len(data)),
1262 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1265 if draw(booleans()):
1266 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1268 integers(min_value=0, max_value=255),
1269 min_size=len(schema),
1270 max_size=len(schema),
1272 schema = list(zip(schema, bits))
1274 def _value(value_required):
1275 if not value_required and draw(booleans()):
1277 generation_choice = 0
1279 generation_choice = draw(sampled_from((1, 2, 3)))
1280 if generation_choice == 1 or draw(booleans()):
1281 return "'%s'B" % "".join(draw(lists(
1282 sampled_from(("0", "1")),
1283 max_size=len(schema),
1285 if generation_choice == 2 or draw(booleans()):
1286 return draw(binary(max_size=len(schema) // 8))
1287 if generation_choice == 3 or draw(booleans()):
1288 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1290 value = _value(value_required)
1291 default = _value(value_required=False)
1295 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1297 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1298 optional = draw(one_of(none(), booleans()))
1300 draw(integers(min_value=0)),
1301 draw(integers(min_value=0)),
1302 draw(integers(min_value=0)),
1304 return (schema, value, impl, expl, default, optional, _decoded)
1307 class BitStringInherited(BitString):
1311 class TestBitString(CommonMixin, TestCase):
1312 base_klass = BitString
1314 @given(lists(booleans()))
1315 def test_b_encoding(self, bits):
1316 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1317 self.assertEqual(obj.bit_len, len(bits))
1318 self.assertSequenceEqual(list(obj), bits)
1319 for i, bit in enumerate(bits):
1320 self.assertEqual(obj[i], bit)
1322 @given(lists(booleans()))
1323 def test_out_of_bounds_bits(self, bits):
1324 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1325 for i in range(len(bits), len(bits) * 2):
1326 self.assertFalse(obj[i])
1328 def test_bad_b_encoding(self):
1329 with self.assertRaises(ValueError):
1330 BitString("'010120101'B")
1333 integers(min_value=1, max_value=255),
1334 integers(min_value=1, max_value=255),
1336 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1337 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1338 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1339 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1341 class BS(BitString):
1342 schema = (("whatever", 0),)
1343 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1344 self.assertEqual(obj.bit_len, leading_zeros + 1)
1345 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1347 def test_zero_len(self):
1348 with self.assertRaises(NotEnoughData):
1349 BitString().decode(b"".join((
1350 BitString.tag_default,
1354 def test_invalid_value_type(self):
1355 with self.assertRaises(InvalidValueType) as err:
1358 with self.assertRaises(InvalidValueType) as err:
1362 def test_obj_unknown(self):
1363 with self.assertRaises(ObjUnknown) as err:
1364 BitString(b"whatever")["whenever"]
1367 def test_get_invalid_type(self):
1368 with self.assertRaises(InvalidValueType) as err:
1369 BitString(b"whatever")[(1, 2, 3)]
1372 @given(data_strategy())
1373 def test_unknown_name(self, d):
1374 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1375 missing = _schema.pop()
1377 class BS(BitString):
1378 schema = [(n, i) for i, n in enumerate(_schema)]
1379 with self.assertRaises(ObjUnknown) as err:
1384 def test_optional(self, optional):
1385 obj = BitString(default=BitString(b""), optional=optional)
1386 self.assertTrue(obj.optional)
1389 def test_ready(self, value):
1391 self.assertFalse(obj.ready)
1394 pprint(obj, big_blobs=True, with_decode_path=True)
1395 with self.assertRaises(ObjNotReady) as err:
1398 with self.assertRaises(ObjNotReady) as err:
1400 obj = BitString(value)
1401 self.assertTrue(obj.ready)
1404 pprint(obj, big_blobs=True, with_decode_path=True)
1407 tuples(integers(min_value=0), binary()),
1408 tuples(integers(min_value=0), binary()),
1412 def test_comparison(self, value1, value2, tag1, tag2):
1413 for klass in (BitString, BitStringInherited):
1414 obj1 = klass(value1)
1415 obj2 = klass(value2)
1416 self.assertEqual(obj1 == obj2, value1 == value2)
1417 self.assertEqual(obj1 != obj2, value1 != value2)
1418 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1419 obj1 = klass(value1, impl=tag1)
1420 obj2 = klass(value1, impl=tag2)
1421 self.assertEqual(obj1 == obj2, tag1 == tag2)
1422 self.assertEqual(obj1 != obj2, tag1 != tag2)
1424 @given(data_strategy())
1425 def test_call(self, d):
1426 for klass in (BitString, BitStringInherited):
1435 ) = d.draw(bit_string_values_strategy())
1438 schema = schema_initial
1440 value=value_initial,
1443 default=default_initial,
1444 optional=optional_initial or False,
1445 _decoded=_decoded_initial,
1455 ) = d.draw(bit_string_values_strategy(
1456 schema=schema_initial,
1457 do_expl=impl_initial is None,
1466 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1467 self.assertEqual(obj.expl_tag, expl or expl_initial)
1468 if obj.default is None:
1469 optional = optional_initial if optional is None else optional
1470 optional = False if optional is None else optional
1473 self.assertEqual(obj.optional, optional)
1474 self.assertEqual(obj.specs, obj_initial.specs)
1476 @given(bit_string_values_strategy())
1477 def test_copy(self, values):
1478 for klass in (BitString, BitStringInherited):
1479 _schema, value, impl, expl, default, optional, _decoded = values
1489 optional=optional or False,
1492 for copy_func in copy_funcs:
1493 obj_copied = copy_func(obj)
1494 self.assert_copied_basic_fields(obj, obj_copied)
1495 self.assertEqual(obj.specs, obj_copied.specs)
1496 self.assertEqual(obj._value, obj_copied._value)
1500 integers(min_value=1).map(tag_encode),
1502 def test_stripped(self, value, tag_impl):
1503 obj = BitString(value, impl=tag_impl)
1504 with self.assertRaises(NotEnoughData):
1505 obj.decode(obj.encode()[:-1])
1509 integers(min_value=1).map(tag_ctxc),
1511 def test_stripped_expl(self, value, tag_expl):
1512 obj = BitString(value, expl=tag_expl)
1513 with self.assertRaises(NotEnoughData):
1514 obj.decode(obj.encode()[:-1])
1517 integers(min_value=31),
1518 integers(min_value=0),
1521 def test_bad_tag(self, tag, offset, decode_path):
1522 with self.assertRaises(DecodeError) as err:
1524 tag_encode(tag)[:-1],
1526 decode_path=decode_path,
1529 self.assertEqual(err.exception.offset, offset)
1530 self.assertEqual(err.exception.decode_path, decode_path)
1533 integers(min_value=128),
1534 integers(min_value=0),
1537 def test_bad_len(self, l, offset, decode_path):
1538 with self.assertRaises(DecodeError) as err:
1540 BitString.tag_default + len_encode(l)[:-1],
1542 decode_path=decode_path,
1545 self.assertEqual(err.exception.offset, offset)
1546 self.assertEqual(err.exception.decode_path, decode_path)
1548 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1549 @given(data_strategy())
1550 def test_symmetric(self, d):
1559 ) = d.draw(bit_string_values_strategy(value_required=True))
1560 tail_junk = d.draw(binary(max_size=5))
1561 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1562 offset = d.draw(integers(min_value=0))
1563 decode_path = d.draw(decode_path_strat)
1564 for klass in (BitString, BitStringInherited):
1575 pprint(obj, big_blobs=True, with_decode_path=True)
1576 self.assertFalse(obj.expled)
1577 obj_encoded = obj.encode()
1578 self.assertEqual(encode2pass(obj), obj_encoded)
1579 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1580 obj_expled = obj(value, expl=tag_expl)
1581 self.assertTrue(obj_expled.expled)
1583 list(obj_expled.pps())
1584 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1585 obj_expled_encoded = obj_expled.encode()
1586 obj_expled_cer = encode_cer(obj_expled)
1587 self.assertNotEqual(obj_expled_cer, obj_encoded)
1588 self.assertSequenceEqual(
1589 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1592 ctx_copied = deepcopy(ctx_dummy)
1593 obj_decoded, tail = obj_expled.decode(
1594 obj_expled_encoded + tail_junk,
1598 self.assertDictEqual(ctx_copied, ctx_dummy)
1600 list(obj_decoded.pps())
1601 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1602 self.assertEqual(tail, tail_junk)
1603 self.assertEqual(obj_decoded, obj_expled)
1604 self.assertNotEqual(obj_decoded, obj)
1605 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1606 self.assertEqual(bytes(obj_decoded), bytes(obj))
1607 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1608 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1609 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1611 obj_decoded.expl_llen,
1612 len(len_encode(len(obj_encoded))),
1614 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1615 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1618 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1620 self.assertEqual(obj_decoded.expl_offset, offset)
1621 if isinstance(value, tuple):
1622 self.assertSetEqual(set(value), set(obj_decoded.named))
1625 assert_exceeding_data(
1627 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1631 evgens = list(obj_expled.decode_evgen(
1632 obj_expled_encoded + tail_junk,
1634 decode_path=decode_path,
1637 self.assertEqual(len(evgens), 1)
1638 _decode_path, obj, tail = evgens[0]
1639 self.assertSequenceEqual(tail, tail_junk)
1640 self.assertEqual(_decode_path, decode_path)
1641 self.assertEqual(obj.expl_offset, offset)
1645 @given(integers(min_value=1, max_value=255))
1646 def test_bad_zero_value(self, pad_size):
1647 with self.assertRaises(DecodeError):
1648 BitString().decode(b"".join((
1649 BitString.tag_default,
1654 def test_go_vectors_invalid(self):
1660 with self.assertRaises(DecodeError):
1661 BitString().decode(b"".join((
1662 BitString.tag_default,
1667 def test_go_vectors_valid(self):
1668 obj, _ = BitString().decode(b"".join((
1669 BitString.tag_default,
1673 self.assertEqual(bytes(obj), b"")
1674 self.assertEqual(obj.bit_len, 0)
1676 obj, _ = BitString().decode(b"".join((
1677 BitString.tag_default,
1681 self.assertEqual(bytes(obj), b"\x00")
1682 self.assertEqual(obj.bit_len, 1)
1684 obj = BitString((16, b"\x82\x40"))
1685 self.assertTrue(obj[0])
1686 self.assertFalse(obj[1])
1687 self.assertTrue(obj[6])
1688 self.assertTrue(obj[9])
1689 self.assertFalse(obj[17])
1691 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1693 integers(min_value=1, max_value=30),
1696 binary(min_size=1, max_size=5),
1698 binary(min_size=1, max_size=5),
1706 lists(booleans(), min_size=1),
1710 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1711 def chunk_constructed(contents):
1713 tag_encode(form=TagFormConstructed, num=3) +
1715 b"".join(BitString(content).encode() for content in contents) +
1719 chunks_len_expected = []
1720 payload_expected = b""
1721 bit_len_expected = 0
1722 for chunk_input in chunk_inputs:
1723 if isinstance(chunk_input, binary_type):
1724 chunks.append(BitString(chunk_input).encode())
1725 payload_expected += chunk_input
1726 bit_len_expected += len(chunk_input) * 8
1727 chunks_len_expected.append(len(chunk_input) + 1)
1729 chunks.append(chunk_constructed(chunk_input))
1730 payload = b"".join(chunk_input)
1731 payload_expected += payload
1732 bit_len_expected += len(payload) * 8
1733 for c in chunk_input:
1734 chunks_len_expected.append(len(c) + 1)
1735 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1736 chunk_last = BitString("'%s'B" % "".join(
1737 "1" if bit else "0" for bit in chunk_last_bits
1739 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1740 payload_expected += bytes(chunk_last)
1741 bit_len_expected += chunk_last.bit_len
1742 encoded_indefinite = (
1743 tag_encode(form=TagFormConstructed, num=impl) +
1746 chunk_last.encode() +
1749 encoded_definite = (
1750 tag_encode(form=TagFormConstructed, num=impl) +
1751 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1755 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1756 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1757 for lenindef_expected, encoded in (
1758 (True, encoded_indefinite),
1759 (False, encoded_definite),
1761 obj, tail = BitString(impl=tag_encode(impl)).decode(
1763 ctx={"bered": True},
1765 self.assertSequenceEqual(tail, junk)
1766 self.assertEqual(obj.bit_len, bit_len_expected)
1767 self.assertSequenceEqual(bytes(obj), payload_expected)
1768 self.assertTrue(obj.ber_encoded)
1769 self.assertEqual(obj.lenindef, lenindef_expected)
1770 self.assertTrue(obj.bered)
1772 self.assertTrue(obj.ber_encoded)
1773 self.assertEqual(obj.lenindef, lenindef_expected)
1774 self.assertTrue(obj.bered)
1775 self.assertEqual(len(encoded), obj.tlvlen)
1778 pprint(obj, big_blobs=True, with_decode_path=True)
1780 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1782 decode_path=decode_path,
1783 ctx={"bered": True},
1785 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1786 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1787 self.assertGreater(len(dp), len(decode_path))
1788 self.assertEqual(obj.vlen, chunk_len_expected)
1791 integers(min_value=0),
1794 def test_ber_definite_too_short(self, offset, decode_path):
1795 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1797 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1799 decode_path=decode_path,
1800 ctx={"bered": True},
1802 self.assertEqual(err.exception.decode_path, decode_path)
1803 self.assertEqual(err.exception.offset, offset)
1806 integers(min_value=0),
1809 def test_ber_definite_no_data(self, offset, decode_path):
1810 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1812 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1814 decode_path=decode_path,
1815 ctx={"bered": True},
1817 self.assertEqual(err.exception.decode_path, decode_path)
1818 self.assertEqual(err.exception.offset, offset)
1821 integers(min_value=0),
1823 integers(min_value=1, max_value=3),
1825 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1826 bs = BitString(b"data").encode()
1827 with self.assertRaises(NotEnoughData) as err:
1829 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1831 decode_path=decode_path,
1832 ctx={"bered": True},
1834 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1835 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1838 integers(min_value=0),
1840 integers(min_value=1, max_value=3),
1842 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1843 bs = BitString(b"data").encode()
1844 bs_longer = BitString(b"data-longer").encode()
1845 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1848 tag_encode(3, form=TagFormConstructed) +
1849 len_encode((chunks + 1) * len(bs)) +
1854 decode_path=decode_path,
1855 ctx={"bered": True},
1857 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1858 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1861 integers(min_value=0),
1864 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1865 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1867 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1869 decode_path=decode_path,
1870 ctx={"bered": True},
1872 self.assertEqual(err.exception.decode_path, decode_path)
1873 self.assertEqual(err.exception.offset, offset)
1875 @given(data_strategy())
1876 def test_ber_indefinite_not_multiple(self, d):
1877 bs_short = BitString("'A'H").encode()
1878 bs_full = BitString("'AA'H").encode()
1879 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1880 chunks.append(bs_short)
1881 d.draw(permutations(chunks))
1882 chunks.append(bs_short)
1883 offset = d.draw(integers(min_value=0))
1884 decode_path = d.draw(decode_path_strat)
1885 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1888 tag_encode(3, form=TagFormConstructed) +
1894 decode_path=decode_path,
1895 ctx={"bered": True},
1898 err.exception.decode_path,
1899 decode_path + (str(chunks.index(bs_short)),),
1902 err.exception.offset,
1903 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1906 def test_x690_vector(self):
1907 vector = BitString("'0A3B5F291CD'H")
1908 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1909 self.assertSequenceEqual(tail, b"")
1910 self.assertEqual(obj, vector)
1911 obj, tail = BitString().decode(
1912 hexdec("23800303000A3B0305045F291CD00000"),
1913 ctx={"bered": True},
1915 self.assertSequenceEqual(tail, b"")
1916 self.assertEqual(obj, vector)
1917 self.assertTrue(obj.ber_encoded)
1918 self.assertTrue(obj.lenindef)
1919 self.assertTrue(obj.bered)
1921 self.assertTrue(obj.ber_encoded)
1922 self.assertTrue(obj.lenindef)
1923 self.assertTrue(obj.bered)
1925 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1926 @given(integers(min_value=1000, max_value=3000))
1927 def test_cer(self, data_len):
1928 data = urandom(data_len)
1929 encoded = encode_cer(BitString(data))
1930 ctx = {"bered": True}
1931 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1932 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1933 evgens_expected = data_len // 999
1934 if evgens_expected * 999 != data_len:
1935 evgens_expected += 1
1936 evgens_expected += 1
1937 self.assertEqual(len(evgens), evgens_expected)
1938 for (_, obj, _) in evgens[:-2]:
1939 self.assertEqual(obj.vlen, 1000)
1940 _, obj, _ = evgens[-2]
1941 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1945 def octet_string_values_strategy(draw, do_expl=False):
1946 bound_min, bound_max = sorted(draw(sets(
1947 integers(min_value=0, max_value=1 << 7),
1951 value = draw(one_of(
1953 binary(min_size=bound_min, max_size=bound_max),
1955 default = draw(one_of(
1957 binary(min_size=bound_min, max_size=bound_max),
1960 if draw(booleans()):
1961 bounds = (bound_min, bound_max)
1965 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1967 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1968 optional = draw(one_of(none(), booleans()))
1970 draw(integers(min_value=0)),
1971 draw(integers(min_value=0)),
1972 draw(integers(min_value=0)),
1974 return (value, bounds, impl, expl, default, optional, _decoded)
1977 class OctetStringInherited(OctetString):
1981 class TestOctetString(CommonMixin, TestCase):
1982 base_klass = OctetString
1984 def test_invalid_value_type(self):
1985 with self.assertRaises(InvalidValueType) as err:
1986 OctetString(text_type(123))
1990 def test_optional(self, optional):
1991 obj = OctetString(default=OctetString(b""), optional=optional)
1992 self.assertTrue(obj.optional)
1995 def test_ready(self, value):
1997 self.assertFalse(obj.ready)
2000 pprint(obj, big_blobs=True, with_decode_path=True)
2001 with self.assertRaises(ObjNotReady) as err:
2004 with self.assertRaises(ObjNotReady) as err:
2006 obj = OctetString(value)
2007 self.assertTrue(obj.ready)
2010 pprint(obj, big_blobs=True, with_decode_path=True)
2012 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2013 def test_comparison(self, value1, value2, tag1, tag2):
2014 for klass in (OctetString, OctetStringInherited):
2015 obj1 = klass(value1)
2016 obj2 = klass(value2)
2017 self.assertEqual(obj1 == obj2, value1 == value2)
2018 self.assertEqual(obj1 != obj2, value1 != value2)
2019 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2020 obj1 = klass(value1, impl=tag1)
2021 obj2 = klass(value1, impl=tag2)
2022 self.assertEqual(obj1 == obj2, tag1 == tag2)
2023 self.assertEqual(obj1 != obj2, tag1 != tag2)
2025 @given(lists(binary()))
2026 def test_sorted_works(self, values):
2027 self.assertSequenceEqual(
2028 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2032 @given(data_strategy())
2033 def test_bounds_satisfied(self, d):
2034 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2035 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2036 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2037 OctetString(value=value, bounds=(bound_min, bound_max))
2039 @given(data_strategy())
2040 def test_bounds_unsatisfied(self, d):
2041 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2042 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2043 value = d.draw(binary(max_size=bound_min - 1))
2044 with self.assertRaises(BoundsError) as err:
2045 OctetString(value=value, bounds=(bound_min, bound_max))
2047 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2048 OctetString(bounds=(bound_min, bound_max)).decode(
2049 OctetString(value).encode()
2052 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2053 OctetString(bounds=(bound_min, bound_max)).decode(
2054 encode2pass(OctetString(value))
2056 value = d.draw(binary(min_size=bound_max + 1))
2057 with self.assertRaises(BoundsError) as err:
2058 OctetString(value=value, bounds=(bound_min, bound_max))
2060 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2061 OctetString(bounds=(bound_min, bound_max)).decode(
2062 OctetString(value).encode()
2065 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2066 OctetString(bounds=(bound_min, bound_max)).decode(
2067 encode2pass(OctetString(value))
2070 @given(data_strategy())
2071 def test_call(self, d):
2072 for klass in (OctetString, OctetStringInherited):
2081 ) = d.draw(octet_string_values_strategy())
2082 obj_initial = klass(
2088 optional_initial or False,
2099 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2100 if (default is None) and (obj_initial.default is not None):
2103 (bounds is None) and
2104 (value is not None) and
2105 (bounds_initial is not None) and
2106 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2110 (bounds is None) and
2111 (default is not None) and
2112 (bounds_initial is not None) and
2113 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2116 obj = obj_initial(value, bounds, impl, expl, default, optional)
2118 value_expected = default if value is None else value
2120 default_initial if value_expected is None
2123 self.assertEqual(obj, value_expected)
2124 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2125 self.assertEqual(obj.expl_tag, expl or expl_initial)
2128 default_initial if default is None else default,
2130 if obj.default is None:
2131 optional = optional_initial if optional is None else optional
2132 optional = False if optional is None else optional
2135 self.assertEqual(obj.optional, optional)
2137 (obj._bound_min, obj._bound_max),
2138 bounds or bounds_initial or (0, float("+inf")),
2141 @given(octet_string_values_strategy())
2142 def test_copy(self, values):
2143 for klass in (OctetString, OctetStringInherited):
2144 obj = klass(*values)
2145 for copy_func in copy_funcs:
2146 obj_copied = copy_func(obj)
2147 self.assert_copied_basic_fields(obj, obj_copied)
2148 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2149 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2150 self.assertEqual(obj._value, obj_copied._value)
2154 integers(min_value=1).map(tag_encode),
2156 def test_stripped(self, value, tag_impl):
2157 obj = OctetString(value, impl=tag_impl)
2158 with self.assertRaises(NotEnoughData):
2159 obj.decode(obj.encode()[:-1])
2163 integers(min_value=1).map(tag_ctxc),
2165 def test_stripped_expl(self, value, tag_expl):
2166 obj = OctetString(value, expl=tag_expl)
2167 with self.assertRaises(NotEnoughData):
2168 obj.decode(obj.encode()[:-1])
2171 integers(min_value=31),
2172 integers(min_value=0),
2175 def test_bad_tag(self, tag, offset, decode_path):
2176 with self.assertRaises(DecodeError) as err:
2177 OctetString().decode(
2178 tag_encode(tag)[:-1],
2180 decode_path=decode_path,
2183 self.assertEqual(err.exception.offset, offset)
2184 self.assertEqual(err.exception.decode_path, decode_path)
2187 integers(min_value=128),
2188 integers(min_value=0),
2191 def test_bad_len(self, l, offset, decode_path):
2192 with self.assertRaises(DecodeError) as err:
2193 OctetString().decode(
2194 OctetString.tag_default + len_encode(l)[:-1],
2196 decode_path=decode_path,
2199 self.assertEqual(err.exception.offset, offset)
2200 self.assertEqual(err.exception.decode_path, decode_path)
2203 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2204 integers(min_value=0),
2207 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2208 value, bound_min = list(sorted(ints))
2210 class String(OctetString):
2211 bounds = (bound_min, bound_min)
2212 with self.assertRaises(DecodeError) as err:
2214 OctetString(b"\x00" * value).encode(),
2216 decode_path=decode_path,
2219 self.assertEqual(err.exception.offset, offset)
2220 self.assertEqual(err.exception.decode_path, decode_path)
2222 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2224 octet_string_values_strategy(),
2226 integers(min_value=1).map(tag_ctxc),
2227 integers(min_value=0),
2231 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2232 for klass in (OctetString, OctetStringInherited):
2233 _, _, _, _, default, optional, _decoded = values
2242 pprint(obj, big_blobs=True, with_decode_path=True)
2243 self.assertFalse(obj.expled)
2244 obj_encoded = obj.encode()
2245 self.assertEqual(encode2pass(obj), obj_encoded)
2246 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2247 obj_expled = obj(value, expl=tag_expl)
2248 self.assertTrue(obj_expled.expled)
2250 list(obj_expled.pps())
2251 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2252 obj_expled_encoded = obj_expled.encode()
2253 obj_expled_cer = encode_cer(obj_expled)
2254 self.assertNotEqual(obj_expled_cer, obj_encoded)
2255 self.assertSequenceEqual(
2256 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2259 ctx_copied = deepcopy(ctx_dummy)
2260 obj_decoded, tail = obj_expled.decode(
2261 obj_expled_encoded + tail_junk,
2265 self.assertDictEqual(ctx_copied, ctx_dummy)
2267 list(obj_decoded.pps())
2268 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2269 self.assertEqual(tail, tail_junk)
2270 self.assertEqual(obj_decoded, obj_expled)
2271 self.assertNotEqual(obj_decoded, obj)
2272 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2273 self.assertEqual(bytes(obj_decoded), bytes(obj))
2274 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2275 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2276 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2278 obj_decoded.expl_llen,
2279 len(len_encode(len(obj_encoded))),
2281 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2282 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2285 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2287 self.assertEqual(obj_decoded.expl_offset, offset)
2288 assert_exceeding_data(
2290 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2294 evgens = list(obj_expled.decode_evgen(
2295 obj_expled_encoded + tail_junk,
2297 decode_path=decode_path,
2300 self.assertEqual(len(evgens), 1)
2301 _decode_path, obj, tail = evgens[0]
2302 self.assertSequenceEqual(tail, tail_junk)
2303 self.assertEqual(_decode_path, decode_path)
2304 self.assertEqual(obj.expl_offset, offset)
2308 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2310 integers(min_value=1, max_value=30),
2313 binary(min_size=1, max_size=5),
2315 binary(min_size=1, max_size=5),
2326 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2327 def chunk_constructed(contents):
2329 tag_encode(form=TagFormConstructed, num=4) +
2331 b"".join(OctetString(content).encode() for content in contents) +
2335 chunks_len_expected = []
2336 payload_expected = b""
2337 for chunk_input in chunk_inputs:
2338 if isinstance(chunk_input, binary_type):
2339 chunks.append(OctetString(chunk_input).encode())
2340 payload_expected += chunk_input
2341 chunks_len_expected.append(len(chunk_input))
2343 chunks.append(chunk_constructed(chunk_input))
2344 payload = b"".join(chunk_input)
2345 payload_expected += payload
2346 for c in chunk_input:
2347 chunks_len_expected.append(len(c))
2348 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2349 encoded_indefinite = (
2350 tag_encode(form=TagFormConstructed, num=impl) +
2355 encoded_definite = (
2356 tag_encode(form=TagFormConstructed, num=impl) +
2357 len_encode(len(b"".join(chunks))) +
2360 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2361 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2362 for lenindef_expected, encoded in (
2363 (True, encoded_indefinite),
2364 (False, encoded_definite),
2366 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2368 ctx={"bered": True},
2370 self.assertSequenceEqual(tail, junk)
2371 self.assertSequenceEqual(bytes(obj), payload_expected)
2372 self.assertTrue(obj.ber_encoded)
2373 self.assertEqual(obj.lenindef, lenindef_expected)
2374 self.assertTrue(obj.bered)
2376 self.assertTrue(obj.ber_encoded)
2377 self.assertEqual(obj.lenindef, lenindef_expected)
2378 self.assertTrue(obj.bered)
2379 self.assertEqual(len(encoded), obj.tlvlen)
2382 pprint(obj, big_blobs=True, with_decode_path=True)
2384 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2386 decode_path=decode_path,
2387 ctx={"bered": True},
2389 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2390 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2391 self.assertGreater(len(dp), len(decode_path))
2392 self.assertEqual(obj.vlen, chunk_len_expected)
2395 integers(min_value=0),
2398 def test_ber_definite_too_short(self, offset, decode_path):
2399 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2400 OctetString().decode(
2401 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2403 decode_path=decode_path,
2404 ctx={"bered": True},
2406 self.assertEqual(err.exception.decode_path, decode_path)
2407 self.assertEqual(err.exception.offset, offset)
2410 integers(min_value=0),
2412 integers(min_value=1, max_value=3),
2414 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2415 bs = OctetString(b"data").encode()
2416 with self.assertRaises(NotEnoughData) as err:
2417 OctetString().decode(
2418 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2420 decode_path=decode_path,
2421 ctx={"bered": True},
2423 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2424 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2427 integers(min_value=0),
2429 integers(min_value=1, max_value=3),
2431 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2432 bs = OctetString(b"data").encode()
2433 bs_longer = OctetString(b"data-longer").encode()
2434 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2435 OctetString().decode(
2437 tag_encode(4, form=TagFormConstructed) +
2438 len_encode((chunks + 1) * len(bs)) +
2443 decode_path=decode_path,
2444 ctx={"bered": True},
2446 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2447 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2449 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2450 @given(integers(min_value=1001, max_value=3000))
2451 def test_cer(self, data_len):
2452 data = urandom(data_len)
2453 encoded = encode_cer(OctetString(data))
2454 ctx = {"bered": True}
2455 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2456 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2457 evgens_expected = data_len // 1000
2458 if evgens_expected * 1000 != data_len:
2459 evgens_expected += 1
2460 evgens_expected += 1
2461 self.assertEqual(len(evgens), evgens_expected)
2462 for (_, obj, _) in evgens[:-2]:
2463 self.assertEqual(obj.vlen, 1000)
2464 _, obj, _ = evgens[-2]
2465 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2469 def null_values_strategy(draw, do_expl=False):
2473 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2475 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2476 optional = draw(one_of(none(), booleans()))
2478 draw(integers(min_value=0)),
2479 draw(integers(min_value=0)),
2480 draw(integers(min_value=0)),
2482 return (impl, expl, optional, _decoded)
2485 class NullInherited(Null):
2489 class TestNull(CommonMixin, TestCase):
2492 def test_ready(self):
2494 self.assertTrue(obj.ready)
2497 pprint(obj, big_blobs=True, with_decode_path=True)
2499 @given(binary(min_size=1), binary(min_size=1))
2500 def test_comparison(self, tag1, tag2):
2501 for klass in (Null, NullInherited):
2502 obj1 = klass(impl=tag1)
2503 obj2 = klass(impl=tag2)
2504 self.assertEqual(obj1 == obj2, tag1 == tag2)
2505 self.assertEqual(obj1 != obj2, tag1 != tag2)
2506 self.assertNotEqual(obj1, tag2)
2508 @given(data_strategy())
2509 def test_call(self, d):
2510 for klass in (Null, NullInherited):
2516 ) = d.draw(null_values_strategy())
2517 obj_initial = klass(
2520 optional=optional_initial or False,
2521 _decoded=_decoded_initial,
2528 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2529 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2530 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2531 self.assertEqual(obj.expl_tag, expl or expl_initial)
2532 optional = optional_initial if optional is None else optional
2533 optional = False if optional is None else optional
2534 self.assertEqual(obj.optional, optional)
2536 @given(null_values_strategy())
2537 def test_copy(self, values):
2538 for klass in (Null, NullInherited):
2539 impl, expl, optional, _decoded = values
2543 optional=optional or False,
2546 for copy_func in copy_funcs:
2547 obj_copied = copy_func(obj)
2548 self.assert_copied_basic_fields(obj, obj_copied)
2550 @given(integers(min_value=1).map(tag_encode))
2551 def test_stripped(self, tag_impl):
2552 obj = Null(impl=tag_impl)
2553 with self.assertRaises(NotEnoughData):
2554 obj.decode(obj.encode()[:-1])
2556 @given(integers(min_value=1).map(tag_ctxc))
2557 def test_stripped_expl(self, tag_expl):
2558 obj = Null(expl=tag_expl)
2559 with self.assertRaises(NotEnoughData):
2560 obj.decode(obj.encode()[:-1])
2563 integers(min_value=31),
2564 integers(min_value=0),
2567 def test_bad_tag(self, tag, offset, decode_path):
2568 with self.assertRaises(DecodeError) as err:
2570 tag_encode(tag)[:-1],
2572 decode_path=decode_path,
2575 self.assertEqual(err.exception.offset, offset)
2576 self.assertEqual(err.exception.decode_path, decode_path)
2579 integers(min_value=128),
2580 integers(min_value=0),
2583 def test_bad_len(self, l, offset, decode_path):
2584 with self.assertRaises(DecodeError) as err:
2586 Null.tag_default + len_encode(l)[:-1],
2588 decode_path=decode_path,
2591 self.assertEqual(err.exception.offset, offset)
2592 self.assertEqual(err.exception.decode_path, decode_path)
2594 @given(binary(min_size=1))
2595 def test_tag_mismatch(self, impl):
2596 assume(impl != Null.tag_default)
2597 with self.assertRaises(TagMismatch):
2598 Null(impl=impl).decode(Null().encode())
2601 null_values_strategy(),
2602 integers(min_value=1).map(tag_ctxc),
2603 integers(min_value=0),
2607 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2608 for klass in (Null, NullInherited):
2609 _, _, optional, _decoded = values
2610 obj = klass(optional=optional, _decoded=_decoded)
2613 pprint(obj, big_blobs=True, with_decode_path=True)
2614 self.assertFalse(obj.expled)
2615 obj_encoded = obj.encode()
2616 self.assertEqual(encode2pass(obj), obj_encoded)
2617 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2618 obj_expled = obj(expl=tag_expl)
2619 self.assertTrue(obj_expled.expled)
2621 list(obj_expled.pps())
2622 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2623 obj_expled_encoded = obj_expled.encode()
2624 obj_expled_cer = encode_cer(obj_expled)
2625 self.assertNotEqual(obj_expled_cer, obj_encoded)
2626 self.assertSequenceEqual(
2627 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2630 ctx_copied = deepcopy(ctx_dummy)
2631 obj_decoded, tail = obj_expled.decode(
2632 obj_expled_encoded + tail_junk,
2636 self.assertDictEqual(ctx_copied, ctx_dummy)
2638 list(obj_decoded.pps())
2639 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2640 self.assertEqual(tail, tail_junk)
2641 self.assertEqual(obj_decoded, obj_expled)
2642 self.assertNotEqual(obj_decoded, obj)
2643 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2644 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2645 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2647 obj_decoded.expl_llen,
2648 len(len_encode(len(obj_encoded))),
2650 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2651 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2654 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2656 self.assertEqual(obj_decoded.expl_offset, offset)
2657 assert_exceeding_data(
2659 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2663 evgens = list(obj_expled.decode_evgen(
2664 obj_expled_encoded + tail_junk,
2666 decode_path=decode_path,
2669 self.assertEqual(len(evgens), 1)
2670 _decode_path, obj, tail = evgens[0]
2671 self.assertSequenceEqual(tail, tail_junk)
2672 self.assertEqual(_decode_path, decode_path)
2673 self.assertEqual(obj, obj_decoded)
2674 self.assertEqual(obj.expl_offset, offset)
2678 @given(integers(min_value=1))
2679 def test_invalid_len(self, l):
2680 with self.assertRaises(InvalidLength):
2681 Null().decode(b"".join((
2688 def oid_strategy(draw):
2689 first_arc = draw(integers(min_value=0, max_value=2))
2691 if first_arc in (0, 1):
2692 second_arc = draw(integers(min_value=0, max_value=39))
2694 second_arc = draw(integers(min_value=0))
2695 other_arcs = draw(lists(integers(min_value=0)))
2696 return tuple([first_arc, second_arc] + other_arcs)
2700 def oid_values_strategy(draw, do_expl=False):
2701 value = draw(one_of(none(), oid_strategy()))
2705 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2707 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2708 default = draw(one_of(none(), oid_strategy()))
2709 optional = draw(one_of(none(), booleans()))
2711 draw(integers(min_value=0)),
2712 draw(integers(min_value=0)),
2713 draw(integers(min_value=0)),
2715 return (value, impl, expl, default, optional, _decoded)
2718 class ObjectIdentifierInherited(ObjectIdentifier):
2722 class TestObjectIdentifier(CommonMixin, TestCase):
2723 base_klass = ObjectIdentifier
2725 def test_invalid_value_type(self):
2726 with self.assertRaises(InvalidValueType) as err:
2727 ObjectIdentifier(123)
2731 def test_optional(self, optional):
2732 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2733 self.assertTrue(obj.optional)
2735 @given(oid_strategy())
2736 def test_ready(self, value):
2737 obj = ObjectIdentifier()
2738 self.assertFalse(obj.ready)
2741 pprint(obj, big_blobs=True, with_decode_path=True)
2742 with self.assertRaises(ObjNotReady) as err:
2745 with self.assertRaises(ObjNotReady) as err:
2747 obj = ObjectIdentifier(value)
2748 self.assertTrue(obj.ready)
2749 self.assertFalse(obj.ber_encoded)
2752 pprint(obj, big_blobs=True, with_decode_path=True)
2755 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2756 def test_comparison(self, value1, value2, tag1, tag2):
2757 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2758 obj1 = klass(value1)
2759 obj2 = klass(value2)
2760 self.assertEqual(obj1 == obj2, value1 == value2)
2761 self.assertEqual(obj1 != obj2, value1 != value2)
2762 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2763 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2764 obj1 = klass(value1, impl=tag1)
2765 obj2 = klass(value1, impl=tag2)
2766 self.assertEqual(obj1 == obj2, tag1 == tag2)
2767 self.assertEqual(obj1 != obj2, tag1 != tag2)
2769 @given(lists(oid_strategy()))
2770 def test_sorted_works(self, values):
2771 self.assertSequenceEqual(
2772 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2776 @given(data_strategy())
2777 def test_call(self, d):
2778 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2786 ) = d.draw(oid_values_strategy())
2787 obj_initial = klass(
2788 value=value_initial,
2791 default=default_initial,
2792 optional=optional_initial or False,
2793 _decoded=_decoded_initial,
2802 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2811 value_expected = default if value is None else value
2813 default_initial if value_expected is None
2816 self.assertEqual(obj, value_expected)
2817 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2818 self.assertEqual(obj.expl_tag, expl or expl_initial)
2821 default_initial if default is None else default,
2823 if obj.default is None:
2824 optional = optional_initial if optional is None else optional
2825 optional = False if optional is None else optional
2828 self.assertEqual(obj.optional, optional)
2830 @given(oid_values_strategy())
2831 def test_copy(self, values):
2832 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2849 for copy_func in copy_funcs:
2850 obj_copied = copy_func(obj)
2851 self.assert_copied_basic_fields(obj, obj_copied)
2852 self.assertEqual(obj._value, obj_copied._value)
2854 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2857 integers(min_value=1).map(tag_encode),
2859 def test_stripped(self, value, tag_impl):
2860 obj = ObjectIdentifier(value, impl=tag_impl)
2861 with self.assertRaises(NotEnoughData):
2862 obj.decode(obj.encode()[:-1])
2866 integers(min_value=1).map(tag_ctxc),
2868 def test_stripped_expl(self, value, tag_expl):
2869 obj = ObjectIdentifier(value, expl=tag_expl)
2870 with self.assertRaises(NotEnoughData):
2871 obj.decode(obj.encode()[:-1])
2874 integers(min_value=31),
2875 integers(min_value=0),
2878 def test_bad_tag(self, tag, offset, decode_path):
2879 with self.assertRaises(DecodeError) as err:
2880 ObjectIdentifier().decode(
2881 tag_encode(tag)[:-1],
2883 decode_path=decode_path,
2886 self.assertEqual(err.exception.offset, offset)
2887 self.assertEqual(err.exception.decode_path, decode_path)
2890 integers(min_value=128),
2891 integers(min_value=0),
2894 def test_bad_len(self, l, offset, decode_path):
2895 with self.assertRaises(DecodeError) as err:
2896 ObjectIdentifier().decode(
2897 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2899 decode_path=decode_path,
2902 self.assertEqual(err.exception.offset, offset)
2903 self.assertEqual(err.exception.decode_path, decode_path)
2905 def test_zero_oid(self):
2906 with self.assertRaises(NotEnoughData):
2907 ObjectIdentifier().decode(
2908 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2911 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2912 @given(oid_strategy())
2913 def test_unfinished_oid(self, value):
2914 assume(list(value)[-1] > 255)
2915 obj_encoded = ObjectIdentifier(value).encode()
2916 obj, _ = ObjectIdentifier().decode(obj_encoded)
2917 data = obj_encoded[obj.tlen + obj.llen:-1]
2919 ObjectIdentifier.tag_default,
2920 len_encode(len(data)),
2923 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2926 @given(integers(min_value=0))
2927 def test_invalid_short(self, value):
2928 with self.assertRaises(InvalidOID):
2929 ObjectIdentifier((value,))
2930 with self.assertRaises(InvalidOID):
2931 ObjectIdentifier("%d" % value)
2933 @given(integers(min_value=3), integers(min_value=0))
2934 def test_invalid_first_arc(self, first_arc, second_arc):
2935 with self.assertRaises(InvalidOID):
2936 ObjectIdentifier((first_arc, second_arc))
2937 with self.assertRaises(InvalidOID):
2938 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2940 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2941 def test_invalid_second_arc(self, first_arc, second_arc):
2942 with self.assertRaises(InvalidOID):
2943 ObjectIdentifier((first_arc, second_arc))
2944 with self.assertRaises(InvalidOID):
2945 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2947 @given(text(alphabet=ascii_letters + ".", min_size=1))
2948 def test_junk(self, oid):
2949 with self.assertRaises(InvalidOID):
2950 ObjectIdentifier(oid)
2952 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2953 @given(oid_strategy())
2954 def test_validness(self, oid):
2955 obj = ObjectIdentifier(oid)
2956 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2959 pprint(obj, big_blobs=True, with_decode_path=True)
2961 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2963 oid_values_strategy(),
2965 integers(min_value=1).map(tag_ctxc),
2966 integers(min_value=0),
2970 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2971 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2972 _, _, _, default, optional, _decoded = values
2981 pprint(obj, big_blobs=True, with_decode_path=True)
2982 self.assertFalse(obj.expled)
2983 obj_encoded = obj.encode()
2984 self.assertEqual(encode2pass(obj), obj_encoded)
2985 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2986 obj_expled = obj(value, expl=tag_expl)
2987 self.assertTrue(obj_expled.expled)
2989 list(obj_expled.pps())
2990 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2991 obj_expled_encoded = obj_expled.encode()
2992 obj_expled_cer = encode_cer(obj_expled)
2993 self.assertNotEqual(obj_expled_cer, obj_encoded)
2994 self.assertSequenceEqual(
2995 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2998 ctx_copied = deepcopy(ctx_dummy)
2999 obj_decoded, tail = obj_expled.decode(
3000 obj_expled_encoded + tail_junk,
3004 self.assertDictEqual(ctx_copied, ctx_dummy)
3006 list(obj_decoded.pps())
3007 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3008 self.assertEqual(tail, tail_junk)
3009 self.assertEqual(obj_decoded, obj_expled)
3010 self.assertNotEqual(obj_decoded, obj)
3011 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
3012 self.assertEqual(tuple(obj_decoded), tuple(obj))
3013 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3014 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3015 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3017 obj_decoded.expl_llen,
3018 len(len_encode(len(obj_encoded))),
3020 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3021 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3024 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3026 self.assertEqual(obj_decoded.expl_offset, offset)
3027 assert_exceeding_data(
3029 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3033 evgens = list(obj_expled.decode_evgen(
3034 obj_expled_encoded + tail_junk,
3036 decode_path=decode_path,
3039 self.assertEqual(len(evgens), 1)
3040 _decode_path, obj, tail = evgens[0]
3041 self.assertSequenceEqual(tail, tail_junk)
3042 self.assertEqual(_decode_path, decode_path)
3043 self.assertEqual(obj, obj_decoded)
3044 self.assertEqual(obj.expl_offset, offset)
3049 oid_strategy().map(ObjectIdentifier),
3050 oid_strategy().map(ObjectIdentifier),
3052 def test_add(self, oid1, oid2):
3053 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3054 for oid_to_add in (oid2, tuple(oid2)):
3055 self.assertEqual(oid1 + oid_to_add, oid_expect)
3056 with self.assertRaises(InvalidValueType):
3059 def test_go_vectors_valid(self):
3060 for data, expect in (
3062 (b"\x55\x02", (2, 5, 2)),
3063 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3064 (b"\x81\x34\x03", (2, 100, 3)),
3067 ObjectIdentifier().decode(b"".join((
3068 ObjectIdentifier.tag_default,
3069 len_encode(len(data)),
3075 def test_go_vectors_invalid(self):
3076 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3077 with self.assertRaises(DecodeError):
3078 ObjectIdentifier().decode(b"".join((
3079 Integer.tag_default,
3080 len_encode(len(data)),
3084 def test_x690_vector(self):
3086 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3087 ObjectIdentifier((2, 999, 3)),
3090 def test_nonnormalized_first_arc(self):
3092 ObjectIdentifier.tag_default +
3095 ObjectIdentifier((1, 0)).encode()[-1:]
3097 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3098 self.assertTrue(obj.ber_encoded)
3099 self.assertTrue(obj.bered)
3101 self.assertTrue(obj.ber_encoded)
3102 self.assertTrue(obj.bered)
3103 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3104 ObjectIdentifier().decode(tampered)
3106 @given(data_strategy())
3107 def test_negative_arcs(self, d):
3108 oid = list(d.draw(oid_strategy()))
3111 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3113 if oid[idx - 1] == 0:
3115 with self.assertRaises(InvalidOID):
3116 ObjectIdentifier(tuple(oid))
3117 with self.assertRaises(InvalidOID):
3118 ObjectIdentifier(".".join(str(i) for i in oid))
3120 @given(data_strategy())
3121 def test_plused_arcs(self, d):
3122 oid = [str(arc) for arc in d.draw(oid_strategy())]
3123 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3124 oid[idx - 1] = "+" + oid[idx - 1]
3125 with self.assertRaises(InvalidOID):
3126 ObjectIdentifier(".".join(str(i) for i in oid))
3128 @given(data_strategy())
3129 def test_nonnormalized_arcs(self, d):
3130 arcs = d.draw(lists(
3131 integers(min_value=0, max_value=100),
3135 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3136 _, _, lv = tag_strip(dered)
3137 _, _, v = len_decode(lv)
3138 v_no_first_arc = v[1:]
3139 idx_for_tamper = d.draw(integers(
3141 max_value=len(v_no_first_arc) - 1,
3143 tampered = list(bytearray(v_no_first_arc))
3144 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3145 tampered.insert(idx_for_tamper, 0x80)
3146 tampered = bytes(bytearray(tampered))
3148 ObjectIdentifier.tag_default +
3149 len_encode(len(tampered)) +
3152 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3153 self.assertTrue(obj.ber_encoded)
3154 self.assertTrue(obj.bered)
3156 self.assertTrue(obj.ber_encoded)
3157 self.assertTrue(obj.bered)
3158 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3159 ObjectIdentifier().decode(tampered)
3163 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3165 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3166 values = list(draw(sets(
3168 min_size=len(schema),
3169 max_size=len(schema),
3171 schema = list(zip(schema, values))
3172 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3176 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3178 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3179 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3180 optional = draw(one_of(none(), booleans()))
3182 draw(integers(min_value=0)),
3183 draw(integers(min_value=0)),
3184 draw(integers(min_value=0)),
3186 return (schema, value, impl, expl, default, optional, _decoded)
3189 class TestEnumerated(CommonMixin, TestCase):
3190 class EWhatever(Enumerated):
3191 schema = (("whatever", 0),)
3193 base_klass = EWhatever
3195 def test_schema_required(self):
3196 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3199 def test_invalid_value_type(self):
3200 with self.assertRaises(InvalidValueType) as err:
3201 self.base_klass((1, 2))
3204 @given(sets(text_letters(), min_size=2))
3205 def test_unknown_name(self, schema_input):
3206 missing = schema_input.pop()
3208 class E(Enumerated):
3209 schema = [(n, 123) for n in schema_input]
3210 with self.assertRaises(ObjUnknown) as err:
3215 sets(text_letters(), min_size=2),
3216 sets(integers(), min_size=2),
3218 def test_unknown_value(self, schema_input, values_input):
3220 missing_value = values_input.pop()
3221 _input = list(zip(schema_input, values_input))
3223 class E(Enumerated):
3225 with self.assertRaises(DecodeError) as err:
3230 def test_optional(self, optional):
3231 obj = self.base_klass(default="whatever", optional=optional)
3232 self.assertTrue(obj.optional)
3234 def test_ready(self):
3235 obj = self.base_klass()
3236 self.assertFalse(obj.ready)
3239 pprint(obj, big_blobs=True, with_decode_path=True)
3240 with self.assertRaises(ObjNotReady) as err:
3243 obj = self.base_klass("whatever")
3244 self.assertTrue(obj.ready)
3247 pprint(obj, big_blobs=True, with_decode_path=True)
3249 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3250 def test_comparison(self, value1, value2, tag1, tag2):
3251 class E(Enumerated):
3253 ("whatever0", value1),
3254 ("whatever1", value2),
3257 class EInherited(E):
3259 for klass in (E, EInherited):
3260 obj1 = klass(value1)
3261 obj2 = klass(value2)
3262 self.assertEqual(obj1 == obj2, value1 == value2)
3263 self.assertEqual(obj1 != obj2, value1 != value2)
3264 self.assertEqual(obj1 == int(obj2), value1 == value2)
3265 obj1 = klass(value1, impl=tag1)
3266 obj2 = klass(value1, impl=tag2)
3267 self.assertEqual(obj1 == obj2, tag1 == tag2)
3268 self.assertEqual(obj1 != obj2, tag1 != tag2)
3270 @given(data_strategy())
3271 def test_call(self, d):
3280 ) = d.draw(enumerated_values_strategy())
3282 class E(Enumerated):
3283 schema = schema_initial
3285 value=value_initial,
3288 default=default_initial,
3289 optional=optional_initial or False,
3290 _decoded=_decoded_initial,
3300 ) = d.draw(enumerated_values_strategy(
3301 schema=schema_initial,
3302 do_expl=impl_initial is None,
3312 value_expected = default if value is None else value
3314 default_initial if value_expected is None
3319 dict(schema_initial).get(value_expected, value_expected),
3321 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3322 self.assertEqual(obj.expl_tag, expl or expl_initial)
3325 default_initial if default is None else default,
3327 if obj.default is None:
3328 optional = optional_initial if optional is None else optional
3329 optional = False if optional is None else optional
3332 self.assertEqual(obj.optional, optional)
3333 self.assertEqual(obj.specs, dict(schema_initial))
3335 @given(enumerated_values_strategy())
3336 def test_copy(self, values):
3337 schema_input, value, impl, expl, default, optional, _decoded = values
3339 class E(Enumerated):
3340 schema = schema_input
3350 for copy_func in copy_funcs:
3351 obj_copied = copy_func(obj)
3352 self.assert_copied_basic_fields(obj, obj_copied)
3353 self.assertEqual(obj.specs, obj_copied.specs)
3355 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3356 @given(data_strategy())
3357 def test_symmetric(self, d):
3358 schema_input, _, _, _, default, optional, _decoded = d.draw(
3359 enumerated_values_strategy(),
3361 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3362 offset = d.draw(integers(min_value=0))
3363 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3364 tail_junk = d.draw(binary(max_size=5))
3365 decode_path = d.draw(decode_path_strat)
3367 class E(Enumerated):
3368 schema = schema_input
3377 pprint(obj, big_blobs=True, with_decode_path=True)
3378 self.assertFalse(obj.expled)
3379 obj_encoded = obj.encode()
3380 self.assertEqual(encode2pass(obj), obj_encoded)
3381 obj_expled = obj(value, expl=tag_expl)
3382 self.assertTrue(obj_expled.expled)
3384 list(obj_expled.pps())
3385 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3386 obj_expled_encoded = obj_expled.encode()
3387 ctx_copied = deepcopy(ctx_dummy)
3388 obj_decoded, tail = obj_expled.decode(
3389 obj_expled_encoded + tail_junk,
3393 self.assertDictEqual(ctx_copied, ctx_dummy)
3395 list(obj_decoded.pps())
3396 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3397 self.assertEqual(tail, tail_junk)
3398 self.assertEqual(obj_decoded, obj_expled)
3399 self.assertNotEqual(obj_decoded, obj)
3400 self.assertEqual(int(obj_decoded), int(obj_expled))
3401 self.assertEqual(int(obj_decoded), int(obj))
3402 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3403 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3404 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3406 obj_decoded.expl_llen,
3407 len(len_encode(len(obj_encoded))),
3409 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3410 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3413 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3415 self.assertEqual(obj_decoded.expl_offset, offset)
3416 assert_exceeding_data(
3418 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3422 evgens = list(obj_expled.decode_evgen(
3423 obj_expled_encoded + tail_junk,
3425 decode_path=decode_path,
3428 self.assertEqual(len(evgens), 1)
3429 _decode_path, obj, tail = evgens[0]
3430 self.assertSequenceEqual(tail, tail_junk)
3431 self.assertEqual(_decode_path, decode_path)
3432 self.assertEqual(obj, obj_decoded)
3433 self.assertEqual(obj.expl_offset, offset)
3439 def string_values_strategy(draw, alphabet, do_expl=False):
3440 bound_min, bound_max = sorted(draw(sets(
3441 integers(min_value=0, max_value=1 << 7),
3445 value = draw(one_of(
3447 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3449 default = draw(one_of(
3451 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3454 if draw(booleans()):
3455 bounds = (bound_min, bound_max)
3459 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3461 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3462 optional = draw(one_of(none(), booleans()))
3464 draw(integers(min_value=0)),
3465 draw(integers(min_value=0)),
3466 draw(integers(min_value=0)),
3468 return (value, bounds, impl, expl, default, optional, _decoded)
3471 class StringMixin(object):
3472 def test_invalid_value_type(self):
3473 with self.assertRaises(InvalidValueType) as err:
3474 self.base_klass((1, 2))
3477 def text_alphabet(self):
3478 return "".join(six_unichr(c) for c in six_xrange(256))
3481 def test_optional(self, optional):
3482 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3483 self.assertTrue(obj.optional)
3485 @given(data_strategy())
3486 def test_ready(self, d):
3487 obj = self.base_klass()
3488 self.assertFalse(obj.ready)
3491 pprint(obj, big_blobs=True, with_decode_path=True)
3493 with self.assertRaises(ObjNotReady) as err:
3496 with self.assertRaises(ObjNotReady) as err:
3498 value = d.draw(text(alphabet=self.text_alphabet()))
3499 obj = self.base_klass(value)
3500 self.assertTrue(obj.ready)
3503 pprint(obj, big_blobs=True, with_decode_path=True)
3506 @given(data_strategy())
3507 def test_comparison(self, d):
3508 value1 = d.draw(text(alphabet=self.text_alphabet()))
3509 value2 = d.draw(text(alphabet=self.text_alphabet()))
3510 tag1 = d.draw(binary(min_size=1))
3511 tag2 = d.draw(binary(min_size=1))
3512 obj1 = self.base_klass(value1)
3513 obj2 = self.base_klass(value2)
3514 self.assertEqual(obj1 == obj2, value1 == value2)
3515 self.assertEqual(obj1 != obj2, value1 != value2)
3516 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3517 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3518 obj1 = self.base_klass(value1, impl=tag1)
3519 obj2 = self.base_klass(value1, impl=tag2)
3520 self.assertEqual(obj1 == obj2, tag1 == tag2)
3521 self.assertEqual(obj1 != obj2, tag1 != tag2)
3523 @given(data_strategy())
3524 def test_bounds_satisfied(self, d):
3525 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3526 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3527 value = d.draw(text(
3528 alphabet=self.text_alphabet(),
3532 self.base_klass(value=value, bounds=(bound_min, bound_max))
3534 @given(data_strategy())
3535 def test_bounds_unsatisfied(self, d):
3536 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3537 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3538 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3539 with self.assertRaises(BoundsError) as err:
3540 self.base_klass(value=value, bounds=(bound_min, bound_max))
3542 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3543 self.base_klass(bounds=(bound_min, bound_max)).decode(
3544 self.base_klass(value).encode()
3547 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3548 self.base_klass(bounds=(bound_min, bound_max)).decode(
3549 encode2pass(self.base_klass(value))
3551 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3552 with self.assertRaises(BoundsError) as err:
3553 self.base_klass(value=value, bounds=(bound_min, bound_max))
3555 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3556 self.base_klass(bounds=(bound_min, bound_max)).decode(
3557 self.base_klass(value).encode()
3560 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3561 self.base_klass(bounds=(bound_min, bound_max)).decode(
3562 encode2pass(self.base_klass(value))
3565 @given(data_strategy())
3566 def test_call(self, d):
3575 ) = d.draw(string_values_strategy(self.text_alphabet()))
3576 obj_initial = self.base_klass(
3582 optional_initial or False,
3593 ) = d.draw(string_values_strategy(
3594 self.text_alphabet(),
3595 do_expl=impl_initial is None,
3597 if (default is None) and (obj_initial.default is not None):
3600 (bounds is None) and
3601 (value is not None) and
3602 (bounds_initial is not None) and
3603 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3607 (bounds is None) and
3608 (default is not None) and
3609 (bounds_initial is not None) and
3610 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3613 obj = obj_initial(value, bounds, impl, expl, default, optional)
3615 value_expected = default if value is None else value
3617 default_initial if value_expected is None
3620 self.assertEqual(obj, value_expected)
3621 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3622 self.assertEqual(obj.expl_tag, expl or expl_initial)
3625 default_initial if default is None else default,
3627 if obj.default is None:
3628 optional = optional_initial if optional is None else optional
3629 optional = False if optional is None else optional
3632 self.assertEqual(obj.optional, optional)
3634 (obj._bound_min, obj._bound_max),
3635 bounds or bounds_initial or (0, float("+inf")),
3638 @given(data_strategy())
3639 def test_copy(self, d):
3640 values = d.draw(string_values_strategy(self.text_alphabet()))
3641 obj = self.base_klass(*values)
3642 for copy_func in copy_funcs:
3643 obj_copied = copy_func(obj)
3644 self.assert_copied_basic_fields(obj, obj_copied)
3645 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3646 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3647 self.assertEqual(obj._value, obj_copied._value)
3649 @given(data_strategy())
3650 def test_stripped(self, d):
3651 value = d.draw(text(alphabet=self.text_alphabet()))
3652 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3653 obj = self.base_klass(value, impl=tag_impl)
3654 with self.assertRaises(NotEnoughData):
3655 obj.decode(obj.encode()[:-1])
3657 @given(data_strategy())
3658 def test_stripped_expl(self, d):
3659 value = d.draw(text(alphabet=self.text_alphabet()))
3660 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3661 obj = self.base_klass(value, expl=tag_expl)
3662 with self.assertRaises(NotEnoughData):
3663 obj.decode(obj.encode()[:-1])
3666 integers(min_value=31),
3667 integers(min_value=0),
3670 def test_bad_tag(self, tag, offset, decode_path):
3671 with self.assertRaises(DecodeError) as err:
3672 self.base_klass().decode(
3673 tag_encode(tag)[:-1],
3675 decode_path=decode_path,
3678 self.assertEqual(err.exception.offset, offset)
3679 self.assertEqual(err.exception.decode_path, decode_path)
3682 integers(min_value=128),
3683 integers(min_value=0),
3686 def test_bad_len(self, l, offset, decode_path):
3687 with self.assertRaises(DecodeError) as err:
3688 self.base_klass().decode(
3689 self.base_klass.tag_default + len_encode(l)[:-1],
3691 decode_path=decode_path,
3694 self.assertEqual(err.exception.offset, offset)
3695 self.assertEqual(err.exception.decode_path, decode_path)
3698 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3699 integers(min_value=0),
3702 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3703 value, bound_min = list(sorted(ints))
3705 class String(self.base_klass):
3706 # Multiply this value by four, to satisfy UTF-32 bounds
3707 # (4 bytes per character) validation
3708 bounds = (bound_min * 4, bound_min * 4)
3709 with self.assertRaises(DecodeError) as err:
3711 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3713 decode_path=decode_path,
3716 self.assertEqual(err.exception.offset, offset)
3717 self.assertEqual(err.exception.decode_path, decode_path)
3719 @given(data_strategy())
3720 def test_symmetric(self, d):
3721 values = d.draw(string_values_strategy(self.text_alphabet()))
3722 value = d.draw(text(alphabet=self.text_alphabet()))
3723 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3724 offset = d.draw(integers(min_value=0))
3725 tail_junk = d.draw(binary(max_size=5))
3726 decode_path = d.draw(decode_path_strat)
3727 _, _, _, _, default, optional, _decoded = values
3728 obj = self.base_klass(
3736 pprint(obj, big_blobs=True, with_decode_path=True)
3737 self.assertFalse(obj.expled)
3738 obj_encoded = obj.encode()
3739 self.assertEqual(encode2pass(obj), obj_encoded)
3740 obj_expled = obj(value, expl=tag_expl)
3741 self.assertTrue(obj_expled.expled)
3743 list(obj_expled.pps())
3744 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3745 obj_expled_encoded = obj_expled.encode()
3746 ctx_copied = deepcopy(ctx_dummy)
3747 obj_decoded, tail = obj_expled.decode(
3748 obj_expled_encoded + tail_junk,
3752 self.assertDictEqual(ctx_copied, ctx_dummy)
3754 list(obj_decoded.pps())
3755 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3756 self.assertEqual(tail, tail_junk)
3757 self.assertEqual(obj_decoded, obj_expled)
3758 self.assertNotEqual(obj_decoded, obj)
3759 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3760 self.assertEqual(bytes(obj_decoded), bytes(obj))
3761 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3762 self.assertEqual(text_type(obj_decoded), text_type(obj))
3763 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3764 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3765 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3767 obj_decoded.expl_llen,
3768 len(len_encode(len(obj_encoded))),
3770 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3771 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3774 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3776 self.assertEqual(obj_decoded.expl_offset, offset)
3777 assert_exceeding_data(
3779 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3783 evgens = list(obj_expled.decode_evgen(
3784 obj_expled_encoded + tail_junk,
3786 decode_path=decode_path,
3789 self.assertEqual(len(evgens), 1)
3790 _decode_path, obj, tail = evgens[0]
3791 self.assertSequenceEqual(tail, tail_junk)
3792 self.assertEqual(_decode_path, decode_path)
3793 if not getattr(self, "evgen_mode_skip_value", True):
3794 self.assertEqual(obj, obj_decoded)
3795 self.assertEqual(obj.expl_offset, offset)
3800 cyrillic_letters = text(
3801 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3807 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3808 base_klass = UTF8String
3810 @given(cyrillic_letters)
3811 def test_byte_per_primitive(self, chars):
3813 char_raw = char.encode("utf-8")
3814 encoded = b"".join((
3815 self.base_klass().tag_constructed,
3817 OctetString(char_raw[:1]).encode(),
3818 OctetString(char_raw[1:2]).encode(),
3822 self.base_klass().decod(encoded, ctx={"bered": True}),
3827 class UnicodeDecodeErrorMixin(object):
3828 @given(cyrillic_letters)
3829 def test_unicode_decode_error(self, cyrillic_text):
3830 with self.assertRaises(DecodeError):
3831 self.base_klass(cyrillic_text)
3834 class TestNumericString(StringMixin, CommonMixin, TestCase):
3835 base_klass = NumericString
3837 def text_alphabet(self):
3840 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3841 def test_non_numeric(self, non_numeric_text):
3842 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3843 self.base_klass(non_numeric_text)
3846 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3847 integers(min_value=0),
3850 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3851 value, bound_min = list(sorted(ints))
3853 class String(self.base_klass):
3854 bounds = (bound_min, bound_min)
3855 with self.assertRaises(DecodeError) as err:
3857 self.base_klass(b"1" * value).encode(),
3859 decode_path=decode_path,
3862 self.assertEqual(err.exception.offset, offset)
3863 self.assertEqual(err.exception.decode_path, decode_path)
3865 def test_byte_per_primitive(self):
3866 encoded = b"".join((
3867 self.base_klass().tag_constructed,
3869 OctetString(b"1").encode(),
3870 OctetString(b"2").encode(),
3874 self.base_klass().decod(encoded, ctx={"bered": True}),
3879 class TestPrintableString(
3880 UnicodeDecodeErrorMixin,
3885 base_klass = PrintableString
3887 def text_alphabet(self):
3888 return ascii_letters + digits + " '()+,-./:=?"
3890 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3891 def test_non_printable(self, non_printable_text):
3892 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3893 self.base_klass(non_printable_text)
3896 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3897 integers(min_value=0),
3900 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3901 value, bound_min = list(sorted(ints))
3903 class String(self.base_klass):
3904 bounds = (bound_min, bound_min)
3905 with self.assertRaises(DecodeError) as err:
3907 self.base_klass(b"1" * value).encode(),
3909 decode_path=decode_path,
3912 self.assertEqual(err.exception.offset, offset)
3913 self.assertEqual(err.exception.decode_path, decode_path)
3915 def test_allowable_invalid_chars(self):
3917 ("*", {"allow_asterisk": True}),
3918 ("&", {"allow_ampersand": True}),
3919 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3922 obj = self.base_klass(s)
3923 for prop in kwargs.keys():
3924 self.assertFalse(getattr(obj, prop))
3926 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3928 self.base_klass(s, **kwargs)
3929 klass = self.base_klass(**kwargs)
3931 for prop in kwargs.keys():
3932 self.assertTrue(getattr(obj, prop))
3935 for prop in kwargs.keys():
3936 self.assertTrue(getattr(obj, prop))
3939 class TestTeletexString(
3940 UnicodeDecodeErrorMixin,
3945 base_klass = TeletexString
3948 class TestVideotexString(
3949 UnicodeDecodeErrorMixin,
3954 base_klass = VideotexString
3957 class TestIA5String(
3958 UnicodeDecodeErrorMixin,
3963 base_klass = IA5String
3965 def text_alphabet(self):
3966 return "".join(six_unichr(c) for c in six_xrange(128))
3968 @given(integers(min_value=128, max_value=255))
3969 def test_alphabet_bad(self, code):
3970 with self.assertRaises(DecodeError):
3971 self.base_klass().decod(
3972 self.base_klass.tag_default +
3974 bytes(bytearray([code])),
3978 class TestGraphicString(
3979 UnicodeDecodeErrorMixin,
3984 base_klass = GraphicString
3987 class TestVisibleString(
3988 UnicodeDecodeErrorMixin,
3993 base_klass = VisibleString
3995 def text_alphabet(self):
3996 return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
3998 def test_x690_vector(self):
3999 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
4000 self.assertSequenceEqual(tail, b"")
4001 self.assertEqual(str(obj), "Jones")
4002 self.assertFalse(obj.ber_encoded)
4003 self.assertFalse(obj.lenindef)
4004 self.assertFalse(obj.bered)
4006 obj, tail = VisibleString().decode(
4007 hexdec("3A0904034A6F6E04026573"),
4008 ctx={"bered": True},
4010 self.assertSequenceEqual(tail, b"")
4011 self.assertEqual(str(obj), "Jones")
4012 self.assertTrue(obj.ber_encoded)
4013 self.assertFalse(obj.lenindef)
4014 self.assertTrue(obj.bered)
4016 self.assertTrue(obj.ber_encoded)
4017 self.assertFalse(obj.lenindef)
4018 self.assertTrue(obj.bered)
4020 obj, tail = VisibleString().decode(
4021 hexdec("3A8004034A6F6E040265730000"),
4022 ctx={"bered": True},
4024 self.assertSequenceEqual(tail, b"")
4025 self.assertEqual(str(obj), "Jones")
4026 self.assertTrue(obj.ber_encoded)
4027 self.assertTrue(obj.lenindef)
4028 self.assertTrue(obj.bered)
4030 self.assertTrue(obj.ber_encoded)
4031 self.assertTrue(obj.lenindef)
4032 self.assertTrue(obj.bered)
4035 integers(min_value=0, max_value=ord(" ") - 1),
4036 integers(min_value=ord("~") + 1, max_value=255),
4038 def test_alphabet_bad(self, code):
4039 with self.assertRaises(DecodeError):
4040 self.base_klass().decod(
4041 self.base_klass.tag_default +
4043 bytes(bytearray([code])),
4047 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
4048 integers(min_value=0),
4051 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
4052 value, bound_min = list(sorted(ints))
4054 class String(self.base_klass):
4055 bounds = (bound_min, bound_min)
4056 with self.assertRaises(DecodeError) as err:
4058 self.base_klass(b"1" * value).encode(),
4060 decode_path=decode_path,
4063 self.assertEqual(err.exception.offset, offset)
4064 self.assertEqual(err.exception.decode_path, decode_path)
4067 class TestGeneralString(
4068 UnicodeDecodeErrorMixin,
4073 base_klass = GeneralString
4076 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4077 base_klass = UniversalString
4080 class TestBMPString(StringMixin, CommonMixin, TestCase):
4081 base_klass = BMPString
4085 def generalized_time_values_strategy(
4093 if draw(booleans()):
4094 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4096 value = value.replace(microsecond=0)
4098 if draw(booleans()):
4099 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4101 default = default.replace(microsecond=0)
4105 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4107 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4108 optional = draw(one_of(none(), booleans()))
4110 draw(integers(min_value=0)),
4111 draw(integers(min_value=0)),
4112 draw(integers(min_value=0)),
4114 return (value, impl, expl, default, optional, _decoded)
4117 class TimeMixin(object):
4118 def test_invalid_value_type(self):
4119 with self.assertRaises(InvalidValueType) as err:
4120 self.base_klass(datetime.now().timetuple())
4123 @given(data_strategy())
4124 def test_optional(self, d):
4125 default = d.draw(datetimes(
4126 min_value=self.min_datetime,
4127 max_value=self.max_datetime,
4129 optional = d.draw(booleans())
4130 obj = self.base_klass(default=default, optional=optional)
4131 self.assertTrue(obj.optional)
4133 @given(data_strategy())
4134 def test_ready(self, d):
4135 obj = self.base_klass()
4136 self.assertFalse(obj.ready)
4139 pprint(obj, big_blobs=True, with_decode_path=True)
4140 with self.assertRaises(ObjNotReady) as err:
4143 with self.assertRaises(ObjNotReady) as err:
4145 value = d.draw(datetimes(
4146 min_value=self.min_datetime,
4147 max_value=self.max_datetime,
4149 obj = self.base_klass(value)
4150 self.assertTrue(obj.ready)
4153 pprint(obj, big_blobs=True, with_decode_path=True)
4155 @given(data_strategy())
4156 def test_comparison(self, d):
4157 value1 = d.draw(datetimes(
4158 min_value=self.min_datetime,
4159 max_value=self.max_datetime,
4161 value2 = d.draw(datetimes(
4162 min_value=self.min_datetime,
4163 max_value=self.max_datetime,
4165 tag1 = d.draw(binary(min_size=1))
4166 tag2 = d.draw(binary(min_size=1))
4168 value1 = value1.replace(microsecond=0)
4169 value2 = value2.replace(microsecond=0)
4170 obj1 = self.base_klass(value1)
4171 obj2 = self.base_klass(value2)
4172 self.assertEqual(obj1 == obj2, value1 == value2)
4173 self.assertEqual(obj1 != obj2, value1 != value2)
4174 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4175 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4176 obj1 = self.base_klass(value1, impl=tag1)
4177 obj2 = self.base_klass(value1, impl=tag2)
4178 self.assertEqual(obj1 == obj2, tag1 == tag2)
4179 self.assertEqual(obj1 != obj2, tag1 != tag2)
4181 @given(data_strategy())
4182 def test_call(self, d):
4190 ) = d.draw(generalized_time_values_strategy(
4191 min_datetime=self.min_datetime,
4192 max_datetime=self.max_datetime,
4193 omit_ms=self.omit_ms,
4195 obj_initial = self.base_klass(
4196 value=value_initial,
4199 default=default_initial,
4200 optional=optional_initial or False,
4201 _decoded=_decoded_initial,
4210 ) = d.draw(generalized_time_values_strategy(
4211 min_datetime=self.min_datetime,
4212 max_datetime=self.max_datetime,
4213 omit_ms=self.omit_ms,
4214 do_expl=impl_initial is None,
4224 value_expected = default if value is None else value
4226 default_initial if value_expected is None
4229 self.assertEqual(obj, value_expected)
4230 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4231 self.assertEqual(obj.expl_tag, expl or expl_initial)
4234 default_initial if default is None else default,
4236 if obj.default is None:
4237 optional = optional_initial if optional is None else optional
4238 optional = False if optional is None else optional
4241 self.assertEqual(obj.optional, optional)
4243 @given(data_strategy())
4244 def test_copy(self, d):
4245 values = d.draw(generalized_time_values_strategy(
4246 min_datetime=self.min_datetime,
4247 max_datetime=self.max_datetime,
4249 obj = self.base_klass(*values)
4250 for copy_func in copy_funcs:
4251 obj_copied = copy_func(obj)
4252 self.assert_copied_basic_fields(obj, obj_copied)
4253 self.assertEqual(obj._value, obj_copied._value)
4255 @given(data_strategy())
4256 def test_stripped(self, d):
4257 value = d.draw(datetimes(
4258 min_value=self.min_datetime,
4259 max_value=self.max_datetime,
4261 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4262 obj = self.base_klass(value, impl=tag_impl)
4263 with self.assertRaises(NotEnoughData):
4264 obj.decode(obj.encode()[:-1])
4266 @given(data_strategy())
4267 def test_stripped_expl(self, d):
4268 value = d.draw(datetimes(
4269 min_value=self.min_datetime,
4270 max_value=self.max_datetime,
4272 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4273 obj = self.base_klass(value, expl=tag_expl)
4274 with self.assertRaises(NotEnoughData):
4275 obj.decode(obj.encode()[:-1])
4277 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4278 @given(data_strategy())
4279 def test_symmetric(self, d):
4280 values = d.draw(generalized_time_values_strategy(
4281 min_datetime=self.min_datetime,
4282 max_datetime=self.max_datetime,
4284 value = d.draw(datetimes(
4285 min_value=self.min_datetime,
4286 max_value=self.max_datetime,
4288 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4289 offset = d.draw(integers(min_value=0))
4290 tail_junk = d.draw(binary(max_size=5))
4291 _, _, _, default, optional, _decoded = values
4292 obj = self.base_klass(
4300 pprint(obj, big_blobs=True, with_decode_path=True)
4301 self.assertFalse(obj.expled)
4302 obj_encoded = obj.encode()
4303 self.assertEqual(encode2pass(obj), obj_encoded)
4304 self.additional_symmetric_check(value, obj_encoded)
4305 obj_expled = obj(value, expl=tag_expl)
4306 self.assertTrue(obj_expled.expled)
4308 list(obj_expled.pps())
4309 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4310 obj_expled_encoded = obj_expled.encode()
4311 ctx_copied = deepcopy(ctx_dummy)
4312 obj_decoded, tail = obj_expled.decode(
4313 obj_expled_encoded + tail_junk,
4317 self.assertDictEqual(ctx_copied, ctx_dummy)
4319 list(obj_decoded.pps())
4320 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4321 self.assertEqual(tail, tail_junk)
4322 self.assertEqual(obj_decoded, obj_expled)
4323 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4324 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4325 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4326 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4327 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4329 obj_decoded.expl_llen,
4330 len(len_encode(len(obj_encoded))),
4332 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4333 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4336 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4338 self.assertEqual(obj_decoded.expl_offset, offset)
4339 assert_exceeding_data(
4341 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4346 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4347 base_klass = GeneralizedTime
4349 min_datetime = datetime(1900, 1, 1)
4350 max_datetime = datetime(9999, 12, 31)
4351 evgen_mode_skip_value = False
4353 def additional_symmetric_check(self, value, obj_encoded):
4354 if value.microsecond > 0:
4355 self.assertFalse(obj_encoded.endswith(b"0Z"))
4357 def test_repr_not_ready(self):
4358 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4359 repr(GeneralizedTime())
4361 def test_x690_vector_valid(self):
4365 b"19920722132100.3Z",
4367 GeneralizedTime(data)
4369 def test_x690_vector_invalid(self):
4372 b"19920622123421.0Z",
4373 b"19920722132100.30Z",
4375 with self.assertRaises(DecodeError) as err:
4376 GeneralizedTime(data)
4379 def test_go_vectors_invalid(self):
4391 b"-20100102030410Z",
4392 b"2010-0102030410Z",
4393 b"2010-0002030410Z",
4394 b"201001-02030410Z",
4395 b"20100102-030410Z",
4396 b"2010010203-0410Z",
4397 b"201001020304-10Z",
4398 # These ones are INVALID in *DER*, but accepted
4399 # by Go's encoding/asn1
4400 b"20100102030405+0607",
4401 b"20100102030405-0607",
4403 with self.assertRaises(DecodeError) as err:
4404 GeneralizedTime(data)
4407 def test_go_vectors_valid(self):
4409 GeneralizedTime(b"20100102030405Z").todatetime(),
4410 datetime(2010, 1, 2, 3, 4, 5, 0),
4413 def test_go_vectors_valid_ber(self):
4415 b"20100102030405+0607",
4416 b"20100102030405-0607",
4418 GeneralizedTime(data, ctx={"bered": True})
4420 def test_utc_offsets(self):
4421 """Some know equal UTC offsets
4424 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4428 "200101011130-0700",
4429 "200101011500-03:30",
4432 self.assertEqual(dts[0], dts[1])
4433 self.assertEqual(dts[0], dts[2])
4434 self.assertEqual(dts[0], dts[3])
4436 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4437 @given(data_strategy())
4438 def test_valid_ber(self, d):
4439 min_year = 1901 if PY2 else 2
4440 year = d.draw(integers(min_value=min_year, max_value=9999))
4441 month = d.draw(integers(min_value=1, max_value=12))
4442 day = d.draw(integers(min_value=1, max_value=28))
4443 hours = d.draw(integers(min_value=0, max_value=23))
4444 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4445 dt = datetime(year, month, day, hours)
4446 fractions_sign = d.draw(sampled_from(" ,."))
4448 if fractions_sign != " ":
4449 fractions = random()
4450 if d.draw(booleans()):
4451 minutes = d.draw(integers(min_value=0, max_value=59))
4452 data += "%02d" % minutes
4453 dt += timedelta(seconds=60 * minutes)
4454 if d.draw(booleans()):
4455 seconds = d.draw(integers(min_value=0, max_value=59))
4456 data += "%02d" % seconds
4457 dt += timedelta(seconds=seconds)
4458 if fractions is not None:
4459 dt += timedelta(microseconds=10**6 * fractions)
4460 elif fractions is not None:
4461 dt += timedelta(seconds=60 * fractions)
4462 elif fractions is not None:
4463 dt += timedelta(seconds=3600 * fractions)
4464 if fractions is not None:
4465 data += fractions_sign + str(fractions)[2:]
4466 if d.draw(booleans()):
4468 elif d.draw(booleans()):
4469 offset_hour = d.draw(integers(min_value=0, max_value=13))
4471 if d.draw(booleans()):
4476 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4477 data += "%02d" % offset_hour
4478 minutes_separator = d.draw(sampled_from((None, "", ":")))
4479 if minutes_separator is not None:
4480 offset_minute = d.draw(integers(min_value=0, max_value=59))
4481 dt -= timedelta(seconds=sign * 60 * offset_minute)
4482 data += "%s%02d" % (minutes_separator, offset_minute)
4483 data = data.encode("ascii")
4484 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4486 GeneralizedTime().decod(data_der)
4491 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4494 mktime(obj.todatetime().timetuple()),
4495 mktime(dt.timetuple()),
4498 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4499 self.assertEqual(obj.ber_encoded, not dered)
4500 self.assertEqual(obj.bered, not dered)
4501 self.assertEqual(obj.ber_raw, None if dered else data)
4502 self.assertEqual(obj.encode() == data_der, dered)
4507 def test_invalid_ber(self):
4509 # "00010203040506.07",
4510 "-0010203040506.07",
4511 "0001-203040506.07",
4512 "000102-3040506.07",
4513 "00010203-40506.07",
4514 "0001020304-506.07",
4515 "000102030405-6.07",
4516 "00010203040506.-7",
4517 "+0010203040506.07",
4518 "0001+203040506.07",
4519 "000102+3040506.07",
4520 "00010203+40506.07",
4521 "0001020304+506.07",
4522 "000102030405+6.07",
4523 "00010203040506.+7",
4524 " 0010203040506.07",
4525 "0001 203040506.07",
4526 "000102 3040506.07",
4527 "00010203 40506.07",
4528 "0001020304 506.07",
4529 "000102030405 6.07",
4530 "00010203040506. 7",
4531 "001 0203040506.07",
4532 "00012 03040506.07",
4533 "0001023 040506.07",
4534 "000102034 0506.07",
4535 "00010203045 06.07",
4536 "0001020304056 .07",
4537 "00010203040506.7 ",
4617 "00010203040506.07+15",
4618 "00010203040506.07-15",
4619 "00010203040506.07+14:60",
4620 "00010203040506.07+1460",
4621 "00010203040506.07-1460",
4622 "00010203040506.07+00:60",
4623 "00010203040506.07-00:60",
4625 "00010203040506+15",
4626 "00010203040506-15",
4627 "00010203040506+14:60",
4628 "00010203040506+1460",
4629 "00010203040506-1460",
4630 "00010203040506+00:60",
4631 "00010203040506-00:60",
4640 with self.assertRaises(DecodeError):
4641 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4642 data = data.replace(".", ",")
4643 with self.assertRaises(DecodeError):
4644 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4648 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4649 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4651 binary(min_size=1, max_size=1),
4653 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4654 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4657 def test_junk(self, part0, part1, part2):
4658 junk = part0 + part1 + part2
4659 assume(not (set(junk) <= set(digits.encode("ascii"))))
4660 with self.assertRaises(DecodeError):
4661 GeneralizedTime().decode(
4662 GeneralizedTime.tag_default +
4663 len_encode(len(junk)) +
4669 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4670 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4672 binary(min_size=1, max_size=1),
4674 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4675 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4678 def test_junk_dm(self, part0, part1, part2):
4679 junk = part0 + part1 + part2
4680 assume(not (set(junk) <= set(digits.encode("ascii"))))
4681 with self.assertRaises(DecodeError):
4682 GeneralizedTime().decode(
4683 GeneralizedTime.tag_default +
4684 len_encode(len(junk)) +
4688 def test_ns_fractions(self):
4689 GeneralizedTime(b"20010101000000.000001Z")
4690 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4691 GeneralizedTime(b"20010101000000.0000001Z")
4693 def test_non_pure_integers(self):
4695 # b"20000102030405Z,
4702 b"20000102030405.+6Z",
4703 b"20000102030405.-6Z",
4710 b"20000102030405._6Z",
4711 b"20000102030405.6_Z",
4718 b"20000102030405. 6Z",
4725 b"20000102030405.6 Z",
4727 with self.assertRaises(DecodeError):
4728 GeneralizedTime(data)
4731 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4732 base_klass = UTCTime
4734 min_datetime = datetime(2000, 1, 1)
4735 max_datetime = datetime(2049, 12, 31)
4736 evgen_mode_skip_value = False
4738 def additional_symmetric_check(self, value, obj_encoded):
4741 def test_repr_not_ready(self):
4742 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4745 def test_x690_vector_valid(self):
4753 def test_x690_vector_invalid(self):
4758 with self.assertRaises(DecodeError) as err:
4762 def test_go_vectors_invalid(self):
4788 # These ones are INVALID in *DER*, but accepted
4789 # by Go's encoding/asn1
4790 b"910506164540-0700",
4791 b"910506164540+0730",
4795 with self.assertRaises(DecodeError) as err:
4799 def test_go_vectors_valid(self):
4801 UTCTime(b"910506234540Z").todatetime(),
4802 datetime(1991, 5, 6, 23, 45, 40, 0),
4805 def test_non_pure_integers(self):
4834 with self.assertRaises(DecodeError):
4837 def test_x680_vector_valid_ber(self):
4839 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4840 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4841 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4842 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4844 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4845 obj = UTCTime().decod(data_der, ctx={"bered": True})
4846 self.assertEqual(obj, dt)
4847 self.assertEqual(obj.todatetime(), dt)
4848 self.assertTrue(obj.ber_encoded)
4849 self.assertTrue(obj.bered)
4850 self.assertEqual(obj.ber_raw, data)
4851 self.assertNotEqual(obj.encode(), data_der)
4854 def test_go_vectors_valid_ber(self):
4856 b"910506164540-0700",
4857 b"910506164540+0730",
4861 data = UTCTime.tag_default + len_encode(len(data)) + data
4862 obj = UTCTime().decod(data, ctx={"bered": True})
4863 self.assertTrue(obj.ber_encoded)
4864 self.assertTrue(obj.bered)
4865 self.assertNotEqual(obj.encode(), data)
4868 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4869 @given(data_strategy())
4870 def test_valid_ber(self, d):
4871 year = d.draw(integers(min_value=0, max_value=99))
4872 month = d.draw(integers(min_value=1, max_value=12))
4873 day = d.draw(integers(min_value=1, max_value=28))
4874 hours = d.draw(integers(min_value=0, max_value=23))
4875 minute = d.draw(integers(min_value=0, max_value=59))
4876 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4878 year + (2000 if year < 50 else 1900),
4885 if d.draw(booleans()):
4887 seconds = d.draw(integers(min_value=0, max_value=59))
4888 data += "%02d" % seconds
4889 dt += timedelta(seconds=seconds)
4890 if d.draw(booleans()):
4894 offset_hour = d.draw(integers(min_value=0, max_value=13))
4895 offset_minute = d.draw(integers(min_value=0, max_value=59))
4896 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4897 if d.draw(booleans()):
4903 data += "%02d%02d" % (offset_hour, offset_minute)
4904 data = data.encode("ascii")
4905 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4906 obj = UTCTime().decod(data_der, ctx={"bered": True})
4907 self.assertEqual(obj, dt)
4908 self.assertEqual(obj.todatetime(), dt)
4909 self.assertEqual(obj.ber_encoded, not dered)
4910 self.assertEqual(obj.bered, not dered)
4911 self.assertEqual(obj.ber_raw, None if dered else data)
4912 self.assertEqual(obj.encode() == data_der, dered)
4917 def test_invalid_ber(self):
4958 b"0001020304+0000Z",
4967 with self.assertRaises(DecodeError):
4968 UTCTime(data, ctx={"bered": True})
4969 data = data[:8] + data[8+2:]
4970 with self.assertRaises(DecodeError):
4971 UTCTime(data, ctx={"bered": True})
5016 b"000102030405+000",
5017 b"000102030405+000Z",
5018 b"000102030405+0000Z",
5019 b"000102030405+-101",
5020 b"000102030405+01-1",
5021 b"000102030405+0060",
5022 b"000102030405+1401",
5023 b"500101000002+0003",
5025 with self.assertRaises(DecodeError):
5026 UTCTime(data, ctx={"bered": True})
5028 @given(integers(min_value=0, max_value=49))
5029 def test_pre50(self, year):
5031 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5035 @given(integers(min_value=50, max_value=99))
5036 def test_post50(self, year):
5038 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5044 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5045 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5047 binary(min_size=1, max_size=1),
5049 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5050 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5053 def test_junk(self, part0, part1, part2):
5054 junk = part0 + part1 + part2
5055 assume(not (set(junk) <= set(digits.encode("ascii"))))
5056 with self.assertRaises(DecodeError):
5058 UTCTime.tag_default +
5059 len_encode(len(junk)) +
5065 def tlv_value_strategy(draw):
5066 tag_num = draw(integers(min_value=1))
5067 data = draw(binary())
5068 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5072 def any_values_strategy(draw, do_expl=False):
5073 value = draw(one_of(none(), tlv_value_strategy()))
5076 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5077 optional = draw(one_of(none(), booleans()))
5079 draw(integers(min_value=0)),
5080 draw(integers(min_value=0)),
5081 draw(integers(min_value=0)),
5083 return (value, expl, optional, _decoded)
5086 class AnyInherited(Any):
5090 class TestAny(CommonMixin, TestCase):
5093 def test_invalid_value_type(self):
5094 with self.assertRaises(InvalidValueType) as err:
5099 def test_optional(self, optional):
5100 obj = Any(optional=optional)
5101 self.assertEqual(obj.optional, optional)
5103 @given(tlv_value_strategy())
5104 def test_ready(self, value):
5106 self.assertFalse(obj.ready)
5109 pprint(obj, big_blobs=True, with_decode_path=True)
5110 with self.assertRaises(ObjNotReady) as err:
5113 with self.assertRaises(ObjNotReady) as err:
5116 self.assertTrue(obj.ready)
5119 pprint(obj, big_blobs=True, with_decode_path=True)
5122 def test_basic(self, value):
5123 integer_encoded = Integer(value).encode()
5125 Any(integer_encoded),
5126 Any(Integer(value)),
5127 Any(Any(Integer(value))),
5129 self.assertSequenceEqual(bytes(obj), integer_encoded)
5131 obj.decode(obj.encode())[0].vlen,
5132 len(integer_encoded),
5136 pprint(obj, big_blobs=True, with_decode_path=True)
5137 self.assertSequenceEqual(obj.encode(), integer_encoded)
5139 @given(tlv_value_strategy(), tlv_value_strategy())
5140 def test_comparison(self, value1, value2):
5141 for klass in (Any, AnyInherited):
5142 obj1 = klass(value1)
5143 obj2 = klass(value2)
5144 self.assertEqual(obj1 == obj2, value1 == value2)
5145 self.assertEqual(obj1 != obj2, value1 != value2)
5146 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5148 @given(data_strategy())
5149 def test_call(self, d):
5150 for klass in (Any, AnyInherited):
5156 ) = d.draw(any_values_strategy())
5157 obj_initial = klass(
5160 optional_initial or False,
5168 ) = d.draw(any_values_strategy(do_expl=True))
5169 obj = obj_initial(value, expl, optional)
5171 value_expected = None if value is None else value
5172 self.assertEqual(obj, value_expected)
5173 self.assertEqual(obj.expl_tag, expl or expl_initial)
5174 if obj.default is None:
5175 optional = optional_initial if optional is None else optional
5176 optional = False if optional is None else optional
5177 self.assertEqual(obj.optional, optional)
5179 def test_simultaneous_impl_expl(self):
5180 # override it, as Any does not have implicit tag
5183 def test_decoded(self):
5184 # override it, as Any does not have implicit tag
5187 @given(any_values_strategy())
5188 def test_copy(self, values):
5189 for klass in (Any, AnyInherited):
5190 obj = klass(*values)
5191 for copy_func in copy_funcs:
5192 obj_copied = copy_func(obj)
5193 self.assert_copied_basic_fields(obj, obj_copied)
5194 self.assertEqual(obj._value, obj_copied._value)
5196 @given(binary().map(OctetString))
5197 def test_stripped(self, value):
5199 with self.assertRaises(NotEnoughData):
5200 obj.decode(obj.encode()[:-1])
5203 tlv_value_strategy(),
5204 integers(min_value=1).map(tag_ctxc),
5206 def test_stripped_expl(self, value, tag_expl):
5207 obj = Any(value, expl=tag_expl)
5208 with self.assertRaises(NotEnoughData):
5209 obj.decode(obj.encode()[:-1])
5212 integers(min_value=31),
5213 integers(min_value=0),
5216 def test_bad_tag(self, tag, offset, decode_path):
5217 with self.assertRaises(DecodeError) as err:
5219 tag_encode(tag)[:-1],
5221 decode_path=decode_path,
5224 self.assertEqual(err.exception.offset, offset)
5225 self.assertEqual(err.exception.decode_path, decode_path)
5228 integers(min_value=128),
5229 integers(min_value=0),
5232 def test_bad_len(self, l, offset, decode_path):
5233 with self.assertRaises(DecodeError) as err:
5235 Any.tag_default + len_encode(l)[:-1],
5237 decode_path=decode_path,
5240 self.assertEqual(err.exception.offset, offset)
5241 self.assertEqual(err.exception.decode_path, decode_path)
5243 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5245 any_values_strategy(),
5246 integers().map(lambda x: Integer(x).encode()),
5247 integers(min_value=1).map(tag_ctxc),
5248 integers(min_value=0),
5252 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5253 for klass in (Any, AnyInherited):
5254 _, _, optional, _decoded = values
5255 obj = klass(value=value, optional=optional, _decoded=_decoded)
5258 pprint(obj, big_blobs=True, with_decode_path=True)
5259 self.assertFalse(obj.expled)
5260 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5261 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5262 obj_encoded = obj.encode()
5263 self.assertEqual(encode2pass(obj), obj_encoded)
5264 obj_expled = obj(value, expl=tag_expl)
5265 self.assertTrue(obj_expled.expled)
5266 tag_class, _, tag_num = tag_decode(tag_expl)
5267 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5269 list(obj_expled.pps())
5270 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5271 obj_expled_encoded = obj_expled.encode()
5272 ctx_copied = deepcopy(ctx_dummy)
5273 obj_decoded, tail = obj_expled.decode(
5274 obj_expled_encoded + tail_junk,
5278 self.assertDictEqual(ctx_copied, ctx_dummy)
5280 list(obj_decoded.pps())
5281 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5282 self.assertEqual(tail, tail_junk)
5283 self.assertEqual(obj_decoded, obj_expled)
5284 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5285 self.assertEqual(bytes(obj_decoded), bytes(obj))
5286 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5287 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5288 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5290 obj_decoded.expl_llen,
5291 len(len_encode(len(obj_encoded))),
5293 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5294 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5297 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5299 self.assertEqual(obj_decoded.expl_offset, offset)
5300 self.assertEqual(obj_decoded.tlen, 0)
5301 self.assertEqual(obj_decoded.llen, 0)
5302 self.assertEqual(obj_decoded.vlen, len(value))
5303 assert_exceeding_data(
5305 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5309 evgens = list(obj_expled.decode_evgen(
5310 obj_expled_encoded + tail_junk,
5312 decode_path=decode_path,
5315 self.assertEqual(len(evgens), 1)
5316 _decode_path, obj, tail = evgens[0]
5317 self.assertSequenceEqual(tail, tail_junk)
5318 self.assertEqual(_decode_path, decode_path)
5319 self.assertEqual(obj.expl_offset, offset)
5324 integers(min_value=1).map(tag_ctxc),
5325 integers(min_value=0, max_value=3),
5326 integers(min_value=0),
5330 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5331 chunk = Boolean(False, expl=expl).encode()
5333 OctetString.tag_default +
5335 b"".join([chunk] * chunks) +
5338 with self.assertRaises(LenIndefForm):
5342 decode_path=decode_path,
5344 obj, tail = Any().decode(
5347 decode_path=decode_path,
5348 ctx={"bered": True},
5350 self.assertSequenceEqual(tail, junk)
5351 self.assertEqual(obj.offset, offset)
5352 self.assertEqual(obj.tlvlen, len(encoded))
5353 self.assertTrue(obj.lenindef)
5354 self.assertFalse(obj.ber_encoded)
5355 self.assertTrue(obj.bered)
5357 self.assertTrue(obj.lenindef)
5358 self.assertFalse(obj.ber_encoded)
5359 self.assertTrue(obj.bered)
5362 pprint(obj, big_blobs=True, with_decode_path=True)
5363 with self.assertRaises(NotEnoughData) as err:
5367 decode_path=decode_path,
5368 ctx={"bered": True},
5370 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5371 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5373 class SeqOf(SequenceOf):
5374 schema = Boolean(expl=expl)
5376 class Seq(Sequence):
5378 ("type", ObjectIdentifier(defines=((("value",), {
5379 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5384 ("type", ObjectIdentifier("1.2.3")),
5385 ("value", Any(encoded)),
5387 seq_encoded = seq.encode()
5388 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5389 self.assertIsNotNone(seq_decoded["value"].defined)
5391 list(seq_decoded.pps())
5392 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5393 self.assertTrue(seq_decoded.bered)
5394 self.assertFalse(seq_decoded["type"].bered)
5395 self.assertTrue(seq_decoded["value"].bered)
5397 chunk = chunk[:-1] + b"\x01"
5398 chunks = b"".join([chunk] * (chunks + 1))
5399 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5401 ("type", ObjectIdentifier("1.2.3")),
5402 ("value", Any(encoded)),
5404 seq_encoded = seq.encode()
5405 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5406 self.assertIsNotNone(seq_decoded["value"].defined)
5408 list(seq_decoded.pps())
5409 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5410 self.assertTrue(seq_decoded.bered)
5411 self.assertFalse(seq_decoded["type"].bered)
5412 self.assertTrue(seq_decoded["value"].bered)
5416 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5418 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5419 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5421 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5422 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5424 min_size=len(names),
5425 max_size=len(names),
5428 (name, Integer(**tag_kwargs))
5429 for name, tag_kwargs in zip(names, tags)
5432 if value_required or draw(booleans()):
5433 value = draw(tuples(
5434 sampled_from([name for name, _ in schema]),
5435 integers().map(Integer),
5439 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5440 default = draw(one_of(
5442 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5444 optional = draw(one_of(none(), booleans()))
5446 draw(integers(min_value=0)),
5447 draw(integers(min_value=0)),
5448 draw(integers(min_value=0)),
5450 return (schema, value, expl, default, optional, _decoded)
5453 class ChoiceInherited(Choice):
5457 class TestChoice(CommonMixin, TestCase):
5459 schema = (("whatever", Boolean()),)
5462 def test_schema_required(self):
5463 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5466 def test_impl_forbidden(self):
5467 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5468 Choice(impl=b"whatever")
5470 def test_invalid_value_type(self):
5471 with self.assertRaises(InvalidValueType) as err:
5472 self.base_klass(123)
5474 with self.assertRaises(ObjUnknown) as err:
5475 self.base_klass(("whenever", Boolean(False)))
5477 with self.assertRaises(InvalidValueType) as err:
5478 self.base_klass(("whatever", Integer(123)))
5482 def test_optional(self, optional):
5483 obj = self.base_klass(
5484 default=self.base_klass(("whatever", Boolean(False))),
5487 self.assertTrue(obj.optional)
5490 def test_ready(self, value):
5491 obj = self.base_klass()
5492 self.assertFalse(obj.ready)
5495 pprint(obj, big_blobs=True, with_decode_path=True)
5496 self.assertIsNone(obj["whatever"])
5497 with self.assertRaises(ObjNotReady) as err:
5500 with self.assertRaises(ObjNotReady) as err:
5502 obj["whatever"] = Boolean()
5503 self.assertFalse(obj.ready)
5506 pprint(obj, big_blobs=True, with_decode_path=True)
5507 obj["whatever"] = Boolean(value)
5508 self.assertTrue(obj.ready)
5511 pprint(obj, big_blobs=True, with_decode_path=True)
5513 @given(booleans(), booleans())
5514 def test_comparison(self, value1, value2):
5515 class WahlInherited(self.base_klass):
5517 for klass in (self.base_klass, WahlInherited):
5518 obj1 = klass(("whatever", Boolean(value1)))
5519 obj2 = klass(("whatever", Boolean(value2)))
5520 self.assertEqual(obj1 == obj2, value1 == value2)
5521 self.assertEqual(obj1 != obj2, value1 != value2)
5522 self.assertEqual(obj1 == obj2._value, value1 == value2)
5523 self.assertFalse(obj1 == obj2._value[1])
5525 @given(data_strategy())
5526 def test_call(self, d):
5527 for klass in (Choice, ChoiceInherited):
5535 ) = d.draw(choice_values_strategy())
5538 schema = schema_initial
5540 value=value_initial,
5542 default=default_initial,
5543 optional=optional_initial or False,
5544 _decoded=_decoded_initial,
5553 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5554 obj = obj_initial(value, expl, default, optional)
5556 value_expected = default if value is None else value
5558 default_initial if value_expected is None
5561 self.assertEqual(obj.choice, value_expected[0])
5562 self.assertEqual(obj.value, int(value_expected[1]))
5563 self.assertEqual(obj.expl_tag, expl or expl_initial)
5564 default_expect = default_initial if default is None else default
5565 if default_expect is not None:
5566 self.assertEqual(obj.default.choice, default_expect[0])
5567 self.assertEqual(obj.default.value, int(default_expect[1]))
5568 if obj.default is None:
5569 optional = optional_initial if optional is None else optional
5570 optional = False if optional is None else optional
5573 self.assertEqual(obj.optional, optional)
5574 self.assertEqual(obj.specs, obj_initial.specs)
5576 def test_simultaneous_impl_expl(self):
5577 # override it, as Any does not have implicit tag
5580 def test_decoded(self):
5581 # override it, as Any does not have implicit tag
5584 @given(choice_values_strategy())
5585 def test_copy(self, values):
5586 _schema, value, expl, default, optional, _decoded = values
5588 class Wahl(self.base_klass):
5590 register_class(Wahl)
5595 optional=optional or False,
5598 for copy_func in copy_funcs:
5599 obj_copied = copy_func(obj)
5600 self.assertIsNone(obj.tag)
5601 self.assertIsNone(obj_copied.tag)
5602 # hack for assert_copied_basic_fields
5603 obj.tag = "whatever"
5604 obj_copied.tag = "whatever"
5605 self.assert_copied_basic_fields(obj, obj_copied)
5607 self.assertEqual(obj._value, obj_copied._value)
5608 self.assertEqual(obj.specs, obj_copied.specs)
5611 def test_stripped(self, value):
5612 obj = self.base_klass(("whatever", Boolean(value)))
5613 with self.assertRaises(NotEnoughData):
5614 obj.decode(obj.encode()[:-1])
5618 integers(min_value=1).map(tag_ctxc),
5620 def test_stripped_expl(self, value, tag_expl):
5621 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5622 with self.assertRaises(NotEnoughData):
5623 obj.decode(obj.encode()[:-1])
5625 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5626 @given(data_strategy())
5627 def test_symmetric(self, d):
5628 _schema, value, _, default, optional, _decoded = d.draw(
5629 choice_values_strategy(value_required=True)
5631 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5632 offset = d.draw(integers(min_value=0))
5633 tail_junk = d.draw(binary(max_size=5))
5634 decode_path = d.draw(decode_path_strat)
5636 class Wahl(self.base_klass):
5646 pprint(obj, big_blobs=True, with_decode_path=True)
5647 self.assertFalse(obj.expled)
5648 self.assertEqual(obj.tag_order, obj.value.tag_order)
5649 obj_encoded = obj.encode()
5650 self.assertEqual(encode2pass(obj), obj_encoded)
5651 obj_expled = obj(value, expl=tag_expl)
5652 self.assertTrue(obj_expled.expled)
5653 tag_class, _, tag_num = tag_decode(tag_expl)
5654 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5656 list(obj_expled.pps())
5657 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5658 obj_expled_encoded = obj_expled.encode()
5659 ctx_copied = deepcopy(ctx_dummy)
5660 obj_decoded, tail = obj_expled.decode(
5661 obj_expled_encoded + tail_junk,
5665 self.assertDictEqual(ctx_copied, ctx_dummy)
5667 list(obj_decoded.pps())
5668 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5669 self.assertEqual(tail, tail_junk)
5670 self.assertEqual(obj_decoded, obj_expled)
5671 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5672 self.assertEqual(obj_decoded.value, obj_expled.value)
5673 self.assertEqual(obj_decoded.choice, obj.choice)
5674 self.assertEqual(obj_decoded.value, obj.value)
5675 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5676 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5677 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5679 obj_decoded.expl_llen,
5680 len(len_encode(len(obj_encoded))),
5682 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5683 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5686 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5688 self.assertEqual(obj_decoded.expl_offset, offset)
5689 self.assertSequenceEqual(
5691 obj_decoded.value.fulloffset - offset:
5692 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5696 assert_exceeding_data(
5698 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5702 evgens = list(obj_expled.decode_evgen(
5703 obj_expled_encoded + tail_junk,
5705 decode_path=decode_path,
5708 self.assertEqual(len(evgens), 2)
5709 _decode_path, obj, tail = evgens[0]
5710 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5711 _decode_path, obj, tail = evgens[1]
5712 self.assertSequenceEqual(tail, tail_junk)
5713 self.assertEqual(_decode_path, decode_path)
5714 self.assertEqual(obj.expl_offset, offset)
5719 def test_set_get(self, value):
5722 ("erste", Boolean()),
5723 ("zweite", Integer()),
5726 with self.assertRaises(ObjUnknown) as err:
5727 obj["whatever"] = "whenever"
5728 with self.assertRaises(InvalidValueType) as err:
5729 obj["zweite"] = Boolean(False)
5730 obj["zweite"] = Integer(value)
5732 with self.assertRaises(ObjUnknown) as err:
5735 self.assertIsNone(obj["erste"])
5736 self.assertEqual(obj["zweite"], Integer(value))
5738 def test_tag_mismatch(self):
5741 ("erste", Boolean()),
5743 int_encoded = Integer(123).encode()
5744 bool_encoded = Boolean(False).encode()
5746 obj.decode(bool_encoded)
5747 with self.assertRaises(TagMismatch):
5748 obj.decode(int_encoded)
5750 def test_tag_mismatch_underlying(self):
5751 class SeqOfBoolean(SequenceOf):
5754 class SeqOfInteger(SequenceOf):
5759 ("erste", SeqOfBoolean()),
5762 int_encoded = SeqOfInteger((Integer(123),)).encode()
5763 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5765 obj.decode(bool_encoded)
5766 with self.assertRaises(TagMismatch) as err:
5767 obj.decode(int_encoded)
5768 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5772 def seq_values_strategy(draw, seq_klass, do_expl=False):
5774 if draw(booleans()):
5776 value._value = draw(dictionaries(
5779 booleans().map(Boolean),
5780 integers().map(Integer),
5784 if draw(booleans()):
5785 schema = list(draw(dictionaries(
5788 booleans().map(Boolean),
5789 integers().map(Integer),
5795 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5797 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5799 if draw(booleans()):
5800 default = seq_klass()
5801 default._value = draw(dictionaries(
5804 booleans().map(Boolean),
5805 integers().map(Integer),
5808 optional = draw(one_of(none(), booleans()))
5810 draw(integers(min_value=0)),
5811 draw(integers(min_value=0)),
5812 draw(integers(min_value=0)),
5814 return (value, schema, impl, expl, default, optional, _decoded)
5818 def sequence_strategy(draw, seq_klass):
5819 inputs = draw(lists(
5821 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5822 tuples(just(Integer), integers(), one_of(none(), integers())),
5827 integers(min_value=1),
5828 min_size=len(inputs),
5829 max_size=len(inputs),
5832 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5833 for tag, expled in zip(tags, draw(lists(
5835 min_size=len(inputs),
5836 max_size=len(inputs),
5840 for i, optional in enumerate(draw(lists(
5841 sampled_from(("required", "optional", "empty")),
5842 min_size=len(inputs),
5843 max_size=len(inputs),
5845 if optional in ("optional", "empty"):
5846 inits[i]["optional"] = True
5847 if optional == "empty":
5849 empties = set(empties)
5850 names = list(draw(sets(
5852 min_size=len(inputs),
5853 max_size=len(inputs),
5856 for i, (klass, value, default) in enumerate(inputs):
5857 schema.append((names[i], klass(default=default, **inits[i])))
5858 seq_name = draw(text_letters())
5859 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5862 for i, (klass, value, default) in enumerate(inputs):
5869 "default_value": None if spec.default is None else default,
5873 expect["optional"] = True
5875 expect["presented"] = True
5876 expect["value"] = value
5878 expect["optional"] = True
5879 if default is not None and default == value:
5880 expect["presented"] = False
5881 seq[name] = klass(value)
5882 expects.append(expect)
5887 def sequences_strategy(draw, seq_klass):
5888 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5890 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5891 for tag, expled in zip(tags, draw(lists(
5898 i for i, is_default in enumerate(draw(lists(
5904 names = list(draw(sets(
5909 seq_expectses = draw(lists(
5910 sequence_strategy(seq_klass=seq_klass),
5914 seqs = [seq for seq, _ in seq_expectses]
5916 for i, (name, seq) in enumerate(zip(names, seqs)):
5919 seq(default=(seq if i in defaulted else None), **inits[i]),
5921 seq_name = draw(text_letters())
5922 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5925 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5928 "expects": expects_inner,
5931 seq_outer[name] = seq_inner
5932 if seq_outer.specs[name].default is None:
5933 expect["presented"] = True
5934 expect_outers.append(expect)
5935 return seq_outer, expect_outers
5938 class SeqMixing(object):
5939 def test_invalid_value_type(self):
5940 with self.assertRaises(InvalidValueType) as err:
5941 self.base_klass(123)
5944 def test_invalid_value_type_set(self):
5945 class Seq(self.base_klass):
5946 schema = (("whatever", Boolean()),)
5948 with self.assertRaises(InvalidValueType) as err:
5949 seq["whatever"] = Integer(123)
5953 def test_optional(self, optional):
5954 obj = self.base_klass(default=self.base_klass(), optional=optional)
5955 self.assertTrue(obj.optional)
5957 @given(data_strategy())
5958 def test_ready(self, d):
5960 str(i): v for i, v in enumerate(d.draw(lists(
5967 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5974 for name in d.draw(permutations(
5975 list(ready.keys()) + list(non_ready.keys()),
5977 schema_input.append((name, Boolean()))
5979 class Seq(self.base_klass):
5980 schema = tuple(schema_input)
5982 for name in ready.keys():
5984 seq[name] = Boolean()
5985 self.assertFalse(seq.ready)
5988 pprint(seq, big_blobs=True, with_decode_path=True)
5989 for name, value in ready.items():
5990 seq[name] = Boolean(value)
5991 self.assertFalse(seq.ready)
5994 pprint(seq, big_blobs=True, with_decode_path=True)
5995 with self.assertRaises(ObjNotReady) as err:
5998 with self.assertRaises(ObjNotReady) as err:
6000 for name, value in non_ready.items():
6001 seq[name] = Boolean(value)
6002 self.assertTrue(seq.ready)
6005 pprint(seq, big_blobs=True, with_decode_path=True)
6007 @given(data_strategy())
6008 def test_call(self, d):
6009 class SeqInherited(self.base_klass):
6011 for klass in (self.base_klass, SeqInherited):
6020 ) = d.draw(seq_values_strategy(seq_klass=klass))
6021 obj_initial = klass(
6027 optional_initial or False,
6038 ) = d.draw(seq_values_strategy(
6040 do_expl=impl_initial is None,
6042 obj = obj_initial(value, impl, expl, default, optional)
6043 value_expected = default if value is None else value
6045 default_initial if value_expected is None
6048 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
6049 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6050 self.assertEqual(obj.expl_tag, expl or expl_initial)
6052 {} if obj.default is None else obj.default._value,
6053 getattr(default_initial if default is None else default, "_value", {}),
6055 if obj.default is None:
6056 optional = optional_initial if optional is None else optional
6057 optional = False if optional is None else optional
6060 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6061 self.assertEqual(obj.optional, optional)
6063 @given(data_strategy())
6064 def test_copy(self, d):
6065 class SeqInherited(self.base_klass):
6067 register_class(SeqInherited)
6068 for klass in (self.base_klass, SeqInherited):
6069 values = d.draw(seq_values_strategy(seq_klass=klass))
6070 obj = klass(*values)
6071 for copy_func in copy_funcs:
6072 obj_copied = copy_func(obj)
6073 self.assert_copied_basic_fields(obj, obj_copied)
6074 self.assertEqual(obj.specs, obj_copied.specs)
6075 self.assertEqual(obj._value, obj_copied._value)
6077 @given(data_strategy())
6078 def test_stripped(self, d):
6079 value = d.draw(integers())
6080 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6082 class Seq(self.base_klass):
6084 schema = (("whatever", Integer()),)
6086 seq["whatever"] = Integer(value)
6087 with self.assertRaises(NotEnoughData):
6088 seq.decode(seq.encode()[:-1])
6090 @given(data_strategy())
6091 def test_stripped_expl(self, d):
6092 value = d.draw(integers())
6093 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6095 class Seq(self.base_klass):
6097 schema = (("whatever", Integer()),)
6099 seq["whatever"] = Integer(value)
6100 with self.assertRaises(NotEnoughData):
6101 seq.decode(seq.encode()[:-1])
6103 @given(integers(min_value=3), binary(min_size=2))
6104 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6105 junk = tag_encode(junk_tag_num) + junk
6107 _, _, len_encoded = tag_strip(memoryview(junk))
6108 len_decode(len_encoded)
6114 class Seq(self.base_klass):
6116 ("whatever", Integer()),
6118 ("whenever", Integer()),
6121 seq["whatever"] = Integer(123)
6122 seq["junk"] = Any(junk)
6123 seq["whenever"] = Integer(123)
6124 with self.assertRaises(DecodeError):
6125 seq.decode(seq.encode())
6128 integers(min_value=31),
6129 integers(min_value=0),
6132 def test_bad_tag(self, tag, offset, decode_path):
6133 with self.assertRaises(DecodeError) as err:
6134 self.base_klass().decode(
6135 tag_encode(tag)[:-1],
6137 decode_path=decode_path,
6140 self.assertEqual(err.exception.offset, offset)
6141 self.assertEqual(err.exception.decode_path, decode_path)
6144 integers(min_value=128),
6145 integers(min_value=0),
6148 def test_bad_len(self, l, offset, decode_path):
6149 with self.assertRaises(DecodeError) as err:
6150 self.base_klass().decode(
6151 self.base_klass.tag_default + len_encode(l)[:-1],
6153 decode_path=decode_path,
6156 self.assertEqual(err.exception.offset, offset)
6157 self.assertEqual(err.exception.decode_path, decode_path)
6159 def _assert_expects(self, seq, expects):
6160 for expect in expects:
6162 seq.specs[expect["name"]].optional,
6165 if expect["default_value"] is not None:
6167 seq.specs[expect["name"]].default,
6168 expect["default_value"],
6170 if expect["presented"]:
6171 self.assertIn(expect["name"], seq)
6172 self.assertEqual(seq[expect["name"]], expect["value"])
6174 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6175 @given(data_strategy())
6176 def test_symmetric(self, d):
6177 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6178 tail_junk = d.draw(binary(max_size=5))
6179 decode_path = d.draw(decode_path_strat)
6180 self.assertTrue(seq.ready)
6181 self.assertFalse(seq.decoded)
6182 self._assert_expects(seq, expects)
6185 pprint(seq, big_blobs=True, with_decode_path=True)
6186 self.assertTrue(seq.ready)
6187 seq_encoded = seq.encode()
6188 self.assertEqual(encode2pass(seq), seq_encoded)
6189 seq_encoded_cer = encode_cer(seq)
6190 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6191 self.assertSequenceEqual(
6192 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6195 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6196 self.assertFalse(seq_decoded.lenindef)
6197 self.assertFalse(seq_decoded.ber_encoded)
6198 self.assertFalse(seq_decoded.bered)
6200 t, _, lv = tag_strip(seq_encoded)
6201 _, _, v = len_decode(lv)
6202 seq_encoded_lenindef = t + LENINDEF + v + EOC
6203 with self.assertRaises(DecodeError):
6204 seq.decode(seq_encoded_lenindef)
6205 ctx_copied = deepcopy(ctx_dummy)
6206 ctx_copied["bered"] = True
6207 seq_decoded_lenindef, tail_lenindef = seq.decode(
6208 seq_encoded_lenindef + tail_junk,
6211 del ctx_copied["bered"]
6212 self.assertDictEqual(ctx_copied, ctx_dummy)
6213 self.assertTrue(seq_decoded_lenindef.lenindef)
6214 self.assertTrue(seq_decoded_lenindef.bered)
6215 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6216 self.assertTrue(seq_decoded_lenindef.lenindef)
6217 self.assertTrue(seq_decoded_lenindef.bered)
6218 with self.assertRaises(DecodeError):
6219 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6220 with self.assertRaises(DecodeError):
6221 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6222 repr(seq_decoded_lenindef)
6223 list(seq_decoded_lenindef.pps())
6224 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6225 self.assertTrue(seq_decoded_lenindef.ready)
6227 for decoded, decoded_tail, encoded in (
6228 (seq_decoded, tail, seq_encoded),
6229 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6231 self.assertEqual(decoded_tail, tail_junk)
6232 self._assert_expects(decoded, expects)
6233 self.assertEqual(seq, decoded)
6234 self.assertEqual(decoded.encode(), seq_encoded)
6235 self.assertEqual(decoded.tlvlen, len(encoded))
6236 for expect in expects:
6237 if not expect["presented"]:
6238 self.assertNotIn(expect["name"], decoded)
6240 self.assertIn(expect["name"], decoded)
6241 obj = decoded[expect["name"]]
6242 self.assertTrue(obj.decoded)
6243 offset = obj.expl_offset if obj.expled else obj.offset
6244 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6245 self.assertSequenceEqual(
6246 seq_encoded[offset:offset + tlvlen],
6250 evgens = list(seq.decode_evgen(
6251 encoded + decoded_tail,
6252 decode_path=decode_path,
6253 ctx={"bered": True},
6255 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6256 for _decode_path, obj, _ in evgens[:-1]:
6257 self.assertEqual(_decode_path[:-1], decode_path)
6260 _decode_path, obj, tail = evgens[-1]
6261 self.assertEqual(_decode_path, decode_path)
6265 assert_exceeding_data(
6267 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6271 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6272 @given(data_strategy())
6273 def test_symmetric_with_seq(self, d):
6274 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6275 self.assertTrue(seq.ready)
6276 seq_encoded = seq.encode()
6277 self.assertEqual(encode2pass(seq), seq_encoded)
6278 seq_decoded, tail = seq.decode(seq_encoded)
6279 self.assertEqual(tail, b"")
6280 self.assertTrue(seq.ready)
6281 self.assertEqual(seq, seq_decoded)
6282 self.assertEqual(seq_decoded.encode(), seq_encoded)
6283 for expect_outer in expect_outers:
6284 if not expect_outer["presented"]:
6285 self.assertNotIn(expect_outer["name"], seq_decoded)
6287 self.assertIn(expect_outer["name"], seq_decoded)
6288 obj = seq_decoded[expect_outer["name"]]
6289 self.assertTrue(obj.decoded)
6290 offset = obj.expl_offset if obj.expled else obj.offset
6291 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6292 self.assertSequenceEqual(
6293 seq_encoded[offset:offset + tlvlen],
6296 self._assert_expects(obj, expect_outer["expects"])
6298 @given(data_strategy())
6299 def test_default_disappears(self, d):
6300 _schema = list(d.draw(dictionaries(
6302 sets(integers(), min_size=2, max_size=2),
6306 class Seq(self.base_klass):
6308 (n, Integer(default=d))
6309 for n, (_, d) in _schema
6312 for name, (value, _) in _schema:
6313 seq[name] = Integer(value)
6314 self.assertEqual(len(seq._value), len(_schema))
6315 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6316 self.assertGreater(len(seq.encode()), len(empty_seq))
6317 for name, (_, default) in _schema:
6318 seq[name] = Integer(default)
6319 self.assertEqual(len(seq._value), 0)
6320 self.assertSequenceEqual(seq.encode(), empty_seq)
6322 @given(data_strategy())
6323 def test_encoded_default_not_accepted(self, d):
6324 _schema = list(d.draw(dictionaries(
6329 tags = [tag_encode(tag) for tag in d.draw(sets(
6330 integers(min_value=1),
6331 min_size=len(_schema),
6332 max_size=len(_schema),
6336 schema = (("int", Integer()),)
6338 class SeqWithoutDefault(self.base_klass):
6341 for (n, _), t in zip(_schema, tags)
6343 seq_without_default = SeqWithoutDefault()
6344 for name, value in _schema:
6345 seq_without_default[name] = Wahl(("int", Integer(value)))
6346 seq_encoded = seq_without_default.encode()
6347 seq_without_default.decode(seq_encoded)
6349 len(list(seq_without_default.decode_evgen(seq_encoded))),
6350 len(_schema) * 2 + 1,
6353 class SeqWithDefault(self.base_klass):
6355 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6356 for (n, v), t in zip(_schema, tags)
6358 seq_with_default = SeqWithDefault()
6359 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6360 seq_with_default.decode(seq_encoded)
6361 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6362 list(seq_with_default.decode_evgen(seq_encoded))
6363 for ctx in ({"bered": True}, {"allow_default_values": True}):
6364 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6365 self.assertTrue(seq_decoded.ber_encoded)
6366 self.assertTrue(seq_decoded.bered)
6367 seq_decoded = copy(seq_decoded)
6368 self.assertTrue(seq_decoded.ber_encoded)
6369 self.assertTrue(seq_decoded.bered)
6370 for name, value in _schema:
6371 self.assertEqual(seq_decoded[name], seq_with_default[name])
6372 self.assertEqual(seq_decoded[name].value, value)
6374 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6378 seq_without_default = SeqWithoutDefault()
6379 for name, value in _schema:
6380 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6381 seq_encoded = seq_without_default.encode()
6382 seq_with_default.decode(seq_encoded)
6384 len(list(seq_with_default.decode_evgen(seq_encoded))),
6388 @given(data_strategy())
6389 def test_missing_from_spec(self, d):
6390 names = list(d.draw(sets(text_letters(), min_size=2)))
6391 tags = [tag_encode(tag) for tag in d.draw(sets(
6392 integers(min_value=1),
6393 min_size=len(names),
6394 max_size=len(names),
6396 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6398 class SeqFull(self.base_klass):
6399 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6400 seq_full = SeqFull()
6401 for i, name in enumerate(names):
6402 seq_full[name] = Integer(i)
6403 seq_encoded = seq_full.encode()
6404 altered = names_tags[:-2] + names_tags[-1:]
6406 class SeqMissing(self.base_klass):
6407 schema = [(n, Integer(impl=t)) for n, t in altered]
6408 seq_missing = SeqMissing()
6409 with self.assertRaises(TagMismatch):
6410 seq_missing.decode(seq_encoded)
6411 with self.assertRaises(TagMismatch):
6412 list(seq_missing.decode_evgen(seq_encoded))
6414 def test_bered(self):
6415 class Seq(self.base_klass):
6416 schema = (("underlying", Boolean()),)
6417 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6418 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6419 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6420 self.assertFalse(decoded.ber_encoded)
6421 self.assertFalse(decoded.lenindef)
6422 self.assertTrue(decoded.bered)
6423 decoded = copy(decoded)
6424 self.assertFalse(decoded.ber_encoded)
6425 self.assertFalse(decoded.lenindef)
6426 self.assertTrue(decoded.bered)
6428 class Seq(self.base_klass):
6429 schema = (("underlying", OctetString()),)
6431 tag_encode(form=TagFormConstructed, num=4) +
6433 OctetString(b"whatever").encode() +
6436 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6437 with self.assertRaises(DecodeError):
6438 Seq().decode(encoded)
6439 with self.assertRaises(DecodeError):
6440 list(Seq().decode_evgen(encoded))
6441 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6442 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6443 self.assertFalse(decoded.ber_encoded)
6444 self.assertFalse(decoded.lenindef)
6445 self.assertTrue(decoded.bered)
6446 decoded = copy(decoded)
6447 self.assertFalse(decoded.ber_encoded)
6448 self.assertFalse(decoded.lenindef)
6449 self.assertTrue(decoded.bered)
6452 class TestSequence(SeqMixing, CommonMixin, TestCase):
6453 base_klass = Sequence
6459 def test_remaining(self, value, junk):
6460 class Seq(Sequence):
6462 ("whatever", Integer()),
6464 int_encoded = Integer(value).encode()
6466 Sequence.tag_default,
6467 len_encode(len(int_encoded + junk)),
6470 with assertRaisesRegex(self, DecodeError, "remaining"):
6471 Seq().decode(junked)
6473 @given(sets(text_letters(), min_size=2))
6474 def test_obj_unknown(self, names):
6475 missing = names.pop()
6477 class Seq(Sequence):
6478 schema = [(n, Boolean()) for n in names]
6480 with self.assertRaises(ObjUnknown) as err:
6483 with self.assertRaises(ObjUnknown) as err:
6484 seq[missing] = Boolean()
6487 def test_x690_vector(self):
6488 class Seq(Sequence):
6490 ("name", IA5String()),
6493 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6494 self.assertEqual(seq["name"], "Smith")
6495 self.assertEqual(seq["ok"], True)
6498 class TestSet(SeqMixing, CommonMixin, TestCase):
6501 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6502 @given(data_strategy())
6503 def test_sorted(self, d):
6504 class DummySeq(Sequence):
6505 schema = (("null", Null()),)
6507 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6508 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6509 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6510 tag_nums -= set([dummy_seq_tag_num])
6511 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6512 _schema.append(("seq", DummySeq()))
6515 schema = d.draw(permutations(_schema))
6517 for name, _ in _schema:
6519 seq[name] = OctetString(name.encode("ascii"))
6520 seq["seq"] = DummySeq((("null", Null()),))
6522 seq_encoded = seq.encode()
6523 seq_decoded, _ = seq.decode(seq_encoded)
6524 seq_encoded_expected = []
6525 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6526 if tag_num == dummy_seq_tag_num:
6527 seq_encoded_expected.append(seq["seq"].encode())
6529 seq_encoded_expected.append(seq[str(tag_num)].encode())
6530 self.assertSequenceEqual(
6531 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6532 b"".join(seq_encoded_expected),
6535 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6536 encoded += seq["seq"].encode()
6537 seq_encoded = b"".join((
6539 len_encode(len(encoded)),
6542 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6543 seq.decode(seq_encoded)
6544 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6545 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6546 self.assertTrue(seq_decoded.ber_encoded)
6547 self.assertTrue(seq_decoded.bered)
6548 seq_decoded = copy(seq_decoded)
6549 self.assertTrue(seq_decoded.ber_encoded)
6550 self.assertTrue(seq_decoded.bered)
6552 def test_same_value_twice(self):
6555 ("bool", Boolean()),
6559 encoded = b"".join((
6560 Integer(123).encode(),
6561 Integer(234).encode(),
6562 Boolean(True).encode(),
6564 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6565 with self.assertRaises(TagMismatch):
6566 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6570 def seqof_values_strategy(draw, schema=None, do_expl=False):
6572 schema = draw(sampled_from((Boolean(), Integer())))
6573 bound_min, bound_max = sorted(draw(sets(
6574 integers(min_value=0, max_value=10),
6578 if isinstance(schema, Boolean):
6579 values_generator = booleans().map(Boolean)
6580 elif isinstance(schema, Integer):
6581 values_generator = integers().map(Integer)
6582 values_generator = lists(
6587 values = draw(one_of(none(), values_generator))
6591 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6593 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6594 default = draw(one_of(none(), values_generator))
6595 optional = draw(one_of(none(), booleans()))
6597 draw(integers(min_value=0)),
6598 draw(integers(min_value=0)),
6599 draw(integers(min_value=0)),
6604 (bound_min, bound_max),
6613 class SeqOfMixing(object):
6614 def test_invalid_value_type(self):
6615 with self.assertRaises(InvalidValueType) as err:
6616 self.base_klass(123)
6619 def test_invalid_values_type(self):
6620 class SeqOf(self.base_klass):
6622 with self.assertRaises(InvalidValueType) as err:
6623 SeqOf([Integer(123), Boolean(False), Integer(234)])
6626 def test_schema_required(self):
6627 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6628 self.base_klass.__mro__[1]()
6630 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6631 def test_comparison(self, value1, value2, tag1, tag2):
6632 class SeqOf(self.base_klass):
6634 obj1 = SeqOf([Boolean(value1)])
6635 obj2 = SeqOf([Boolean(value2)])
6636 self.assertEqual(obj1 == obj2, value1 == value2)
6637 self.assertEqual(obj1 != obj2, value1 != value2)
6638 self.assertEqual(obj1 == list(obj2), value1 == value2)
6639 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6640 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6641 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6642 self.assertEqual(obj1 == obj2, tag1 == tag2)
6643 self.assertEqual(obj1 != obj2, tag1 != tag2)
6645 @given(lists(booleans()))
6646 def test_iter(self, values):
6647 class SeqOf(self.base_klass):
6649 obj = SeqOf([Boolean(value) for value in values])
6650 self.assertEqual(len(obj), len(values))
6651 for i, value in enumerate(obj):
6652 self.assertEqual(value, values[i])
6654 @given(data_strategy())
6655 def test_ready(self, d):
6656 ready = [Integer(v) for v in d.draw(lists(
6663 range(d.draw(integers(min_value=1, max_value=5)))
6666 class SeqOf(self.base_klass):
6668 values = d.draw(permutations(ready + non_ready))
6670 for value in values:
6672 self.assertFalse(seqof.ready)
6675 pprint(seqof, big_blobs=True, with_decode_path=True)
6676 with self.assertRaises(ObjNotReady) as err:
6679 with self.assertRaises(ObjNotReady) as err:
6681 for i, value in enumerate(values):
6682 self.assertEqual(seqof[i], value)
6683 if not seqof[i].ready:
6684 seqof[i] = Integer(i)
6685 self.assertTrue(seqof.ready)
6688 pprint(seqof, big_blobs=True, with_decode_path=True)
6690 def test_spec_mismatch(self):
6691 class SeqOf(self.base_klass):
6694 seqof.append(Integer(123))
6695 with self.assertRaises(ValueError):
6696 seqof.append(Boolean(False))
6697 with self.assertRaises(ValueError):
6698 seqof[0] = Boolean(False)
6700 @given(data_strategy())
6701 def test_bounds_satisfied(self, d):
6702 class SeqOf(self.base_klass):
6704 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6705 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6706 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6707 SeqOf(value=value, bounds=(bound_min, bound_max))
6709 @given(data_strategy())
6710 def test_bounds_unsatisfied(self, d):
6711 class SeqOf(self.base_klass):
6713 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6714 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6715 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6716 with self.assertRaises(BoundsError) as err:
6717 SeqOf(value=value, bounds=(bound_min, bound_max))
6719 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6720 SeqOf(bounds=(bound_min, bound_max)).decode(
6721 SeqOf(value).encode()
6724 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6725 SeqOf(bounds=(bound_min, bound_max)).decode(
6726 encode2pass(SeqOf(value))
6728 value = [Boolean(True)] * d.draw(integers(
6729 min_value=bound_max + 1,
6730 max_value=bound_max + 10,
6732 with self.assertRaises(BoundsError) as err:
6733 SeqOf(value=value, bounds=(bound_min, bound_max))
6735 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6736 SeqOf(bounds=(bound_min, bound_max)).decode(
6737 SeqOf(value).encode()
6740 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6741 SeqOf(bounds=(bound_min, bound_max)).decode(
6742 encode2pass(SeqOf(value))
6745 @given(integers(min_value=1, max_value=10))
6746 def test_out_of_bounds(self, bound_max):
6747 class SeqOf(self.base_klass):
6749 bounds = (0, bound_max)
6751 for _ in range(bound_max):
6752 seqof.append(Integer(123))
6753 with self.assertRaises(BoundsError):
6754 seqof.append(Integer(123))
6756 @given(data_strategy())
6757 def test_call(self, d):
6767 ) = d.draw(seqof_values_strategy())
6769 class SeqOf(self.base_klass):
6770 schema = schema_initial
6771 obj_initial = SeqOf(
6772 value=value_initial,
6773 bounds=bounds_initial,
6776 default=default_initial,
6777 optional=optional_initial or False,
6778 _decoded=_decoded_initial,
6789 ) = d.draw(seqof_values_strategy(
6790 schema=schema_initial,
6791 do_expl=impl_initial is None,
6793 if (default is None) and (obj_initial.default is not None):
6796 (bounds is None) and
6797 (value is not None) and
6798 (bounds_initial is not None) and
6799 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6803 (bounds is None) and
6804 (default is not None) and
6805 (bounds_initial is not None) and
6806 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6818 value_expected = default if value is None else value
6820 default_initial if value_expected is None
6823 value_expected = () if value_expected is None else value_expected
6824 self.assertEqual(obj, value_expected)
6825 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6826 self.assertEqual(obj.expl_tag, expl or expl_initial)
6829 default_initial if default is None else default,
6831 if obj.default is None:
6832 optional = optional_initial if optional is None else optional
6833 optional = False if optional is None else optional
6836 self.assertEqual(obj.optional, optional)
6838 (obj._bound_min, obj._bound_max),
6839 bounds or bounds_initial or (0, float("+inf")),
6842 @given(seqof_values_strategy())
6843 def test_copy(self, values):
6844 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6846 class SeqOf(self.base_klass):
6848 register_class(SeqOf)
6855 optional=optional or False,
6858 for copy_func in copy_funcs:
6859 obj_copied = copy_func(obj)
6860 self.assert_copied_basic_fields(obj, obj_copied)
6861 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6862 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6863 self.assertEqual(obj._value, obj_copied._value)
6867 integers(min_value=1).map(tag_encode),
6869 def test_stripped(self, values, tag_impl):
6870 class SeqOf(self.base_klass):
6871 schema = OctetString()
6872 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6873 with self.assertRaises(NotEnoughData):
6874 obj.decode(obj.encode()[:-1])
6878 integers(min_value=1).map(tag_ctxc),
6880 def test_stripped_expl(self, values, tag_expl):
6881 class SeqOf(self.base_klass):
6882 schema = OctetString()
6883 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6884 with self.assertRaises(NotEnoughData):
6885 obj.decode(obj.encode()[:-1])
6888 integers(min_value=31),
6889 integers(min_value=0),
6892 def test_bad_tag(self, tag, offset, decode_path):
6893 with self.assertRaises(DecodeError) as err:
6894 self.base_klass().decode(
6895 tag_encode(tag)[:-1],
6897 decode_path=decode_path,
6900 self.assertEqual(err.exception.offset, offset)
6901 self.assertEqual(err.exception.decode_path, decode_path)
6904 integers(min_value=128),
6905 integers(min_value=0),
6908 def test_bad_len(self, l, offset, decode_path):
6909 with self.assertRaises(DecodeError) as err:
6910 self.base_klass().decode(
6911 self.base_klass.tag_default + len_encode(l)[:-1],
6913 decode_path=decode_path,
6916 self.assertEqual(err.exception.offset, offset)
6917 self.assertEqual(err.exception.decode_path, decode_path)
6919 @given(binary(min_size=1))
6920 def test_tag_mismatch(self, impl):
6921 assume(impl != self.base_klass.tag_default)
6922 with self.assertRaises(TagMismatch):
6923 self.base_klass(impl=impl).decode(self.base_klass().encode())
6925 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6927 seqof_values_strategy(schema=Integer()),
6928 lists(integers().map(Integer)),
6929 integers(min_value=1).map(tag_ctxc),
6930 integers(min_value=0),
6934 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6935 _, _, _, _, _, default, optional, _decoded = values
6937 class SeqOf(self.base_klass):
6947 pprint(obj, big_blobs=True, with_decode_path=True)
6948 self.assertFalse(obj.expled)
6949 obj_encoded = obj.encode()
6950 self.assertEqual(encode2pass(obj), obj_encoded)
6951 obj_encoded_cer = encode_cer(obj)
6952 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6953 self.assertSequenceEqual(
6954 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6957 obj_expled = obj(value, expl=tag_expl)
6958 self.assertTrue(obj_expled.expled)
6960 list(obj_expled.pps())
6961 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6962 obj_expled_encoded = obj_expled.encode()
6963 ctx_copied = deepcopy(ctx_dummy)
6964 obj_decoded, tail = obj_expled.decode(
6965 obj_expled_encoded + tail_junk,
6969 self.assertDictEqual(ctx_copied, ctx_dummy)
6971 list(obj_decoded.pps())
6972 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6973 self.assertEqual(tail, tail_junk)
6974 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6975 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6976 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6977 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6979 obj_decoded.expl_llen,
6980 len(len_encode(len(obj_encoded))),
6982 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6983 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6986 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6988 self.assertEqual(obj_decoded.expl_offset, offset)
6989 for obj_inner in obj_decoded:
6990 self.assertIn(obj_inner, obj_decoded)
6991 self.assertSequenceEqual(
6994 obj_inner.offset - offset:
6995 obj_inner.offset + obj_inner.tlvlen - offset
6999 t, _, lv = tag_strip(obj_encoded)
7000 _, _, v = len_decode(lv)
7001 obj_encoded_lenindef = t + LENINDEF + v + EOC
7002 with self.assertRaises(DecodeError):
7003 obj.decode(obj_encoded_lenindef)
7004 obj_decoded_lenindef, tail_lenindef = obj.decode(
7005 obj_encoded_lenindef + tail_junk,
7006 ctx={"bered": True},
7008 self.assertTrue(obj_decoded_lenindef.lenindef)
7009 self.assertTrue(obj_decoded_lenindef.bered)
7010 obj_decoded_lenindef = copy(obj_decoded_lenindef)
7011 self.assertTrue(obj_decoded_lenindef.lenindef)
7012 self.assertTrue(obj_decoded_lenindef.bered)
7013 repr(obj_decoded_lenindef)
7014 list(obj_decoded_lenindef.pps())
7015 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
7016 self.assertEqual(tail_lenindef, tail_junk)
7017 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
7018 with self.assertRaises(DecodeError):
7019 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
7020 with self.assertRaises(DecodeError):
7021 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
7023 evgens = list(obj.decode_evgen(
7024 obj_encoded_lenindef + tail_junk,
7025 decode_path=decode_path,
7026 ctx={"bered": True},
7028 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
7029 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
7030 self.assertEqual(_decode_path, decode_path + (str(i),))
7033 _decode_path, obj, tail = evgens[-1]
7034 self.assertEqual(_decode_path, decode_path)
7038 assert_exceeding_data(
7040 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
7044 def test_bered(self):
7045 class SeqOf(self.base_klass):
7047 encoded = Boolean(False).encode()
7048 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
7049 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7050 with self.assertRaises(DecodeError):
7051 SeqOf().decode(encoded)
7052 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7053 self.assertFalse(decoded.ber_encoded)
7054 self.assertFalse(decoded.lenindef)
7055 self.assertTrue(decoded.bered)
7056 decoded = copy(decoded)
7057 self.assertFalse(decoded.ber_encoded)
7058 self.assertFalse(decoded.lenindef)
7059 self.assertTrue(decoded.bered)
7061 class SeqOf(self.base_klass):
7062 schema = OctetString()
7063 encoded = OctetString(b"whatever").encode()
7065 tag_encode(form=TagFormConstructed, num=4) +
7067 OctetString(b"whatever").encode() +
7070 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7071 with self.assertRaises(DecodeError):
7072 SeqOf().decode(encoded)
7073 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7074 self.assertFalse(decoded.ber_encoded)
7075 self.assertFalse(decoded.lenindef)
7076 self.assertTrue(decoded.bered)
7077 decoded = copy(decoded)
7078 self.assertFalse(decoded.ber_encoded)
7079 self.assertFalse(decoded.lenindef)
7080 self.assertTrue(decoded.bered)
7083 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7084 class SeqOf(SequenceOf):
7088 def _test_symmetric_compare_objs(self, obj1, obj2):
7089 self.assertEqual(obj1, obj2)
7090 self.assertSequenceEqual(list(obj1), list(obj2))
7092 def test_iterator_pickling(self):
7093 class SeqOf(SequenceOf):
7095 register_class(SeqOf)
7098 seqof = seqof(iter(six_xrange(10)))
7099 with assertRaisesRegex(self, ValueError, "iterator"):
7102 def test_iterator_bounds(self):
7103 class SeqOf(SequenceOf):
7109 for i in six_xrange(n):
7112 seqof = SeqOf(gen(n))
7113 self.assertTrue(seqof.ready)
7114 with self.assertRaises(BoundsError):
7116 self.assertFalse(seqof.ready)
7117 seqof = seqof(gen(n))
7118 self.assertTrue(seqof.ready)
7119 with self.assertRaises(BoundsError):
7121 self.assertFalse(seqof.ready)
7123 def test_iterator_twice(self):
7124 class SeqOf(SequenceOf):
7126 bounds = (1, float("+inf"))
7129 for i in six_xrange(10):
7131 seqof = SeqOf(gen())
7132 self.assertTrue(seqof.ready)
7134 self.assertFalse(seqof.ready)
7135 register_class(SeqOf)
7138 def test_iterator_2pass(self):
7139 class SeqOf(SequenceOf):
7141 bounds = (1, float("+inf"))
7144 for i in six_xrange(10):
7146 seqof = SeqOf(gen())
7147 self.assertTrue(seqof.ready)
7148 _, state = seqof.encode1st()
7149 self.assertFalse(seqof.ready)
7150 seqof = seqof(gen())
7151 self.assertTrue(seqof.ready)
7153 seqof.encode2nd(buf.write, iter(state))
7154 self.assertSequenceEqual(
7155 [int(i) for i in seqof.decod(buf.getvalue())],
7159 def test_non_ready_bound_min(self):
7160 class SeqOf(SequenceOf):
7162 bounds = (1, float("+inf"))
7164 self.assertFalse(seqof.ready)
7167 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7172 def _test_symmetric_compare_objs(self, obj1, obj2):
7173 self.assertSetEqual(
7174 set(int(v) for v in obj1),
7175 set(int(v) for v in obj2),
7178 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7179 @given(data_strategy())
7180 def test_sorted(self, d):
7181 values = [OctetString(v) for v in d.draw(lists(binary()))]
7184 schema = OctetString()
7186 seq_encoded = seq.encode()
7187 seq_decoded, _ = seq.decode(seq_encoded)
7188 self.assertSequenceEqual(
7189 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7190 b"".join(sorted([v.encode() for v in values])),
7193 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7194 @given(data_strategy())
7195 def test_unsorted(self, d):
7196 values = [OctetString(v).encode() for v in d.draw(sets(
7197 binary(min_size=1, max_size=5),
7201 values = d.draw(permutations(values))
7202 assume(values != sorted(values))
7203 encoded = b"".join(values)
7204 seq_encoded = b"".join((
7206 len_encode(len(encoded)),
7211 schema = OctetString()
7213 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7214 seq.decode(seq_encoded)
7216 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7217 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7218 self.assertTrue(seq_decoded.ber_encoded)
7219 self.assertTrue(seq_decoded.bered)
7220 seq_decoded = copy(seq_decoded)
7221 self.assertTrue(seq_decoded.ber_encoded)
7222 self.assertTrue(seq_decoded.bered)
7223 self.assertSequenceEqual(
7224 [obj.encode() for obj in seq_decoded],
7229 class TestGoMarshalVectors(TestCase):
7231 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7232 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7233 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7234 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7235 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7237 class Seq(Sequence):
7239 ("erste", Integer()),
7240 ("zweite", Integer(optional=True))
7243 seq["erste"] = Integer(64)
7244 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7245 seq["erste"] = Integer(0x123456)
7246 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7247 seq["erste"] = Integer(64)
7248 seq["zweite"] = Integer(65)
7249 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7251 class NestedSeq(Sequence):
7255 seq["erste"] = Integer(127)
7256 seq["zweite"] = None
7257 nested = NestedSeq()
7258 nested["nest"] = seq
7259 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7261 self.assertSequenceEqual(
7262 OctetString(b"\x01\x02\x03").encode(),
7263 hexdec("0403010203"),
7266 class Seq(Sequence):
7268 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7271 seq["erste"] = Integer(64)
7272 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7274 class Seq(Sequence):
7276 ("erste", Integer(expl=tag_ctxc(5))),
7279 seq["erste"] = Integer(64)
7280 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7282 class Seq(Sequence):
7285 impl=tag_encode(0, klass=TagClassContext),
7290 seq["erste"] = Null()
7291 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7293 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7295 self.assertSequenceEqual(
7296 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7297 hexdec("170d3730303130313030303030305a"),
7299 self.assertSequenceEqual(
7300 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7301 hexdec("170d3039313131353232353631365a"),
7303 self.assertSequenceEqual(
7304 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7305 hexdec("180f32313030303430353132303130315a"),
7308 class Seq(Sequence):
7310 ("erste", GeneralizedTime()),
7313 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7314 self.assertSequenceEqual(
7316 hexdec("3011180f32303039313131353232353631365a"),
7319 self.assertSequenceEqual(
7320 BitString((1, b"\x80")).encode(),
7323 self.assertSequenceEqual(
7324 BitString((12, b"\x81\xF0")).encode(),
7325 hexdec("03030481f0"),
7328 self.assertSequenceEqual(
7329 ObjectIdentifier("1.2.3.4").encode(),
7330 hexdec("06032a0304"),
7332 self.assertSequenceEqual(
7333 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7334 hexdec("06092a864888932d010105"),
7336 self.assertSequenceEqual(
7337 ObjectIdentifier("2.100.3").encode(),
7338 hexdec("0603813403"),
7341 self.assertSequenceEqual(
7342 PrintableString("test").encode(),
7343 hexdec("130474657374"),
7345 self.assertSequenceEqual(
7346 PrintableString("x" * 127).encode(),
7347 hexdec("137F" + "78" * 127),
7349 self.assertSequenceEqual(
7350 PrintableString("x" * 128).encode(),
7351 hexdec("138180" + "78" * 128),
7353 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7355 class Seq(Sequence):
7357 ("erste", IA5String()),
7360 seq["erste"] = IA5String("test")
7361 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7363 class Seq(Sequence):
7365 ("erste", PrintableString()),
7368 seq["erste"] = PrintableString("test")
7369 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7370 # Asterisk is actually not allowable
7371 PrintableString._allowable_chars |= set(b"*")
7372 seq["erste"] = PrintableString("test*")
7373 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7374 PrintableString._allowable_chars -= set(b"*")
7376 class Seq(Sequence):
7378 ("erste", Any(optional=True)),
7379 ("zweite", Integer()),
7382 seq["zweite"] = Integer(64)
7383 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7388 seq.append(Integer(10))
7389 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7391 class _SeqOf(SequenceOf):
7392 schema = PrintableString()
7394 class SeqOf(SequenceOf):
7397 _seqof.append(PrintableString("1"))
7399 seqof.append(_seqof)
7400 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7402 class Seq(Sequence):
7404 ("erste", Integer(default=1)),
7407 seq["erste"] = Integer(0)
7408 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7409 seq["erste"] = Integer(1)
7410 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7411 seq["erste"] = Integer(2)
7412 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7415 class TestPP(TestCase):
7416 @given(data_strategy())
7417 def test_oid_printing(self, d):
7419 str(ObjectIdentifier(k)): v * 2
7420 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7422 chosen = d.draw(sampled_from(sorted(oids)))
7423 chosen_id = oids[chosen]
7424 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7425 self.assertNotIn(chosen_id, pp_console_row(pp))
7428 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7432 class TestAutoAddSlots(TestCase):
7434 class Inher(Integer):
7437 with self.assertRaises(AttributeError):
7439 inher.unexistent = "whatever"
7442 class TestOIDDefines(TestCase):
7443 @given(data_strategy())
7444 def runTest(self, d):
7445 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7446 value_name_chosen = d.draw(sampled_from(value_names))
7448 ObjectIdentifier(oid)
7449 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7451 oid_chosen = d.draw(sampled_from(oids))
7452 values = d.draw(lists(
7454 min_size=len(value_names),
7455 max_size=len(value_names),
7457 for definable_class in (Any, OctetString, BitString):
7459 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7460 oid: Integer() for oid in oids[:-1]
7463 for i, value_name in enumerate(value_names):
7464 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7466 class Seq(Sequence):
7469 for value_name, value in zip(value_names, values):
7470 seq[value_name] = definable_class(Integer(value).encode())
7471 seq["type"] = oid_chosen
7472 seq, _ = Seq().decode(seq.encode())
7473 for value_name in value_names:
7474 if value_name == value_name_chosen:
7476 self.assertIsNone(seq[value_name].defined)
7477 if value_name_chosen in oids[:-1]:
7478 self.assertIsNotNone(seq[value_name_chosen].defined)
7479 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7480 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7483 pprint(seq, big_blobs=True, with_decode_path=True)
7486 class TestDefinesByPath(TestCase):
7487 def test_generated(self):
7488 class Seq(Sequence):
7490 ("type", ObjectIdentifier()),
7491 ("value", OctetString(expl=tag_ctxc(123))),
7494 class SeqInner(Sequence):
7496 ("typeInner", ObjectIdentifier()),
7497 ("valueInner", Any()),
7500 class PairValue(SetOf):
7503 class Pair(Sequence):
7505 ("type", ObjectIdentifier()),
7506 ("value", PairValue()),
7509 class Pairs(SequenceOf):
7516 type_octet_stringed,
7518 ObjectIdentifier(oid)
7519 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7521 seq_integered = Seq()
7522 seq_integered["type"] = type_integered
7523 seq_integered["value"] = OctetString(Integer(123).encode())
7524 seq_integered_raw = seq_integered.encode()
7528 (type_octet_stringed, OctetString(b"whatever")),
7529 (type_integered, Integer(123)),
7530 (type_octet_stringed, OctetString(b"whenever")),
7531 (type_integered, Integer(234)),
7533 for t, v in pairs_input:
7536 ("value", PairValue((Any(v),))),
7538 seq_inner = SeqInner()
7539 seq_inner["typeInner"] = type_innered
7540 seq_inner["valueInner"] = Any(pairs)
7541 seq_sequenced = Seq()
7542 seq_sequenced["type"] = type_sequenced
7543 seq_sequenced["value"] = OctetString(seq_inner.encode())
7544 seq_sequenced_raw = seq_sequenced.encode()
7546 list(seq_sequenced.pps())
7547 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7549 defines_by_path = []
7550 ctx_copied = deepcopy(ctx_dummy)
7551 seq_integered, _ = Seq().decode(
7555 self.assertDictEqual(ctx_copied, ctx_dummy)
7556 self.assertIsNone(seq_integered["value"].defined)
7557 defines_by_path.append(
7558 (("type",), ((("value",), {
7559 type_integered: Integer(),
7560 type_sequenced: SeqInner(),
7563 ctx_copied["defines_by_path"] = defines_by_path
7564 seq_integered, _ = Seq().decode(
7568 del ctx_copied["defines_by_path"]
7569 self.assertDictEqual(ctx_copied, ctx_dummy)
7570 self.assertIsNotNone(seq_integered["value"].defined)
7571 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7572 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7573 self.assertTrue(seq_integered_raw[
7574 seq_integered["value"].defined[1].offset:
7575 ].startswith(Integer(123).encode()))
7577 list(seq_integered.pps())
7578 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7580 ctx_copied["defines_by_path"] = defines_by_path
7581 seq_sequenced, _ = Seq().decode(
7585 del ctx_copied["defines_by_path"]
7586 self.assertDictEqual(ctx_copied, ctx_dummy)
7587 self.assertIsNotNone(seq_sequenced["value"].defined)
7588 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7589 seq_inner = seq_sequenced["value"].defined[1]
7590 self.assertIsNone(seq_inner["valueInner"].defined)
7592 list(seq_sequenced.pps())
7593 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7595 defines_by_path.append((
7596 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7597 ((("valueInner",), {type_innered: Pairs()}),),
7599 ctx_copied["defines_by_path"] = defines_by_path
7600 seq_sequenced, _ = Seq().decode(
7604 del ctx_copied["defines_by_path"]
7605 self.assertDictEqual(ctx_copied, ctx_dummy)
7606 self.assertIsNotNone(seq_sequenced["value"].defined)
7607 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7608 seq_inner = seq_sequenced["value"].defined[1]
7609 self.assertIsNotNone(seq_inner["valueInner"].defined)
7610 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7611 pairs = seq_inner["valueInner"].defined[1]
7613 self.assertIsNone(pair["value"][0].defined)
7615 list(seq_sequenced.pps())
7616 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7618 defines_by_path.append((
7621 DecodePathDefBy(type_sequenced),
7623 DecodePathDefBy(type_innered),
7628 type_integered: Integer(),
7629 type_octet_stringed: OctetString(),
7632 ctx_copied["defines_by_path"] = defines_by_path
7633 seq_sequenced, _ = Seq().decode(
7637 del ctx_copied["defines_by_path"]
7638 self.assertDictEqual(ctx_copied, ctx_dummy)
7639 self.assertIsNotNone(seq_sequenced["value"].defined)
7640 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7641 seq_inner = seq_sequenced["value"].defined[1]
7642 self.assertIsNotNone(seq_inner["valueInner"].defined)
7643 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7644 pairs_got = seq_inner["valueInner"].defined[1]
7645 for pair_input, pair_got in zip(pairs_input, pairs_got):
7646 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7647 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7649 list(seq_sequenced.pps())
7650 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7652 @given(oid_strategy(), integers())
7653 def test_simple(self, oid, tgt):
7654 class Inner(Sequence):
7656 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7657 ObjectIdentifier(oid): Integer(),
7661 class Outer(Sequence):
7664 ("tgt", OctetString()),
7668 inner["oid"] = ObjectIdentifier(oid)
7670 outer["inner"] = inner
7671 outer["tgt"] = OctetString(Integer(tgt).encode())
7672 decoded, _ = Outer().decode(outer.encode())
7673 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7675 def test_remaining_data(self):
7676 oid = ObjectIdentifier("1.2.3")
7678 class Seq(Sequence):
7680 ("oid", ObjectIdentifier(defines=((("tgt",), {
7683 ("tgt", OctetString()),
7688 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7690 with assertRaisesRegex(self, DecodeError, "remaining data"):
7691 Seq().decode(seq.encode())
7693 def test_remaining_data_seqof(self):
7694 oid = ObjectIdentifier("1.2.3")
7697 schema = OctetString()
7699 class Seq(Sequence):
7701 ("oid", ObjectIdentifier(defines=((("tgt",), {
7709 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7711 with assertRaisesRegex(self, DecodeError, "remaining data"):
7712 Seq().decode(seq.encode())
7715 class TestAbsDecodePath(TestCase):
7717 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7718 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7720 def test_concat(self, decode_path, rel_path):
7721 dp = abs_decode_path(decode_path, rel_path)
7722 self.assertSequenceEqual(dp, decode_path + rel_path)
7726 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7727 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7729 def test_abs(self, decode_path, rel_path):
7730 self.assertSequenceEqual(
7731 abs_decode_path(decode_path, ("/",) + rel_path),
7736 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7737 integers(min_value=1, max_value=3),
7738 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7740 def test_dots(self, decode_path, number_of_dots, rel_path):
7741 self.assertSequenceEqual(
7742 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7743 decode_path[:-number_of_dots] + rel_path,
7747 class TestStrictDefaultExistence(TestCase):
7748 @given(data_strategy())
7749 def runTest(self, d):
7750 count = d.draw(integers(min_value=1, max_value=10))
7751 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7753 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7754 for i in range(count)
7756 for klass in (Sequence, Set):
7760 for i in range(count):
7761 seq["int%d" % i] = Integer(123)
7763 chosen_choice = "int%d" % chosen
7764 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7765 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7767 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7768 self.assertTrue(decoded.ber_encoded)
7769 self.assertTrue(decoded.bered)
7770 decoded = copy(decoded)
7771 self.assertTrue(decoded.ber_encoded)
7772 self.assertTrue(decoded.bered)
7773 decoded, _ = seq.decode(raw, ctx={"bered": True})
7774 self.assertTrue(decoded.ber_encoded)
7775 self.assertTrue(decoded.bered)
7776 decoded = copy(decoded)
7777 self.assertTrue(decoded.ber_encoded)
7778 self.assertTrue(decoded.bered)
7781 class TestX690PrefixedType(TestCase):
7783 self.assertSequenceEqual(
7784 VisibleString("Jones").encode(),
7785 hexdec("1A054A6F6E6573"),
7789 self.assertSequenceEqual(
7792 impl=tag_encode(3, klass=TagClassApplication),
7794 hexdec("43054A6F6E6573"),
7798 self.assertSequenceEqual(
7802 impl=tag_encode(3, klass=TagClassApplication),
7806 hexdec("A20743054A6F6E6573"),
7810 self.assertSequenceEqual(
7814 impl=tag_encode(3, klass=TagClassApplication),
7816 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7818 hexdec("670743054A6F6E6573"),
7822 self.assertSequenceEqual(
7823 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7824 hexdec("82054A6F6E6573"),
7828 class TestExplOOB(TestCase):
7830 expl = tag_ctxc(123)
7831 raw = Integer(123).encode() + Integer(234).encode()
7832 raw = b"".join((expl, len_encode(len(raw)), raw))
7833 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7834 Integer(expl=expl).decode(raw)
7835 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7838 class TestPickleDifferentVersion(TestCase):
7840 pickled = pickle_dumps(Integer(123), pickle_proto)
7842 version_orig = pyderasn.__version__
7843 pyderasn.__version__ += "different"
7844 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7845 pickle_loads(pickled)
7846 pyderasn.__version__ = version_orig
7847 pickle_loads(pickled)
7850 class TestCERSetOrdering(TestCase):
7851 def test_vectors(self):
7852 """Taken from X.690-201508
7856 ("c", Integer(impl=tag_ctxp(2))),
7857 ("d", Integer(impl=tag_ctxp(4))),
7862 ("g", Integer(impl=tag_ctxp(5))),
7863 ("h", Integer(impl=tag_ctxp(6))),
7868 ("j", Integer(impl=tag_ctxp(0))),
7879 ("a", Integer(impl=tag_ctxp(3))),
7880 ("b", B(expl=tag_ctxc(1))),
7885 ("a", Integer(123)),
7886 ("b", B(("d", Integer(234)))),
7887 ("e", E(("f", F(("g", Integer(345)))))),
7889 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7890 self.assertSequenceEqual(
7891 [i.__class__.__name__ for i in order],
7892 ("E", "B", "Integer"),