2 # PyDERASN -- Python ASN.1 DER/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 operator import attrgetter
24 from os import environ
25 from os import urandom
26 from random import random
27 from string import ascii_letters
28 from string import digits
29 from string import printable
30 from string import whitespace
31 from time import mktime
33 from unittest import TestCase
35 from hypothesis import assume
36 from hypothesis import given
37 from hypothesis import settings
38 from hypothesis.strategies import binary
39 from hypothesis.strategies import booleans
40 from hypothesis.strategies import composite
41 from hypothesis.strategies import data as data_strategy
42 from hypothesis.strategies import datetimes
43 from hypothesis.strategies import dictionaries
44 from hypothesis.strategies import integers
45 from hypothesis.strategies import just
46 from hypothesis.strategies import lists
47 from hypothesis.strategies import none
48 from hypothesis.strategies import one_of
49 from hypothesis.strategies import permutations
50 from hypothesis.strategies import sampled_from
51 from hypothesis.strategies import sets
52 from hypothesis.strategies import text
53 from hypothesis.strategies import tuples
54 from six import assertRaisesRegex
55 from six import binary_type
56 from six import byte2int
57 from six import indexbytes
58 from six import int2byte
59 from six import iterbytes
61 from six import text_type
62 from six import unichr as six_unichr
63 from six.moves import xrange as six_xrange
64 from six.moves.cPickle import dumps as pickle_dumps
65 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
66 from six.moves.cPickle import loads as pickle_loads
68 from pyderasn import _pp
69 from pyderasn import abs_decode_path
70 from pyderasn import Any
71 from pyderasn import BitString
72 from pyderasn import BMPString
73 from pyderasn import Boolean
74 from pyderasn import BoundsError
75 from pyderasn import Choice
76 from pyderasn import DecodeError
77 from pyderasn import DecodePathDefBy
78 from pyderasn import encode_cer
79 from pyderasn import Enumerated
80 from pyderasn import EOC
81 from pyderasn import EOC_LEN
82 from pyderasn import ExceedingData
83 from pyderasn import GeneralizedTime
84 from pyderasn import GeneralString
85 from pyderasn import GraphicString
86 from pyderasn import hexdec
87 from pyderasn import hexenc
88 from pyderasn import IA5String
89 from pyderasn import Integer
90 from pyderasn import InvalidLength
91 from pyderasn import InvalidOID
92 from pyderasn import InvalidValueType
93 from pyderasn import len_decode
94 from pyderasn import len_encode
95 from pyderasn import LEN_YYMMDDHHMMSSZ
96 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
97 from pyderasn import LEN_YYYYMMDDHHMMSSZ
98 from pyderasn import LENINDEF
99 from pyderasn import LenIndefForm
100 from pyderasn import NotEnoughData
101 from pyderasn import Null
102 from pyderasn import NumericString
103 from pyderasn import ObjectIdentifier
104 from pyderasn import ObjNotReady
105 from pyderasn import ObjUnknown
106 from pyderasn import OctetString
107 from pyderasn import pp_console_row
108 from pyderasn import pprint
109 from pyderasn import PrintableString
110 from pyderasn import Sequence
111 from pyderasn import SequenceOf
112 from pyderasn import Set
113 from pyderasn import SetOf
114 from pyderasn import tag_ctxc
115 from pyderasn import tag_ctxp
116 from pyderasn import tag_decode
117 from pyderasn import tag_encode
118 from pyderasn import tag_strip
119 from pyderasn import TagClassApplication
120 from pyderasn import TagClassContext
121 from pyderasn import TagClassPrivate
122 from pyderasn import TagClassUniversal
123 from pyderasn import TagFormConstructed
124 from pyderasn import TagFormPrimitive
125 from pyderasn import TagMismatch
126 from pyderasn import TeletexString
127 from pyderasn import UniversalString
128 from pyderasn import UTCTime
129 from pyderasn import UTF8String
130 from pyderasn import VideotexString
131 from pyderasn import VisibleString
134 max_examples = environ.get("MAX_EXAMPLES")
135 settings.register_profile("local", settings(
137 **({"max_examples": int(max_examples)} if max_examples else {})
139 settings.load_profile("local")
140 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
142 tag_classes = sampled_from((
148 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
149 decode_path_strat = lists(integers(), max_size=3).map(
150 lambda decode_path: tuple(str(dp) for dp in decode_path)
152 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
155 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
157 self_module = import_module(__name__)
160 def register_class(klass):
161 klassname = klass.__name__ + str(time()).replace(".", "")
162 klass.__name__ = klassname
163 klass.__qualname__ = klassname
164 setattr(self_module, klassname, klass)
167 def assert_exceeding_data(self, call, junk):
170 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
175 class TestHex(TestCase):
177 def test_symmetric(self, data):
178 self.assertEqual(hexdec(hexenc(data)), data)
181 class TestTagCoder(TestCase):
182 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
186 integers(min_value=0, max_value=30),
189 def test_short(self, klass, form, num, junk):
190 raw = tag_encode(klass=klass, form=form, num=num)
191 self.assertEqual(tag_decode(raw), (klass, form, num))
192 self.assertEqual(len(raw), 1)
194 byte2int(tag_encode(klass=klass, form=form, num=0)),
195 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
197 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
198 self.assertSequenceEqual(stripped.tobytes(), raw)
199 self.assertEqual(tlen, len(raw))
200 self.assertSequenceEqual(tail, junk)
202 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
206 integers(min_value=31),
209 def test_long(self, klass, form, num, junk):
210 raw = tag_encode(klass=klass, form=form, num=num)
211 self.assertEqual(tag_decode(raw), (klass, form, num))
212 self.assertGreater(len(raw), 1)
214 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
217 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
218 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
219 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
220 self.assertSequenceEqual(stripped.tobytes(), raw)
221 self.assertEqual(tlen, len(raw))
222 self.assertSequenceEqual(tail, junk)
224 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
225 @given(integers(min_value=31))
226 def test_unfinished_tag(self, num):
227 raw = bytearray(tag_encode(num=num))
228 for i in range(1, len(raw)):
230 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
231 tag_strip(bytes(raw))
233 def test_go_vectors_valid(self):
234 for data, (eklass, etag, elen, eform) in (
235 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
236 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
237 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
238 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
239 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
240 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
241 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
242 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
243 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
244 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
246 tag, _, len_encoded = tag_strip(memoryview(data))
247 klass, form, num = tag_decode(tag)
248 _len, _, tail = len_decode(len_encoded)
249 self.assertSequenceEqual(tail, b"")
250 self.assertEqual(klass, eklass)
251 self.assertEqual(num, etag)
252 self.assertEqual(_len, elen)
253 self.assertEqual(form, eform)
255 def test_go_vectors_invalid(self):
263 with self.assertRaises(DecodeError):
264 _, _, len_encoded = tag_strip(memoryview(data))
265 len_decode(len_encoded)
268 integers(min_value=0, max_value=127),
269 integers(min_value=0, max_value=2),
271 def test_long_instead_of_short(self, l, dummy_num):
272 octets = (b"\x00" * dummy_num) + int2byte(l)
273 octets = int2byte((dummy_num + 1) | 0x80) + octets
274 with self.assertRaises(DecodeError):
278 class TestLenCoder(TestCase):
279 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
281 integers(min_value=0, max_value=127),
284 def test_short(self, l, junk):
285 raw = len_encode(l) + junk
286 decoded, llen, tail = len_decode(memoryview(raw))
287 self.assertEqual(decoded, l)
288 self.assertEqual(llen, 1)
289 self.assertEqual(len(raw), 1 + len(junk))
290 self.assertEqual(tail.tobytes(), junk)
292 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
294 integers(min_value=128),
297 def test_long(self, l, junk):
298 raw = len_encode(l) + junk
299 decoded, llen, tail = len_decode(memoryview(raw))
300 self.assertEqual(decoded, l)
301 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
302 self.assertEqual(llen, len(raw) - len(junk))
303 self.assertNotEqual(indexbytes(raw, 1), 0)
304 self.assertSequenceEqual(tail.tobytes(), junk)
306 def test_empty(self):
307 with self.assertRaises(NotEnoughData):
310 @given(integers(min_value=128))
311 def test_stripped(self, _len):
312 with self.assertRaises(NotEnoughData):
313 len_decode(len_encode(_len)[:-1])
316 text_printable = text(alphabet=printable, min_size=1)
320 def text_letters(draw):
321 result = draw(text(alphabet=ascii_letters, min_size=1))
323 result = result.encode("ascii")
327 class CommonMixin(object):
328 def test_tag_default(self):
329 obj = self.base_klass()
330 self.assertEqual(obj.tag, obj.tag_default)
332 def test_simultaneous_impl_expl(self):
333 with self.assertRaises(ValueError):
334 self.base_klass(impl=b"whatever", expl=b"whenever")
336 @given(binary(min_size=1), integers(), integers(), integers())
337 def test_decoded(self, impl, offset, llen, vlen):
338 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
339 self.assertEqual(obj.offset, offset)
340 self.assertEqual(obj.llen, llen)
341 self.assertEqual(obj.vlen, vlen)
342 self.assertEqual(obj.tlen, len(impl))
343 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
345 @given(binary(min_size=1))
346 def test_impl_inherited(self, impl_tag):
347 class Inherited(self.base_klass):
350 self.assertSequenceEqual(obj.impl, impl_tag)
351 self.assertFalse(obj.expled)
353 tag_class, _, tag_num = tag_decode(impl_tag)
354 self.assertEqual(obj.tag_order, (tag_class, tag_num))
356 @given(binary(min_size=1))
357 def test_expl_inherited(self, expl_tag):
358 class Inherited(self.base_klass):
361 self.assertSequenceEqual(obj.expl, expl_tag)
362 self.assertTrue(obj.expled)
364 tag_class, _, tag_num = tag_decode(expl_tag)
365 self.assertEqual(obj.tag_order, (tag_class, tag_num))
367 def assert_copied_basic_fields(self, obj, obj_copied):
368 self.assertEqual(obj, obj_copied)
369 self.assertSequenceEqual(obj.tag, obj_copied.tag)
370 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
371 self.assertEqual(obj.default, obj_copied.default)
372 self.assertEqual(obj.optional, obj_copied.optional)
373 self.assertEqual(obj.offset, obj_copied.offset)
374 self.assertEqual(obj.llen, obj_copied.llen)
375 self.assertEqual(obj.vlen, obj_copied.vlen)
377 self.assertEqual(obj.tag_order, obj_copied.tag_order)
381 def boolean_values_strategy(draw, do_expl=False):
382 value = draw(one_of(none(), booleans()))
386 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
388 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
389 default = draw(one_of(none(), booleans()))
390 optional = draw(one_of(none(), booleans()))
392 draw(integers(min_value=0)),
393 draw(integers(min_value=0)),
394 draw(integers(min_value=0)),
396 return (value, impl, expl, default, optional, _decoded)
399 class BooleanInherited(Boolean):
403 class TestBoolean(CommonMixin, TestCase):
406 def test_invalid_value_type(self):
407 with self.assertRaises(InvalidValueType) as err:
412 def test_optional(self, optional):
413 obj = Boolean(default=Boolean(False), optional=optional)
414 self.assertTrue(obj.optional)
417 def test_ready(self, value):
419 self.assertFalse(obj.ready)
422 pprint(obj, big_blobs=True, with_decode_path=True)
423 with self.assertRaises(ObjNotReady) as err:
427 self.assertTrue(obj.ready)
430 pprint(obj, big_blobs=True, with_decode_path=True)
432 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
433 def test_comparison(self, value1, value2, tag1, tag2):
434 for klass in (Boolean, BooleanInherited):
437 self.assertEqual(obj1 == obj2, value1 == value2)
438 self.assertEqual(obj1 != obj2, value1 != value2)
439 self.assertEqual(obj1 == bool(obj2), value1 == value2)
440 obj1 = klass(value1, impl=tag1)
441 obj2 = klass(value1, impl=tag2)
442 self.assertEqual(obj1 == obj2, tag1 == tag2)
443 self.assertEqual(obj1 != obj2, tag1 != tag2)
445 @given(data_strategy())
446 def test_call(self, d):
447 for klass in (Boolean, BooleanInherited):
455 ) = d.draw(boolean_values_strategy())
461 optional_initial or False,
471 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
472 obj = obj_initial(value, impl, expl, default, optional)
474 value_expected = default if value is None else value
476 default_initial if value_expected is None
479 self.assertEqual(obj, value_expected)
480 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
481 self.assertEqual(obj.expl_tag, expl or expl_initial)
484 default_initial if default is None else default,
486 if obj.default is None:
487 optional = optional_initial if optional is None else optional
488 optional = False if optional is None else optional
491 self.assertEqual(obj.optional, optional)
493 @given(boolean_values_strategy())
494 def test_copy(self, values):
495 for klass in (Boolean, BooleanInherited):
497 for copy_func in copy_funcs:
498 obj_copied = copy_func(obj)
499 self.assert_copied_basic_fields(obj, obj_copied)
503 integers(min_value=1).map(tag_encode),
505 def test_stripped(self, value, tag_impl):
506 obj = Boolean(value, impl=tag_impl)
507 with self.assertRaises(NotEnoughData):
508 obj.decode(obj.encode()[:-1])
512 integers(min_value=1).map(tag_ctxc),
514 def test_stripped_expl(self, value, tag_expl):
515 obj = Boolean(value, expl=tag_expl)
516 with self.assertRaises(NotEnoughData):
517 obj.decode(obj.encode()[:-1])
520 integers(min_value=31),
521 integers(min_value=0),
524 def test_bad_tag(self, tag, offset, decode_path):
525 with self.assertRaises(DecodeError) as err:
527 tag_encode(tag)[:-1],
529 decode_path=decode_path,
532 self.assertEqual(err.exception.offset, offset)
533 self.assertEqual(err.exception.decode_path, decode_path)
536 integers(min_value=31),
537 integers(min_value=0),
540 def test_bad_expl_tag(self, tag, offset, decode_path):
541 with self.assertRaises(DecodeError) as err:
542 Boolean(expl=Boolean.tag_default).decode(
543 tag_encode(tag)[:-1],
545 decode_path=decode_path,
548 self.assertEqual(err.exception.offset, offset)
549 self.assertEqual(err.exception.decode_path, decode_path)
552 integers(min_value=128),
553 integers(min_value=0),
556 def test_bad_len(self, l, offset, decode_path):
557 with self.assertRaises(DecodeError) as err:
559 Boolean.tag_default + len_encode(l)[:-1],
561 decode_path=decode_path,
564 self.assertEqual(err.exception.offset, offset)
565 self.assertEqual(err.exception.decode_path, decode_path)
568 integers(min_value=128),
569 integers(min_value=0),
572 def test_bad_expl_len(self, l, offset, decode_path):
573 with self.assertRaises(DecodeError) as err:
574 Boolean(expl=Boolean.tag_default).decode(
575 Boolean.tag_default + len_encode(l)[:-1],
577 decode_path=decode_path,
580 self.assertEqual(err.exception.offset, offset)
581 self.assertEqual(err.exception.decode_path, decode_path)
583 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
585 boolean_values_strategy(),
587 integers(min_value=1).map(tag_ctxc),
588 integers(min_value=0),
592 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
593 for klass in (Boolean, BooleanInherited):
594 _, _, _, default, optional, _decoded = values
603 pprint(obj, big_blobs=True, with_decode_path=True)
604 self.assertFalse(obj.expled)
605 obj_encoded = obj.encode()
606 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
607 obj_expled = obj(value, expl=tag_expl)
608 self.assertTrue(obj_expled.expled)
610 list(obj_expled.pps())
611 pprint(obj_expled, big_blobs=True, with_decode_path=True)
612 obj_expled_cer = encode_cer(obj_expled)
613 self.assertNotEqual(obj_expled_cer, obj_encoded)
614 self.assertSequenceEqual(
615 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
618 obj_expled_hex_encoded = obj_expled.hexencode()
619 ctx_copied = deepcopy(ctx_dummy)
620 obj_decoded, tail = obj_expled.hexdecode(
621 obj_expled_hex_encoded + hexenc(tail_junk),
625 self.assertDictEqual(ctx_copied, ctx_dummy)
627 list(obj_decoded.pps())
628 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
629 self.assertEqual(tail, tail_junk)
630 self.assertEqual(obj_decoded, obj_expled)
631 self.assertNotEqual(obj_decoded, obj)
632 self.assertEqual(bool(obj_decoded), bool(obj_expled))
633 self.assertEqual(bool(obj_decoded), bool(obj))
634 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
635 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
636 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
638 obj_decoded.expl_llen,
639 len(len_encode(len(obj_encoded))),
641 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
642 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
645 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
647 self.assertEqual(obj_decoded.expl_offset, offset)
648 assert_exceeding_data(
650 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
654 evgens = list(obj_expled.decode_evgen(
655 hexdec(obj_expled_hex_encoded) + tail_junk,
657 decode_path=decode_path,
660 self.assertEqual(len(evgens), 1)
661 _decode_path, obj, tail = evgens[0]
662 self.assertSequenceEqual(tail, tail_junk)
663 self.assertEqual(_decode_path, decode_path)
664 self.assertEqual(obj, obj_decoded)
665 self.assertEqual(obj.expl_offset, offset)
669 @given(integers(min_value=2))
670 def test_invalid_len(self, l):
671 with self.assertRaises(InvalidLength):
672 Boolean().decode(b"".join((
678 @given(integers(min_value=0 + 1, max_value=255 - 1))
679 def test_ber_value(self, value):
680 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
681 Boolean().decode(b"".join((
691 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
692 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
693 self.assertTrue(bool(obj))
694 self.assertTrue(obj.ber_encoded)
695 self.assertFalse(obj.lenindef)
696 self.assertTrue(obj.bered)
698 self.assertTrue(obj.ber_encoded)
699 self.assertFalse(obj.lenindef)
700 self.assertTrue(obj.bered)
703 integers(min_value=1).map(tag_ctxc),
704 binary().filter(lambda x: not x.startswith(EOC)),
706 def test_ber_expl_no_eoc(self, expl, junk):
707 encoded = expl + LENINDEF + Boolean(False).encode()
708 with self.assertRaises(LenIndefForm):
709 Boolean(expl=expl).decode(encoded + junk)
710 with assertRaisesRegex(self, DecodeError, "no EOC"):
711 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
712 obj, tail = Boolean(expl=expl).decode(
713 encoded + EOC + junk,
716 self.assertTrue(obj.expl_lenindef)
717 self.assertFalse(obj.lenindef)
718 self.assertFalse(obj.ber_encoded)
719 self.assertTrue(obj.bered)
721 self.assertTrue(obj.expl_lenindef)
722 self.assertFalse(obj.lenindef)
723 self.assertFalse(obj.ber_encoded)
724 self.assertTrue(obj.bered)
725 self.assertSequenceEqual(tail, junk)
728 pprint(obj, big_blobs=True, with_decode_path=True)
731 integers(min_value=1).map(tag_ctxc),
738 def test_ber_expl(self, expl, values):
744 Boolean(value).encode() +
747 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
749 class SeqOf(SequenceOf):
750 schema = Boolean(expl=expl)
751 with self.assertRaises(LenIndefForm):
752 SeqOf().decode(encoded)
753 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
754 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
755 self.assertSequenceEqual(tail, b"")
756 self.assertSequenceEqual([bool(v) for v in seqof], values)
772 len(expl) + 1 + 3 + EOC_LEN,
783 pprint(seqof, big_blobs=True, with_decode_path=True)
787 def integer_values_strategy(draw, do_expl=False):
788 bound_min, value, default, bound_max = sorted(draw(sets(
797 _specs = draw(sets(text_letters()))
800 min_size=len(_specs),
801 max_size=len(_specs),
803 _specs = list(zip(_specs, values))
806 bounds = (bound_min, bound_max)
810 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
812 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
815 optional = draw(one_of(none(), booleans()))
817 draw(integers(min_value=0)),
818 draw(integers(min_value=0)),
819 draw(integers(min_value=0)),
821 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
824 class IntegerInherited(Integer):
828 class TestInteger(CommonMixin, TestCase):
831 def test_invalid_value_type(self):
832 with self.assertRaises(InvalidValueType) as err:
836 @given(sets(text_letters(), min_size=2))
837 def test_unknown_name(self, names_input):
838 missing = names_input.pop()
841 schema = [(n, 123) for n in names_input]
842 with self.assertRaises(ObjUnknown) as err:
846 @given(sets(text_letters(), min_size=2))
847 def test_known_name(self, names_input):
849 schema = [(n, 123) for n in names_input]
850 Int(names_input.pop())
853 def test_optional(self, optional):
854 obj = Integer(default=Integer(0), optional=optional)
855 self.assertTrue(obj.optional)
858 def test_ready(self, value):
860 self.assertFalse(obj.ready)
863 pprint(obj, big_blobs=True, with_decode_path=True)
864 with self.assertRaises(ObjNotReady) as err:
868 self.assertTrue(obj.ready)
871 pprint(obj, big_blobs=True, with_decode_path=True)
874 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
875 def test_comparison(self, value1, value2, tag1, tag2):
876 for klass in (Integer, IntegerInherited):
879 self.assertEqual(obj1 == obj2, value1 == value2)
880 self.assertEqual(obj1 != obj2, value1 != value2)
881 self.assertEqual(obj1 == int(obj2), value1 == value2)
882 obj1 = klass(value1, impl=tag1)
883 obj2 = klass(value1, impl=tag2)
884 self.assertEqual(obj1 == obj2, tag1 == tag2)
885 self.assertEqual(obj1 != obj2, tag1 != tag2)
887 @given(lists(integers()))
888 def test_sorted_works(self, values):
889 self.assertSequenceEqual(
890 [int(v) for v in sorted(Integer(v) for v in values)],
894 @given(data_strategy())
895 def test_named(self, d):
896 names_input = list(d.draw(sets(text_letters(), min_size=1)))
897 values_input = list(d.draw(sets(
899 min_size=len(names_input),
900 max_size=len(names_input),
902 chosen_name = d.draw(sampled_from(names_input))
903 names_input = dict(zip(names_input, values_input))
907 _int = Int(chosen_name)
908 self.assertEqual(_int.named, chosen_name)
909 self.assertEqual(int(_int), names_input[chosen_name])
911 @given(integers(), integers(min_value=0), integers(min_value=0))
912 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
913 value = bound_min + value_delta
914 bound_max = value + bound_delta
915 Integer(value=value, bounds=(bound_min, bound_max))
917 @given(sets(integers(), min_size=3, max_size=3))
918 def test_bounds_unsatisfied(self, values):
919 values = sorted(values)
920 with self.assertRaises(BoundsError) as err:
921 Integer(value=values[0], bounds=(values[1], values[2]))
923 with assertRaisesRegex(self, DecodeError, "bounds") as err:
924 Integer(bounds=(values[1], values[2])).decode(
925 Integer(values[0]).encode()
928 with self.assertRaises(BoundsError) as err:
929 Integer(value=values[2], bounds=(values[0], values[1]))
931 with assertRaisesRegex(self, DecodeError, "bounds") as err:
932 Integer(bounds=(values[0], values[1])).decode(
933 Integer(values[2]).encode()
937 @given(data_strategy())
938 def test_call(self, d):
939 for klass in (Integer, IntegerInherited):
949 ) = d.draw(integer_values_strategy())
956 optional_initial or False,
969 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
970 if (default is None) and (obj_initial.default is not None):
974 (value is not None) and
975 (bounds_initial is not None) and
976 not (bounds_initial[0] <= value <= bounds_initial[1])
981 (default is not None) and
982 (bounds_initial is not None) and
983 not (bounds_initial[0] <= default <= bounds_initial[1])
986 obj = obj_initial(value, bounds, impl, expl, default, optional)
988 value_expected = default if value is None else value
990 default_initial if value_expected is None
993 self.assertEqual(obj, value_expected)
994 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
995 self.assertEqual(obj.expl_tag, expl or expl_initial)
998 default_initial if default is None else default,
1000 if obj.default is None:
1001 optional = optional_initial if optional is None else optional
1002 optional = False if optional is None else optional
1005 self.assertEqual(obj.optional, optional)
1007 (obj._bound_min, obj._bound_max),
1008 bounds or bounds_initial or (float("-inf"), float("+inf")),
1012 {} if _specs_initial is None else dict(_specs_initial),
1015 @given(integer_values_strategy())
1016 def test_copy(self, values):
1017 for klass in (Integer, IntegerInherited):
1018 obj = klass(*values)
1019 for copy_func in copy_funcs:
1020 obj_copied = copy_func(obj)
1021 self.assert_copied_basic_fields(obj, obj_copied)
1022 self.assertEqual(obj.specs, obj_copied.specs)
1023 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1024 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1025 self.assertEqual(obj._value, obj_copied._value)
1029 integers(min_value=1).map(tag_encode),
1031 def test_stripped(self, value, tag_impl):
1032 obj = Integer(value, impl=tag_impl)
1033 with self.assertRaises(NotEnoughData):
1034 obj.decode(obj.encode()[:-1])
1038 integers(min_value=1).map(tag_ctxc),
1040 def test_stripped_expl(self, value, tag_expl):
1041 obj = Integer(value, expl=tag_expl)
1042 with self.assertRaises(NotEnoughData):
1043 obj.decode(obj.encode()[:-1])
1045 def test_zero_len(self):
1046 with self.assertRaises(NotEnoughData):
1047 Integer().decode(b"".join((
1048 Integer.tag_default,
1053 integers(min_value=31),
1054 integers(min_value=0),
1057 def test_bad_tag(self, tag, offset, decode_path):
1058 with self.assertRaises(DecodeError) as err:
1060 tag_encode(tag)[:-1],
1062 decode_path=decode_path,
1065 self.assertEqual(err.exception.offset, offset)
1066 self.assertEqual(err.exception.decode_path, decode_path)
1069 integers(min_value=128),
1070 integers(min_value=0),
1073 def test_bad_len(self, l, offset, decode_path):
1074 with self.assertRaises(DecodeError) as err:
1076 Integer.tag_default + len_encode(l)[:-1],
1078 decode_path=decode_path,
1081 self.assertEqual(err.exception.offset, offset)
1082 self.assertEqual(err.exception.decode_path, decode_path)
1085 sets(integers(), min_size=2, max_size=2),
1086 integers(min_value=0),
1089 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1090 value, bound_min = list(sorted(ints))
1093 bounds = (bound_min, bound_min)
1094 with self.assertRaises(DecodeError) as err:
1096 Integer(value).encode(),
1098 decode_path=decode_path,
1101 self.assertEqual(err.exception.offset, offset)
1102 self.assertEqual(err.exception.decode_path, decode_path)
1104 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1106 integer_values_strategy(),
1108 integers(min_value=1).map(tag_ctxc),
1109 integers(min_value=0),
1113 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1114 for klass in (Integer, IntegerInherited):
1115 _, _, _, _, default, optional, _, _decoded = values
1124 pprint(obj, big_blobs=True, with_decode_path=True)
1125 self.assertFalse(obj.expled)
1126 obj_encoded = obj.encode()
1127 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1128 obj_expled = obj(value, expl=tag_expl)
1129 self.assertTrue(obj_expled.expled)
1131 list(obj_expled.pps())
1132 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1133 obj_expled_encoded = obj_expled.encode()
1134 obj_expled_cer = encode_cer(obj_expled)
1135 self.assertNotEqual(obj_expled_cer, obj_encoded)
1136 self.assertSequenceEqual(
1137 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1140 ctx_copied = deepcopy(ctx_dummy)
1141 obj_decoded, tail = obj_expled.decode(
1142 obj_expled_encoded + tail_junk,
1146 self.assertDictEqual(ctx_copied, ctx_dummy)
1148 list(obj_decoded.pps())
1149 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1150 self.assertEqual(tail, tail_junk)
1151 self.assertEqual(obj_decoded, obj_expled)
1152 self.assertNotEqual(obj_decoded, obj)
1153 self.assertEqual(int(obj_decoded), int(obj_expled))
1154 self.assertEqual(int(obj_decoded), int(obj))
1155 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1156 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1157 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1159 obj_decoded.expl_llen,
1160 len(len_encode(len(obj_encoded))),
1162 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1163 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1166 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1168 self.assertEqual(obj_decoded.expl_offset, offset)
1169 assert_exceeding_data(
1171 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1175 evgens = list(obj_expled.decode_evgen(
1176 obj_expled_encoded + tail_junk,
1178 decode_path=decode_path,
1181 self.assertEqual(len(evgens), 1)
1182 _decode_path, obj, tail = evgens[0]
1183 self.assertSequenceEqual(tail, tail_junk)
1184 self.assertEqual(_decode_path, decode_path)
1185 self.assertEqual(obj, obj_decoded)
1186 self.assertEqual(obj.expl_offset, offset)
1190 def test_go_vectors_valid(self):
1191 for data, expect in ((
1195 (b"\xff\x7f", -129),
1199 (b"\xff\x00", -256),
1203 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1204 (b"\x80\x00\x00\x00", -2147483648),
1207 Integer().decode(b"".join((
1208 Integer.tag_default,
1209 len_encode(len(data)),
1215 def test_go_vectors_invalid(self):
1220 with self.assertRaises(DecodeError):
1221 Integer().decode(b"".join((
1222 Integer.tag_default,
1223 len_encode(len(data)),
1229 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1232 if draw(booleans()):
1233 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1235 integers(min_value=0, max_value=255),
1236 min_size=len(schema),
1237 max_size=len(schema),
1239 schema = list(zip(schema, bits))
1241 def _value(value_required):
1242 if not value_required and draw(booleans()):
1244 generation_choice = 0
1246 generation_choice = draw(sampled_from((1, 2, 3)))
1247 if generation_choice == 1 or draw(booleans()):
1248 return "'%s'B" % "".join(draw(lists(
1249 sampled_from(("0", "1")),
1250 max_size=len(schema),
1252 if generation_choice == 2 or draw(booleans()):
1253 return draw(binary(max_size=len(schema) // 8))
1254 if generation_choice == 3 or draw(booleans()):
1255 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1257 value = _value(value_required)
1258 default = _value(value_required=False)
1262 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1264 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1265 optional = draw(one_of(none(), booleans()))
1267 draw(integers(min_value=0)),
1268 draw(integers(min_value=0)),
1269 draw(integers(min_value=0)),
1271 return (schema, value, impl, expl, default, optional, _decoded)
1274 class BitStringInherited(BitString):
1278 class TestBitString(CommonMixin, TestCase):
1279 base_klass = BitString
1281 @given(lists(booleans()))
1282 def test_b_encoding(self, bits):
1283 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1284 self.assertEqual(obj.bit_len, len(bits))
1285 self.assertSequenceEqual(list(obj), bits)
1286 for i, bit in enumerate(bits):
1287 self.assertEqual(obj[i], bit)
1289 @given(lists(booleans()))
1290 def test_out_of_bounds_bits(self, bits):
1291 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1292 for i in range(len(bits), len(bits) * 2):
1293 self.assertFalse(obj[i])
1295 def test_bad_b_encoding(self):
1296 with self.assertRaises(ValueError):
1297 BitString("'010120101'B")
1300 integers(min_value=1, max_value=255),
1301 integers(min_value=1, max_value=255),
1303 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1304 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1305 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1306 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1308 class BS(BitString):
1309 schema = (("whatever", 0),)
1310 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1311 self.assertEqual(obj.bit_len, leading_zeros + 1)
1312 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1314 def test_zero_len(self):
1315 with self.assertRaises(NotEnoughData):
1316 BitString().decode(b"".join((
1317 BitString.tag_default,
1321 def test_invalid_value_type(self):
1322 with self.assertRaises(InvalidValueType) as err:
1325 with self.assertRaises(InvalidValueType) as err:
1329 def test_obj_unknown(self):
1330 with self.assertRaises(ObjUnknown) as err:
1331 BitString(b"whatever")["whenever"]
1334 def test_get_invalid_type(self):
1335 with self.assertRaises(InvalidValueType) as err:
1336 BitString(b"whatever")[(1, 2, 3)]
1339 @given(data_strategy())
1340 def test_unknown_name(self, d):
1341 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1342 missing = _schema.pop()
1344 class BS(BitString):
1345 schema = [(n, i) for i, n in enumerate(_schema)]
1346 with self.assertRaises(ObjUnknown) as err:
1351 def test_optional(self, optional):
1352 obj = BitString(default=BitString(b""), optional=optional)
1353 self.assertTrue(obj.optional)
1356 def test_ready(self, value):
1358 self.assertFalse(obj.ready)
1361 pprint(obj, big_blobs=True, with_decode_path=True)
1362 with self.assertRaises(ObjNotReady) as err:
1365 obj = BitString(value)
1366 self.assertTrue(obj.ready)
1369 pprint(obj, big_blobs=True, with_decode_path=True)
1372 tuples(integers(min_value=0), binary()),
1373 tuples(integers(min_value=0), binary()),
1377 def test_comparison(self, value1, value2, tag1, tag2):
1378 for klass in (BitString, BitStringInherited):
1379 obj1 = klass(value1)
1380 obj2 = klass(value2)
1381 self.assertEqual(obj1 == obj2, value1 == value2)
1382 self.assertEqual(obj1 != obj2, value1 != value2)
1383 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1384 obj1 = klass(value1, impl=tag1)
1385 obj2 = klass(value1, impl=tag2)
1386 self.assertEqual(obj1 == obj2, tag1 == tag2)
1387 self.assertEqual(obj1 != obj2, tag1 != tag2)
1389 @given(data_strategy())
1390 def test_call(self, d):
1391 for klass in (BitString, BitStringInherited):
1400 ) = d.draw(bit_string_values_strategy())
1403 schema = schema_initial
1405 value=value_initial,
1408 default=default_initial,
1409 optional=optional_initial or False,
1410 _decoded=_decoded_initial,
1420 ) = d.draw(bit_string_values_strategy(
1421 schema=schema_initial,
1422 do_expl=impl_initial is None,
1431 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1432 self.assertEqual(obj.expl_tag, expl or expl_initial)
1433 if obj.default is None:
1434 optional = optional_initial if optional is None else optional
1435 optional = False if optional is None else optional
1438 self.assertEqual(obj.optional, optional)
1439 self.assertEqual(obj.specs, obj_initial.specs)
1441 @given(bit_string_values_strategy())
1442 def test_copy(self, values):
1443 for klass in (BitString, BitStringInherited):
1444 _schema, value, impl, expl, default, optional, _decoded = values
1454 optional=optional or False,
1457 for copy_func in copy_funcs:
1458 obj_copied = copy_func(obj)
1459 self.assert_copied_basic_fields(obj, obj_copied)
1460 self.assertEqual(obj.specs, obj_copied.specs)
1461 self.assertEqual(obj._value, obj_copied._value)
1465 integers(min_value=1).map(tag_encode),
1467 def test_stripped(self, value, tag_impl):
1468 obj = BitString(value, impl=tag_impl)
1469 with self.assertRaises(NotEnoughData):
1470 obj.decode(obj.encode()[:-1])
1474 integers(min_value=1).map(tag_ctxc),
1476 def test_stripped_expl(self, value, tag_expl):
1477 obj = BitString(value, expl=tag_expl)
1478 with self.assertRaises(NotEnoughData):
1479 obj.decode(obj.encode()[:-1])
1482 integers(min_value=31),
1483 integers(min_value=0),
1486 def test_bad_tag(self, tag, offset, decode_path):
1487 with self.assertRaises(DecodeError) as err:
1489 tag_encode(tag)[:-1],
1491 decode_path=decode_path,
1494 self.assertEqual(err.exception.offset, offset)
1495 self.assertEqual(err.exception.decode_path, decode_path)
1498 integers(min_value=128),
1499 integers(min_value=0),
1502 def test_bad_len(self, l, offset, decode_path):
1503 with self.assertRaises(DecodeError) as err:
1505 BitString.tag_default + len_encode(l)[:-1],
1507 decode_path=decode_path,
1510 self.assertEqual(err.exception.offset, offset)
1511 self.assertEqual(err.exception.decode_path, decode_path)
1513 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1514 @given(data_strategy())
1515 def test_symmetric(self, d):
1524 ) = d.draw(bit_string_values_strategy(value_required=True))
1525 tail_junk = d.draw(binary(max_size=5))
1526 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1527 offset = d.draw(integers(min_value=0))
1528 decode_path = d.draw(decode_path_strat)
1529 for klass in (BitString, BitStringInherited):
1540 pprint(obj, big_blobs=True, with_decode_path=True)
1541 self.assertFalse(obj.expled)
1542 obj_encoded = obj.encode()
1543 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1544 obj_expled = obj(value, expl=tag_expl)
1545 self.assertTrue(obj_expled.expled)
1547 list(obj_expled.pps())
1548 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1549 obj_expled_encoded = obj_expled.encode()
1550 obj_expled_cer = encode_cer(obj_expled)
1551 self.assertNotEqual(obj_expled_cer, obj_encoded)
1552 self.assertSequenceEqual(
1553 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1556 ctx_copied = deepcopy(ctx_dummy)
1557 obj_decoded, tail = obj_expled.decode(
1558 obj_expled_encoded + tail_junk,
1562 self.assertDictEqual(ctx_copied, ctx_dummy)
1564 list(obj_decoded.pps())
1565 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1566 self.assertEqual(tail, tail_junk)
1567 self.assertEqual(obj_decoded, obj_expled)
1568 self.assertNotEqual(obj_decoded, obj)
1569 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1570 self.assertEqual(bytes(obj_decoded), bytes(obj))
1571 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1572 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1573 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1575 obj_decoded.expl_llen,
1576 len(len_encode(len(obj_encoded))),
1578 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1579 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1582 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1584 self.assertEqual(obj_decoded.expl_offset, offset)
1585 if isinstance(value, tuple):
1586 self.assertSetEqual(set(value), set(obj_decoded.named))
1589 assert_exceeding_data(
1591 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1595 evgens = list(obj_expled.decode_evgen(
1596 obj_expled_encoded + tail_junk,
1598 decode_path=decode_path,
1601 self.assertEqual(len(evgens), 1)
1602 _decode_path, obj, tail = evgens[0]
1603 self.assertSequenceEqual(tail, tail_junk)
1604 self.assertEqual(_decode_path, decode_path)
1605 self.assertEqual(obj.expl_offset, offset)
1609 @given(integers(min_value=1, max_value=255))
1610 def test_bad_zero_value(self, pad_size):
1611 with self.assertRaises(DecodeError):
1612 BitString().decode(b"".join((
1613 BitString.tag_default,
1618 def test_go_vectors_invalid(self):
1624 with self.assertRaises(DecodeError):
1625 BitString().decode(b"".join((
1626 BitString.tag_default,
1631 def test_go_vectors_valid(self):
1632 obj, _ = BitString().decode(b"".join((
1633 BitString.tag_default,
1637 self.assertEqual(bytes(obj), b"")
1638 self.assertEqual(obj.bit_len, 0)
1640 obj, _ = BitString().decode(b"".join((
1641 BitString.tag_default,
1645 self.assertEqual(bytes(obj), b"\x00")
1646 self.assertEqual(obj.bit_len, 1)
1648 obj = BitString((16, b"\x82\x40"))
1649 self.assertTrue(obj[0])
1650 self.assertFalse(obj[1])
1651 self.assertTrue(obj[6])
1652 self.assertTrue(obj[9])
1653 self.assertFalse(obj[17])
1655 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1657 integers(min_value=1, max_value=30),
1660 binary(min_size=1, max_size=5),
1662 binary(min_size=1, max_size=5),
1670 lists(booleans(), min_size=1),
1674 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1675 def chunk_constructed(contents):
1677 tag_encode(form=TagFormConstructed, num=3) +
1679 b"".join(BitString(content).encode() for content in contents) +
1683 chunks_len_expected = []
1684 payload_expected = b""
1685 bit_len_expected = 0
1686 for chunk_input in chunk_inputs:
1687 if isinstance(chunk_input, binary_type):
1688 chunks.append(BitString(chunk_input).encode())
1689 payload_expected += chunk_input
1690 bit_len_expected += len(chunk_input) * 8
1691 chunks_len_expected.append(len(chunk_input) + 1)
1693 chunks.append(chunk_constructed(chunk_input))
1694 payload = b"".join(chunk_input)
1695 payload_expected += payload
1696 bit_len_expected += len(payload) * 8
1697 for c in chunk_input:
1698 chunks_len_expected.append(len(c) + 1)
1699 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1700 chunk_last = BitString("'%s'B" % "".join(
1701 "1" if bit else "0" for bit in chunk_last_bits
1703 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1704 payload_expected += bytes(chunk_last)
1705 bit_len_expected += chunk_last.bit_len
1706 encoded_indefinite = (
1707 tag_encode(form=TagFormConstructed, num=impl) +
1710 chunk_last.encode() +
1713 encoded_definite = (
1714 tag_encode(form=TagFormConstructed, num=impl) +
1715 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1719 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1720 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1721 for lenindef_expected, encoded in (
1722 (True, encoded_indefinite),
1723 (False, encoded_definite),
1725 obj, tail = BitString(impl=tag_encode(impl)).decode(
1727 ctx={"bered": True},
1729 self.assertSequenceEqual(tail, junk)
1730 self.assertEqual(obj.bit_len, bit_len_expected)
1731 self.assertSequenceEqual(bytes(obj), payload_expected)
1732 self.assertTrue(obj.ber_encoded)
1733 self.assertEqual(obj.lenindef, lenindef_expected)
1734 self.assertTrue(obj.bered)
1736 self.assertTrue(obj.ber_encoded)
1737 self.assertEqual(obj.lenindef, lenindef_expected)
1738 self.assertTrue(obj.bered)
1739 self.assertEqual(len(encoded), obj.tlvlen)
1742 pprint(obj, big_blobs=True, with_decode_path=True)
1744 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1746 decode_path=decode_path,
1747 ctx={"bered": True},
1749 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1750 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1751 self.assertGreater(len(dp), len(decode_path))
1752 self.assertEqual(obj.vlen, chunk_len_expected)
1755 integers(min_value=0),
1758 def test_ber_definite_too_short(self, offset, decode_path):
1759 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1761 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1763 decode_path=decode_path,
1764 ctx={"bered": True},
1766 self.assertEqual(err.exception.decode_path, decode_path)
1767 self.assertEqual(err.exception.offset, offset)
1770 integers(min_value=0),
1773 def test_ber_definite_no_data(self, offset, decode_path):
1774 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1776 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1778 decode_path=decode_path,
1779 ctx={"bered": True},
1781 self.assertEqual(err.exception.decode_path, decode_path)
1782 self.assertEqual(err.exception.offset, offset)
1785 integers(min_value=0),
1787 integers(min_value=1, max_value=3),
1789 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1790 bs = BitString(b"data").encode()
1791 with self.assertRaises(NotEnoughData) as err:
1793 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1795 decode_path=decode_path,
1796 ctx={"bered": True},
1798 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1799 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1802 integers(min_value=0),
1804 integers(min_value=1, max_value=3),
1806 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1807 bs = BitString(b"data").encode()
1808 bs_longer = BitString(b"data-longer").encode()
1809 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1812 tag_encode(3, form=TagFormConstructed) +
1813 len_encode((chunks + 1) * len(bs)) +
1818 decode_path=decode_path,
1819 ctx={"bered": True},
1821 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1822 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1825 integers(min_value=0),
1828 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1829 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1831 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1833 decode_path=decode_path,
1834 ctx={"bered": True},
1836 self.assertEqual(err.exception.decode_path, decode_path)
1837 self.assertEqual(err.exception.offset, offset)
1839 @given(data_strategy())
1840 def test_ber_indefinite_not_multiple(self, d):
1841 bs_short = BitString("'A'H").encode()
1842 bs_full = BitString("'AA'H").encode()
1843 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1844 chunks.append(bs_short)
1845 d.draw(permutations(chunks))
1846 chunks.append(bs_short)
1847 offset = d.draw(integers(min_value=0))
1848 decode_path = d.draw(decode_path_strat)
1849 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1852 tag_encode(3, form=TagFormConstructed) +
1858 decode_path=decode_path,
1859 ctx={"bered": True},
1862 err.exception.decode_path,
1863 decode_path + (str(chunks.index(bs_short)),),
1866 err.exception.offset,
1867 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1870 def test_x690_vector(self):
1871 vector = BitString("'0A3B5F291CD'H")
1872 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1873 self.assertSequenceEqual(tail, b"")
1874 self.assertEqual(obj, vector)
1875 obj, tail = BitString().decode(
1876 hexdec("23800303000A3B0305045F291CD00000"),
1877 ctx={"bered": True},
1879 self.assertSequenceEqual(tail, b"")
1880 self.assertEqual(obj, vector)
1881 self.assertTrue(obj.ber_encoded)
1882 self.assertTrue(obj.lenindef)
1883 self.assertTrue(obj.bered)
1885 self.assertTrue(obj.ber_encoded)
1886 self.assertTrue(obj.lenindef)
1887 self.assertTrue(obj.bered)
1889 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1890 @given(integers(min_value=1000, max_value=3000))
1891 def test_cer(self, data_len):
1892 data = urandom(data_len)
1893 encoded = encode_cer(BitString(data))
1894 ctx = {"bered": True}
1895 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1896 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1897 evgens_expected = data_len // 999
1898 if evgens_expected * 999 != data_len:
1899 evgens_expected += 1
1900 evgens_expected += 1
1901 self.assertEqual(len(evgens), evgens_expected)
1902 for (_, obj, _) in evgens[:-2]:
1903 self.assertEqual(obj.vlen, 1000)
1904 _, obj, _ = evgens[-2]
1905 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1909 def octet_string_values_strategy(draw, do_expl=False):
1910 bound_min, bound_max = sorted(draw(sets(
1911 integers(min_value=0, max_value=1 << 7),
1915 value = draw(one_of(
1917 binary(min_size=bound_min, max_size=bound_max),
1919 default = draw(one_of(
1921 binary(min_size=bound_min, max_size=bound_max),
1924 if draw(booleans()):
1925 bounds = (bound_min, bound_max)
1929 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1931 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1932 optional = draw(one_of(none(), booleans()))
1934 draw(integers(min_value=0)),
1935 draw(integers(min_value=0)),
1936 draw(integers(min_value=0)),
1938 return (value, bounds, impl, expl, default, optional, _decoded)
1941 class OctetStringInherited(OctetString):
1945 class TestOctetString(CommonMixin, TestCase):
1946 base_klass = OctetString
1948 def test_invalid_value_type(self):
1949 with self.assertRaises(InvalidValueType) as err:
1950 OctetString(text_type(123))
1954 def test_optional(self, optional):
1955 obj = OctetString(default=OctetString(b""), optional=optional)
1956 self.assertTrue(obj.optional)
1959 def test_ready(self, value):
1961 self.assertFalse(obj.ready)
1964 pprint(obj, big_blobs=True, with_decode_path=True)
1965 with self.assertRaises(ObjNotReady) as err:
1968 obj = OctetString(value)
1969 self.assertTrue(obj.ready)
1972 pprint(obj, big_blobs=True, with_decode_path=True)
1974 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
1975 def test_comparison(self, value1, value2, tag1, tag2):
1976 for klass in (OctetString, OctetStringInherited):
1977 obj1 = klass(value1)
1978 obj2 = klass(value2)
1979 self.assertEqual(obj1 == obj2, value1 == value2)
1980 self.assertEqual(obj1 != obj2, value1 != value2)
1981 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
1982 obj1 = klass(value1, impl=tag1)
1983 obj2 = klass(value1, impl=tag2)
1984 self.assertEqual(obj1 == obj2, tag1 == tag2)
1985 self.assertEqual(obj1 != obj2, tag1 != tag2)
1987 @given(lists(binary()))
1988 def test_sorted_works(self, values):
1989 self.assertSequenceEqual(
1990 [bytes(v) for v in sorted(OctetString(v) for v in values)],
1994 @given(data_strategy())
1995 def test_bounds_satisfied(self, d):
1996 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
1997 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1998 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
1999 OctetString(value=value, bounds=(bound_min, bound_max))
2001 @given(data_strategy())
2002 def test_bounds_unsatisfied(self, d):
2003 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2004 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2005 value = d.draw(binary(max_size=bound_min - 1))
2006 with self.assertRaises(BoundsError) as err:
2007 OctetString(value=value, bounds=(bound_min, bound_max))
2009 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2010 OctetString(bounds=(bound_min, bound_max)).decode(
2011 OctetString(value).encode()
2014 value = d.draw(binary(min_size=bound_max + 1))
2015 with self.assertRaises(BoundsError) as err:
2016 OctetString(value=value, bounds=(bound_min, bound_max))
2018 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2019 OctetString(bounds=(bound_min, bound_max)).decode(
2020 OctetString(value).encode()
2024 @given(data_strategy())
2025 def test_call(self, d):
2026 for klass in (OctetString, OctetStringInherited):
2035 ) = d.draw(octet_string_values_strategy())
2036 obj_initial = klass(
2042 optional_initial or False,
2053 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2054 if (default is None) and (obj_initial.default is not None):
2057 (bounds is None) and
2058 (value is not None) and
2059 (bounds_initial is not None) and
2060 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2064 (bounds is None) and
2065 (default is not None) and
2066 (bounds_initial is not None) and
2067 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2070 obj = obj_initial(value, bounds, impl, expl, default, optional)
2072 value_expected = default if value is None else value
2074 default_initial if value_expected is None
2077 self.assertEqual(obj, value_expected)
2078 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2079 self.assertEqual(obj.expl_tag, expl or expl_initial)
2082 default_initial if default is None else default,
2084 if obj.default is None:
2085 optional = optional_initial if optional is None else optional
2086 optional = False if optional is None else optional
2089 self.assertEqual(obj.optional, optional)
2091 (obj._bound_min, obj._bound_max),
2092 bounds or bounds_initial or (0, float("+inf")),
2095 @given(octet_string_values_strategy())
2096 def test_copy(self, values):
2097 for klass in (OctetString, OctetStringInherited):
2098 obj = klass(*values)
2099 for copy_func in copy_funcs:
2100 obj_copied = copy_func(obj)
2101 self.assert_copied_basic_fields(obj, obj_copied)
2102 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2103 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2104 self.assertEqual(obj._value, obj_copied._value)
2108 integers(min_value=1).map(tag_encode),
2110 def test_stripped(self, value, tag_impl):
2111 obj = OctetString(value, impl=tag_impl)
2112 with self.assertRaises(NotEnoughData):
2113 obj.decode(obj.encode()[:-1])
2117 integers(min_value=1).map(tag_ctxc),
2119 def test_stripped_expl(self, value, tag_expl):
2120 obj = OctetString(value, expl=tag_expl)
2121 with self.assertRaises(NotEnoughData):
2122 obj.decode(obj.encode()[:-1])
2125 integers(min_value=31),
2126 integers(min_value=0),
2129 def test_bad_tag(self, tag, offset, decode_path):
2130 with self.assertRaises(DecodeError) as err:
2131 OctetString().decode(
2132 tag_encode(tag)[:-1],
2134 decode_path=decode_path,
2137 self.assertEqual(err.exception.offset, offset)
2138 self.assertEqual(err.exception.decode_path, decode_path)
2141 integers(min_value=128),
2142 integers(min_value=0),
2145 def test_bad_len(self, l, offset, decode_path):
2146 with self.assertRaises(DecodeError) as err:
2147 OctetString().decode(
2148 OctetString.tag_default + len_encode(l)[:-1],
2150 decode_path=decode_path,
2153 self.assertEqual(err.exception.offset, offset)
2154 self.assertEqual(err.exception.decode_path, decode_path)
2157 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2158 integers(min_value=0),
2161 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2162 value, bound_min = list(sorted(ints))
2164 class String(OctetString):
2165 bounds = (bound_min, bound_min)
2166 with self.assertRaises(DecodeError) as err:
2168 OctetString(b"\x00" * value).encode(),
2170 decode_path=decode_path,
2173 self.assertEqual(err.exception.offset, offset)
2174 self.assertEqual(err.exception.decode_path, decode_path)
2176 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2178 octet_string_values_strategy(),
2180 integers(min_value=1).map(tag_ctxc),
2181 integers(min_value=0),
2185 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2186 for klass in (OctetString, OctetStringInherited):
2187 _, _, _, _, default, optional, _decoded = values
2196 pprint(obj, big_blobs=True, with_decode_path=True)
2197 self.assertFalse(obj.expled)
2198 obj_encoded = obj.encode()
2199 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2200 obj_expled = obj(value, expl=tag_expl)
2201 self.assertTrue(obj_expled.expled)
2203 list(obj_expled.pps())
2204 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2205 obj_expled_encoded = obj_expled.encode()
2206 obj_expled_cer = encode_cer(obj_expled)
2207 self.assertNotEqual(obj_expled_cer, obj_encoded)
2208 self.assertSequenceEqual(
2209 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2212 ctx_copied = deepcopy(ctx_dummy)
2213 obj_decoded, tail = obj_expled.decode(
2214 obj_expled_encoded + tail_junk,
2218 self.assertDictEqual(ctx_copied, ctx_dummy)
2220 list(obj_decoded.pps())
2221 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2222 self.assertEqual(tail, tail_junk)
2223 self.assertEqual(obj_decoded, obj_expled)
2224 self.assertNotEqual(obj_decoded, obj)
2225 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2226 self.assertEqual(bytes(obj_decoded), bytes(obj))
2227 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2228 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2229 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2231 obj_decoded.expl_llen,
2232 len(len_encode(len(obj_encoded))),
2234 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2235 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2238 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2240 self.assertEqual(obj_decoded.expl_offset, offset)
2241 assert_exceeding_data(
2243 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2247 evgens = list(obj_expled.decode_evgen(
2248 obj_expled_encoded + tail_junk,
2250 decode_path=decode_path,
2253 self.assertEqual(len(evgens), 1)
2254 _decode_path, obj, tail = evgens[0]
2255 self.assertSequenceEqual(tail, tail_junk)
2256 self.assertEqual(_decode_path, decode_path)
2257 self.assertEqual(obj.expl_offset, offset)
2261 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2263 integers(min_value=1, max_value=30),
2266 binary(min_size=1, max_size=5),
2268 binary(min_size=1, max_size=5),
2279 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2280 def chunk_constructed(contents):
2282 tag_encode(form=TagFormConstructed, num=4) +
2284 b"".join(OctetString(content).encode() for content in contents) +
2288 chunks_len_expected = []
2289 payload_expected = b""
2290 for chunk_input in chunk_inputs:
2291 if isinstance(chunk_input, binary_type):
2292 chunks.append(OctetString(chunk_input).encode())
2293 payload_expected += chunk_input
2294 chunks_len_expected.append(len(chunk_input))
2296 chunks.append(chunk_constructed(chunk_input))
2297 payload = b"".join(chunk_input)
2298 payload_expected += payload
2299 for c in chunk_input:
2300 chunks_len_expected.append(len(c))
2301 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2302 encoded_indefinite = (
2303 tag_encode(form=TagFormConstructed, num=impl) +
2308 encoded_definite = (
2309 tag_encode(form=TagFormConstructed, num=impl) +
2310 len_encode(len(b"".join(chunks))) +
2313 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2314 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2315 for lenindef_expected, encoded in (
2316 (True, encoded_indefinite),
2317 (False, encoded_definite),
2319 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2321 ctx={"bered": True},
2323 self.assertSequenceEqual(tail, junk)
2324 self.assertSequenceEqual(bytes(obj), payload_expected)
2325 self.assertTrue(obj.ber_encoded)
2326 self.assertEqual(obj.lenindef, lenindef_expected)
2327 self.assertTrue(obj.bered)
2329 self.assertTrue(obj.ber_encoded)
2330 self.assertEqual(obj.lenindef, lenindef_expected)
2331 self.assertTrue(obj.bered)
2332 self.assertEqual(len(encoded), obj.tlvlen)
2335 pprint(obj, big_blobs=True, with_decode_path=True)
2337 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2339 decode_path=decode_path,
2340 ctx={"bered": True},
2342 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2343 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2344 self.assertGreater(len(dp), len(decode_path))
2345 self.assertEqual(obj.vlen, chunk_len_expected)
2348 integers(min_value=0),
2351 def test_ber_definite_too_short(self, offset, decode_path):
2352 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2353 OctetString().decode(
2354 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2356 decode_path=decode_path,
2357 ctx={"bered": True},
2359 self.assertEqual(err.exception.decode_path, decode_path)
2360 self.assertEqual(err.exception.offset, offset)
2363 integers(min_value=0),
2365 integers(min_value=1, max_value=3),
2367 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2368 bs = OctetString(b"data").encode()
2369 with self.assertRaises(NotEnoughData) as err:
2370 OctetString().decode(
2371 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2373 decode_path=decode_path,
2374 ctx={"bered": True},
2376 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2377 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2380 integers(min_value=0),
2382 integers(min_value=1, max_value=3),
2384 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2385 bs = OctetString(b"data").encode()
2386 bs_longer = OctetString(b"data-longer").encode()
2387 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2388 OctetString().decode(
2390 tag_encode(4, form=TagFormConstructed) +
2391 len_encode((chunks + 1) * len(bs)) +
2396 decode_path=decode_path,
2397 ctx={"bered": True},
2399 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2400 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2402 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2403 @given(integers(min_value=1001, max_value=3000))
2404 def test_cer(self, data_len):
2405 data = urandom(data_len)
2406 encoded = encode_cer(OctetString(data))
2407 ctx = {"bered": True}
2408 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2409 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2410 evgens_expected = data_len // 1000
2411 if evgens_expected * 1000 != data_len:
2412 evgens_expected += 1
2413 evgens_expected += 1
2414 self.assertEqual(len(evgens), evgens_expected)
2415 for (_, obj, _) in evgens[:-2]:
2416 self.assertEqual(obj.vlen, 1000)
2417 _, obj, _ = evgens[-2]
2418 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2422 def null_values_strategy(draw, do_expl=False):
2426 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2428 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2429 optional = draw(one_of(none(), booleans()))
2431 draw(integers(min_value=0)),
2432 draw(integers(min_value=0)),
2433 draw(integers(min_value=0)),
2435 return (impl, expl, optional, _decoded)
2438 class NullInherited(Null):
2442 class TestNull(CommonMixin, TestCase):
2445 def test_ready(self):
2447 self.assertTrue(obj.ready)
2450 pprint(obj, big_blobs=True, with_decode_path=True)
2452 @given(binary(min_size=1), binary(min_size=1))
2453 def test_comparison(self, tag1, tag2):
2454 for klass in (Null, NullInherited):
2455 obj1 = klass(impl=tag1)
2456 obj2 = klass(impl=tag2)
2457 self.assertEqual(obj1 == obj2, tag1 == tag2)
2458 self.assertEqual(obj1 != obj2, tag1 != tag2)
2459 self.assertNotEqual(obj1, tag2)
2461 @given(data_strategy())
2462 def test_call(self, d):
2463 for klass in (Null, NullInherited):
2469 ) = d.draw(null_values_strategy())
2470 obj_initial = klass(
2473 optional=optional_initial or False,
2474 _decoded=_decoded_initial,
2481 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2482 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2483 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2484 self.assertEqual(obj.expl_tag, expl or expl_initial)
2485 optional = optional_initial if optional is None else optional
2486 optional = False if optional is None else optional
2487 self.assertEqual(obj.optional, optional)
2489 @given(null_values_strategy())
2490 def test_copy(self, values):
2491 for klass in (Null, NullInherited):
2492 impl, expl, optional, _decoded = values
2496 optional=optional or False,
2499 for copy_func in copy_funcs:
2500 obj_copied = copy_func(obj)
2501 self.assert_copied_basic_fields(obj, obj_copied)
2503 @given(integers(min_value=1).map(tag_encode))
2504 def test_stripped(self, tag_impl):
2505 obj = Null(impl=tag_impl)
2506 with self.assertRaises(NotEnoughData):
2507 obj.decode(obj.encode()[:-1])
2509 @given(integers(min_value=1).map(tag_ctxc))
2510 def test_stripped_expl(self, tag_expl):
2511 obj = Null(expl=tag_expl)
2512 with self.assertRaises(NotEnoughData):
2513 obj.decode(obj.encode()[:-1])
2516 integers(min_value=31),
2517 integers(min_value=0),
2520 def test_bad_tag(self, tag, offset, decode_path):
2521 with self.assertRaises(DecodeError) as err:
2523 tag_encode(tag)[:-1],
2525 decode_path=decode_path,
2528 self.assertEqual(err.exception.offset, offset)
2529 self.assertEqual(err.exception.decode_path, decode_path)
2532 integers(min_value=128),
2533 integers(min_value=0),
2536 def test_bad_len(self, l, offset, decode_path):
2537 with self.assertRaises(DecodeError) as err:
2539 Null.tag_default + len_encode(l)[:-1],
2541 decode_path=decode_path,
2544 self.assertEqual(err.exception.offset, offset)
2545 self.assertEqual(err.exception.decode_path, decode_path)
2547 @given(binary(min_size=1))
2548 def test_tag_mismatch(self, impl):
2549 assume(impl != Null.tag_default)
2550 with self.assertRaises(TagMismatch):
2551 Null(impl=impl).decode(Null().encode())
2554 null_values_strategy(),
2555 integers(min_value=1).map(tag_ctxc),
2556 integers(min_value=0),
2560 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2561 for klass in (Null, NullInherited):
2562 _, _, optional, _decoded = values
2563 obj = klass(optional=optional, _decoded=_decoded)
2566 pprint(obj, big_blobs=True, with_decode_path=True)
2567 self.assertFalse(obj.expled)
2568 obj_encoded = obj.encode()
2569 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2570 obj_expled = obj(expl=tag_expl)
2571 self.assertTrue(obj_expled.expled)
2573 list(obj_expled.pps())
2574 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2575 obj_expled_encoded = obj_expled.encode()
2576 obj_expled_cer = encode_cer(obj_expled)
2577 self.assertNotEqual(obj_expled_cer, obj_encoded)
2578 self.assertSequenceEqual(
2579 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2582 ctx_copied = deepcopy(ctx_dummy)
2583 obj_decoded, tail = obj_expled.decode(
2584 obj_expled_encoded + tail_junk,
2588 self.assertDictEqual(ctx_copied, ctx_dummy)
2590 list(obj_decoded.pps())
2591 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2592 self.assertEqual(tail, tail_junk)
2593 self.assertEqual(obj_decoded, obj_expled)
2594 self.assertNotEqual(obj_decoded, obj)
2595 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2596 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2597 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2599 obj_decoded.expl_llen,
2600 len(len_encode(len(obj_encoded))),
2602 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2603 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2606 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2608 self.assertEqual(obj_decoded.expl_offset, offset)
2609 assert_exceeding_data(
2611 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2615 evgens = list(obj_expled.decode_evgen(
2616 obj_expled_encoded + tail_junk,
2618 decode_path=decode_path,
2621 self.assertEqual(len(evgens), 1)
2622 _decode_path, obj, tail = evgens[0]
2623 self.assertSequenceEqual(tail, tail_junk)
2624 self.assertEqual(_decode_path, decode_path)
2625 self.assertEqual(obj, obj_decoded)
2626 self.assertEqual(obj.expl_offset, offset)
2631 @given(integers(min_value=1))
2632 def test_invalid_len(self, l):
2633 with self.assertRaises(InvalidLength):
2634 Null().decode(b"".join((
2641 def oid_strategy(draw):
2642 first_arc = draw(integers(min_value=0, max_value=2))
2644 if first_arc in (0, 1):
2645 second_arc = draw(integers(min_value=0, max_value=39))
2647 second_arc = draw(integers(min_value=0))
2648 other_arcs = draw(lists(integers(min_value=0)))
2649 return tuple([first_arc, second_arc] + other_arcs)
2653 def oid_values_strategy(draw, do_expl=False):
2654 value = draw(one_of(none(), oid_strategy()))
2658 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2660 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2661 default = draw(one_of(none(), oid_strategy()))
2662 optional = draw(one_of(none(), booleans()))
2664 draw(integers(min_value=0)),
2665 draw(integers(min_value=0)),
2666 draw(integers(min_value=0)),
2668 return (value, impl, expl, default, optional, _decoded)
2671 class ObjectIdentifierInherited(ObjectIdentifier):
2675 class TestObjectIdentifier(CommonMixin, TestCase):
2676 base_klass = ObjectIdentifier
2678 def test_invalid_value_type(self):
2679 with self.assertRaises(InvalidValueType) as err:
2680 ObjectIdentifier(123)
2684 def test_optional(self, optional):
2685 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2686 self.assertTrue(obj.optional)
2688 @given(oid_strategy())
2689 def test_ready(self, value):
2690 obj = ObjectIdentifier()
2691 self.assertFalse(obj.ready)
2694 pprint(obj, big_blobs=True, with_decode_path=True)
2695 with self.assertRaises(ObjNotReady) as err:
2698 obj = ObjectIdentifier(value)
2699 self.assertTrue(obj.ready)
2700 self.assertFalse(obj.ber_encoded)
2703 pprint(obj, big_blobs=True, with_decode_path=True)
2706 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2707 def test_comparison(self, value1, value2, tag1, tag2):
2708 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2709 obj1 = klass(value1)
2710 obj2 = klass(value2)
2711 self.assertEqual(obj1 == obj2, value1 == value2)
2712 self.assertEqual(obj1 != obj2, value1 != value2)
2713 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2714 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2715 obj1 = klass(value1, impl=tag1)
2716 obj2 = klass(value1, impl=tag2)
2717 self.assertEqual(obj1 == obj2, tag1 == tag2)
2718 self.assertEqual(obj1 != obj2, tag1 != tag2)
2720 @given(lists(oid_strategy()))
2721 def test_sorted_works(self, values):
2722 self.assertSequenceEqual(
2723 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2727 @given(data_strategy())
2728 def test_call(self, d):
2729 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2737 ) = d.draw(oid_values_strategy())
2738 obj_initial = klass(
2739 value=value_initial,
2742 default=default_initial,
2743 optional=optional_initial or False,
2744 _decoded=_decoded_initial,
2753 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2762 value_expected = default if value is None else value
2764 default_initial if value_expected is None
2767 self.assertEqual(obj, value_expected)
2768 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2769 self.assertEqual(obj.expl_tag, expl or expl_initial)
2772 default_initial if default is None else default,
2774 if obj.default is None:
2775 optional = optional_initial if optional is None else optional
2776 optional = False if optional is None else optional
2779 self.assertEqual(obj.optional, optional)
2781 @given(oid_values_strategy())
2782 def test_copy(self, values):
2783 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2800 for copy_func in copy_funcs:
2801 obj_copied = copy_func(obj)
2802 self.assert_copied_basic_fields(obj, obj_copied)
2803 self.assertEqual(obj._value, obj_copied._value)
2805 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2808 integers(min_value=1).map(tag_encode),
2810 def test_stripped(self, value, tag_impl):
2811 obj = ObjectIdentifier(value, impl=tag_impl)
2812 with self.assertRaises(NotEnoughData):
2813 obj.decode(obj.encode()[:-1])
2817 integers(min_value=1).map(tag_ctxc),
2819 def test_stripped_expl(self, value, tag_expl):
2820 obj = ObjectIdentifier(value, expl=tag_expl)
2821 with self.assertRaises(NotEnoughData):
2822 obj.decode(obj.encode()[:-1])
2825 integers(min_value=31),
2826 integers(min_value=0),
2829 def test_bad_tag(self, tag, offset, decode_path):
2830 with self.assertRaises(DecodeError) as err:
2831 ObjectIdentifier().decode(
2832 tag_encode(tag)[:-1],
2834 decode_path=decode_path,
2837 self.assertEqual(err.exception.offset, offset)
2838 self.assertEqual(err.exception.decode_path, decode_path)
2841 integers(min_value=128),
2842 integers(min_value=0),
2845 def test_bad_len(self, l, offset, decode_path):
2846 with self.assertRaises(DecodeError) as err:
2847 ObjectIdentifier().decode(
2848 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2850 decode_path=decode_path,
2853 self.assertEqual(err.exception.offset, offset)
2854 self.assertEqual(err.exception.decode_path, decode_path)
2856 def test_zero_oid(self):
2857 with self.assertRaises(NotEnoughData):
2858 ObjectIdentifier().decode(
2859 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2862 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2863 @given(oid_strategy())
2864 def test_unfinished_oid(self, value):
2865 assume(list(value)[-1] > 255)
2866 obj_encoded = ObjectIdentifier(value).encode()
2867 obj, _ = ObjectIdentifier().decode(obj_encoded)
2868 data = obj_encoded[obj.tlen + obj.llen:-1]
2870 ObjectIdentifier.tag_default,
2871 len_encode(len(data)),
2874 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2877 @given(integers(min_value=0))
2878 def test_invalid_short(self, value):
2879 with self.assertRaises(InvalidOID):
2880 ObjectIdentifier((value,))
2881 with self.assertRaises(InvalidOID):
2882 ObjectIdentifier("%d" % value)
2884 @given(integers(min_value=3), integers(min_value=0))
2885 def test_invalid_first_arc(self, first_arc, second_arc):
2886 with self.assertRaises(InvalidOID):
2887 ObjectIdentifier((first_arc, second_arc))
2888 with self.assertRaises(InvalidOID):
2889 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2891 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2892 def test_invalid_second_arc(self, first_arc, second_arc):
2893 with self.assertRaises(InvalidOID):
2894 ObjectIdentifier((first_arc, second_arc))
2895 with self.assertRaises(InvalidOID):
2896 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2898 @given(text(alphabet=ascii_letters + ".", min_size=1))
2899 def test_junk(self, oid):
2900 with self.assertRaises(InvalidOID):
2901 ObjectIdentifier(oid)
2903 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2904 @given(oid_strategy())
2905 def test_validness(self, oid):
2906 obj = ObjectIdentifier(oid)
2907 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2910 pprint(obj, big_blobs=True, with_decode_path=True)
2912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2914 oid_values_strategy(),
2916 integers(min_value=1).map(tag_ctxc),
2917 integers(min_value=0),
2921 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2922 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2923 _, _, _, default, optional, _decoded = values
2932 pprint(obj, big_blobs=True, with_decode_path=True)
2933 self.assertFalse(obj.expled)
2934 obj_encoded = obj.encode()
2935 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2936 obj_expled = obj(value, expl=tag_expl)
2937 self.assertTrue(obj_expled.expled)
2939 list(obj_expled.pps())
2940 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2941 obj_expled_encoded = obj_expled.encode()
2942 obj_expled_cer = encode_cer(obj_expled)
2943 self.assertNotEqual(obj_expled_cer, obj_encoded)
2944 self.assertSequenceEqual(
2945 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2948 ctx_copied = deepcopy(ctx_dummy)
2949 obj_decoded, tail = obj_expled.decode(
2950 obj_expled_encoded + tail_junk,
2954 self.assertDictEqual(ctx_copied, ctx_dummy)
2956 list(obj_decoded.pps())
2957 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2958 self.assertEqual(tail, tail_junk)
2959 self.assertEqual(obj_decoded, obj_expled)
2960 self.assertNotEqual(obj_decoded, obj)
2961 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
2962 self.assertEqual(tuple(obj_decoded), tuple(obj))
2963 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2964 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2965 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2967 obj_decoded.expl_llen,
2968 len(len_encode(len(obj_encoded))),
2970 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2971 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2974 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2976 self.assertEqual(obj_decoded.expl_offset, offset)
2977 assert_exceeding_data(
2979 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2983 evgens = list(obj_expled.decode_evgen(
2984 obj_expled_encoded + tail_junk,
2986 decode_path=decode_path,
2989 self.assertEqual(len(evgens), 1)
2990 _decode_path, obj, tail = evgens[0]
2991 self.assertSequenceEqual(tail, tail_junk)
2992 self.assertEqual(_decode_path, decode_path)
2993 self.assertEqual(obj, obj_decoded)
2994 self.assertEqual(obj.expl_offset, offset)
2999 oid_strategy().map(ObjectIdentifier),
3000 oid_strategy().map(ObjectIdentifier),
3002 def test_add(self, oid1, oid2):
3003 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3004 for oid_to_add in (oid2, tuple(oid2)):
3005 self.assertEqual(oid1 + oid_to_add, oid_expect)
3006 with self.assertRaises(InvalidValueType):
3009 def test_go_vectors_valid(self):
3010 for data, expect in (
3012 (b"\x55\x02", (2, 5, 2)),
3013 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3014 (b"\x81\x34\x03", (2, 100, 3)),
3017 ObjectIdentifier().decode(b"".join((
3018 ObjectIdentifier.tag_default,
3019 len_encode(len(data)),
3025 def test_go_vectors_invalid(self):
3026 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3027 with self.assertRaises(DecodeError):
3028 ObjectIdentifier().decode(b"".join((
3029 Integer.tag_default,
3030 len_encode(len(data)),
3034 def test_x690_vector(self):
3036 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3037 ObjectIdentifier((2, 999, 3)),
3040 def test_nonnormalized_first_arc(self):
3042 ObjectIdentifier.tag_default +
3045 ObjectIdentifier((1, 0)).encode()[-1:]
3047 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3048 self.assertTrue(obj.ber_encoded)
3049 self.assertTrue(obj.bered)
3051 self.assertTrue(obj.ber_encoded)
3052 self.assertTrue(obj.bered)
3053 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3054 ObjectIdentifier().decode(tampered)
3056 @given(data_strategy())
3057 def test_negative_arcs(self, d):
3058 oid = list(d.draw(oid_strategy()))
3061 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3063 if oid[idx - 1] == 0:
3065 with self.assertRaises(InvalidOID):
3066 ObjectIdentifier(tuple(oid))
3067 with self.assertRaises(InvalidOID):
3068 ObjectIdentifier(".".join(str(i) for i in oid))
3070 @given(data_strategy())
3071 def test_plused_arcs(self, d):
3072 oid = [str(arc) for arc in d.draw(oid_strategy())]
3073 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3074 oid[idx - 1] = "+" + oid[idx - 1]
3075 with self.assertRaises(InvalidOID):
3076 ObjectIdentifier(".".join(str(i) for i in oid))
3078 @given(data_strategy())
3079 def test_nonnormalized_arcs(self, d):
3080 arcs = d.draw(lists(
3081 integers(min_value=0, max_value=100),
3085 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3086 _, _, lv = tag_strip(dered)
3087 _, _, v = len_decode(lv)
3088 v_no_first_arc = v[1:]
3089 idx_for_tamper = d.draw(integers(
3091 max_value=len(v_no_first_arc) - 1,
3093 tampered = list(bytearray(v_no_first_arc))
3094 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3095 tampered.insert(idx_for_tamper, 0x80)
3096 tampered = bytes(bytearray(tampered))
3098 ObjectIdentifier.tag_default +
3099 len_encode(len(tampered)) +
3102 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3103 self.assertTrue(obj.ber_encoded)
3104 self.assertTrue(obj.bered)
3106 self.assertTrue(obj.ber_encoded)
3107 self.assertTrue(obj.bered)
3108 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3109 ObjectIdentifier().decode(tampered)
3113 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3115 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3116 values = list(draw(sets(
3118 min_size=len(schema),
3119 max_size=len(schema),
3121 schema = list(zip(schema, values))
3122 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3126 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3128 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3129 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3130 optional = draw(one_of(none(), booleans()))
3132 draw(integers(min_value=0)),
3133 draw(integers(min_value=0)),
3134 draw(integers(min_value=0)),
3136 return (schema, value, impl, expl, default, optional, _decoded)
3139 class TestEnumerated(CommonMixin, TestCase):
3140 class EWhatever(Enumerated):
3141 schema = (("whatever", 0),)
3143 base_klass = EWhatever
3145 def test_schema_required(self):
3146 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3149 def test_invalid_value_type(self):
3150 with self.assertRaises(InvalidValueType) as err:
3151 self.base_klass((1, 2))
3154 @given(sets(text_letters(), min_size=2))
3155 def test_unknown_name(self, schema_input):
3156 missing = schema_input.pop()
3158 class E(Enumerated):
3159 schema = [(n, 123) for n in schema_input]
3160 with self.assertRaises(ObjUnknown) as err:
3165 sets(text_letters(), min_size=2),
3166 sets(integers(), min_size=2),
3168 def test_unknown_value(self, schema_input, values_input):
3170 missing_value = values_input.pop()
3171 _input = list(zip(schema_input, values_input))
3173 class E(Enumerated):
3175 with self.assertRaises(DecodeError) as err:
3180 def test_optional(self, optional):
3181 obj = self.base_klass(default="whatever", optional=optional)
3182 self.assertTrue(obj.optional)
3184 def test_ready(self):
3185 obj = self.base_klass()
3186 self.assertFalse(obj.ready)
3189 pprint(obj, big_blobs=True, with_decode_path=True)
3190 with self.assertRaises(ObjNotReady) as err:
3193 obj = self.base_klass("whatever")
3194 self.assertTrue(obj.ready)
3197 pprint(obj, big_blobs=True, with_decode_path=True)
3199 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3200 def test_comparison(self, value1, value2, tag1, tag2):
3201 class E(Enumerated):
3203 ("whatever0", value1),
3204 ("whatever1", value2),
3207 class EInherited(E):
3209 for klass in (E, EInherited):
3210 obj1 = klass(value1)
3211 obj2 = klass(value2)
3212 self.assertEqual(obj1 == obj2, value1 == value2)
3213 self.assertEqual(obj1 != obj2, value1 != value2)
3214 self.assertEqual(obj1 == int(obj2), value1 == value2)
3215 obj1 = klass(value1, impl=tag1)
3216 obj2 = klass(value1, impl=tag2)
3217 self.assertEqual(obj1 == obj2, tag1 == tag2)
3218 self.assertEqual(obj1 != obj2, tag1 != tag2)
3220 @given(data_strategy())
3221 def test_call(self, d):
3230 ) = d.draw(enumerated_values_strategy())
3232 class E(Enumerated):
3233 schema = schema_initial
3235 value=value_initial,
3238 default=default_initial,
3239 optional=optional_initial or False,
3240 _decoded=_decoded_initial,
3250 ) = d.draw(enumerated_values_strategy(
3251 schema=schema_initial,
3252 do_expl=impl_initial is None,
3262 value_expected = default if value is None else value
3264 default_initial if value_expected is None
3269 dict(schema_initial).get(value_expected, value_expected),
3271 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3272 self.assertEqual(obj.expl_tag, expl or expl_initial)
3275 default_initial if default is None else default,
3277 if obj.default is None:
3278 optional = optional_initial if optional is None else optional
3279 optional = False if optional is None else optional
3282 self.assertEqual(obj.optional, optional)
3283 self.assertEqual(obj.specs, dict(schema_initial))
3285 @given(enumerated_values_strategy())
3286 def test_copy(self, values):
3287 schema_input, value, impl, expl, default, optional, _decoded = values
3289 class E(Enumerated):
3290 schema = schema_input
3300 for copy_func in copy_funcs:
3301 obj_copied = copy_func(obj)
3302 self.assert_copied_basic_fields(obj, obj_copied)
3303 self.assertEqual(obj.specs, obj_copied.specs)
3305 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3306 @given(data_strategy())
3307 def test_symmetric(self, d):
3308 schema_input, _, _, _, default, optional, _decoded = d.draw(
3309 enumerated_values_strategy(),
3311 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3312 offset = d.draw(integers(min_value=0))
3313 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3314 tail_junk = d.draw(binary(max_size=5))
3315 decode_path = d.draw(decode_path_strat)
3317 class E(Enumerated):
3318 schema = schema_input
3327 pprint(obj, big_blobs=True, with_decode_path=True)
3328 self.assertFalse(obj.expled)
3329 obj_encoded = obj.encode()
3330 obj_expled = obj(value, expl=tag_expl)
3331 self.assertTrue(obj_expled.expled)
3333 list(obj_expled.pps())
3334 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3335 obj_expled_encoded = obj_expled.encode()
3336 ctx_copied = deepcopy(ctx_dummy)
3337 obj_decoded, tail = obj_expled.decode(
3338 obj_expled_encoded + tail_junk,
3342 self.assertDictEqual(ctx_copied, ctx_dummy)
3344 list(obj_decoded.pps())
3345 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3346 self.assertEqual(tail, tail_junk)
3347 self.assertEqual(obj_decoded, obj_expled)
3348 self.assertNotEqual(obj_decoded, obj)
3349 self.assertEqual(int(obj_decoded), int(obj_expled))
3350 self.assertEqual(int(obj_decoded), int(obj))
3351 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3352 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3353 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3355 obj_decoded.expl_llen,
3356 len(len_encode(len(obj_encoded))),
3358 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3359 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3362 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3364 self.assertEqual(obj_decoded.expl_offset, offset)
3365 assert_exceeding_data(
3367 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3371 evgens = list(obj_expled.decode_evgen(
3372 obj_expled_encoded + tail_junk,
3374 decode_path=decode_path,
3377 self.assertEqual(len(evgens), 1)
3378 _decode_path, obj, tail = evgens[0]
3379 self.assertSequenceEqual(tail, tail_junk)
3380 self.assertEqual(_decode_path, decode_path)
3381 self.assertEqual(obj, obj_decoded)
3382 self.assertEqual(obj.expl_offset, offset)
3388 def string_values_strategy(draw, alphabet, do_expl=False):
3389 bound_min, bound_max = sorted(draw(sets(
3390 integers(min_value=0, max_value=1 << 7),
3394 value = draw(one_of(
3396 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3398 default = draw(one_of(
3400 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3403 if draw(booleans()):
3404 bounds = (bound_min, bound_max)
3408 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3410 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3411 optional = draw(one_of(none(), booleans()))
3413 draw(integers(min_value=0)),
3414 draw(integers(min_value=0)),
3415 draw(integers(min_value=0)),
3417 return (value, bounds, impl, expl, default, optional, _decoded)
3420 class StringMixin(object):
3421 def test_invalid_value_type(self):
3422 with self.assertRaises(InvalidValueType) as err:
3423 self.base_klass((1, 2))
3426 def text_alphabet(self):
3427 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
3428 return printable + whitespace
3432 def test_optional(self, optional):
3433 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3434 self.assertTrue(obj.optional)
3436 @given(data_strategy())
3437 def test_ready(self, d):
3438 obj = self.base_klass()
3439 self.assertFalse(obj.ready)
3442 pprint(obj, big_blobs=True, with_decode_path=True)
3444 with self.assertRaises(ObjNotReady) as err:
3447 value = d.draw(text(alphabet=self.text_alphabet()))
3448 obj = self.base_klass(value)
3449 self.assertTrue(obj.ready)
3452 pprint(obj, big_blobs=True, with_decode_path=True)
3455 @given(data_strategy())
3456 def test_comparison(self, d):
3457 value1 = d.draw(text(alphabet=self.text_alphabet()))
3458 value2 = d.draw(text(alphabet=self.text_alphabet()))
3459 tag1 = d.draw(binary(min_size=1))
3460 tag2 = d.draw(binary(min_size=1))
3461 obj1 = self.base_klass(value1)
3462 obj2 = self.base_klass(value2)
3463 self.assertEqual(obj1 == obj2, value1 == value2)
3464 self.assertEqual(obj1 != obj2, value1 != value2)
3465 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3466 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3467 obj1 = self.base_klass(value1, impl=tag1)
3468 obj2 = self.base_klass(value1, impl=tag2)
3469 self.assertEqual(obj1 == obj2, tag1 == tag2)
3470 self.assertEqual(obj1 != obj2, tag1 != tag2)
3472 @given(data_strategy())
3473 def test_bounds_satisfied(self, d):
3474 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3475 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3476 value = d.draw(text(
3477 alphabet=self.text_alphabet(),
3481 self.base_klass(value=value, bounds=(bound_min, bound_max))
3483 @given(data_strategy())
3484 def test_bounds_unsatisfied(self, d):
3485 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3486 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3487 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3488 with self.assertRaises(BoundsError) as err:
3489 self.base_klass(value=value, bounds=(bound_min, bound_max))
3491 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3492 self.base_klass(bounds=(bound_min, bound_max)).decode(
3493 self.base_klass(value).encode()
3496 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3497 with self.assertRaises(BoundsError) as err:
3498 self.base_klass(value=value, bounds=(bound_min, bound_max))
3500 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3501 self.base_klass(bounds=(bound_min, bound_max)).decode(
3502 self.base_klass(value).encode()
3506 @given(data_strategy())
3507 def test_call(self, d):
3516 ) = d.draw(string_values_strategy(self.text_alphabet()))
3517 obj_initial = self.base_klass(
3523 optional_initial or False,
3534 ) = d.draw(string_values_strategy(
3535 self.text_alphabet(),
3536 do_expl=impl_initial is None,
3538 if (default is None) and (obj_initial.default is not None):
3541 (bounds is None) and
3542 (value is not None) and
3543 (bounds_initial is not None) and
3544 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3548 (bounds is None) and
3549 (default is not None) and
3550 (bounds_initial is not None) and
3551 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3554 obj = obj_initial(value, bounds, impl, expl, default, optional)
3556 value_expected = default if value is None else value
3558 default_initial if value_expected is None
3561 self.assertEqual(obj, value_expected)
3562 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3563 self.assertEqual(obj.expl_tag, expl or expl_initial)
3566 default_initial if default is None else default,
3568 if obj.default is None:
3569 optional = optional_initial if optional is None else optional
3570 optional = False if optional is None else optional
3573 self.assertEqual(obj.optional, optional)
3575 (obj._bound_min, obj._bound_max),
3576 bounds or bounds_initial or (0, float("+inf")),
3579 @given(data_strategy())
3580 def test_copy(self, d):
3581 values = d.draw(string_values_strategy(self.text_alphabet()))
3582 obj = self.base_klass(*values)
3583 for copy_func in copy_funcs:
3584 obj_copied = copy_func(obj)
3585 self.assert_copied_basic_fields(obj, obj_copied)
3586 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3587 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3588 self.assertEqual(obj._value, obj_copied._value)
3590 @given(data_strategy())
3591 def test_stripped(self, d):
3592 value = d.draw(text(alphabet=self.text_alphabet()))
3593 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3594 obj = self.base_klass(value, impl=tag_impl)
3595 with self.assertRaises(NotEnoughData):
3596 obj.decode(obj.encode()[:-1])
3598 @given(data_strategy())
3599 def test_stripped_expl(self, d):
3600 value = d.draw(text(alphabet=self.text_alphabet()))
3601 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3602 obj = self.base_klass(value, expl=tag_expl)
3603 with self.assertRaises(NotEnoughData):
3604 obj.decode(obj.encode()[:-1])
3607 integers(min_value=31),
3608 integers(min_value=0),
3611 def test_bad_tag(self, tag, offset, decode_path):
3612 with self.assertRaises(DecodeError) as err:
3613 self.base_klass().decode(
3614 tag_encode(tag)[:-1],
3616 decode_path=decode_path,
3619 self.assertEqual(err.exception.offset, offset)
3620 self.assertEqual(err.exception.decode_path, decode_path)
3623 integers(min_value=128),
3624 integers(min_value=0),
3627 def test_bad_len(self, l, offset, decode_path):
3628 with self.assertRaises(DecodeError) as err:
3629 self.base_klass().decode(
3630 self.base_klass.tag_default + len_encode(l)[:-1],
3632 decode_path=decode_path,
3635 self.assertEqual(err.exception.offset, offset)
3636 self.assertEqual(err.exception.decode_path, decode_path)
3639 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3640 integers(min_value=0),
3643 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3644 value, bound_min = list(sorted(ints))
3646 class String(self.base_klass):
3647 # Multiply this value by four, to satisfy UTF-32 bounds
3648 # (4 bytes per character) validation
3649 bounds = (bound_min * 4, bound_min * 4)
3650 with self.assertRaises(DecodeError) as err:
3652 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3654 decode_path=decode_path,
3657 self.assertEqual(err.exception.offset, offset)
3658 self.assertEqual(err.exception.decode_path, decode_path)
3660 @given(data_strategy())
3661 def test_symmetric(self, d):
3662 values = d.draw(string_values_strategy(self.text_alphabet()))
3663 value = d.draw(text(alphabet=self.text_alphabet()))
3664 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3665 offset = d.draw(integers(min_value=0))
3666 tail_junk = d.draw(binary(max_size=5))
3667 decode_path = d.draw(decode_path_strat)
3668 _, _, _, _, default, optional, _decoded = values
3669 obj = self.base_klass(
3677 pprint(obj, big_blobs=True, with_decode_path=True)
3678 self.assertFalse(obj.expled)
3679 obj_encoded = obj.encode()
3680 obj_expled = obj(value, expl=tag_expl)
3681 self.assertTrue(obj_expled.expled)
3683 list(obj_expled.pps())
3684 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3685 obj_expled_encoded = obj_expled.encode()
3686 ctx_copied = deepcopy(ctx_dummy)
3687 obj_decoded, tail = obj_expled.decode(
3688 obj_expled_encoded + tail_junk,
3692 self.assertDictEqual(ctx_copied, ctx_dummy)
3694 list(obj_decoded.pps())
3695 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3696 self.assertEqual(tail, tail_junk)
3697 self.assertEqual(obj_decoded, obj_expled)
3698 self.assertNotEqual(obj_decoded, obj)
3699 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3700 self.assertEqual(bytes(obj_decoded), bytes(obj))
3701 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3702 self.assertEqual(text_type(obj_decoded), text_type(obj))
3703 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3704 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3705 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3707 obj_decoded.expl_llen,
3708 len(len_encode(len(obj_encoded))),
3710 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3711 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3714 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3716 self.assertEqual(obj_decoded.expl_offset, offset)
3717 assert_exceeding_data(
3719 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3723 evgens = list(obj_expled.decode_evgen(
3724 obj_expled_encoded + tail_junk,
3726 decode_path=decode_path,
3729 self.assertEqual(len(evgens), 1)
3730 _decode_path, obj, tail = evgens[0]
3731 self.assertSequenceEqual(tail, tail_junk)
3732 self.assertEqual(_decode_path, decode_path)
3733 if not getattr(self, "evgen_mode_skip_value", True):
3734 self.assertEqual(obj, obj_decoded)
3735 self.assertEqual(obj.expl_offset, offset)
3740 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3741 base_klass = UTF8String
3744 cyrillic_letters = text(
3745 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3751 class UnicodeDecodeErrorMixin(object):
3752 @given(cyrillic_letters)
3753 def test_unicode_decode_error(self, cyrillic_text):
3754 with self.assertRaises(DecodeError):
3755 self.base_klass(cyrillic_text)
3758 class TestNumericString(StringMixin, CommonMixin, TestCase):
3759 base_klass = NumericString
3761 def text_alphabet(self):
3764 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3765 def test_non_numeric(self, non_numeric_text):
3766 with assertRaisesRegex(self, DecodeError, "non-numeric"):
3767 self.base_klass(non_numeric_text)
3770 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3771 integers(min_value=0),
3774 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3775 value, bound_min = list(sorted(ints))
3777 class String(self.base_klass):
3778 bounds = (bound_min, bound_min)
3779 with self.assertRaises(DecodeError) as err:
3781 self.base_klass(b"1" * value).encode(),
3783 decode_path=decode_path,
3786 self.assertEqual(err.exception.offset, offset)
3787 self.assertEqual(err.exception.decode_path, decode_path)
3790 class TestPrintableString(
3791 UnicodeDecodeErrorMixin,
3796 base_klass = PrintableString
3798 def text_alphabet(self):
3799 return ascii_letters + digits + " '()+,-./:=?"
3801 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3802 def test_non_printable(self, non_printable_text):
3803 with assertRaisesRegex(self, DecodeError, "non-printable"):
3804 self.base_klass(non_printable_text)
3807 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3808 integers(min_value=0),
3811 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3812 value, bound_min = list(sorted(ints))
3814 class String(self.base_klass):
3815 bounds = (bound_min, bound_min)
3816 with self.assertRaises(DecodeError) as err:
3818 self.base_klass(b"1" * value).encode(),
3820 decode_path=decode_path,
3823 self.assertEqual(err.exception.offset, offset)
3824 self.assertEqual(err.exception.decode_path, decode_path)
3826 def test_allowable_invalid_chars(self):
3828 ("*", {"allow_asterisk": True}),
3829 ("&", {"allow_ampersand": True}),
3830 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3833 obj = self.base_klass(s)
3834 for prop in kwargs.keys():
3835 self.assertFalse(getattr(obj, prop))
3837 with assertRaisesRegex(self, DecodeError, "non-printable"):
3839 self.base_klass(s, **kwargs)
3840 klass = self.base_klass(**kwargs)
3842 for prop in kwargs.keys():
3843 self.assertTrue(getattr(obj, prop))
3846 for prop in kwargs.keys():
3847 self.assertTrue(getattr(obj, prop))
3850 class TestTeletexString(
3851 UnicodeDecodeErrorMixin,
3856 base_klass = TeletexString
3859 class TestVideotexString(
3860 UnicodeDecodeErrorMixin,
3865 base_klass = VideotexString
3868 class TestIA5String(
3869 UnicodeDecodeErrorMixin,
3874 base_klass = IA5String
3877 class TestGraphicString(
3878 UnicodeDecodeErrorMixin,
3883 base_klass = GraphicString
3886 class TestVisibleString(
3887 UnicodeDecodeErrorMixin,
3892 base_klass = VisibleString
3894 def test_x690_vector(self):
3895 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3896 self.assertSequenceEqual(tail, b"")
3897 self.assertEqual(str(obj), "Jones")
3898 self.assertFalse(obj.ber_encoded)
3899 self.assertFalse(obj.lenindef)
3900 self.assertFalse(obj.bered)
3902 obj, tail = VisibleString().decode(
3903 hexdec("3A0904034A6F6E04026573"),
3904 ctx={"bered": True},
3906 self.assertSequenceEqual(tail, b"")
3907 self.assertEqual(str(obj), "Jones")
3908 self.assertTrue(obj.ber_encoded)
3909 self.assertFalse(obj.lenindef)
3910 self.assertTrue(obj.bered)
3912 self.assertTrue(obj.ber_encoded)
3913 self.assertFalse(obj.lenindef)
3914 self.assertTrue(obj.bered)
3916 obj, tail = VisibleString().decode(
3917 hexdec("3A8004034A6F6E040265730000"),
3918 ctx={"bered": True},
3920 self.assertSequenceEqual(tail, b"")
3921 self.assertEqual(str(obj), "Jones")
3922 self.assertTrue(obj.ber_encoded)
3923 self.assertTrue(obj.lenindef)
3924 self.assertTrue(obj.bered)
3926 self.assertTrue(obj.ber_encoded)
3927 self.assertTrue(obj.lenindef)
3928 self.assertTrue(obj.bered)
3931 class TestGeneralString(
3932 UnicodeDecodeErrorMixin,
3937 base_klass = GeneralString
3940 class TestUniversalString(StringMixin, CommonMixin, TestCase):
3941 base_klass = UniversalString
3944 class TestBMPString(StringMixin, CommonMixin, TestCase):
3945 base_klass = BMPString
3949 def generalized_time_values_strategy(
3957 if draw(booleans()):
3958 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
3960 value = value.replace(microsecond=0)
3962 if draw(booleans()):
3963 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
3965 default = default.replace(microsecond=0)
3969 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3971 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3972 optional = draw(one_of(none(), booleans()))
3974 draw(integers(min_value=0)),
3975 draw(integers(min_value=0)),
3976 draw(integers(min_value=0)),
3978 return (value, impl, expl, default, optional, _decoded)
3981 class TimeMixin(object):
3982 def test_invalid_value_type(self):
3983 with self.assertRaises(InvalidValueType) as err:
3984 self.base_klass(datetime.now().timetuple())
3987 @given(data_strategy())
3988 def test_optional(self, d):
3989 default = d.draw(datetimes(
3990 min_value=self.min_datetime,
3991 max_value=self.max_datetime,
3993 optional = d.draw(booleans())
3994 obj = self.base_klass(default=default, optional=optional)
3995 self.assertTrue(obj.optional)
3997 @given(data_strategy())
3998 def test_ready(self, d):
3999 obj = self.base_klass()
4000 self.assertFalse(obj.ready)
4003 pprint(obj, big_blobs=True, with_decode_path=True)
4004 with self.assertRaises(ObjNotReady) as err:
4007 value = d.draw(datetimes(
4008 min_value=self.min_datetime,
4009 max_value=self.max_datetime,
4011 obj = self.base_klass(value)
4012 self.assertTrue(obj.ready)
4015 pprint(obj, big_blobs=True, with_decode_path=True)
4017 @given(data_strategy())
4018 def test_comparison(self, d):
4019 value1 = d.draw(datetimes(
4020 min_value=self.min_datetime,
4021 max_value=self.max_datetime,
4023 value2 = d.draw(datetimes(
4024 min_value=self.min_datetime,
4025 max_value=self.max_datetime,
4027 tag1 = d.draw(binary(min_size=1))
4028 tag2 = d.draw(binary(min_size=1))
4030 value1 = value1.replace(microsecond=0)
4031 value2 = value2.replace(microsecond=0)
4032 obj1 = self.base_klass(value1)
4033 obj2 = self.base_klass(value2)
4034 self.assertEqual(obj1 == obj2, value1 == value2)
4035 self.assertEqual(obj1 != obj2, value1 != value2)
4036 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4037 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4038 obj1 = self.base_klass(value1, impl=tag1)
4039 obj2 = self.base_klass(value1, impl=tag2)
4040 self.assertEqual(obj1 == obj2, tag1 == tag2)
4041 self.assertEqual(obj1 != obj2, tag1 != tag2)
4043 @given(data_strategy())
4044 def test_call(self, d):
4052 ) = d.draw(generalized_time_values_strategy(
4053 min_datetime=self.min_datetime,
4054 max_datetime=self.max_datetime,
4055 omit_ms=self.omit_ms,
4057 obj_initial = self.base_klass(
4058 value=value_initial,
4061 default=default_initial,
4062 optional=optional_initial or False,
4063 _decoded=_decoded_initial,
4072 ) = d.draw(generalized_time_values_strategy(
4073 min_datetime=self.min_datetime,
4074 max_datetime=self.max_datetime,
4075 omit_ms=self.omit_ms,
4076 do_expl=impl_initial is None,
4086 value_expected = default if value is None else value
4088 default_initial if value_expected is None
4091 self.assertEqual(obj, value_expected)
4092 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4093 self.assertEqual(obj.expl_tag, expl or expl_initial)
4096 default_initial if default is None else default,
4098 if obj.default is None:
4099 optional = optional_initial if optional is None else optional
4100 optional = False if optional is None else optional
4103 self.assertEqual(obj.optional, optional)
4105 @given(data_strategy())
4106 def test_copy(self, d):
4107 values = d.draw(generalized_time_values_strategy(
4108 min_datetime=self.min_datetime,
4109 max_datetime=self.max_datetime,
4111 obj = self.base_klass(*values)
4112 for copy_func in copy_funcs:
4113 obj_copied = copy_func(obj)
4114 self.assert_copied_basic_fields(obj, obj_copied)
4115 self.assertEqual(obj._value, obj_copied._value)
4117 @given(data_strategy())
4118 def test_stripped(self, d):
4119 value = d.draw(datetimes(
4120 min_value=self.min_datetime,
4121 max_value=self.max_datetime,
4123 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4124 obj = self.base_klass(value, impl=tag_impl)
4125 with self.assertRaises(NotEnoughData):
4126 obj.decode(obj.encode()[:-1])
4128 @given(data_strategy())
4129 def test_stripped_expl(self, d):
4130 value = d.draw(datetimes(
4131 min_value=self.min_datetime,
4132 max_value=self.max_datetime,
4134 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4135 obj = self.base_klass(value, expl=tag_expl)
4136 with self.assertRaises(NotEnoughData):
4137 obj.decode(obj.encode()[:-1])
4139 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4140 @given(data_strategy())
4141 def test_symmetric(self, d):
4142 values = d.draw(generalized_time_values_strategy(
4143 min_datetime=self.min_datetime,
4144 max_datetime=self.max_datetime,
4146 value = d.draw(datetimes(
4147 min_value=self.min_datetime,
4148 max_value=self.max_datetime,
4150 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4151 offset = d.draw(integers(min_value=0))
4152 tail_junk = d.draw(binary(max_size=5))
4153 _, _, _, default, optional, _decoded = values
4154 obj = self.base_klass(
4162 pprint(obj, big_blobs=True, with_decode_path=True)
4163 self.assertFalse(obj.expled)
4164 obj_encoded = obj.encode()
4165 self.additional_symmetric_check(value, obj_encoded)
4166 obj_expled = obj(value, expl=tag_expl)
4167 self.assertTrue(obj_expled.expled)
4169 list(obj_expled.pps())
4170 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4171 obj_expled_encoded = obj_expled.encode()
4172 ctx_copied = deepcopy(ctx_dummy)
4173 obj_decoded, tail = obj_expled.decode(
4174 obj_expled_encoded + tail_junk,
4178 self.assertDictEqual(ctx_copied, ctx_dummy)
4180 list(obj_decoded.pps())
4181 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4182 self.assertEqual(tail, tail_junk)
4183 self.assertEqual(obj_decoded, obj_expled)
4184 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4185 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4186 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4187 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4188 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4190 obj_decoded.expl_llen,
4191 len(len_encode(len(obj_encoded))),
4193 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4194 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4197 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4199 self.assertEqual(obj_decoded.expl_offset, offset)
4200 assert_exceeding_data(
4202 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4207 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4208 base_klass = GeneralizedTime
4210 min_datetime = datetime(1900, 1, 1)
4211 max_datetime = datetime(9999, 12, 31)
4212 evgen_mode_skip_value = False
4214 def additional_symmetric_check(self, value, obj_encoded):
4215 if value.microsecond > 0:
4216 self.assertFalse(obj_encoded.endswith(b"0Z"))
4218 def test_repr_not_ready(self):
4219 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4220 repr(GeneralizedTime())
4222 def test_x690_vector_valid(self):
4226 b"19920722132100.3Z",
4228 GeneralizedTime(data)
4230 def test_x690_vector_invalid(self):
4233 b"19920622123421.0Z",
4234 b"19920722132100.30Z",
4236 with self.assertRaises(DecodeError) as err:
4237 GeneralizedTime(data)
4240 def test_go_vectors_invalid(self):
4252 b"-20100102030410Z",
4253 b"2010-0102030410Z",
4254 b"2010-0002030410Z",
4255 b"201001-02030410Z",
4256 b"20100102-030410Z",
4257 b"2010010203-0410Z",
4258 b"201001020304-10Z",
4259 # These ones are INVALID in *DER*, but accepted
4260 # by Go's encoding/asn1
4261 b"20100102030405+0607",
4262 b"20100102030405-0607",
4264 with self.assertRaises(DecodeError) as err:
4265 GeneralizedTime(data)
4268 def test_go_vectors_valid(self):
4270 GeneralizedTime(b"20100102030405Z").todatetime(),
4271 datetime(2010, 1, 2, 3, 4, 5, 0),
4274 def test_go_vectors_valid_ber(self):
4276 b"20100102030405+0607",
4277 b"20100102030405-0607",
4279 GeneralizedTime(data, ctx={"bered": True})
4281 def test_utc_offsets(self):
4282 """Some know equal UTC offsets
4285 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4289 "200101011130-0700",
4290 "200101011500-03:30",
4293 self.assertEqual(dts[0], dts[1])
4294 self.assertEqual(dts[0], dts[2])
4295 self.assertEqual(dts[0], dts[3])
4297 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4298 @given(data_strategy())
4299 def test_valid_ber(self, d):
4300 min_year = 1901 if PY2 else 2
4301 year = d.draw(integers(min_value=min_year, max_value=9999))
4302 month = d.draw(integers(min_value=1, max_value=12))
4303 day = d.draw(integers(min_value=1, max_value=28))
4304 hours = d.draw(integers(min_value=0, max_value=23))
4305 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4306 dt = datetime(year, month, day, hours)
4307 fractions_sign = d.draw(sampled_from(" ,."))
4309 if fractions_sign != " ":
4310 fractions = random()
4311 if d.draw(booleans()):
4312 minutes = d.draw(integers(min_value=0, max_value=59))
4313 data += "%02d" % minutes
4314 dt += timedelta(seconds=60 * minutes)
4315 if d.draw(booleans()):
4316 seconds = d.draw(integers(min_value=0, max_value=59))
4317 data += "%02d" % seconds
4318 dt += timedelta(seconds=seconds)
4319 if fractions is not None:
4320 dt += timedelta(microseconds=10**6 * fractions)
4321 elif fractions is not None:
4322 dt += timedelta(seconds=60 * fractions)
4323 elif fractions is not None:
4324 dt += timedelta(seconds=3600 * fractions)
4325 if fractions is not None:
4326 data += fractions_sign + str(fractions)[2:]
4327 if d.draw(booleans()):
4329 elif d.draw(booleans()):
4330 offset_hour = d.draw(integers(min_value=0, max_value=13))
4332 if d.draw(booleans()):
4337 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4338 data += "%02d" % offset_hour
4339 minutes_separator = d.draw(sampled_from((None, "", ":")))
4340 if minutes_separator is not None:
4341 offset_minute = d.draw(integers(min_value=0, max_value=59))
4342 dt -= timedelta(seconds=sign * 60 * offset_minute)
4343 data += "%s%02d" % (minutes_separator, offset_minute)
4344 data = data.encode("ascii")
4345 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4347 GeneralizedTime().decod(data_der)
4352 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4355 mktime(obj.todatetime().timetuple()),
4356 mktime(dt.timetuple()),
4359 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4360 self.assertEqual(obj.ber_encoded, not dered)
4361 self.assertEqual(obj.bered, not dered)
4362 self.assertEqual(obj.ber_raw, None if dered else data)
4363 self.assertEqual(obj.encode() == data_der, dered)
4368 def test_invalid_ber(self):
4370 # "00010203040506.07",
4371 "-0010203040506.07",
4372 "0001-203040506.07",
4373 "000102-3040506.07",
4374 "00010203-40506.07",
4375 "0001020304-506.07",
4376 "000102030405-6.07",
4377 "00010203040506.-7",
4378 "+0010203040506.07",
4379 "0001+203040506.07",
4380 "000102+3040506.07",
4381 "00010203+40506.07",
4382 "0001020304+506.07",
4383 "000102030405+6.07",
4384 "00010203040506.+7",
4385 " 0010203040506.07",
4386 "0001 203040506.07",
4387 "000102 3040506.07",
4388 "00010203 40506.07",
4389 "0001020304 506.07",
4390 "000102030405 6.07",
4391 "00010203040506. 7",
4392 "001 0203040506.07",
4393 "00012 03040506.07",
4394 "0001023 040506.07",
4395 "000102034 0506.07",
4396 "00010203045 06.07",
4397 "0001020304056 .07",
4398 "00010203040506.7 ",
4478 "00010203040506.07+15",
4479 "00010203040506.07-15",
4480 "00010203040506.07+14:60",
4481 "00010203040506.07+1460",
4482 "00010203040506.07-1460",
4483 "00010203040506.07+00:60",
4484 "00010203040506.07-00:60",
4486 "00010203040506+15",
4487 "00010203040506-15",
4488 "00010203040506+14:60",
4489 "00010203040506+1460",
4490 "00010203040506-1460",
4491 "00010203040506+00:60",
4492 "00010203040506-00:60",
4501 with self.assertRaises(DecodeError):
4502 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4503 data = data.replace(".", ",")
4504 with self.assertRaises(DecodeError):
4505 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4509 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4510 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4512 binary(min_size=1, max_size=1),
4514 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4515 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4518 def test_junk(self, part0, part1, part2):
4519 junk = part0 + part1 + part2
4520 assume(not (set(junk) <= set(digits.encode("ascii"))))
4521 with self.assertRaises(DecodeError):
4522 GeneralizedTime().decode(
4523 GeneralizedTime.tag_default +
4524 len_encode(len(junk)) +
4530 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4531 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4533 binary(min_size=1, max_size=1),
4535 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4536 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4539 def test_junk_dm(self, part0, part1, part2):
4540 junk = part0 + part1 + part2
4541 assume(not (set(junk) <= set(digits.encode("ascii"))))
4542 with self.assertRaises(DecodeError):
4543 GeneralizedTime().decode(
4544 GeneralizedTime.tag_default +
4545 len_encode(len(junk)) +
4549 def test_ns_fractions(self):
4550 GeneralizedTime(b"20010101000000.000001Z")
4551 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4552 GeneralizedTime(b"20010101000000.0000001Z")
4554 def test_non_pure_integers(self):
4556 # b"20000102030405Z,
4563 b"20000102030405.+6Z",
4564 b"20000102030405.-6Z",
4571 b"20000102030405._6Z",
4572 b"20000102030405.6_Z",
4579 b"20000102030405. 6Z",
4586 b"20000102030405.6 Z",
4588 with self.assertRaises(DecodeError):
4589 GeneralizedTime(data)
4592 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4593 base_klass = UTCTime
4595 min_datetime = datetime(2000, 1, 1)
4596 max_datetime = datetime(2049, 12, 31)
4597 evgen_mode_skip_value = False
4599 def additional_symmetric_check(self, value, obj_encoded):
4602 def test_repr_not_ready(self):
4603 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4606 def test_x690_vector_valid(self):
4614 def test_x690_vector_invalid(self):
4619 with self.assertRaises(DecodeError) as err:
4623 def test_go_vectors_invalid(self):
4649 # These ones are INVALID in *DER*, but accepted
4650 # by Go's encoding/asn1
4651 b"910506164540-0700",
4652 b"910506164540+0730",
4656 with self.assertRaises(DecodeError) as err:
4660 def test_go_vectors_valid(self):
4662 UTCTime(b"910506234540Z").todatetime(),
4663 datetime(1991, 5, 6, 23, 45, 40, 0),
4666 def test_non_pure_integers(self):
4695 with self.assertRaises(DecodeError):
4698 def test_x680_vector_valid_ber(self):
4700 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4701 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4702 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4703 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4705 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4706 obj = UTCTime().decod(data_der, ctx={"bered": True})
4707 self.assertEqual(obj, dt)
4708 self.assertEqual(obj.todatetime(), dt)
4709 self.assertTrue(obj.ber_encoded)
4710 self.assertTrue(obj.bered)
4711 self.assertEqual(obj.ber_raw, data)
4712 self.assertNotEqual(obj.encode(), data_der)
4715 def test_go_vectors_valid_ber(self):
4717 b"910506164540-0700",
4718 b"910506164540+0730",
4722 data = UTCTime.tag_default + len_encode(len(data)) + data
4723 obj = UTCTime().decod(data, ctx={"bered": True})
4724 self.assertTrue(obj.ber_encoded)
4725 self.assertTrue(obj.bered)
4726 self.assertNotEqual(obj.encode(), data)
4729 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4730 @given(data_strategy())
4731 def test_valid_ber(self, d):
4732 year = d.draw(integers(min_value=0, max_value=99))
4733 month = d.draw(integers(min_value=1, max_value=12))
4734 day = d.draw(integers(min_value=1, max_value=28))
4735 hours = d.draw(integers(min_value=0, max_value=23))
4736 minute = d.draw(integers(min_value=0, max_value=59))
4737 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4739 year + (2000 if year < 50 else 1900),
4746 if d.draw(booleans()):
4748 seconds = d.draw(integers(min_value=0, max_value=59))
4749 data += "%02d" % seconds
4750 dt += timedelta(seconds=seconds)
4751 if d.draw(booleans()):
4755 offset_hour = d.draw(integers(min_value=0, max_value=13))
4756 offset_minute = d.draw(integers(min_value=0, max_value=59))
4757 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4758 if d.draw(booleans()):
4764 data += "%02d%02d" % (offset_hour, offset_minute)
4765 data = data.encode("ascii")
4766 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4767 obj = UTCTime().decod(data_der, ctx={"bered": True})
4768 self.assertEqual(obj, dt)
4769 self.assertEqual(obj.todatetime(), dt)
4770 self.assertEqual(obj.ber_encoded, not dered)
4771 self.assertEqual(obj.bered, not dered)
4772 self.assertEqual(obj.ber_raw, None if dered else data)
4773 self.assertEqual(obj.encode() == data_der, dered)
4778 def test_invalid_ber(self):
4819 b"0001020304+0000Z",
4828 with self.assertRaises(DecodeError):
4829 UTCTime(data, ctx={"bered": True})
4830 data = data[:8] + data[8+2:]
4831 with self.assertRaises(DecodeError):
4832 UTCTime(data, ctx={"bered": True})
4877 b"000102030405+000",
4878 b"000102030405+000Z",
4879 b"000102030405+0000Z",
4880 b"000102030405+-101",
4881 b"000102030405+01-1",
4882 b"000102030405+0060",
4883 b"000102030405+1401",
4884 b"500101000002+0003",
4886 with self.assertRaises(DecodeError):
4887 UTCTime(data, ctx={"bered": True})
4889 @given(integers(min_value=0, max_value=49))
4890 def test_pre50(self, year):
4892 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4896 @given(integers(min_value=50, max_value=99))
4897 def test_post50(self, year):
4899 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4905 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4906 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4908 binary(min_size=1, max_size=1),
4910 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4911 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4914 def test_junk(self, part0, part1, part2):
4915 junk = part0 + part1 + part2
4916 assume(not (set(junk) <= set(digits.encode("ascii"))))
4917 with self.assertRaises(DecodeError):
4919 UTCTime.tag_default +
4920 len_encode(len(junk)) +
4926 def tlv_value_strategy(draw):
4927 tag_num = draw(integers(min_value=1))
4928 data = draw(binary())
4929 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
4933 def any_values_strategy(draw, do_expl=False):
4934 value = draw(one_of(none(), tlv_value_strategy()))
4937 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4938 optional = draw(one_of(none(), booleans()))
4940 draw(integers(min_value=0)),
4941 draw(integers(min_value=0)),
4942 draw(integers(min_value=0)),
4944 return (value, expl, optional, _decoded)
4947 class AnyInherited(Any):
4951 class TestAny(CommonMixin, TestCase):
4954 def test_invalid_value_type(self):
4955 with self.assertRaises(InvalidValueType) as err:
4960 def test_optional(self, optional):
4961 obj = Any(optional=optional)
4962 self.assertEqual(obj.optional, optional)
4964 @given(tlv_value_strategy())
4965 def test_ready(self, value):
4967 self.assertFalse(obj.ready)
4970 pprint(obj, big_blobs=True, with_decode_path=True)
4971 with self.assertRaises(ObjNotReady) as err:
4975 self.assertTrue(obj.ready)
4978 pprint(obj, big_blobs=True, with_decode_path=True)
4981 def test_basic(self, value):
4982 integer_encoded = Integer(value).encode()
4984 Any(integer_encoded),
4985 Any(Integer(value)),
4986 Any(Any(Integer(value))),
4988 self.assertSequenceEqual(bytes(obj), integer_encoded)
4990 obj.decode(obj.encode())[0].vlen,
4991 len(integer_encoded),
4995 pprint(obj, big_blobs=True, with_decode_path=True)
4996 self.assertSequenceEqual(obj.encode(), integer_encoded)
4998 @given(tlv_value_strategy(), tlv_value_strategy())
4999 def test_comparison(self, value1, value2):
5000 for klass in (Any, AnyInherited):
5001 obj1 = klass(value1)
5002 obj2 = klass(value2)
5003 self.assertEqual(obj1 == obj2, value1 == value2)
5004 self.assertEqual(obj1 != obj2, value1 != value2)
5005 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5007 @given(data_strategy())
5008 def test_call(self, d):
5009 for klass in (Any, AnyInherited):
5015 ) = d.draw(any_values_strategy())
5016 obj_initial = klass(
5019 optional_initial or False,
5027 ) = d.draw(any_values_strategy(do_expl=True))
5028 obj = obj_initial(value, expl, optional)
5030 value_expected = None if value is None else value
5031 self.assertEqual(obj, value_expected)
5032 self.assertEqual(obj.expl_tag, expl or expl_initial)
5033 if obj.default is None:
5034 optional = optional_initial if optional is None else optional
5035 optional = False if optional is None else optional
5036 self.assertEqual(obj.optional, optional)
5038 def test_simultaneous_impl_expl(self):
5039 # override it, as Any does not have implicit tag
5042 def test_decoded(self):
5043 # override it, as Any does not have implicit tag
5046 @given(any_values_strategy())
5047 def test_copy(self, values):
5048 for klass in (Any, AnyInherited):
5049 obj = klass(*values)
5050 for copy_func in copy_funcs:
5051 obj_copied = copy_func(obj)
5052 self.assert_copied_basic_fields(obj, obj_copied)
5053 self.assertEqual(obj._value, obj_copied._value)
5055 @given(binary().map(OctetString))
5056 def test_stripped(self, value):
5058 with self.assertRaises(NotEnoughData):
5059 obj.decode(obj.encode()[:-1])
5062 tlv_value_strategy(),
5063 integers(min_value=1).map(tag_ctxc),
5065 def test_stripped_expl(self, value, tag_expl):
5066 obj = Any(value, expl=tag_expl)
5067 with self.assertRaises(NotEnoughData):
5068 obj.decode(obj.encode()[:-1])
5071 integers(min_value=31),
5072 integers(min_value=0),
5075 def test_bad_tag(self, tag, offset, decode_path):
5076 with self.assertRaises(DecodeError) as err:
5078 tag_encode(tag)[:-1],
5080 decode_path=decode_path,
5083 self.assertEqual(err.exception.offset, offset)
5084 self.assertEqual(err.exception.decode_path, decode_path)
5087 integers(min_value=128),
5088 integers(min_value=0),
5091 def test_bad_len(self, l, offset, decode_path):
5092 with self.assertRaises(DecodeError) as err:
5094 Any.tag_default + len_encode(l)[:-1],
5096 decode_path=decode_path,
5099 self.assertEqual(err.exception.offset, offset)
5100 self.assertEqual(err.exception.decode_path, decode_path)
5102 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5104 any_values_strategy(),
5105 integers().map(lambda x: Integer(x).encode()),
5106 integers(min_value=1).map(tag_ctxc),
5107 integers(min_value=0),
5111 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5112 for klass in (Any, AnyInherited):
5113 _, _, optional, _decoded = values
5114 obj = klass(value=value, optional=optional, _decoded=_decoded)
5117 pprint(obj, big_blobs=True, with_decode_path=True)
5118 self.assertFalse(obj.expled)
5119 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5120 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5121 obj_encoded = obj.encode()
5122 obj_expled = obj(value, expl=tag_expl)
5123 self.assertTrue(obj_expled.expled)
5124 tag_class, _, tag_num = tag_decode(tag_expl)
5125 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5127 list(obj_expled.pps())
5128 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5129 obj_expled_encoded = obj_expled.encode()
5130 ctx_copied = deepcopy(ctx_dummy)
5131 obj_decoded, tail = obj_expled.decode(
5132 obj_expled_encoded + tail_junk,
5136 self.assertDictEqual(ctx_copied, ctx_dummy)
5138 list(obj_decoded.pps())
5139 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5140 self.assertEqual(tail, tail_junk)
5141 self.assertEqual(obj_decoded, obj_expled)
5142 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5143 self.assertEqual(bytes(obj_decoded), bytes(obj))
5144 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5145 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5146 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5148 obj_decoded.expl_llen,
5149 len(len_encode(len(obj_encoded))),
5151 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5152 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5155 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5157 self.assertEqual(obj_decoded.expl_offset, offset)
5158 self.assertEqual(obj_decoded.tlen, 0)
5159 self.assertEqual(obj_decoded.llen, 0)
5160 self.assertEqual(obj_decoded.vlen, len(value))
5161 assert_exceeding_data(
5163 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5167 evgens = list(obj_expled.decode_evgen(
5168 obj_expled_encoded + tail_junk,
5170 decode_path=decode_path,
5173 self.assertEqual(len(evgens), 1)
5174 _decode_path, obj, tail = evgens[0]
5175 self.assertSequenceEqual(tail, tail_junk)
5176 self.assertEqual(_decode_path, decode_path)
5177 self.assertEqual(obj.expl_offset, offset)
5182 integers(min_value=1).map(tag_ctxc),
5183 integers(min_value=0, max_value=3),
5184 integers(min_value=0),
5188 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5189 chunk = Boolean(False, expl=expl).encode()
5191 OctetString.tag_default +
5193 b"".join([chunk] * chunks) +
5196 with self.assertRaises(LenIndefForm):
5200 decode_path=decode_path,
5202 obj, tail = Any().decode(
5205 decode_path=decode_path,
5206 ctx={"bered": True},
5208 self.assertSequenceEqual(tail, junk)
5209 self.assertEqual(obj.offset, offset)
5210 self.assertEqual(obj.tlvlen, len(encoded))
5211 self.assertTrue(obj.lenindef)
5212 self.assertFalse(obj.ber_encoded)
5213 self.assertTrue(obj.bered)
5215 self.assertTrue(obj.lenindef)
5216 self.assertFalse(obj.ber_encoded)
5217 self.assertTrue(obj.bered)
5220 pprint(obj, big_blobs=True, with_decode_path=True)
5221 with self.assertRaises(NotEnoughData) as err:
5225 decode_path=decode_path,
5226 ctx={"bered": True},
5228 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5229 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5231 class SeqOf(SequenceOf):
5232 schema = Boolean(expl=expl)
5234 class Seq(Sequence):
5236 ("type", ObjectIdentifier(defines=((("value",), {
5237 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5242 ("type", ObjectIdentifier("1.2.3")),
5243 ("value", Any(encoded)),
5245 seq_encoded = seq.encode()
5246 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5247 self.assertIsNotNone(seq_decoded["value"].defined)
5249 list(seq_decoded.pps())
5250 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5251 self.assertTrue(seq_decoded.bered)
5252 self.assertFalse(seq_decoded["type"].bered)
5253 self.assertTrue(seq_decoded["value"].bered)
5255 chunk = chunk[:-1] + b"\x01"
5256 chunks = b"".join([chunk] * (chunks + 1))
5257 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5259 ("type", ObjectIdentifier("1.2.3")),
5260 ("value", Any(encoded)),
5262 seq_encoded = seq.encode()
5263 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5264 self.assertIsNotNone(seq_decoded["value"].defined)
5266 list(seq_decoded.pps())
5267 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5268 self.assertTrue(seq_decoded.bered)
5269 self.assertFalse(seq_decoded["type"].bered)
5270 self.assertTrue(seq_decoded["value"].bered)
5274 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5276 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5277 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5279 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5280 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5282 min_size=len(names),
5283 max_size=len(names),
5286 (name, Integer(**tag_kwargs))
5287 for name, tag_kwargs in zip(names, tags)
5290 if value_required or draw(booleans()):
5291 value = draw(tuples(
5292 sampled_from([name for name, _ in schema]),
5293 integers().map(Integer),
5297 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5298 default = draw(one_of(
5300 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5302 optional = draw(one_of(none(), booleans()))
5304 draw(integers(min_value=0)),
5305 draw(integers(min_value=0)),
5306 draw(integers(min_value=0)),
5308 return (schema, value, expl, default, optional, _decoded)
5311 class ChoiceInherited(Choice):
5315 class TestChoice(CommonMixin, TestCase):
5317 schema = (("whatever", Boolean()),)
5320 def test_schema_required(self):
5321 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5324 def test_impl_forbidden(self):
5325 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5326 Choice(impl=b"whatever")
5328 def test_invalid_value_type(self):
5329 with self.assertRaises(InvalidValueType) as err:
5330 self.base_klass(123)
5332 with self.assertRaises(ObjUnknown) as err:
5333 self.base_klass(("whenever", Boolean(False)))
5335 with self.assertRaises(InvalidValueType) as err:
5336 self.base_klass(("whatever", Integer(123)))
5340 def test_optional(self, optional):
5341 obj = self.base_klass(
5342 default=self.base_klass(("whatever", Boolean(False))),
5345 self.assertTrue(obj.optional)
5348 def test_ready(self, value):
5349 obj = self.base_klass()
5350 self.assertFalse(obj.ready)
5353 pprint(obj, big_blobs=True, with_decode_path=True)
5354 self.assertIsNone(obj["whatever"])
5355 with self.assertRaises(ObjNotReady) as err:
5358 obj["whatever"] = Boolean()
5359 self.assertFalse(obj.ready)
5362 pprint(obj, big_blobs=True, with_decode_path=True)
5363 obj["whatever"] = Boolean(value)
5364 self.assertTrue(obj.ready)
5367 pprint(obj, big_blobs=True, with_decode_path=True)
5369 @given(booleans(), booleans())
5370 def test_comparison(self, value1, value2):
5371 class WahlInherited(self.base_klass):
5373 for klass in (self.base_klass, WahlInherited):
5374 obj1 = klass(("whatever", Boolean(value1)))
5375 obj2 = klass(("whatever", Boolean(value2)))
5376 self.assertEqual(obj1 == obj2, value1 == value2)
5377 self.assertEqual(obj1 != obj2, value1 != value2)
5378 self.assertEqual(obj1 == obj2._value, value1 == value2)
5379 self.assertFalse(obj1 == obj2._value[1])
5381 @given(data_strategy())
5382 def test_call(self, d):
5383 for klass in (Choice, ChoiceInherited):
5391 ) = d.draw(choice_values_strategy())
5394 schema = schema_initial
5396 value=value_initial,
5398 default=default_initial,
5399 optional=optional_initial or False,
5400 _decoded=_decoded_initial,
5409 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5410 obj = obj_initial(value, expl, default, optional)
5412 value_expected = default if value is None else value
5414 default_initial if value_expected is None
5417 self.assertEqual(obj.choice, value_expected[0])
5418 self.assertEqual(obj.value, int(value_expected[1]))
5419 self.assertEqual(obj.expl_tag, expl or expl_initial)
5420 default_expect = default_initial if default is None else default
5421 if default_expect is not None:
5422 self.assertEqual(obj.default.choice, default_expect[0])
5423 self.assertEqual(obj.default.value, int(default_expect[1]))
5424 if obj.default is None:
5425 optional = optional_initial if optional is None else optional
5426 optional = False if optional is None else optional
5429 self.assertEqual(obj.optional, optional)
5430 self.assertEqual(obj.specs, obj_initial.specs)
5432 def test_simultaneous_impl_expl(self):
5433 # override it, as Any does not have implicit tag
5436 def test_decoded(self):
5437 # override it, as Any does not have implicit tag
5440 @given(choice_values_strategy())
5441 def test_copy(self, values):
5442 _schema, value, expl, default, optional, _decoded = values
5444 class Wahl(self.base_klass):
5446 register_class(Wahl)
5451 optional=optional or False,
5454 for copy_func in copy_funcs:
5455 obj_copied = copy_func(obj)
5456 self.assertIsNone(obj.tag)
5457 self.assertIsNone(obj_copied.tag)
5458 # hack for assert_copied_basic_fields
5459 obj.tag = "whatever"
5460 obj_copied.tag = "whatever"
5461 self.assert_copied_basic_fields(obj, obj_copied)
5463 self.assertEqual(obj._value, obj_copied._value)
5464 self.assertEqual(obj.specs, obj_copied.specs)
5467 def test_stripped(self, value):
5468 obj = self.base_klass(("whatever", Boolean(value)))
5469 with self.assertRaises(NotEnoughData):
5470 obj.decode(obj.encode()[:-1])
5474 integers(min_value=1).map(tag_ctxc),
5476 def test_stripped_expl(self, value, tag_expl):
5477 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5478 with self.assertRaises(NotEnoughData):
5479 obj.decode(obj.encode()[:-1])
5481 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5482 @given(data_strategy())
5483 def test_symmetric(self, d):
5484 _schema, value, _, default, optional, _decoded = d.draw(
5485 choice_values_strategy(value_required=True)
5487 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5488 offset = d.draw(integers(min_value=0))
5489 tail_junk = d.draw(binary(max_size=5))
5490 decode_path = d.draw(decode_path_strat)
5492 class Wahl(self.base_klass):
5502 pprint(obj, big_blobs=True, with_decode_path=True)
5503 self.assertFalse(obj.expled)
5504 self.assertEqual(obj.tag_order, obj.value.tag_order)
5505 obj_encoded = obj.encode()
5506 obj_expled = obj(value, expl=tag_expl)
5507 self.assertTrue(obj_expled.expled)
5508 tag_class, _, tag_num = tag_decode(tag_expl)
5509 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5511 list(obj_expled.pps())
5512 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5513 obj_expled_encoded = obj_expled.encode()
5514 ctx_copied = deepcopy(ctx_dummy)
5515 obj_decoded, tail = obj_expled.decode(
5516 obj_expled_encoded + tail_junk,
5520 self.assertDictEqual(ctx_copied, ctx_dummy)
5522 list(obj_decoded.pps())
5523 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5524 self.assertEqual(tail, tail_junk)
5525 self.assertEqual(obj_decoded, obj_expled)
5526 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5527 self.assertEqual(obj_decoded.value, obj_expled.value)
5528 self.assertEqual(obj_decoded.choice, obj.choice)
5529 self.assertEqual(obj_decoded.value, obj.value)
5530 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5531 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5532 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5534 obj_decoded.expl_llen,
5535 len(len_encode(len(obj_encoded))),
5537 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5538 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5541 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5543 self.assertEqual(obj_decoded.expl_offset, offset)
5544 self.assertSequenceEqual(
5546 obj_decoded.value.fulloffset - offset:
5547 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5551 assert_exceeding_data(
5553 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5557 evgens = list(obj_expled.decode_evgen(
5558 obj_expled_encoded + tail_junk,
5560 decode_path=decode_path,
5563 self.assertEqual(len(evgens), 2)
5564 _decode_path, obj, tail = evgens[0]
5565 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5566 _decode_path, obj, tail = evgens[1]
5567 self.assertSequenceEqual(tail, tail_junk)
5568 self.assertEqual(_decode_path, decode_path)
5569 self.assertEqual(obj.expl_offset, offset)
5574 def test_set_get(self, value):
5577 ("erste", Boolean()),
5578 ("zweite", Integer()),
5581 with self.assertRaises(ObjUnknown) as err:
5582 obj["whatever"] = "whenever"
5583 with self.assertRaises(InvalidValueType) as err:
5584 obj["zweite"] = Boolean(False)
5585 obj["zweite"] = Integer(value)
5587 with self.assertRaises(ObjUnknown) as err:
5590 self.assertIsNone(obj["erste"])
5591 self.assertEqual(obj["zweite"], Integer(value))
5593 def test_tag_mismatch(self):
5596 ("erste", Boolean()),
5598 int_encoded = Integer(123).encode()
5599 bool_encoded = Boolean(False).encode()
5601 obj.decode(bool_encoded)
5602 with self.assertRaises(TagMismatch):
5603 obj.decode(int_encoded)
5605 def test_tag_mismatch_underlying(self):
5606 class SeqOfBoolean(SequenceOf):
5609 class SeqOfInteger(SequenceOf):
5614 ("erste", SeqOfBoolean()),
5617 int_encoded = SeqOfInteger((Integer(123),)).encode()
5618 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5620 obj.decode(bool_encoded)
5621 with self.assertRaises(TagMismatch) as err:
5622 obj.decode(int_encoded)
5623 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5627 def seq_values_strategy(draw, seq_klass, do_expl=False):
5629 if draw(booleans()):
5631 value._value = draw(dictionaries(
5634 booleans().map(Boolean),
5635 integers().map(Integer),
5639 if draw(booleans()):
5640 schema = list(draw(dictionaries(
5643 booleans().map(Boolean),
5644 integers().map(Integer),
5650 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5652 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5654 if draw(booleans()):
5655 default = seq_klass()
5656 default._value = draw(dictionaries(
5659 booleans().map(Boolean),
5660 integers().map(Integer),
5663 optional = draw(one_of(none(), booleans()))
5665 draw(integers(min_value=0)),
5666 draw(integers(min_value=0)),
5667 draw(integers(min_value=0)),
5669 return (value, schema, impl, expl, default, optional, _decoded)
5673 def sequence_strategy(draw, seq_klass):
5674 inputs = draw(lists(
5676 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5677 tuples(just(Integer), integers(), one_of(none(), integers())),
5682 integers(min_value=1),
5683 min_size=len(inputs),
5684 max_size=len(inputs),
5687 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5688 for tag, expled in zip(tags, draw(lists(
5690 min_size=len(inputs),
5691 max_size=len(inputs),
5695 for i, optional in enumerate(draw(lists(
5696 sampled_from(("required", "optional", "empty")),
5697 min_size=len(inputs),
5698 max_size=len(inputs),
5700 if optional in ("optional", "empty"):
5701 inits[i]["optional"] = True
5702 if optional == "empty":
5704 empties = set(empties)
5705 names = list(draw(sets(
5707 min_size=len(inputs),
5708 max_size=len(inputs),
5711 for i, (klass, value, default) in enumerate(inputs):
5712 schema.append((names[i], klass(default=default, **inits[i])))
5713 seq_name = draw(text_letters())
5714 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5717 for i, (klass, value, default) in enumerate(inputs):
5724 "default_value": None if spec.default is None else default,
5728 expect["optional"] = True
5730 expect["presented"] = True
5731 expect["value"] = value
5733 expect["optional"] = True
5734 if default is not None and default == value:
5735 expect["presented"] = False
5736 seq[name] = klass(value)
5737 expects.append(expect)
5742 def sequences_strategy(draw, seq_klass):
5743 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5745 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5746 for tag, expled in zip(tags, draw(lists(
5753 i for i, is_default in enumerate(draw(lists(
5759 names = list(draw(sets(
5764 seq_expectses = draw(lists(
5765 sequence_strategy(seq_klass=seq_klass),
5769 seqs = [seq for seq, _ in seq_expectses]
5771 for i, (name, seq) in enumerate(zip(names, seqs)):
5774 seq(default=(seq if i in defaulted else None), **inits[i]),
5776 seq_name = draw(text_letters())
5777 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5780 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5783 "expects": expects_inner,
5786 seq_outer[name] = seq_inner
5787 if seq_outer.specs[name].default is None:
5788 expect["presented"] = True
5789 expect_outers.append(expect)
5790 return seq_outer, expect_outers
5793 class SeqMixing(object):
5794 def test_invalid_value_type(self):
5795 with self.assertRaises(InvalidValueType) as err:
5796 self.base_klass(123)
5799 def test_invalid_value_type_set(self):
5800 class Seq(self.base_klass):
5801 schema = (("whatever", Boolean()),)
5803 with self.assertRaises(InvalidValueType) as err:
5804 seq["whatever"] = Integer(123)
5808 def test_optional(self, optional):
5809 obj = self.base_klass(default=self.base_klass(), optional=optional)
5810 self.assertTrue(obj.optional)
5812 @given(data_strategy())
5813 def test_ready(self, d):
5815 str(i): v for i, v in enumerate(d.draw(lists(
5822 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5829 for name in d.draw(permutations(
5830 list(ready.keys()) + list(non_ready.keys()),
5832 schema_input.append((name, Boolean()))
5834 class Seq(self.base_klass):
5835 schema = tuple(schema_input)
5837 for name in ready.keys():
5839 seq[name] = Boolean()
5840 self.assertFalse(seq.ready)
5843 pprint(seq, big_blobs=True, with_decode_path=True)
5844 for name, value in ready.items():
5845 seq[name] = Boolean(value)
5846 self.assertFalse(seq.ready)
5849 pprint(seq, big_blobs=True, with_decode_path=True)
5850 with self.assertRaises(ObjNotReady) as err:
5853 for name, value in non_ready.items():
5854 seq[name] = Boolean(value)
5855 self.assertTrue(seq.ready)
5858 pprint(seq, big_blobs=True, with_decode_path=True)
5860 @given(data_strategy())
5861 def test_call(self, d):
5862 class SeqInherited(self.base_klass):
5864 for klass in (self.base_klass, SeqInherited):
5873 ) = d.draw(seq_values_strategy(seq_klass=klass))
5874 obj_initial = klass(
5880 optional_initial or False,
5891 ) = d.draw(seq_values_strategy(
5893 do_expl=impl_initial is None,
5895 obj = obj_initial(value, impl, expl, default, optional)
5896 value_expected = default if value is None else value
5898 default_initial if value_expected is None
5901 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
5902 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
5903 self.assertEqual(obj.expl_tag, expl or expl_initial)
5905 {} if obj.default is None else obj.default._value,
5906 getattr(default_initial if default is None else default, "_value", {}),
5908 if obj.default is None:
5909 optional = optional_initial if optional is None else optional
5910 optional = False if optional is None else optional
5913 self.assertEqual(list(obj.specs.items()), schema_initial or [])
5914 self.assertEqual(obj.optional, optional)
5916 @given(data_strategy())
5917 def test_copy(self, d):
5918 class SeqInherited(self.base_klass):
5920 register_class(SeqInherited)
5921 for klass in (self.base_klass, SeqInherited):
5922 values = d.draw(seq_values_strategy(seq_klass=klass))
5923 obj = klass(*values)
5924 for copy_func in copy_funcs:
5925 obj_copied = copy_func(obj)
5926 self.assert_copied_basic_fields(obj, obj_copied)
5927 self.assertEqual(obj.specs, obj_copied.specs)
5928 self.assertEqual(obj._value, obj_copied._value)
5930 @given(data_strategy())
5931 def test_stripped(self, d):
5932 value = d.draw(integers())
5933 tag_impl = tag_encode(d.draw(integers(min_value=1)))
5935 class Seq(self.base_klass):
5937 schema = (("whatever", Integer()),)
5939 seq["whatever"] = Integer(value)
5940 with self.assertRaises(NotEnoughData):
5941 seq.decode(seq.encode()[:-1])
5943 @given(data_strategy())
5944 def test_stripped_expl(self, d):
5945 value = d.draw(integers())
5946 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5948 class Seq(self.base_klass):
5950 schema = (("whatever", Integer()),)
5952 seq["whatever"] = Integer(value)
5953 with self.assertRaises(NotEnoughData):
5954 seq.decode(seq.encode()[:-1])
5956 @given(integers(min_value=3), binary(min_size=2))
5957 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
5958 junk = tag_encode(junk_tag_num) + junk
5960 _, _, len_encoded = tag_strip(memoryview(junk))
5961 len_decode(len_encoded)
5967 class Seq(self.base_klass):
5969 ("whatever", Integer()),
5971 ("whenever", Integer()),
5974 seq["whatever"] = Integer(123)
5975 seq["junk"] = Any(junk)
5976 seq["whenever"] = Integer(123)
5977 with self.assertRaises(DecodeError):
5978 seq.decode(seq.encode())
5981 integers(min_value=31),
5982 integers(min_value=0),
5985 def test_bad_tag(self, tag, offset, decode_path):
5986 with self.assertRaises(DecodeError) as err:
5987 self.base_klass().decode(
5988 tag_encode(tag)[:-1],
5990 decode_path=decode_path,
5993 self.assertEqual(err.exception.offset, offset)
5994 self.assertEqual(err.exception.decode_path, decode_path)
5997 integers(min_value=128),
5998 integers(min_value=0),
6001 def test_bad_len(self, l, offset, decode_path):
6002 with self.assertRaises(DecodeError) as err:
6003 self.base_klass().decode(
6004 self.base_klass.tag_default + len_encode(l)[:-1],
6006 decode_path=decode_path,
6009 self.assertEqual(err.exception.offset, offset)
6010 self.assertEqual(err.exception.decode_path, decode_path)
6012 def _assert_expects(self, seq, expects):
6013 for expect in expects:
6015 seq.specs[expect["name"]].optional,
6018 if expect["default_value"] is not None:
6020 seq.specs[expect["name"]].default,
6021 expect["default_value"],
6023 if expect["presented"]:
6024 self.assertIn(expect["name"], seq)
6025 self.assertEqual(seq[expect["name"]], expect["value"])
6027 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6028 @given(data_strategy())
6029 def test_symmetric(self, d):
6030 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6031 tail_junk = d.draw(binary(max_size=5))
6032 decode_path = d.draw(decode_path_strat)
6033 self.assertTrue(seq.ready)
6034 self.assertFalse(seq.decoded)
6035 self._assert_expects(seq, expects)
6038 pprint(seq, big_blobs=True, with_decode_path=True)
6039 self.assertTrue(seq.ready)
6040 seq_encoded = seq.encode()
6041 seq_encoded_cer = encode_cer(seq)
6042 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6043 self.assertSequenceEqual(
6044 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6047 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6048 self.assertFalse(seq_decoded.lenindef)
6049 self.assertFalse(seq_decoded.ber_encoded)
6050 self.assertFalse(seq_decoded.bered)
6052 t, _, lv = tag_strip(seq_encoded)
6053 _, _, v = len_decode(lv)
6054 seq_encoded_lenindef = t + LENINDEF + v + EOC
6055 with self.assertRaises(DecodeError):
6056 seq.decode(seq_encoded_lenindef)
6057 ctx_copied = deepcopy(ctx_dummy)
6058 ctx_copied["bered"] = True
6059 seq_decoded_lenindef, tail_lenindef = seq.decode(
6060 seq_encoded_lenindef + tail_junk,
6063 del ctx_copied["bered"]
6064 self.assertDictEqual(ctx_copied, ctx_dummy)
6065 self.assertTrue(seq_decoded_lenindef.lenindef)
6066 self.assertTrue(seq_decoded_lenindef.bered)
6067 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6068 self.assertTrue(seq_decoded_lenindef.lenindef)
6069 self.assertTrue(seq_decoded_lenindef.bered)
6070 with self.assertRaises(DecodeError):
6071 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6072 with self.assertRaises(DecodeError):
6073 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6074 repr(seq_decoded_lenindef)
6075 list(seq_decoded_lenindef.pps())
6076 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6077 self.assertTrue(seq_decoded_lenindef.ready)
6079 for decoded, decoded_tail, encoded in (
6080 (seq_decoded, tail, seq_encoded),
6081 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6083 self.assertEqual(decoded_tail, tail_junk)
6084 self._assert_expects(decoded, expects)
6085 self.assertEqual(seq, decoded)
6086 self.assertEqual(decoded.encode(), seq_encoded)
6087 self.assertEqual(decoded.tlvlen, len(encoded))
6088 for expect in expects:
6089 if not expect["presented"]:
6090 self.assertNotIn(expect["name"], decoded)
6092 self.assertIn(expect["name"], decoded)
6093 obj = decoded[expect["name"]]
6094 self.assertTrue(obj.decoded)
6095 offset = obj.expl_offset if obj.expled else obj.offset
6096 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6097 self.assertSequenceEqual(
6098 seq_encoded[offset:offset + tlvlen],
6102 evgens = list(seq.decode_evgen(
6103 encoded + decoded_tail,
6104 decode_path=decode_path,
6105 ctx={"bered": True},
6107 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6108 for _decode_path, obj, _ in evgens[:-1]:
6109 self.assertEqual(_decode_path[:-1], decode_path)
6112 _decode_path, obj, tail = evgens[-1]
6113 self.assertEqual(_decode_path, decode_path)
6117 assert_exceeding_data(
6119 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6123 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6124 @given(data_strategy())
6125 def test_symmetric_with_seq(self, d):
6126 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6127 self.assertTrue(seq.ready)
6128 seq_encoded = seq.encode()
6129 seq_decoded, tail = seq.decode(seq_encoded)
6130 self.assertEqual(tail, b"")
6131 self.assertTrue(seq.ready)
6132 self.assertEqual(seq, seq_decoded)
6133 self.assertEqual(seq_decoded.encode(), seq_encoded)
6134 for expect_outer in expect_outers:
6135 if not expect_outer["presented"]:
6136 self.assertNotIn(expect_outer["name"], seq_decoded)
6138 self.assertIn(expect_outer["name"], seq_decoded)
6139 obj = seq_decoded[expect_outer["name"]]
6140 self.assertTrue(obj.decoded)
6141 offset = obj.expl_offset if obj.expled else obj.offset
6142 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6143 self.assertSequenceEqual(
6144 seq_encoded[offset:offset + tlvlen],
6147 self._assert_expects(obj, expect_outer["expects"])
6149 @given(data_strategy())
6150 def test_default_disappears(self, d):
6151 _schema = list(d.draw(dictionaries(
6153 sets(integers(), min_size=2, max_size=2),
6157 class Seq(self.base_klass):
6159 (n, Integer(default=d))
6160 for n, (_, d) in _schema
6163 for name, (value, _) in _schema:
6164 seq[name] = Integer(value)
6165 self.assertEqual(len(seq._value), len(_schema))
6166 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6167 self.assertGreater(len(seq.encode()), len(empty_seq))
6168 for name, (_, default) in _schema:
6169 seq[name] = Integer(default)
6170 self.assertEqual(len(seq._value), 0)
6171 self.assertSequenceEqual(seq.encode(), empty_seq)
6173 @given(data_strategy())
6174 def test_encoded_default_not_accepted(self, d):
6175 _schema = list(d.draw(dictionaries(
6180 tags = [tag_encode(tag) for tag in d.draw(sets(
6181 integers(min_value=1),
6182 min_size=len(_schema),
6183 max_size=len(_schema),
6186 class SeqWithoutDefault(self.base_klass):
6188 (n, Integer(impl=t))
6189 for (n, _), t in zip(_schema, tags)
6191 seq_without_default = SeqWithoutDefault()
6192 for name, value in _schema:
6193 seq_without_default[name] = Integer(value)
6194 seq_encoded = seq_without_default.encode()
6196 class SeqWithDefault(self.base_klass):
6198 (n, Integer(default=v, impl=t))
6199 for (n, v), t in zip(_schema, tags)
6201 seq_with_default = SeqWithDefault()
6202 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6203 seq_with_default.decode(seq_encoded)
6204 for ctx in ({"bered": True}, {"allow_default_values": True}):
6205 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6206 self.assertTrue(seq_decoded.ber_encoded)
6207 self.assertTrue(seq_decoded.bered)
6208 seq_decoded = copy(seq_decoded)
6209 self.assertTrue(seq_decoded.ber_encoded)
6210 self.assertTrue(seq_decoded.bered)
6211 for name, value in _schema:
6212 self.assertEqual(seq_decoded[name], seq_with_default[name])
6213 self.assertEqual(seq_decoded[name], value)
6215 @given(data_strategy())
6216 def test_missing_from_spec(self, d):
6217 names = list(d.draw(sets(text_letters(), min_size=2)))
6218 tags = [tag_encode(tag) for tag in d.draw(sets(
6219 integers(min_value=1),
6220 min_size=len(names),
6221 max_size=len(names),
6223 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6225 class SeqFull(self.base_klass):
6226 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6227 seq_full = SeqFull()
6228 for i, name in enumerate(names):
6229 seq_full[name] = Integer(i)
6230 seq_encoded = seq_full.encode()
6231 altered = names_tags[:-2] + names_tags[-1:]
6233 class SeqMissing(self.base_klass):
6234 schema = [(n, Integer(impl=t)) for n, t in altered]
6235 seq_missing = SeqMissing()
6236 with self.assertRaises(TagMismatch):
6237 seq_missing.decode(seq_encoded)
6239 def test_bered(self):
6240 class Seq(self.base_klass):
6241 schema = (("underlying", Boolean()),)
6242 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6243 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6244 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6245 self.assertFalse(decoded.ber_encoded)
6246 self.assertFalse(decoded.lenindef)
6247 self.assertTrue(decoded.bered)
6248 decoded = copy(decoded)
6249 self.assertFalse(decoded.ber_encoded)
6250 self.assertFalse(decoded.lenindef)
6251 self.assertTrue(decoded.bered)
6253 class Seq(self.base_klass):
6254 schema = (("underlying", OctetString()),)
6256 tag_encode(form=TagFormConstructed, num=4) +
6258 OctetString(b"whatever").encode() +
6261 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6262 with self.assertRaises(DecodeError):
6263 Seq().decode(encoded)
6264 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6265 self.assertFalse(decoded.ber_encoded)
6266 self.assertFalse(decoded.lenindef)
6267 self.assertTrue(decoded.bered)
6268 decoded = copy(decoded)
6269 self.assertFalse(decoded.ber_encoded)
6270 self.assertFalse(decoded.lenindef)
6271 self.assertTrue(decoded.bered)
6274 class TestSequence(SeqMixing, CommonMixin, TestCase):
6275 base_klass = Sequence
6281 def test_remaining(self, value, junk):
6282 class Seq(Sequence):
6284 ("whatever", Integer()),
6286 int_encoded = Integer(value).encode()
6288 Sequence.tag_default,
6289 len_encode(len(int_encoded + junk)),
6292 with assertRaisesRegex(self, DecodeError, "remaining"):
6293 Seq().decode(junked)
6295 @given(sets(text_letters(), min_size=2))
6296 def test_obj_unknown(self, names):
6297 missing = names.pop()
6299 class Seq(Sequence):
6300 schema = [(n, Boolean()) for n in names]
6302 with self.assertRaises(ObjUnknown) as err:
6305 with self.assertRaises(ObjUnknown) as err:
6306 seq[missing] = Boolean()
6309 def test_x690_vector(self):
6310 class Seq(Sequence):
6312 ("name", IA5String()),
6315 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6316 self.assertEqual(seq["name"], "Smith")
6317 self.assertEqual(seq["ok"], True)
6320 class TestSet(SeqMixing, CommonMixin, TestCase):
6323 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6324 @given(data_strategy())
6325 def test_sorted(self, d):
6326 class DummySeq(Sequence):
6327 schema = (("null", Null()),)
6329 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6330 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6331 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6332 tag_nums -= set([dummy_seq_tag_num])
6333 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6334 _schema.append(("seq", DummySeq()))
6337 schema = d.draw(permutations(_schema))
6339 for name, _ in _schema:
6341 seq[name] = OctetString(name.encode("ascii"))
6342 seq["seq"] = DummySeq((("null", Null()),))
6344 seq_encoded = seq.encode()
6345 seq_decoded, _ = seq.decode(seq_encoded)
6346 seq_encoded_expected = []
6347 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6348 if tag_num == dummy_seq_tag_num:
6349 seq_encoded_expected.append(seq["seq"].encode())
6351 seq_encoded_expected.append(seq[str(tag_num)].encode())
6352 self.assertSequenceEqual(
6353 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6354 b"".join(seq_encoded_expected),
6357 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6358 encoded += seq["seq"].encode()
6359 seq_encoded = b"".join((
6361 len_encode(len(encoded)),
6364 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6365 seq.decode(seq_encoded)
6366 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6367 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6368 self.assertTrue(seq_decoded.ber_encoded)
6369 self.assertTrue(seq_decoded.bered)
6370 seq_decoded = copy(seq_decoded)
6371 self.assertTrue(seq_decoded.ber_encoded)
6372 self.assertTrue(seq_decoded.bered)
6374 def test_same_value_twice(self):
6377 ("bool", Boolean()),
6381 encoded = b"".join((
6382 Integer(123).encode(),
6383 Integer(234).encode(),
6384 Boolean(True).encode(),
6386 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6387 with self.assertRaises(TagMismatch):
6388 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6392 def seqof_values_strategy(draw, schema=None, do_expl=False):
6394 schema = draw(sampled_from((Boolean(), Integer())))
6395 bound_min, bound_max = sorted(draw(sets(
6396 integers(min_value=0, max_value=10),
6400 if isinstance(schema, Boolean):
6401 values_generator = booleans().map(Boolean)
6402 elif isinstance(schema, Integer):
6403 values_generator = integers().map(Integer)
6404 values_generator = lists(
6409 values = draw(one_of(none(), values_generator))
6413 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6415 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6416 default = draw(one_of(none(), values_generator))
6417 optional = draw(one_of(none(), booleans()))
6419 draw(integers(min_value=0)),
6420 draw(integers(min_value=0)),
6421 draw(integers(min_value=0)),
6426 (bound_min, bound_max),
6435 class SeqOfMixing(object):
6436 def test_invalid_value_type(self):
6437 with self.assertRaises(InvalidValueType) as err:
6438 self.base_klass(123)
6441 def test_invalid_values_type(self):
6442 class SeqOf(self.base_klass):
6444 with self.assertRaises(InvalidValueType) as err:
6445 SeqOf([Integer(123), Boolean(False), Integer(234)])
6448 def test_schema_required(self):
6449 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6450 self.base_klass.__mro__[1]()
6452 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6453 def test_comparison(self, value1, value2, tag1, tag2):
6454 class SeqOf(self.base_klass):
6456 obj1 = SeqOf([Boolean(value1)])
6457 obj2 = SeqOf([Boolean(value2)])
6458 self.assertEqual(obj1 == obj2, value1 == value2)
6459 self.assertEqual(obj1 != obj2, value1 != value2)
6460 self.assertEqual(obj1 == list(obj2), value1 == value2)
6461 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6462 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6463 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6464 self.assertEqual(obj1 == obj2, tag1 == tag2)
6465 self.assertEqual(obj1 != obj2, tag1 != tag2)
6467 @given(lists(booleans()))
6468 def test_iter(self, values):
6469 class SeqOf(self.base_klass):
6471 obj = SeqOf([Boolean(value) for value in values])
6472 self.assertEqual(len(obj), len(values))
6473 for i, value in enumerate(obj):
6474 self.assertEqual(value, values[i])
6476 @given(data_strategy())
6477 def test_ready(self, d):
6478 ready = [Integer(v) for v in d.draw(lists(
6485 range(d.draw(integers(min_value=1, max_value=5)))
6488 class SeqOf(self.base_klass):
6490 values = d.draw(permutations(ready + non_ready))
6492 for value in values:
6494 self.assertFalse(seqof.ready)
6497 pprint(seqof, big_blobs=True, with_decode_path=True)
6498 with self.assertRaises(ObjNotReady) as err:
6501 for i, value in enumerate(values):
6502 self.assertEqual(seqof[i], value)
6503 if not seqof[i].ready:
6504 seqof[i] = Integer(i)
6505 self.assertTrue(seqof.ready)
6508 pprint(seqof, big_blobs=True, with_decode_path=True)
6510 def test_spec_mismatch(self):
6511 class SeqOf(self.base_klass):
6514 seqof.append(Integer(123))
6515 with self.assertRaises(ValueError):
6516 seqof.append(Boolean(False))
6517 with self.assertRaises(ValueError):
6518 seqof[0] = Boolean(False)
6520 @given(data_strategy())
6521 def test_bounds_satisfied(self, d):
6522 class SeqOf(self.base_klass):
6524 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6525 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6526 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6527 SeqOf(value=value, bounds=(bound_min, bound_max))
6529 @given(data_strategy())
6530 def test_bounds_unsatisfied(self, d):
6531 class SeqOf(self.base_klass):
6533 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6534 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6535 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6536 with self.assertRaises(BoundsError) as err:
6537 SeqOf(value=value, bounds=(bound_min, bound_max))
6539 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6540 SeqOf(bounds=(bound_min, bound_max)).decode(
6541 SeqOf(value).encode()
6544 value = [Boolean(True)] * d.draw(integers(
6545 min_value=bound_max + 1,
6546 max_value=bound_max + 10,
6548 with self.assertRaises(BoundsError) as err:
6549 SeqOf(value=value, bounds=(bound_min, bound_max))
6551 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6552 SeqOf(bounds=(bound_min, bound_max)).decode(
6553 SeqOf(value).encode()
6557 @given(integers(min_value=1, max_value=10))
6558 def test_out_of_bounds(self, bound_max):
6559 class SeqOf(self.base_klass):
6561 bounds = (0, bound_max)
6563 for _ in range(bound_max):
6564 seqof.append(Integer(123))
6565 with self.assertRaises(BoundsError):
6566 seqof.append(Integer(123))
6568 @given(data_strategy())
6569 def test_call(self, d):
6579 ) = d.draw(seqof_values_strategy())
6581 class SeqOf(self.base_klass):
6582 schema = schema_initial
6583 obj_initial = SeqOf(
6584 value=value_initial,
6585 bounds=bounds_initial,
6588 default=default_initial,
6589 optional=optional_initial or False,
6590 _decoded=_decoded_initial,
6601 ) = d.draw(seqof_values_strategy(
6602 schema=schema_initial,
6603 do_expl=impl_initial is None,
6605 if (default is None) and (obj_initial.default is not None):
6608 (bounds is None) and
6609 (value is not None) and
6610 (bounds_initial is not None) and
6611 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6615 (bounds is None) and
6616 (default is not None) and
6617 (bounds_initial is not None) and
6618 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6630 value_expected = default if value is None else value
6632 default_initial if value_expected is None
6635 value_expected = () if value_expected is None else value_expected
6636 self.assertEqual(obj, value_expected)
6637 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6638 self.assertEqual(obj.expl_tag, expl or expl_initial)
6641 default_initial if default is None else default,
6643 if obj.default is None:
6644 optional = optional_initial if optional is None else optional
6645 optional = False if optional is None else optional
6648 self.assertEqual(obj.optional, optional)
6650 (obj._bound_min, obj._bound_max),
6651 bounds or bounds_initial or (0, float("+inf")),
6654 @given(seqof_values_strategy())
6655 def test_copy(self, values):
6656 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6658 class SeqOf(self.base_klass):
6660 register_class(SeqOf)
6667 optional=optional or False,
6670 for copy_func in copy_funcs:
6671 obj_copied = copy_func(obj)
6672 self.assert_copied_basic_fields(obj, obj_copied)
6673 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6674 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6675 self.assertEqual(obj._value, obj_copied._value)
6679 integers(min_value=1).map(tag_encode),
6681 def test_stripped(self, values, tag_impl):
6682 class SeqOf(self.base_klass):
6683 schema = OctetString()
6684 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6685 with self.assertRaises(NotEnoughData):
6686 obj.decode(obj.encode()[:-1])
6690 integers(min_value=1).map(tag_ctxc),
6692 def test_stripped_expl(self, values, tag_expl):
6693 class SeqOf(self.base_klass):
6694 schema = OctetString()
6695 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6696 with self.assertRaises(NotEnoughData):
6697 obj.decode(obj.encode()[:-1])
6700 integers(min_value=31),
6701 integers(min_value=0),
6704 def test_bad_tag(self, tag, offset, decode_path):
6705 with self.assertRaises(DecodeError) as err:
6706 self.base_klass().decode(
6707 tag_encode(tag)[:-1],
6709 decode_path=decode_path,
6712 self.assertEqual(err.exception.offset, offset)
6713 self.assertEqual(err.exception.decode_path, decode_path)
6716 integers(min_value=128),
6717 integers(min_value=0),
6720 def test_bad_len(self, l, offset, decode_path):
6721 with self.assertRaises(DecodeError) as err:
6722 self.base_klass().decode(
6723 self.base_klass.tag_default + len_encode(l)[:-1],
6725 decode_path=decode_path,
6728 self.assertEqual(err.exception.offset, offset)
6729 self.assertEqual(err.exception.decode_path, decode_path)
6731 @given(binary(min_size=1))
6732 def test_tag_mismatch(self, impl):
6733 assume(impl != self.base_klass.tag_default)
6734 with self.assertRaises(TagMismatch):
6735 self.base_klass(impl=impl).decode(self.base_klass().encode())
6737 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6739 seqof_values_strategy(schema=Integer()),
6740 lists(integers().map(Integer)),
6741 integers(min_value=1).map(tag_ctxc),
6742 integers(min_value=0),
6746 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6747 _, _, _, _, _, default, optional, _decoded = values
6749 class SeqOf(self.base_klass):
6759 pprint(obj, big_blobs=True, with_decode_path=True)
6760 self.assertFalse(obj.expled)
6761 obj_encoded = obj.encode()
6762 obj_encoded_cer = encode_cer(obj)
6763 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6764 self.assertSequenceEqual(
6765 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6768 obj_expled = obj(value, expl=tag_expl)
6769 self.assertTrue(obj_expled.expled)
6771 list(obj_expled.pps())
6772 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6773 obj_expled_encoded = obj_expled.encode()
6774 ctx_copied = deepcopy(ctx_dummy)
6775 obj_decoded, tail = obj_expled.decode(
6776 obj_expled_encoded + tail_junk,
6780 self.assertDictEqual(ctx_copied, ctx_dummy)
6782 list(obj_decoded.pps())
6783 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6784 self.assertEqual(tail, tail_junk)
6785 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6786 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6787 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6788 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6790 obj_decoded.expl_llen,
6791 len(len_encode(len(obj_encoded))),
6793 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6794 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6797 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6799 self.assertEqual(obj_decoded.expl_offset, offset)
6800 for obj_inner in obj_decoded:
6801 self.assertIn(obj_inner, obj_decoded)
6802 self.assertSequenceEqual(
6805 obj_inner.offset - offset:
6806 obj_inner.offset + obj_inner.tlvlen - offset
6810 t, _, lv = tag_strip(obj_encoded)
6811 _, _, v = len_decode(lv)
6812 obj_encoded_lenindef = t + LENINDEF + v + EOC
6813 with self.assertRaises(DecodeError):
6814 obj.decode(obj_encoded_lenindef)
6815 obj_decoded_lenindef, tail_lenindef = obj.decode(
6816 obj_encoded_lenindef + tail_junk,
6817 ctx={"bered": True},
6819 self.assertTrue(obj_decoded_lenindef.lenindef)
6820 self.assertTrue(obj_decoded_lenindef.bered)
6821 obj_decoded_lenindef = copy(obj_decoded_lenindef)
6822 self.assertTrue(obj_decoded_lenindef.lenindef)
6823 self.assertTrue(obj_decoded_lenindef.bered)
6824 repr(obj_decoded_lenindef)
6825 list(obj_decoded_lenindef.pps())
6826 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
6827 self.assertEqual(tail_lenindef, tail_junk)
6828 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
6829 with self.assertRaises(DecodeError):
6830 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
6831 with self.assertRaises(DecodeError):
6832 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
6834 evgens = list(obj.decode_evgen(
6835 obj_encoded_lenindef + tail_junk,
6836 decode_path=decode_path,
6837 ctx={"bered": True},
6839 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
6840 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
6841 self.assertEqual(_decode_path, decode_path + (str(i),))
6844 _decode_path, obj, tail = evgens[-1]
6845 self.assertEqual(_decode_path, decode_path)
6849 assert_exceeding_data(
6851 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
6855 def test_bered(self):
6856 class SeqOf(self.base_klass):
6858 encoded = Boolean(False).encode()
6859 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
6860 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
6861 with self.assertRaises(DecodeError):
6862 SeqOf().decode(encoded)
6863 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
6864 self.assertFalse(decoded.ber_encoded)
6865 self.assertFalse(decoded.lenindef)
6866 self.assertTrue(decoded.bered)
6867 decoded = copy(decoded)
6868 self.assertFalse(decoded.ber_encoded)
6869 self.assertFalse(decoded.lenindef)
6870 self.assertTrue(decoded.bered)
6872 class SeqOf(self.base_klass):
6873 schema = OctetString()
6874 encoded = OctetString(b"whatever").encode()
6876 tag_encode(form=TagFormConstructed, num=4) +
6878 OctetString(b"whatever").encode() +
6881 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
6882 with self.assertRaises(DecodeError):
6883 SeqOf().decode(encoded)
6884 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
6885 self.assertFalse(decoded.ber_encoded)
6886 self.assertFalse(decoded.lenindef)
6887 self.assertTrue(decoded.bered)
6888 decoded = copy(decoded)
6889 self.assertFalse(decoded.ber_encoded)
6890 self.assertFalse(decoded.lenindef)
6891 self.assertTrue(decoded.bered)
6894 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
6895 class SeqOf(SequenceOf):
6899 def _test_symmetric_compare_objs(self, obj1, obj2):
6900 self.assertEqual(obj1, obj2)
6901 self.assertSequenceEqual(list(obj1), list(obj2))
6903 def test_iterator_pickling(self):
6904 class SeqOf(SequenceOf):
6906 register_class(SeqOf)
6909 seqof = seqof(iter(six_xrange(10)))
6910 with assertRaisesRegex(self, ValueError, "iterator"):
6913 def test_iterator_bounds(self):
6914 class SeqOf(SequenceOf):
6919 for i in six_xrange(n):
6922 seqof = SeqOf(gen(n))
6923 self.assertTrue(seqof.ready)
6924 with self.assertRaises(BoundsError):
6926 self.assertFalse(seqof.ready)
6927 seqof = seqof(gen(n))
6928 self.assertTrue(seqof.ready)
6929 with self.assertRaises(BoundsError):
6931 self.assertFalse(seqof.ready)
6933 def test_iterator_twice(self):
6934 class SeqOf(SequenceOf):
6936 bounds = (1, float("+inf"))
6938 for i in six_xrange(10):
6940 seqof = SeqOf(gen())
6941 self.assertTrue(seqof.ready)
6943 self.assertFalse(seqof.ready)
6944 register_class(SeqOf)
6947 def test_non_ready_bound_min(self):
6948 class SeqOf(SequenceOf):
6950 bounds = (1, float("+inf"))
6952 self.assertFalse(seqof.ready)
6955 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
6960 def _test_symmetric_compare_objs(self, obj1, obj2):
6961 self.assertSetEqual(
6962 set(int(v) for v in obj1),
6963 set(int(v) for v in obj2),
6966 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6967 @given(data_strategy())
6968 def test_sorted(self, d):
6969 values = [OctetString(v) for v in d.draw(lists(binary()))]
6972 schema = OctetString()
6974 seq_encoded = seq.encode()
6975 seq_decoded, _ = seq.decode(seq_encoded)
6976 self.assertSequenceEqual(
6977 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6978 b"".join(sorted([v.encode() for v in values])),
6981 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6982 @given(data_strategy())
6983 def test_unsorted(self, d):
6984 values = [OctetString(v).encode() for v in d.draw(sets(
6985 binary(min_size=1, max_size=5),
6989 values = d.draw(permutations(values))
6990 assume(values != sorted(values))
6991 encoded = b"".join(values)
6992 seq_encoded = b"".join((
6994 len_encode(len(encoded)),
6999 schema = OctetString()
7001 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7002 seq.decode(seq_encoded)
7004 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7005 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7006 self.assertTrue(seq_decoded.ber_encoded)
7007 self.assertTrue(seq_decoded.bered)
7008 seq_decoded = copy(seq_decoded)
7009 self.assertTrue(seq_decoded.ber_encoded)
7010 self.assertTrue(seq_decoded.bered)
7011 self.assertSequenceEqual(
7012 [obj.encode() for obj in seq_decoded],
7017 class TestGoMarshalVectors(TestCase):
7019 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7020 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7021 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7022 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7023 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7025 class Seq(Sequence):
7027 ("erste", Integer()),
7028 ("zweite", Integer(optional=True))
7031 seq["erste"] = Integer(64)
7032 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7033 seq["erste"] = Integer(0x123456)
7034 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7035 seq["erste"] = Integer(64)
7036 seq["zweite"] = Integer(65)
7037 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7039 class NestedSeq(Sequence):
7043 seq["erste"] = Integer(127)
7044 seq["zweite"] = None
7045 nested = NestedSeq()
7046 nested["nest"] = seq
7047 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7049 self.assertSequenceEqual(
7050 OctetString(b"\x01\x02\x03").encode(),
7051 hexdec("0403010203"),
7054 class Seq(Sequence):
7056 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7059 seq["erste"] = Integer(64)
7060 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7062 class Seq(Sequence):
7064 ("erste", Integer(expl=tag_ctxc(5))),
7067 seq["erste"] = Integer(64)
7068 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7070 class Seq(Sequence):
7073 impl=tag_encode(0, klass=TagClassContext),
7078 seq["erste"] = Null()
7079 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7081 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7083 self.assertSequenceEqual(
7084 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7085 hexdec("170d3730303130313030303030305a"),
7087 self.assertSequenceEqual(
7088 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7089 hexdec("170d3039313131353232353631365a"),
7091 self.assertSequenceEqual(
7092 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7093 hexdec("180f32313030303430353132303130315a"),
7096 class Seq(Sequence):
7098 ("erste", GeneralizedTime()),
7101 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7102 self.assertSequenceEqual(
7104 hexdec("3011180f32303039313131353232353631365a"),
7107 self.assertSequenceEqual(
7108 BitString((1, b"\x80")).encode(),
7111 self.assertSequenceEqual(
7112 BitString((12, b"\x81\xF0")).encode(),
7113 hexdec("03030481f0"),
7116 self.assertSequenceEqual(
7117 ObjectIdentifier("1.2.3.4").encode(),
7118 hexdec("06032a0304"),
7120 self.assertSequenceEqual(
7121 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7122 hexdec("06092a864888932d010105"),
7124 self.assertSequenceEqual(
7125 ObjectIdentifier("2.100.3").encode(),
7126 hexdec("0603813403"),
7129 self.assertSequenceEqual(
7130 PrintableString("test").encode(),
7131 hexdec("130474657374"),
7133 self.assertSequenceEqual(
7134 PrintableString("x" * 127).encode(),
7135 hexdec("137F" + "78" * 127),
7137 self.assertSequenceEqual(
7138 PrintableString("x" * 128).encode(),
7139 hexdec("138180" + "78" * 128),
7141 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7143 class Seq(Sequence):
7145 ("erste", IA5String()),
7148 seq["erste"] = IA5String("test")
7149 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7151 class Seq(Sequence):
7153 ("erste", PrintableString()),
7156 seq["erste"] = PrintableString("test")
7157 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7158 # Asterisk is actually not allowable
7159 PrintableString._allowable_chars |= set(b"*")
7160 seq["erste"] = PrintableString("test*")
7161 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7162 PrintableString._allowable_chars -= set(b"*")
7164 class Seq(Sequence):
7166 ("erste", Any(optional=True)),
7167 ("zweite", Integer()),
7170 seq["zweite"] = Integer(64)
7171 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7176 seq.append(Integer(10))
7177 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7179 class _SeqOf(SequenceOf):
7180 schema = PrintableString()
7182 class SeqOf(SequenceOf):
7185 _seqof.append(PrintableString("1"))
7187 seqof.append(_seqof)
7188 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7190 class Seq(Sequence):
7192 ("erste", Integer(default=1)),
7195 seq["erste"] = Integer(0)
7196 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7197 seq["erste"] = Integer(1)
7198 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7199 seq["erste"] = Integer(2)
7200 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7203 class TestPP(TestCase):
7204 @given(data_strategy())
7205 def test_oid_printing(self, d):
7207 str(ObjectIdentifier(k)): v * 2
7208 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7210 chosen = d.draw(sampled_from(sorted(oids)))
7211 chosen_id = oids[chosen]
7212 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7213 self.assertNotIn(chosen_id, pp_console_row(pp))
7216 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7220 class TestAutoAddSlots(TestCase):
7222 class Inher(Integer):
7225 with self.assertRaises(AttributeError):
7227 inher.unexistent = "whatever"
7230 class TestOIDDefines(TestCase):
7231 @given(data_strategy())
7232 def runTest(self, d):
7233 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7234 value_name_chosen = d.draw(sampled_from(value_names))
7236 ObjectIdentifier(oid)
7237 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7239 oid_chosen = d.draw(sampled_from(oids))
7240 values = d.draw(lists(
7242 min_size=len(value_names),
7243 max_size=len(value_names),
7245 for definable_class in (Any, OctetString, BitString):
7247 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7248 oid: Integer() for oid in oids[:-1]
7251 for i, value_name in enumerate(value_names):
7252 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7254 class Seq(Sequence):
7257 for value_name, value in zip(value_names, values):
7258 seq[value_name] = definable_class(Integer(value).encode())
7259 seq["type"] = oid_chosen
7260 seq, _ = Seq().decode(seq.encode())
7261 for value_name in value_names:
7262 if value_name == value_name_chosen:
7264 self.assertIsNone(seq[value_name].defined)
7265 if value_name_chosen in oids[:-1]:
7266 self.assertIsNotNone(seq[value_name_chosen].defined)
7267 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7268 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7271 pprint(seq, big_blobs=True, with_decode_path=True)
7274 class TestDefinesByPath(TestCase):
7275 def test_generated(self):
7276 class Seq(Sequence):
7278 ("type", ObjectIdentifier()),
7279 ("value", OctetString(expl=tag_ctxc(123))),
7282 class SeqInner(Sequence):
7284 ("typeInner", ObjectIdentifier()),
7285 ("valueInner", Any()),
7288 class PairValue(SetOf):
7291 class Pair(Sequence):
7293 ("type", ObjectIdentifier()),
7294 ("value", PairValue()),
7297 class Pairs(SequenceOf):
7304 type_octet_stringed,
7306 ObjectIdentifier(oid)
7307 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7309 seq_integered = Seq()
7310 seq_integered["type"] = type_integered
7311 seq_integered["value"] = OctetString(Integer(123).encode())
7312 seq_integered_raw = seq_integered.encode()
7316 (type_octet_stringed, OctetString(b"whatever")),
7317 (type_integered, Integer(123)),
7318 (type_octet_stringed, OctetString(b"whenever")),
7319 (type_integered, Integer(234)),
7321 for t, v in pairs_input:
7324 ("value", PairValue((Any(v),))),
7326 seq_inner = SeqInner()
7327 seq_inner["typeInner"] = type_innered
7328 seq_inner["valueInner"] = Any(pairs)
7329 seq_sequenced = Seq()
7330 seq_sequenced["type"] = type_sequenced
7331 seq_sequenced["value"] = OctetString(seq_inner.encode())
7332 seq_sequenced_raw = seq_sequenced.encode()
7334 list(seq_sequenced.pps())
7335 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7337 defines_by_path = []
7338 ctx_copied = deepcopy(ctx_dummy)
7339 seq_integered, _ = Seq().decode(
7343 self.assertDictEqual(ctx_copied, ctx_dummy)
7344 self.assertIsNone(seq_integered["value"].defined)
7345 defines_by_path.append(
7346 (("type",), ((("value",), {
7347 type_integered: Integer(),
7348 type_sequenced: SeqInner(),
7351 ctx_copied["defines_by_path"] = defines_by_path
7352 seq_integered, _ = Seq().decode(
7356 del ctx_copied["defines_by_path"]
7357 self.assertDictEqual(ctx_copied, ctx_dummy)
7358 self.assertIsNotNone(seq_integered["value"].defined)
7359 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7360 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7361 self.assertTrue(seq_integered_raw[
7362 seq_integered["value"].defined[1].offset:
7363 ].startswith(Integer(123).encode()))
7365 list(seq_integered.pps())
7366 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7368 ctx_copied["defines_by_path"] = defines_by_path
7369 seq_sequenced, _ = Seq().decode(
7373 del ctx_copied["defines_by_path"]
7374 self.assertDictEqual(ctx_copied, ctx_dummy)
7375 self.assertIsNotNone(seq_sequenced["value"].defined)
7376 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7377 seq_inner = seq_sequenced["value"].defined[1]
7378 self.assertIsNone(seq_inner["valueInner"].defined)
7380 list(seq_sequenced.pps())
7381 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7383 defines_by_path.append((
7384 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7385 ((("valueInner",), {type_innered: Pairs()}),),
7387 ctx_copied["defines_by_path"] = defines_by_path
7388 seq_sequenced, _ = Seq().decode(
7392 del ctx_copied["defines_by_path"]
7393 self.assertDictEqual(ctx_copied, ctx_dummy)
7394 self.assertIsNotNone(seq_sequenced["value"].defined)
7395 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7396 seq_inner = seq_sequenced["value"].defined[1]
7397 self.assertIsNotNone(seq_inner["valueInner"].defined)
7398 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7399 pairs = seq_inner["valueInner"].defined[1]
7401 self.assertIsNone(pair["value"][0].defined)
7403 list(seq_sequenced.pps())
7404 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7406 defines_by_path.append((
7409 DecodePathDefBy(type_sequenced),
7411 DecodePathDefBy(type_innered),
7416 type_integered: Integer(),
7417 type_octet_stringed: OctetString(),
7420 ctx_copied["defines_by_path"] = defines_by_path
7421 seq_sequenced, _ = Seq().decode(
7425 del ctx_copied["defines_by_path"]
7426 self.assertDictEqual(ctx_copied, ctx_dummy)
7427 self.assertIsNotNone(seq_sequenced["value"].defined)
7428 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7429 seq_inner = seq_sequenced["value"].defined[1]
7430 self.assertIsNotNone(seq_inner["valueInner"].defined)
7431 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7432 pairs_got = seq_inner["valueInner"].defined[1]
7433 for pair_input, pair_got in zip(pairs_input, pairs_got):
7434 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7435 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7437 list(seq_sequenced.pps())
7438 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7440 @given(oid_strategy(), integers())
7441 def test_simple(self, oid, tgt):
7442 class Inner(Sequence):
7444 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7445 ObjectIdentifier(oid): Integer(),
7449 class Outer(Sequence):
7452 ("tgt", OctetString()),
7456 inner["oid"] = ObjectIdentifier(oid)
7458 outer["inner"] = inner
7459 outer["tgt"] = OctetString(Integer(tgt).encode())
7460 decoded, _ = Outer().decode(outer.encode())
7461 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7463 def test_remaining_data(self):
7464 oid = ObjectIdentifier("1.2.3")
7465 class Seq(Sequence):
7467 ("oid", ObjectIdentifier(defines=((("tgt",), {
7470 ("tgt", OctetString()),
7475 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7477 with assertRaisesRegex(self, DecodeError, "remaining data"):
7478 Seq().decode(seq.encode())
7480 def test_remaining_data_seqof(self):
7481 oid = ObjectIdentifier("1.2.3")
7483 schema = OctetString()
7485 class Seq(Sequence):
7487 ("oid", ObjectIdentifier(defines=((("tgt",), {
7495 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7497 with assertRaisesRegex(self, DecodeError, "remaining data"):
7498 Seq().decode(seq.encode())
7501 class TestAbsDecodePath(TestCase):
7503 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7504 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7506 def test_concat(self, decode_path, rel_path):
7507 dp = abs_decode_path(decode_path, rel_path)
7508 self.assertSequenceEqual(dp, decode_path + rel_path)
7512 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7513 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7515 def test_abs(self, decode_path, rel_path):
7516 self.assertSequenceEqual(
7517 abs_decode_path(decode_path, ("/",) + rel_path),
7522 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7523 integers(min_value=1, max_value=3),
7524 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7526 def test_dots(self, decode_path, number_of_dots, rel_path):
7527 self.assertSequenceEqual(
7528 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7529 decode_path[:-number_of_dots] + rel_path,
7533 class TestStrictDefaultExistence(TestCase):
7534 @given(data_strategy())
7535 def runTest(self, d):
7536 count = d.draw(integers(min_value=1, max_value=10))
7537 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7539 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7540 for i in range(count)
7542 for klass in (Sequence, Set):
7546 for i in range(count):
7547 seq["int%d" % i] = Integer(123)
7549 chosen_choice = "int%d" % chosen
7550 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7551 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7553 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7554 self.assertTrue(decoded.ber_encoded)
7555 self.assertTrue(decoded.bered)
7556 decoded = copy(decoded)
7557 self.assertTrue(decoded.ber_encoded)
7558 self.assertTrue(decoded.bered)
7559 decoded, _ = seq.decode(raw, ctx={"bered": True})
7560 self.assertTrue(decoded.ber_encoded)
7561 self.assertTrue(decoded.bered)
7562 decoded = copy(decoded)
7563 self.assertTrue(decoded.ber_encoded)
7564 self.assertTrue(decoded.bered)
7567 class TestX690PrefixedType(TestCase):
7569 self.assertSequenceEqual(
7570 VisibleString("Jones").encode(),
7571 hexdec("1A054A6F6E6573"),
7575 self.assertSequenceEqual(
7578 impl=tag_encode(3, klass=TagClassApplication),
7580 hexdec("43054A6F6E6573"),
7584 self.assertSequenceEqual(
7588 impl=tag_encode(3, klass=TagClassApplication),
7592 hexdec("A20743054A6F6E6573"),
7596 self.assertSequenceEqual(
7600 impl=tag_encode(3, klass=TagClassApplication),
7602 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7604 hexdec("670743054A6F6E6573"),
7608 self.assertSequenceEqual(
7609 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7610 hexdec("82054A6F6E6573"),
7614 class TestExplOOB(TestCase):
7616 expl = tag_ctxc(123)
7617 raw = Integer(123).encode() + Integer(234).encode()
7618 raw = b"".join((expl, len_encode(len(raw)), raw))
7619 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7620 Integer(expl=expl).decode(raw)
7621 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7624 class TestPickleDifferentVersion(TestCase):
7626 pickled = pickle_dumps(Integer(123), pickle_proto)
7628 version_orig = pyderasn.__version__
7629 pyderasn.__version__ += "different"
7630 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7631 pickle_loads(pickled)
7632 pyderasn.__version__ = version_orig
7633 pickle_loads(pickled)
7636 class TestCERSetOrdering(TestCase):
7637 def test_vectors(self):
7638 """Taken from X.690-201508
7642 ("c", Integer(impl=tag_ctxp(2))),
7643 ("d", Integer(impl=tag_ctxp(4))),
7648 ("g", Integer(impl=tag_ctxp(5))),
7649 ("h", Integer(impl=tag_ctxp(6))),
7654 ("j", Integer(impl=tag_ctxp(0))),
7665 ("a", Integer(impl=tag_ctxp(3))),
7666 ("b", B(expl=tag_ctxc(1))),
7671 ("a", Integer(123)),
7672 ("b", B(("d", Integer(234)))),
7673 ("e", E(("f", F(("g", Integer(345)))))),
7675 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7676 self.assertSequenceEqual(
7677 [i.__class__.__name__ for i in order],
7678 ("E", "B", "Integer"),