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 importlib import import_module
22 from string import ascii_letters
23 from string import digits
24 from string import printable
25 from string import whitespace
27 from unittest import TestCase
29 from hypothesis import assume
30 from hypothesis import given
31 from hypothesis import settings
32 from hypothesis.strategies import binary
33 from hypothesis.strategies import booleans
34 from hypothesis.strategies import composite
35 from hypothesis.strategies import data as data_strategy
36 from hypothesis.strategies import datetimes
37 from hypothesis.strategies import dictionaries
38 from hypothesis.strategies import integers
39 from hypothesis.strategies import just
40 from hypothesis.strategies import lists
41 from hypothesis.strategies import none
42 from hypothesis.strategies import one_of
43 from hypothesis.strategies import permutations
44 from hypothesis.strategies import sampled_from
45 from hypothesis.strategies import sets
46 from hypothesis.strategies import text
47 from hypothesis.strategies import tuples
48 from six import assertRaisesRegex
49 from six import binary_type
50 from six import byte2int
51 from six import indexbytes
52 from six import int2byte
53 from six import iterbytes
55 from six import text_type
56 from six import unichr as six_unichr
57 from six.moves.cPickle import dumps as pickle_dumps
58 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
59 from six.moves.cPickle import loads as pickle_loads
61 from pyderasn import _pp
62 from pyderasn import abs_decode_path
63 from pyderasn import Any
64 from pyderasn import BitString
65 from pyderasn import BMPString
66 from pyderasn import Boolean
67 from pyderasn import BoundsError
68 from pyderasn import Choice
69 from pyderasn import DecodeError
70 from pyderasn import DecodePathDefBy
71 from pyderasn import Enumerated
72 from pyderasn import EOC
73 from pyderasn import EOC_LEN
74 from pyderasn import ExceedingData
75 from pyderasn import GeneralizedTime
76 from pyderasn import GeneralString
77 from pyderasn import GraphicString
78 from pyderasn import hexdec
79 from pyderasn import hexenc
80 from pyderasn import IA5String
81 from pyderasn import Integer
82 from pyderasn import InvalidLength
83 from pyderasn import InvalidOID
84 from pyderasn import InvalidValueType
85 from pyderasn import len_decode
86 from pyderasn import len_encode
87 from pyderasn import LEN_YYMMDDHHMMSSZ
88 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
89 from pyderasn import LEN_YYYYMMDDHHMMSSZ
90 from pyderasn import LENINDEF
91 from pyderasn import LenIndefForm
92 from pyderasn import NotEnoughData
93 from pyderasn import Null
94 from pyderasn import NumericString
95 from pyderasn import ObjectIdentifier
96 from pyderasn import ObjNotReady
97 from pyderasn import ObjUnknown
98 from pyderasn import OctetString
99 from pyderasn import pp_console_row
100 from pyderasn import pprint
101 from pyderasn import PrintableString
102 from pyderasn import Sequence
103 from pyderasn import SequenceOf
104 from pyderasn import Set
105 from pyderasn import SetOf
106 from pyderasn import tag_ctxc
107 from pyderasn import tag_ctxp
108 from pyderasn import tag_decode
109 from pyderasn import tag_encode
110 from pyderasn import tag_strip
111 from pyderasn import TagClassApplication
112 from pyderasn import TagClassContext
113 from pyderasn import TagClassPrivate
114 from pyderasn import TagClassUniversal
115 from pyderasn import TagFormConstructed
116 from pyderasn import TagFormPrimitive
117 from pyderasn import TagMismatch
118 from pyderasn import TeletexString
119 from pyderasn import UniversalString
120 from pyderasn import UTCTime
121 from pyderasn import UTF8String
122 from pyderasn import VideotexString
123 from pyderasn import VisibleString
126 settings.register_profile("local", settings(
129 settings.load_profile("local")
130 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
132 tag_classes = sampled_from((
138 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
139 decode_path_strat = lists(integers(), max_size=3).map(
140 lambda decode_path: tuple(str(dp) for dp in decode_path)
142 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
145 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
147 self_module = import_module(__name__)
150 def register_class(klass):
151 klassname = klass.__name__ + str(time()).replace(".", "")
152 klass.__name__ = klassname
153 klass.__qualname__ = klassname
154 setattr(self_module, klassname, klass)
157 def assert_exceeding_data(self, call, junk):
159 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)):
163 class TestHex(TestCase):
165 def test_symmetric(self, data):
166 self.assertEqual(hexdec(hexenc(data)), data)
169 class TestTagCoder(TestCase):
170 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
174 integers(min_value=0, max_value=30),
177 def test_short(self, klass, form, num, junk):
178 raw = tag_encode(klass=klass, form=form, num=num)
179 self.assertEqual(tag_decode(raw), (klass, form, num))
180 self.assertEqual(len(raw), 1)
182 byte2int(tag_encode(klass=klass, form=form, num=0)),
183 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
185 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
186 self.assertSequenceEqual(stripped.tobytes(), raw)
187 self.assertEqual(tlen, len(raw))
188 self.assertSequenceEqual(tail, junk)
190 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
194 integers(min_value=31),
197 def test_long(self, klass, form, num, junk):
198 raw = tag_encode(klass=klass, form=form, num=num)
199 self.assertEqual(tag_decode(raw), (klass, form, num))
200 self.assertGreater(len(raw), 1)
202 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
205 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
206 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
207 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
208 self.assertSequenceEqual(stripped.tobytes(), raw)
209 self.assertEqual(tlen, len(raw))
210 self.assertSequenceEqual(tail, junk)
212 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
213 @given(integers(min_value=31))
214 def test_unfinished_tag(self, num):
215 raw = bytearray(tag_encode(num=num))
216 for i in range(1, len(raw)):
218 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
219 tag_strip(bytes(raw))
221 def test_go_vectors_valid(self):
222 for data, (eklass, etag, elen, eform) in (
223 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
224 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
225 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
226 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
227 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
228 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
229 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
230 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
231 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
232 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
234 tag, _, len_encoded = tag_strip(memoryview(data))
235 klass, form, num = tag_decode(tag)
236 _len, _, tail = len_decode(len_encoded)
237 self.assertSequenceEqual(tail, b"")
238 self.assertEqual(klass, eklass)
239 self.assertEqual(num, etag)
240 self.assertEqual(_len, elen)
241 self.assertEqual(form, eform)
243 def test_go_vectors_invalid(self):
251 with self.assertRaises(DecodeError):
252 _, _, len_encoded = tag_strip(memoryview(data))
253 len_decode(len_encoded)
256 integers(min_value=0, max_value=127),
257 integers(min_value=0, max_value=2),
259 def test_long_instead_of_short(self, l, dummy_num):
260 octets = (b"\x00" * dummy_num) + int2byte(l)
261 octets = int2byte((dummy_num + 1) | 0x80) + octets
262 with self.assertRaises(DecodeError):
266 class TestLenCoder(TestCase):
267 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
269 integers(min_value=0, max_value=127),
272 def test_short(self, l, junk):
273 raw = len_encode(l) + junk
274 decoded, llen, tail = len_decode(memoryview(raw))
275 self.assertEqual(decoded, l)
276 self.assertEqual(llen, 1)
277 self.assertEqual(len(raw), 1 + len(junk))
278 self.assertEqual(tail.tobytes(), junk)
280 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
282 integers(min_value=128),
285 def test_long(self, l, junk):
286 raw = len_encode(l) + junk
287 decoded, llen, tail = len_decode(memoryview(raw))
288 self.assertEqual(decoded, l)
289 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
290 self.assertEqual(llen, len(raw) - len(junk))
291 self.assertNotEqual(indexbytes(raw, 1), 0)
292 self.assertSequenceEqual(tail.tobytes(), junk)
294 def test_empty(self):
295 with self.assertRaises(NotEnoughData):
298 @given(integers(min_value=128))
299 def test_stripped(self, _len):
300 with self.assertRaises(NotEnoughData):
301 len_decode(len_encode(_len)[:-1])
304 text_printable = text(alphabet=printable, min_size=1)
308 def text_letters(draw):
309 result = draw(text(alphabet=ascii_letters, min_size=1))
311 result = result.encode("ascii")
315 class CommonMixin(object):
316 def test_tag_default(self):
317 obj = self.base_klass()
318 self.assertEqual(obj.tag, obj.tag_default)
320 def test_simultaneous_impl_expl(self):
321 with self.assertRaises(ValueError):
322 self.base_klass(impl=b"whatever", expl=b"whenever")
324 @given(binary(min_size=1), integers(), integers(), integers())
325 def test_decoded(self, impl, offset, llen, vlen):
326 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
327 self.assertEqual(obj.offset, offset)
328 self.assertEqual(obj.llen, llen)
329 self.assertEqual(obj.vlen, vlen)
330 self.assertEqual(obj.tlen, len(impl))
331 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
333 @given(binary(min_size=1))
334 def test_impl_inherited(self, impl_tag):
335 class Inherited(self.base_klass):
338 self.assertSequenceEqual(obj.impl, impl_tag)
339 self.assertFalse(obj.expled)
342 def test_expl_inherited(self, expl_tag):
343 class Inherited(self.base_klass):
346 self.assertSequenceEqual(obj.expl, expl_tag)
347 self.assertTrue(obj.expled)
349 def assert_copied_basic_fields(self, obj, obj_copied):
350 self.assertEqual(obj, obj_copied)
351 self.assertSequenceEqual(obj.tag, obj_copied.tag)
352 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
353 self.assertEqual(obj.default, obj_copied.default)
354 self.assertEqual(obj.optional, obj_copied.optional)
355 self.assertEqual(obj.offset, obj_copied.offset)
356 self.assertEqual(obj.llen, obj_copied.llen)
357 self.assertEqual(obj.vlen, obj_copied.vlen)
361 def boolean_values_strategy(draw, do_expl=False):
362 value = draw(one_of(none(), booleans()))
366 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
368 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
369 default = draw(one_of(none(), booleans()))
370 optional = draw(one_of(none(), booleans()))
372 draw(integers(min_value=0)),
373 draw(integers(min_value=0)),
374 draw(integers(min_value=0)),
376 return (value, impl, expl, default, optional, _decoded)
379 class BooleanInherited(Boolean):
383 class TestBoolean(CommonMixin, TestCase):
386 def test_invalid_value_type(self):
387 with self.assertRaises(InvalidValueType) as err:
392 def test_optional(self, optional):
393 obj = Boolean(default=Boolean(False), optional=optional)
394 self.assertTrue(obj.optional)
397 def test_ready(self, value):
399 self.assertFalse(obj.ready)
402 pprint(obj, big_blobs=True, with_decode_path=True)
403 with self.assertRaises(ObjNotReady) as err:
407 self.assertTrue(obj.ready)
410 pprint(obj, big_blobs=True, with_decode_path=True)
412 @given(booleans(), booleans(), binary(), binary())
413 def test_comparison(self, value1, value2, tag1, tag2):
414 for klass in (Boolean, BooleanInherited):
417 self.assertEqual(obj1 == obj2, value1 == value2)
418 self.assertEqual(obj1 != obj2, value1 != value2)
419 self.assertEqual(obj1 == bool(obj2), value1 == value2)
420 obj1 = klass(value1, impl=tag1)
421 obj2 = klass(value1, impl=tag2)
422 self.assertEqual(obj1 == obj2, tag1 == tag2)
423 self.assertEqual(obj1 != obj2, tag1 != tag2)
425 @given(data_strategy())
426 def test_call(self, d):
427 for klass in (Boolean, BooleanInherited):
435 ) = d.draw(boolean_values_strategy())
441 optional_initial or False,
451 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
452 obj = obj_initial(value, impl, expl, default, optional)
454 value_expected = default if value is None else value
456 default_initial if value_expected is None
459 self.assertEqual(obj, value_expected)
460 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
461 self.assertEqual(obj.expl_tag, expl or expl_initial)
464 default_initial if default is None else default,
466 if obj.default is None:
467 optional = optional_initial if optional is None else optional
468 optional = False if optional is None else optional
471 self.assertEqual(obj.optional, optional)
473 @given(boolean_values_strategy())
474 def test_copy(self, values):
475 for klass in (Boolean, BooleanInherited):
477 for copy_func in copy_funcs:
478 obj_copied = copy_func(obj)
479 self.assert_copied_basic_fields(obj, obj_copied)
483 integers(min_value=1).map(tag_encode),
485 def test_stripped(self, value, tag_impl):
486 obj = Boolean(value, impl=tag_impl)
487 with self.assertRaises(NotEnoughData):
488 obj.decode(obj.encode()[:-1])
492 integers(min_value=1).map(tag_ctxc),
494 def test_stripped_expl(self, value, tag_expl):
495 obj = Boolean(value, expl=tag_expl)
496 with self.assertRaises(NotEnoughData):
497 obj.decode(obj.encode()[:-1])
500 integers(min_value=31),
501 integers(min_value=0),
504 def test_bad_tag(self, tag, offset, decode_path):
505 with self.assertRaises(DecodeError) as err:
507 tag_encode(tag)[:-1],
509 decode_path=decode_path,
512 self.assertEqual(err.exception.offset, offset)
513 self.assertEqual(err.exception.decode_path, decode_path)
516 integers(min_value=31),
517 integers(min_value=0),
520 def test_bad_expl_tag(self, tag, offset, decode_path):
521 with self.assertRaises(DecodeError) as err:
522 Boolean(expl=Boolean.tag_default).decode(
523 tag_encode(tag)[:-1],
525 decode_path=decode_path,
528 self.assertEqual(err.exception.offset, offset)
529 self.assertEqual(err.exception.decode_path, decode_path)
532 integers(min_value=128),
533 integers(min_value=0),
536 def test_bad_len(self, l, offset, decode_path):
537 with self.assertRaises(DecodeError) as err:
539 Boolean.tag_default + len_encode(l)[:-1],
541 decode_path=decode_path,
544 self.assertEqual(err.exception.offset, offset)
545 self.assertEqual(err.exception.decode_path, decode_path)
548 integers(min_value=128),
549 integers(min_value=0),
552 def test_bad_expl_len(self, l, offset, decode_path):
553 with self.assertRaises(DecodeError) as err:
554 Boolean(expl=Boolean.tag_default).decode(
555 Boolean.tag_default + len_encode(l)[:-1],
557 decode_path=decode_path,
560 self.assertEqual(err.exception.offset, offset)
561 self.assertEqual(err.exception.decode_path, decode_path)
563 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
565 boolean_values_strategy(),
567 integers(min_value=1).map(tag_ctxc),
568 integers(min_value=0),
571 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
572 for klass in (Boolean, BooleanInherited):
573 _, _, _, default, optional, _decoded = values
582 pprint(obj, big_blobs=True, with_decode_path=True)
583 self.assertFalse(obj.expled)
584 obj_encoded = obj.encode()
585 obj_expled = obj(value, expl=tag_expl)
586 self.assertTrue(obj_expled.expled)
588 list(obj_expled.pps())
589 pprint(obj_expled, big_blobs=True, with_decode_path=True)
590 obj_expled_hex_encoded = obj_expled.hexencode()
591 ctx_copied = deepcopy(ctx_dummy)
592 obj_decoded, tail = obj_expled.hexdecode(
593 obj_expled_hex_encoded + hexenc(tail_junk),
597 self.assertDictEqual(ctx_copied, ctx_dummy)
599 list(obj_decoded.pps())
600 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
601 self.assertEqual(tail, tail_junk)
602 self.assertEqual(obj_decoded, obj_expled)
603 self.assertNotEqual(obj_decoded, obj)
604 self.assertEqual(bool(obj_decoded), bool(obj_expled))
605 self.assertEqual(bool(obj_decoded), bool(obj))
606 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
607 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
608 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
610 obj_decoded.expl_llen,
611 len(len_encode(len(obj_encoded))),
613 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
614 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
617 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
619 self.assertEqual(obj_decoded.expl_offset, offset)
620 assert_exceeding_data(
622 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
626 @given(integers(min_value=2))
627 def test_invalid_len(self, l):
628 with self.assertRaises(InvalidLength):
629 Boolean().decode(b"".join((
635 @given(integers(min_value=0 + 1, max_value=255 - 1))
636 def test_ber_value(self, value):
637 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
638 Boolean().decode(b"".join((
643 obj, _ = Boolean().decode(
651 self.assertTrue(bool(obj))
652 self.assertTrue(obj.ber_encoded)
653 self.assertFalse(obj.lenindef)
654 self.assertTrue(obj.bered)
656 self.assertTrue(obj.ber_encoded)
657 self.assertFalse(obj.lenindef)
658 self.assertTrue(obj.bered)
661 integers(min_value=1).map(tag_ctxc),
662 binary().filter(lambda x: not x.startswith(EOC)),
664 def test_ber_expl_no_eoc(self, expl, junk):
665 encoded = expl + LENINDEF + Boolean(False).encode()
666 with self.assertRaises(LenIndefForm):
667 Boolean(expl=expl).decode(encoded + junk)
668 with assertRaisesRegex(self, DecodeError, "no EOC"):
669 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
670 obj, tail = Boolean(expl=expl).decode(
671 encoded + EOC + junk,
674 self.assertTrue(obj.expl_lenindef)
675 self.assertFalse(obj.lenindef)
676 self.assertFalse(obj.ber_encoded)
677 self.assertTrue(obj.bered)
679 self.assertTrue(obj.expl_lenindef)
680 self.assertFalse(obj.lenindef)
681 self.assertFalse(obj.ber_encoded)
682 self.assertTrue(obj.bered)
683 self.assertSequenceEqual(tail, junk)
686 pprint(obj, big_blobs=True, with_decode_path=True)
689 integers(min_value=1).map(tag_ctxc),
696 def test_ber_expl(self, expl, values):
702 Boolean(value).encode() +
705 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
707 class SeqOf(SequenceOf):
708 schema = Boolean(expl=expl)
709 with self.assertRaises(LenIndefForm):
710 SeqOf().decode(encoded)
711 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
712 self.assertSequenceEqual(tail, b"")
713 self.assertSequenceEqual([bool(v) for v in seqof], values)
729 len(expl) + 1 + 3 + EOC_LEN,
740 pprint(seqof, big_blobs=True, with_decode_path=True)
744 def integer_values_strategy(draw, do_expl=False):
745 bound_min, value, default, bound_max = sorted(draw(sets(
754 _specs = draw(sets(text_letters()))
757 min_size=len(_specs),
758 max_size=len(_specs),
760 _specs = list(zip(_specs, values))
763 bounds = (bound_min, bound_max)
767 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
769 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
772 optional = draw(one_of(none(), booleans()))
774 draw(integers(min_value=0)),
775 draw(integers(min_value=0)),
776 draw(integers(min_value=0)),
778 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
781 class IntegerInherited(Integer):
785 class TestInteger(CommonMixin, TestCase):
788 def test_invalid_value_type(self):
789 with self.assertRaises(InvalidValueType) as err:
793 @given(sets(text_letters(), min_size=2))
794 def test_unknown_name(self, names_input):
795 missing = names_input.pop()
798 schema = [(n, 123) for n in names_input]
799 with self.assertRaises(ObjUnknown) as err:
803 @given(sets(text_letters(), min_size=2))
804 def test_known_name(self, names_input):
806 schema = [(n, 123) for n in names_input]
807 Int(names_input.pop())
810 def test_optional(self, optional):
811 obj = Integer(default=Integer(0), optional=optional)
812 self.assertTrue(obj.optional)
815 def test_ready(self, value):
817 self.assertFalse(obj.ready)
820 pprint(obj, big_blobs=True, with_decode_path=True)
821 with self.assertRaises(ObjNotReady) as err:
825 self.assertTrue(obj.ready)
828 pprint(obj, big_blobs=True, with_decode_path=True)
831 @given(integers(), integers(), binary(), binary())
832 def test_comparison(self, value1, value2, tag1, tag2):
833 for klass in (Integer, IntegerInherited):
836 self.assertEqual(obj1 == obj2, value1 == value2)
837 self.assertEqual(obj1 != obj2, value1 != value2)
838 self.assertEqual(obj1 == int(obj2), value1 == value2)
839 obj1 = klass(value1, impl=tag1)
840 obj2 = klass(value1, impl=tag2)
841 self.assertEqual(obj1 == obj2, tag1 == tag2)
842 self.assertEqual(obj1 != obj2, tag1 != tag2)
844 @given(lists(integers()))
845 def test_sorted_works(self, values):
846 self.assertSequenceEqual(
847 [int(v) for v in sorted(Integer(v) for v in values)],
851 @given(data_strategy())
852 def test_named(self, d):
853 names_input = list(d.draw(sets(text_letters(), min_size=1)))
854 values_input = list(d.draw(sets(
856 min_size=len(names_input),
857 max_size=len(names_input),
859 chosen_name = d.draw(sampled_from(names_input))
860 names_input = dict(zip(names_input, values_input))
864 _int = Int(chosen_name)
865 self.assertEqual(_int.named, chosen_name)
866 self.assertEqual(int(_int), names_input[chosen_name])
868 @given(integers(), integers(min_value=0), integers(min_value=0))
869 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
870 value = bound_min + value_delta
871 bound_max = value + bound_delta
872 Integer(value=value, bounds=(bound_min, bound_max))
874 @given(sets(integers(), min_size=3, max_size=3))
875 def test_bounds_unsatisfied(self, values):
876 values = sorted(values)
877 with self.assertRaises(BoundsError) as err:
878 Integer(value=values[0], bounds=(values[1], values[2]))
880 with assertRaisesRegex(self, DecodeError, "bounds") as err:
881 Integer(bounds=(values[1], values[2])).decode(
882 Integer(values[0]).encode()
885 with self.assertRaises(BoundsError) as err:
886 Integer(value=values[2], bounds=(values[0], values[1]))
888 with assertRaisesRegex(self, DecodeError, "bounds") as err:
889 Integer(bounds=(values[0], values[1])).decode(
890 Integer(values[2]).encode()
894 @given(data_strategy())
895 def test_call(self, d):
896 for klass in (Integer, IntegerInherited):
906 ) = d.draw(integer_values_strategy())
913 optional_initial or False,
926 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
927 if (default is None) and (obj_initial.default is not None):
931 (value is not None) and
932 (bounds_initial is not None) and
933 not (bounds_initial[0] <= value <= bounds_initial[1])
938 (default is not None) and
939 (bounds_initial is not None) and
940 not (bounds_initial[0] <= default <= bounds_initial[1])
943 obj = obj_initial(value, bounds, impl, expl, default, optional)
945 value_expected = default if value is None else value
947 default_initial if value_expected is None
950 self.assertEqual(obj, value_expected)
951 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
952 self.assertEqual(obj.expl_tag, expl or expl_initial)
955 default_initial if default is None else default,
957 if obj.default is None:
958 optional = optional_initial if optional is None else optional
959 optional = False if optional is None else optional
962 self.assertEqual(obj.optional, optional)
964 (obj._bound_min, obj._bound_max),
965 bounds or bounds_initial or (float("-inf"), float("+inf")),
969 {} if _specs_initial is None else dict(_specs_initial),
972 @given(integer_values_strategy())
973 def test_copy(self, values):
974 for klass in (Integer, IntegerInherited):
976 for copy_func in copy_funcs:
977 obj_copied = copy_func(obj)
978 self.assert_copied_basic_fields(obj, obj_copied)
979 self.assertEqual(obj.specs, obj_copied.specs)
980 self.assertEqual(obj._bound_min, obj_copied._bound_min)
981 self.assertEqual(obj._bound_max, obj_copied._bound_max)
982 self.assertEqual(obj._value, obj_copied._value)
986 integers(min_value=1).map(tag_encode),
988 def test_stripped(self, value, tag_impl):
989 obj = Integer(value, impl=tag_impl)
990 with self.assertRaises(NotEnoughData):
991 obj.decode(obj.encode()[:-1])
995 integers(min_value=1).map(tag_ctxc),
997 def test_stripped_expl(self, value, tag_expl):
998 obj = Integer(value, expl=tag_expl)
999 with self.assertRaises(NotEnoughData):
1000 obj.decode(obj.encode()[:-1])
1002 def test_zero_len(self):
1003 with self.assertRaises(NotEnoughData):
1004 Integer().decode(b"".join((
1005 Integer.tag_default,
1010 integers(min_value=31),
1011 integers(min_value=0),
1014 def test_bad_tag(self, tag, offset, decode_path):
1015 with self.assertRaises(DecodeError) as err:
1017 tag_encode(tag)[:-1],
1019 decode_path=decode_path,
1022 self.assertEqual(err.exception.offset, offset)
1023 self.assertEqual(err.exception.decode_path, decode_path)
1026 integers(min_value=128),
1027 integers(min_value=0),
1030 def test_bad_len(self, l, offset, decode_path):
1031 with self.assertRaises(DecodeError) as err:
1033 Integer.tag_default + len_encode(l)[:-1],
1035 decode_path=decode_path,
1038 self.assertEqual(err.exception.offset, offset)
1039 self.assertEqual(err.exception.decode_path, decode_path)
1042 sets(integers(), min_size=2, max_size=2),
1043 integers(min_value=0),
1046 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1047 value, bound_min = list(sorted(ints))
1050 bounds = (bound_min, bound_min)
1051 with self.assertRaises(DecodeError) as err:
1053 Integer(value).encode(),
1055 decode_path=decode_path,
1058 self.assertEqual(err.exception.offset, offset)
1059 self.assertEqual(err.exception.decode_path, decode_path)
1061 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1063 integer_values_strategy(),
1065 integers(min_value=1).map(tag_ctxc),
1066 integers(min_value=0),
1069 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
1070 for klass in (Integer, IntegerInherited):
1071 _, _, _, _, default, optional, _, _decoded = values
1080 pprint(obj, big_blobs=True, with_decode_path=True)
1081 self.assertFalse(obj.expled)
1082 obj_encoded = obj.encode()
1083 obj_expled = obj(value, expl=tag_expl)
1084 self.assertTrue(obj_expled.expled)
1086 list(obj_expled.pps())
1087 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1088 obj_expled_encoded = obj_expled.encode()
1089 ctx_copied = deepcopy(ctx_dummy)
1090 obj_decoded, tail = obj_expled.decode(
1091 obj_expled_encoded + tail_junk,
1095 self.assertDictEqual(ctx_copied, ctx_dummy)
1097 list(obj_decoded.pps())
1098 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1099 self.assertEqual(tail, tail_junk)
1100 self.assertEqual(obj_decoded, obj_expled)
1101 self.assertNotEqual(obj_decoded, obj)
1102 self.assertEqual(int(obj_decoded), int(obj_expled))
1103 self.assertEqual(int(obj_decoded), int(obj))
1104 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1105 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1106 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1108 obj_decoded.expl_llen,
1109 len(len_encode(len(obj_encoded))),
1111 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1112 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1115 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1117 self.assertEqual(obj_decoded.expl_offset, offset)
1118 assert_exceeding_data(
1120 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1124 def test_go_vectors_valid(self):
1125 for data, expect in ((
1129 (b"\xff\x7f", -129),
1133 (b"\xff\x00", -256),
1137 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1138 (b"\x80\x00\x00\x00", -2147483648),
1141 Integer().decode(b"".join((
1142 Integer.tag_default,
1143 len_encode(len(data)),
1149 def test_go_vectors_invalid(self):
1154 with self.assertRaises(DecodeError):
1155 Integer().decode(b"".join((
1156 Integer.tag_default,
1157 len_encode(len(data)),
1163 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1166 if draw(booleans()):
1167 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1169 integers(min_value=0, max_value=255),
1170 min_size=len(schema),
1171 max_size=len(schema),
1173 schema = list(zip(schema, bits))
1175 def _value(value_required):
1176 if not value_required and draw(booleans()):
1178 generation_choice = 0
1180 generation_choice = draw(sampled_from((1, 2, 3)))
1181 if generation_choice == 1 or draw(booleans()):
1182 return "'%s'B" % "".join(draw(lists(
1183 sampled_from(("0", "1")),
1184 max_size=len(schema),
1186 if generation_choice == 2 or draw(booleans()):
1187 return draw(binary(max_size=len(schema) // 8))
1188 if generation_choice == 3 or draw(booleans()):
1189 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1191 value = _value(value_required)
1192 default = _value(value_required=False)
1196 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1198 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1199 optional = draw(one_of(none(), booleans()))
1201 draw(integers(min_value=0)),
1202 draw(integers(min_value=0)),
1203 draw(integers(min_value=0)),
1205 return (schema, value, impl, expl, default, optional, _decoded)
1208 class BitStringInherited(BitString):
1212 class TestBitString(CommonMixin, TestCase):
1213 base_klass = BitString
1215 @given(lists(booleans()))
1216 def test_b_encoding(self, bits):
1217 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1218 self.assertEqual(obj.bit_len, len(bits))
1219 self.assertSequenceEqual(list(obj), bits)
1220 for i, bit in enumerate(bits):
1221 self.assertEqual(obj[i], bit)
1223 @given(lists(booleans()))
1224 def test_out_of_bounds_bits(self, bits):
1225 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1226 for i in range(len(bits), len(bits) * 2):
1227 self.assertFalse(obj[i])
1229 def test_bad_b_encoding(self):
1230 with self.assertRaises(ValueError):
1231 BitString("'010120101'B")
1234 integers(min_value=1, max_value=255),
1235 integers(min_value=1, max_value=255),
1237 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1238 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1239 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1240 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1242 class BS(BitString):
1243 schema = (("whatever", 0),)
1244 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1245 self.assertEqual(obj.bit_len, leading_zeros + 1)
1246 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1248 def test_zero_len(self):
1249 with self.assertRaises(NotEnoughData):
1250 BitString().decode(b"".join((
1251 BitString.tag_default,
1255 def test_invalid_value_type(self):
1256 with self.assertRaises(InvalidValueType) as err:
1259 with self.assertRaises(InvalidValueType) as err:
1263 def test_obj_unknown(self):
1264 with self.assertRaises(ObjUnknown) as err:
1265 BitString(b"whatever")["whenever"]
1268 def test_get_invalid_type(self):
1269 with self.assertRaises(InvalidValueType) as err:
1270 BitString(b"whatever")[(1, 2, 3)]
1273 @given(data_strategy())
1274 def test_unknown_name(self, d):
1275 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1276 missing = _schema.pop()
1278 class BS(BitString):
1279 schema = [(n, i) for i, n in enumerate(_schema)]
1280 with self.assertRaises(ObjUnknown) as err:
1285 def test_optional(self, optional):
1286 obj = BitString(default=BitString(b""), optional=optional)
1287 self.assertTrue(obj.optional)
1290 def test_ready(self, value):
1292 self.assertFalse(obj.ready)
1295 pprint(obj, big_blobs=True, with_decode_path=True)
1296 with self.assertRaises(ObjNotReady) as err:
1299 obj = BitString(value)
1300 self.assertTrue(obj.ready)
1303 pprint(obj, big_blobs=True, with_decode_path=True)
1306 tuples(integers(min_value=0), binary()),
1307 tuples(integers(min_value=0), binary()),
1311 def test_comparison(self, value1, value2, tag1, tag2):
1312 for klass in (BitString, BitStringInherited):
1313 obj1 = klass(value1)
1314 obj2 = klass(value2)
1315 self.assertEqual(obj1 == obj2, value1 == value2)
1316 self.assertEqual(obj1 != obj2, value1 != value2)
1317 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1318 obj1 = klass(value1, impl=tag1)
1319 obj2 = klass(value1, impl=tag2)
1320 self.assertEqual(obj1 == obj2, tag1 == tag2)
1321 self.assertEqual(obj1 != obj2, tag1 != tag2)
1323 @given(data_strategy())
1324 def test_call(self, d):
1325 for klass in (BitString, BitStringInherited):
1334 ) = d.draw(bit_string_values_strategy())
1337 schema = schema_initial
1339 value=value_initial,
1342 default=default_initial,
1343 optional=optional_initial or False,
1344 _decoded=_decoded_initial,
1354 ) = d.draw(bit_string_values_strategy(
1355 schema=schema_initial,
1356 do_expl=impl_initial is None,
1365 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1366 self.assertEqual(obj.expl_tag, expl or expl_initial)
1367 if obj.default is None:
1368 optional = optional_initial if optional is None else optional
1369 optional = False if optional is None else optional
1372 self.assertEqual(obj.optional, optional)
1373 self.assertEqual(obj.specs, obj_initial.specs)
1375 @given(bit_string_values_strategy())
1376 def test_copy(self, values):
1377 for klass in (BitString, BitStringInherited):
1378 _schema, value, impl, expl, default, optional, _decoded = values
1388 optional=optional or False,
1391 for copy_func in copy_funcs:
1392 obj_copied = copy_func(obj)
1393 self.assert_copied_basic_fields(obj, obj_copied)
1394 self.assertEqual(obj.specs, obj_copied.specs)
1395 self.assertEqual(obj._value, obj_copied._value)
1399 integers(min_value=1).map(tag_encode),
1401 def test_stripped(self, value, tag_impl):
1402 obj = BitString(value, impl=tag_impl)
1403 with self.assertRaises(NotEnoughData):
1404 obj.decode(obj.encode()[:-1])
1408 integers(min_value=1).map(tag_ctxc),
1410 def test_stripped_expl(self, value, tag_expl):
1411 obj = BitString(value, expl=tag_expl)
1412 with self.assertRaises(NotEnoughData):
1413 obj.decode(obj.encode()[:-1])
1416 integers(min_value=31),
1417 integers(min_value=0),
1420 def test_bad_tag(self, tag, offset, decode_path):
1421 with self.assertRaises(DecodeError) as err:
1423 tag_encode(tag)[:-1],
1425 decode_path=decode_path,
1428 self.assertEqual(err.exception.offset, offset)
1429 self.assertEqual(err.exception.decode_path, decode_path)
1432 integers(min_value=128),
1433 integers(min_value=0),
1436 def test_bad_len(self, l, offset, decode_path):
1437 with self.assertRaises(DecodeError) as err:
1439 BitString.tag_default + len_encode(l)[:-1],
1441 decode_path=decode_path,
1444 self.assertEqual(err.exception.offset, offset)
1445 self.assertEqual(err.exception.decode_path, decode_path)
1447 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1448 @given(data_strategy())
1449 def test_symmetric(self, d):
1458 ) = d.draw(bit_string_values_strategy(value_required=True))
1459 tail_junk = d.draw(binary(max_size=5))
1460 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1461 offset = d.draw(integers(min_value=0))
1462 for klass in (BitString, BitStringInherited):
1473 pprint(obj, big_blobs=True, with_decode_path=True)
1474 self.assertFalse(obj.expled)
1475 obj_encoded = obj.encode()
1476 obj_expled = obj(value, expl=tag_expl)
1477 self.assertTrue(obj_expled.expled)
1479 list(obj_expled.pps())
1480 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1481 obj_expled_encoded = obj_expled.encode()
1482 ctx_copied = deepcopy(ctx_dummy)
1483 obj_decoded, tail = obj_expled.decode(
1484 obj_expled_encoded + tail_junk,
1488 self.assertDictEqual(ctx_copied, ctx_dummy)
1490 list(obj_decoded.pps())
1491 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1492 self.assertEqual(tail, tail_junk)
1493 self.assertEqual(obj_decoded, obj_expled)
1494 self.assertNotEqual(obj_decoded, obj)
1495 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1496 self.assertEqual(bytes(obj_decoded), bytes(obj))
1497 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1498 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1499 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1501 obj_decoded.expl_llen,
1502 len(len_encode(len(obj_encoded))),
1504 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1505 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1508 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1510 self.assertEqual(obj_decoded.expl_offset, offset)
1511 if isinstance(value, tuple):
1512 self.assertSetEqual(set(value), set(obj_decoded.named))
1515 assert_exceeding_data(
1517 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1521 @given(integers(min_value=1, max_value=255))
1522 def test_bad_zero_value(self, pad_size):
1523 with self.assertRaises(DecodeError):
1524 BitString().decode(b"".join((
1525 BitString.tag_default,
1530 def test_go_vectors_invalid(self):
1536 with self.assertRaises(DecodeError):
1537 BitString().decode(b"".join((
1538 BitString.tag_default,
1543 def test_go_vectors_valid(self):
1544 obj, _ = BitString().decode(b"".join((
1545 BitString.tag_default,
1549 self.assertEqual(bytes(obj), b"")
1550 self.assertEqual(obj.bit_len, 0)
1552 obj, _ = BitString().decode(b"".join((
1553 BitString.tag_default,
1557 self.assertEqual(bytes(obj), b"\x00")
1558 self.assertEqual(obj.bit_len, 1)
1560 obj = BitString((16, b"\x82\x40"))
1561 self.assertTrue(obj[0])
1562 self.assertFalse(obj[1])
1563 self.assertTrue(obj[6])
1564 self.assertTrue(obj[9])
1565 self.assertFalse(obj[17])
1568 integers(min_value=1, max_value=30),
1571 binary(min_size=1, max_size=5),
1573 binary(min_size=1, max_size=5),
1581 lists(booleans(), min_size=1),
1584 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk):
1585 def chunk_constructed(contents):
1587 tag_encode(form=TagFormConstructed, num=3) +
1589 b"".join(BitString(content).encode() for content in contents) +
1593 payload_expected = b""
1594 bit_len_expected = 0
1595 for chunk_input in chunk_inputs:
1596 if isinstance(chunk_input, binary_type):
1597 chunks.append(BitString(chunk_input).encode())
1598 payload_expected += chunk_input
1599 bit_len_expected += len(chunk_input) * 8
1601 chunks.append(chunk_constructed(chunk_input))
1602 payload = b"".join(chunk_input)
1603 payload_expected += payload
1604 bit_len_expected += len(payload) * 8
1605 chunk_last = BitString("'%s'B" % "".join(
1606 "1" if bit else "0" for bit in chunk_last_bits
1608 payload_expected += bytes(chunk_last)
1609 bit_len_expected += chunk_last.bit_len
1610 encoded_indefinite = (
1611 tag_encode(form=TagFormConstructed, num=impl) +
1614 chunk_last.encode() +
1617 encoded_definite = (
1618 tag_encode(form=TagFormConstructed, num=impl) +
1619 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1623 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1624 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1625 for lenindef_expected, encoded in (
1626 (True, encoded_indefinite),
1627 (False, encoded_definite),
1629 obj, tail = BitString(impl=tag_encode(impl)).decode(
1631 ctx={"bered": True},
1633 self.assertSequenceEqual(tail, junk)
1634 self.assertEqual(obj.bit_len, bit_len_expected)
1635 self.assertSequenceEqual(bytes(obj), payload_expected)
1636 self.assertTrue(obj.ber_encoded)
1637 self.assertEqual(obj.lenindef, lenindef_expected)
1638 self.assertTrue(obj.bered)
1640 self.assertTrue(obj.ber_encoded)
1641 self.assertEqual(obj.lenindef, lenindef_expected)
1642 self.assertTrue(obj.bered)
1643 self.assertEqual(len(encoded), obj.tlvlen)
1646 integers(min_value=0),
1649 def test_ber_definite_too_short(self, offset, decode_path):
1650 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1652 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1654 decode_path=decode_path,
1655 ctx={"bered": True},
1657 self.assertEqual(err.exception.decode_path, decode_path)
1658 self.assertEqual(err.exception.offset, offset)
1661 integers(min_value=0),
1664 def test_ber_definite_no_data(self, offset, decode_path):
1665 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1667 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1669 decode_path=decode_path,
1670 ctx={"bered": True},
1672 self.assertEqual(err.exception.decode_path, decode_path)
1673 self.assertEqual(err.exception.offset, offset)
1676 integers(min_value=0),
1678 integers(min_value=1, max_value=3),
1680 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1681 bs = BitString(b"data").encode()
1682 with self.assertRaises(NotEnoughData) as err:
1684 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1686 decode_path=decode_path,
1687 ctx={"bered": True},
1689 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1690 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1693 integers(min_value=0),
1695 integers(min_value=1, max_value=3),
1697 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1698 bs = BitString(b"data").encode()
1699 bs_longer = BitString(b"data-longer").encode()
1700 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1703 tag_encode(3, form=TagFormConstructed) +
1704 len_encode((chunks + 1) * len(bs)) +
1709 decode_path=decode_path,
1710 ctx={"bered": True},
1712 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1713 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1716 integers(min_value=0),
1719 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1720 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1722 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1724 decode_path=decode_path,
1725 ctx={"bered": True},
1727 self.assertEqual(err.exception.decode_path, decode_path)
1728 self.assertEqual(err.exception.offset, offset)
1730 @given(data_strategy())
1731 def test_ber_indefinite_not_multiple(self, d):
1732 bs_short = BitString("'A'H").encode()
1733 bs_full = BitString("'AA'H").encode()
1734 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1735 chunks.append(bs_short)
1736 d.draw(permutations(chunks))
1737 chunks.append(bs_short)
1738 offset = d.draw(integers(min_value=0))
1739 decode_path = d.draw(decode_path_strat)
1740 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1743 tag_encode(3, form=TagFormConstructed) +
1749 decode_path=decode_path,
1750 ctx={"bered": True},
1753 err.exception.decode_path,
1754 decode_path + (str(chunks.index(bs_short)),),
1757 err.exception.offset,
1758 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1761 def test_x690_vector(self):
1762 vector = BitString("'0A3B5F291CD'H")
1763 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1764 self.assertSequenceEqual(tail, b"")
1765 self.assertEqual(obj, vector)
1766 obj, tail = BitString().decode(
1767 hexdec("23800303000A3B0305045F291CD00000"),
1768 ctx={"bered": True},
1770 self.assertSequenceEqual(tail, b"")
1771 self.assertEqual(obj, vector)
1772 self.assertTrue(obj.ber_encoded)
1773 self.assertTrue(obj.lenindef)
1774 self.assertTrue(obj.bered)
1776 self.assertTrue(obj.ber_encoded)
1777 self.assertTrue(obj.lenindef)
1778 self.assertTrue(obj.bered)
1782 def octet_string_values_strategy(draw, do_expl=False):
1783 bound_min, bound_max = sorted(draw(sets(
1784 integers(min_value=0, max_value=1 << 7),
1788 value = draw(one_of(
1790 binary(min_size=bound_min, max_size=bound_max),
1792 default = draw(one_of(
1794 binary(min_size=bound_min, max_size=bound_max),
1797 if draw(booleans()):
1798 bounds = (bound_min, bound_max)
1802 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1804 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1805 optional = draw(one_of(none(), booleans()))
1807 draw(integers(min_value=0)),
1808 draw(integers(min_value=0)),
1809 draw(integers(min_value=0)),
1811 return (value, bounds, impl, expl, default, optional, _decoded)
1814 class OctetStringInherited(OctetString):
1818 class TestOctetString(CommonMixin, TestCase):
1819 base_klass = OctetString
1821 def test_invalid_value_type(self):
1822 with self.assertRaises(InvalidValueType) as err:
1823 OctetString(text_type(123))
1827 def test_optional(self, optional):
1828 obj = OctetString(default=OctetString(b""), optional=optional)
1829 self.assertTrue(obj.optional)
1832 def test_ready(self, value):
1834 self.assertFalse(obj.ready)
1837 pprint(obj, big_blobs=True, with_decode_path=True)
1838 with self.assertRaises(ObjNotReady) as err:
1841 obj = OctetString(value)
1842 self.assertTrue(obj.ready)
1845 pprint(obj, big_blobs=True, with_decode_path=True)
1847 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
1848 def test_comparison(self, value1, value2, tag1, tag2):
1849 for klass in (OctetString, OctetStringInherited):
1850 obj1 = klass(value1)
1851 obj2 = klass(value2)
1852 self.assertEqual(obj1 == obj2, value1 == value2)
1853 self.assertEqual(obj1 != obj2, value1 != value2)
1854 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
1855 obj1 = klass(value1, impl=tag1)
1856 obj2 = klass(value1, impl=tag2)
1857 self.assertEqual(obj1 == obj2, tag1 == tag2)
1858 self.assertEqual(obj1 != obj2, tag1 != tag2)
1860 @given(lists(binary()))
1861 def test_sorted_works(self, values):
1862 self.assertSequenceEqual(
1863 [bytes(v) for v in sorted(OctetString(v) for v in values)],
1867 @given(data_strategy())
1868 def test_bounds_satisfied(self, d):
1869 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
1870 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1871 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
1872 OctetString(value=value, bounds=(bound_min, bound_max))
1874 @given(data_strategy())
1875 def test_bounds_unsatisfied(self, d):
1876 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
1877 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
1878 value = d.draw(binary(max_size=bound_min - 1))
1879 with self.assertRaises(BoundsError) as err:
1880 OctetString(value=value, bounds=(bound_min, bound_max))
1882 with assertRaisesRegex(self, DecodeError, "bounds") as err:
1883 OctetString(bounds=(bound_min, bound_max)).decode(
1884 OctetString(value).encode()
1887 value = d.draw(binary(min_size=bound_max + 1))
1888 with self.assertRaises(BoundsError) as err:
1889 OctetString(value=value, bounds=(bound_min, bound_max))
1891 with assertRaisesRegex(self, DecodeError, "bounds") as err:
1892 OctetString(bounds=(bound_min, bound_max)).decode(
1893 OctetString(value).encode()
1897 @given(data_strategy())
1898 def test_call(self, d):
1899 for klass in (OctetString, OctetStringInherited):
1908 ) = d.draw(octet_string_values_strategy())
1909 obj_initial = klass(
1915 optional_initial or False,
1926 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
1927 if (default is None) and (obj_initial.default is not None):
1930 (bounds is None) and
1931 (value is not None) and
1932 (bounds_initial is not None) and
1933 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
1937 (bounds is None) and
1938 (default is not None) and
1939 (bounds_initial is not None) and
1940 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
1943 obj = obj_initial(value, bounds, impl, expl, default, optional)
1945 value_expected = default if value is None else value
1947 default_initial if value_expected is None
1950 self.assertEqual(obj, value_expected)
1951 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1952 self.assertEqual(obj.expl_tag, expl or expl_initial)
1955 default_initial if default is None else default,
1957 if obj.default is None:
1958 optional = optional_initial if optional is None else optional
1959 optional = False if optional is None else optional
1962 self.assertEqual(obj.optional, optional)
1964 (obj._bound_min, obj._bound_max),
1965 bounds or bounds_initial or (0, float("+inf")),
1968 @given(octet_string_values_strategy())
1969 def test_copy(self, values):
1970 for klass in (OctetString, OctetStringInherited):
1971 obj = klass(*values)
1972 for copy_func in copy_funcs:
1973 obj_copied = copy_func(obj)
1974 self.assert_copied_basic_fields(obj, obj_copied)
1975 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1976 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1977 self.assertEqual(obj._value, obj_copied._value)
1981 integers(min_value=1).map(tag_encode),
1983 def test_stripped(self, value, tag_impl):
1984 obj = OctetString(value, impl=tag_impl)
1985 with self.assertRaises(NotEnoughData):
1986 obj.decode(obj.encode()[:-1])
1990 integers(min_value=1).map(tag_ctxc),
1992 def test_stripped_expl(self, value, tag_expl):
1993 obj = OctetString(value, expl=tag_expl)
1994 with self.assertRaises(NotEnoughData):
1995 obj.decode(obj.encode()[:-1])
1998 integers(min_value=31),
1999 integers(min_value=0),
2002 def test_bad_tag(self, tag, offset, decode_path):
2003 with self.assertRaises(DecodeError) as err:
2004 OctetString().decode(
2005 tag_encode(tag)[:-1],
2007 decode_path=decode_path,
2010 self.assertEqual(err.exception.offset, offset)
2011 self.assertEqual(err.exception.decode_path, decode_path)
2014 integers(min_value=128),
2015 integers(min_value=0),
2018 def test_bad_len(self, l, offset, decode_path):
2019 with self.assertRaises(DecodeError) as err:
2020 OctetString().decode(
2021 OctetString.tag_default + len_encode(l)[:-1],
2023 decode_path=decode_path,
2026 self.assertEqual(err.exception.offset, offset)
2027 self.assertEqual(err.exception.decode_path, decode_path)
2030 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2031 integers(min_value=0),
2034 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2035 value, bound_min = list(sorted(ints))
2037 class String(OctetString):
2038 bounds = (bound_min, bound_min)
2039 with self.assertRaises(DecodeError) as err:
2041 OctetString(b"\x00" * value).encode(),
2043 decode_path=decode_path,
2046 self.assertEqual(err.exception.offset, offset)
2047 self.assertEqual(err.exception.decode_path, decode_path)
2049 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2051 octet_string_values_strategy(),
2053 integers(min_value=1).map(tag_ctxc),
2054 integers(min_value=0),
2057 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
2058 for klass in (OctetString, OctetStringInherited):
2059 _, _, _, _, default, optional, _decoded = values
2068 pprint(obj, big_blobs=True, with_decode_path=True)
2069 self.assertFalse(obj.expled)
2070 obj_encoded = obj.encode()
2071 obj_expled = obj(value, expl=tag_expl)
2072 self.assertTrue(obj_expled.expled)
2074 list(obj_expled.pps())
2075 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2076 obj_expled_encoded = obj_expled.encode()
2077 ctx_copied = deepcopy(ctx_dummy)
2078 obj_decoded, tail = obj_expled.decode(
2079 obj_expled_encoded + tail_junk,
2083 self.assertDictEqual(ctx_copied, ctx_dummy)
2085 list(obj_decoded.pps())
2086 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2087 self.assertEqual(tail, tail_junk)
2088 self.assertEqual(obj_decoded, obj_expled)
2089 self.assertNotEqual(obj_decoded, obj)
2090 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2091 self.assertEqual(bytes(obj_decoded), bytes(obj))
2092 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2093 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2094 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2096 obj_decoded.expl_llen,
2097 len(len_encode(len(obj_encoded))),
2099 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2100 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2103 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2105 self.assertEqual(obj_decoded.expl_offset, offset)
2106 assert_exceeding_data(
2108 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2113 integers(min_value=1, max_value=30),
2116 binary(min_size=1, max_size=5),
2118 binary(min_size=1, max_size=5),
2128 def test_constructed(self, impl, chunk_inputs, junk):
2129 def chunk_constructed(contents):
2131 tag_encode(form=TagFormConstructed, num=4) +
2133 b"".join(OctetString(content).encode() for content in contents) +
2137 payload_expected = b""
2138 for chunk_input in chunk_inputs:
2139 if isinstance(chunk_input, binary_type):
2140 chunks.append(OctetString(chunk_input).encode())
2141 payload_expected += chunk_input
2143 chunks.append(chunk_constructed(chunk_input))
2144 payload = b"".join(chunk_input)
2145 payload_expected += payload
2146 encoded_indefinite = (
2147 tag_encode(form=TagFormConstructed, num=impl) +
2152 encoded_definite = (
2153 tag_encode(form=TagFormConstructed, num=impl) +
2154 len_encode(len(b"".join(chunks))) +
2157 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2158 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2159 for lenindef_expected, encoded in (
2160 (True, encoded_indefinite),
2161 (False, encoded_definite),
2163 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2165 ctx={"bered": True},
2167 self.assertSequenceEqual(tail, junk)
2168 self.assertSequenceEqual(bytes(obj), payload_expected)
2169 self.assertTrue(obj.ber_encoded)
2170 self.assertEqual(obj.lenindef, lenindef_expected)
2171 self.assertTrue(obj.bered)
2173 self.assertTrue(obj.ber_encoded)
2174 self.assertEqual(obj.lenindef, lenindef_expected)
2175 self.assertTrue(obj.bered)
2176 self.assertEqual(len(encoded), obj.tlvlen)
2179 integers(min_value=0),
2182 def test_ber_definite_too_short(self, offset, decode_path):
2183 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2184 OctetString().decode(
2185 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2187 decode_path=decode_path,
2188 ctx={"bered": True},
2190 self.assertEqual(err.exception.decode_path, decode_path)
2191 self.assertEqual(err.exception.offset, offset)
2194 integers(min_value=0),
2196 integers(min_value=1, max_value=3),
2198 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2199 bs = OctetString(b"data").encode()
2200 with self.assertRaises(NotEnoughData) as err:
2201 OctetString().decode(
2202 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2204 decode_path=decode_path,
2205 ctx={"bered": True},
2207 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2208 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2211 integers(min_value=0),
2213 integers(min_value=1, max_value=3),
2215 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2216 bs = OctetString(b"data").encode()
2217 bs_longer = OctetString(b"data-longer").encode()
2218 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2219 OctetString().decode(
2221 tag_encode(4, form=TagFormConstructed) +
2222 len_encode((chunks + 1) * len(bs)) +
2227 decode_path=decode_path,
2228 ctx={"bered": True},
2230 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2231 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2235 def null_values_strategy(draw, do_expl=False):
2239 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2241 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2242 optional = draw(one_of(none(), booleans()))
2244 draw(integers(min_value=0)),
2245 draw(integers(min_value=0)),
2246 draw(integers(min_value=0)),
2248 return (impl, expl, optional, _decoded)
2251 class NullInherited(Null):
2255 class TestNull(CommonMixin, TestCase):
2258 def test_ready(self):
2260 self.assertTrue(obj.ready)
2263 pprint(obj, big_blobs=True, with_decode_path=True)
2265 @given(binary(), binary())
2266 def test_comparison(self, tag1, tag2):
2267 for klass in (Null, NullInherited):
2268 obj1 = klass(impl=tag1)
2269 obj2 = klass(impl=tag2)
2270 self.assertEqual(obj1 == obj2, tag1 == tag2)
2271 self.assertEqual(obj1 != obj2, tag1 != tag2)
2272 self.assertNotEqual(obj1, tag2)
2274 @given(data_strategy())
2275 def test_call(self, d):
2276 for klass in (Null, NullInherited):
2282 ) = d.draw(null_values_strategy())
2283 obj_initial = klass(
2286 optional=optional_initial or False,
2287 _decoded=_decoded_initial,
2294 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2295 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2296 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2297 self.assertEqual(obj.expl_tag, expl or expl_initial)
2298 optional = optional_initial if optional is None else optional
2299 optional = False if optional is None else optional
2300 self.assertEqual(obj.optional, optional)
2302 @given(null_values_strategy())
2303 def test_copy(self, values):
2304 for klass in (Null, NullInherited):
2305 impl, expl, optional, _decoded = values
2309 optional=optional or False,
2312 for copy_func in copy_funcs:
2313 obj_copied = copy_func(obj)
2314 self.assert_copied_basic_fields(obj, obj_copied)
2316 @given(integers(min_value=1).map(tag_encode))
2317 def test_stripped(self, tag_impl):
2318 obj = Null(impl=tag_impl)
2319 with self.assertRaises(NotEnoughData):
2320 obj.decode(obj.encode()[:-1])
2322 @given(integers(min_value=1).map(tag_ctxc))
2323 def test_stripped_expl(self, tag_expl):
2324 obj = Null(expl=tag_expl)
2325 with self.assertRaises(NotEnoughData):
2326 obj.decode(obj.encode()[:-1])
2329 integers(min_value=31),
2330 integers(min_value=0),
2333 def test_bad_tag(self, tag, offset, decode_path):
2334 with self.assertRaises(DecodeError) as err:
2336 tag_encode(tag)[:-1],
2338 decode_path=decode_path,
2341 self.assertEqual(err.exception.offset, offset)
2342 self.assertEqual(err.exception.decode_path, decode_path)
2345 integers(min_value=128),
2346 integers(min_value=0),
2349 def test_bad_len(self, l, offset, decode_path):
2350 with self.assertRaises(DecodeError) as err:
2352 Null.tag_default + len_encode(l)[:-1],
2354 decode_path=decode_path,
2357 self.assertEqual(err.exception.offset, offset)
2358 self.assertEqual(err.exception.decode_path, decode_path)
2360 @given(binary(min_size=1))
2361 def test_tag_mismatch(self, impl):
2362 assume(impl != Null.tag_default)
2363 with self.assertRaises(TagMismatch):
2364 Null(impl=impl).decode(Null().encode())
2367 null_values_strategy(),
2368 integers(min_value=1).map(tag_ctxc),
2369 integers(min_value=0),
2372 def test_symmetric(self, values, tag_expl, offset, tail_junk):
2373 for klass in (Null, NullInherited):
2374 _, _, optional, _decoded = values
2375 obj = klass(optional=optional, _decoded=_decoded)
2378 pprint(obj, big_blobs=True, with_decode_path=True)
2379 self.assertFalse(obj.expled)
2380 obj_encoded = obj.encode()
2381 obj_expled = obj(expl=tag_expl)
2382 self.assertTrue(obj_expled.expled)
2384 list(obj_expled.pps())
2385 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2386 obj_expled_encoded = obj_expled.encode()
2387 ctx_copied = deepcopy(ctx_dummy)
2388 obj_decoded, tail = obj_expled.decode(
2389 obj_expled_encoded + tail_junk,
2393 self.assertDictEqual(ctx_copied, ctx_dummy)
2395 list(obj_decoded.pps())
2396 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2397 self.assertEqual(tail, tail_junk)
2398 self.assertEqual(obj_decoded, obj_expled)
2399 self.assertNotEqual(obj_decoded, obj)
2400 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2401 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2402 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2404 obj_decoded.expl_llen,
2405 len(len_encode(len(obj_encoded))),
2407 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2408 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2411 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2413 self.assertEqual(obj_decoded.expl_offset, offset)
2414 assert_exceeding_data(
2416 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2420 @given(integers(min_value=1))
2421 def test_invalid_len(self, l):
2422 with self.assertRaises(InvalidLength):
2423 Null().decode(b"".join((
2430 def oid_strategy(draw):
2431 first_arc = draw(integers(min_value=0, max_value=2))
2433 if first_arc in (0, 1):
2434 second_arc = draw(integers(min_value=0, max_value=39))
2436 second_arc = draw(integers(min_value=0))
2437 other_arcs = draw(lists(integers(min_value=0)))
2438 return tuple([first_arc, second_arc] + other_arcs)
2442 def oid_values_strategy(draw, do_expl=False):
2443 value = draw(one_of(none(), oid_strategy()))
2447 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2449 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2450 default = draw(one_of(none(), oid_strategy()))
2451 optional = draw(one_of(none(), booleans()))
2453 draw(integers(min_value=0)),
2454 draw(integers(min_value=0)),
2455 draw(integers(min_value=0)),
2457 return (value, impl, expl, default, optional, _decoded)
2460 class ObjectIdentifierInherited(ObjectIdentifier):
2464 class TestObjectIdentifier(CommonMixin, TestCase):
2465 base_klass = ObjectIdentifier
2467 def test_invalid_value_type(self):
2468 with self.assertRaises(InvalidValueType) as err:
2469 ObjectIdentifier(123)
2473 def test_optional(self, optional):
2474 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2475 self.assertTrue(obj.optional)
2477 @given(oid_strategy())
2478 def test_ready(self, value):
2479 obj = ObjectIdentifier()
2480 self.assertFalse(obj.ready)
2483 pprint(obj, big_blobs=True, with_decode_path=True)
2484 with self.assertRaises(ObjNotReady) as err:
2487 obj = ObjectIdentifier(value)
2488 self.assertTrue(obj.ready)
2489 self.assertFalse(obj.ber_encoded)
2492 pprint(obj, big_blobs=True, with_decode_path=True)
2495 @given(oid_strategy(), oid_strategy(), binary(), binary())
2496 def test_comparison(self, value1, value2, tag1, tag2):
2497 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2498 obj1 = klass(value1)
2499 obj2 = klass(value2)
2500 self.assertEqual(obj1 == obj2, value1 == value2)
2501 self.assertEqual(obj1 != obj2, value1 != value2)
2502 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2503 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2504 obj1 = klass(value1, impl=tag1)
2505 obj2 = klass(value1, impl=tag2)
2506 self.assertEqual(obj1 == obj2, tag1 == tag2)
2507 self.assertEqual(obj1 != obj2, tag1 != tag2)
2509 @given(lists(oid_strategy()))
2510 def test_sorted_works(self, values):
2511 self.assertSequenceEqual(
2512 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2516 @given(data_strategy())
2517 def test_call(self, d):
2518 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2526 ) = d.draw(oid_values_strategy())
2527 obj_initial = klass(
2528 value=value_initial,
2531 default=default_initial,
2532 optional=optional_initial or False,
2533 _decoded=_decoded_initial,
2542 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2551 value_expected = default if value is None else value
2553 default_initial if value_expected is None
2556 self.assertEqual(obj, value_expected)
2557 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2558 self.assertEqual(obj.expl_tag, expl or expl_initial)
2561 default_initial if default is None else default,
2563 if obj.default is None:
2564 optional = optional_initial if optional is None else optional
2565 optional = False if optional is None else optional
2568 self.assertEqual(obj.optional, optional)
2570 @given(oid_values_strategy())
2571 def test_copy(self, values):
2572 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2589 for copy_func in copy_funcs:
2590 obj_copied = copy_func(obj)
2591 self.assert_copied_basic_fields(obj, obj_copied)
2592 self.assertEqual(obj._value, obj_copied._value)
2594 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2597 integers(min_value=1).map(tag_encode),
2599 def test_stripped(self, value, tag_impl):
2600 obj = ObjectIdentifier(value, impl=tag_impl)
2601 with self.assertRaises(NotEnoughData):
2602 obj.decode(obj.encode()[:-1])
2606 integers(min_value=1).map(tag_ctxc),
2608 def test_stripped_expl(self, value, tag_expl):
2609 obj = ObjectIdentifier(value, expl=tag_expl)
2610 with self.assertRaises(NotEnoughData):
2611 obj.decode(obj.encode()[:-1])
2614 integers(min_value=31),
2615 integers(min_value=0),
2618 def test_bad_tag(self, tag, offset, decode_path):
2619 with self.assertRaises(DecodeError) as err:
2620 ObjectIdentifier().decode(
2621 tag_encode(tag)[:-1],
2623 decode_path=decode_path,
2626 self.assertEqual(err.exception.offset, offset)
2627 self.assertEqual(err.exception.decode_path, decode_path)
2630 integers(min_value=128),
2631 integers(min_value=0),
2634 def test_bad_len(self, l, offset, decode_path):
2635 with self.assertRaises(DecodeError) as err:
2636 ObjectIdentifier().decode(
2637 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2639 decode_path=decode_path,
2642 self.assertEqual(err.exception.offset, offset)
2643 self.assertEqual(err.exception.decode_path, decode_path)
2645 def test_zero_oid(self):
2646 with self.assertRaises(NotEnoughData):
2647 ObjectIdentifier().decode(
2648 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2651 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2652 @given(oid_strategy())
2653 def test_unfinished_oid(self, value):
2654 assume(list(value)[-1] > 255)
2655 obj_encoded = ObjectIdentifier(value).encode()
2656 obj, _ = ObjectIdentifier().decode(obj_encoded)
2657 data = obj_encoded[obj.tlen + obj.llen:-1]
2659 ObjectIdentifier.tag_default,
2660 len_encode(len(data)),
2663 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2666 @given(integers(min_value=0))
2667 def test_invalid_short(self, value):
2668 with self.assertRaises(InvalidOID):
2669 ObjectIdentifier((value,))
2670 with self.assertRaises(InvalidOID):
2671 ObjectIdentifier("%d" % value)
2673 @given(integers(min_value=3), integers(min_value=0))
2674 def test_invalid_first_arc(self, first_arc, second_arc):
2675 with self.assertRaises(InvalidOID):
2676 ObjectIdentifier((first_arc, second_arc))
2677 with self.assertRaises(InvalidOID):
2678 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2680 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2681 def test_invalid_second_arc(self, first_arc, second_arc):
2682 with self.assertRaises(InvalidOID):
2683 ObjectIdentifier((first_arc, second_arc))
2684 with self.assertRaises(InvalidOID):
2685 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2687 @given(text(alphabet=ascii_letters + ".", min_size=1))
2688 def test_junk(self, oid):
2689 with self.assertRaises(InvalidOID):
2690 ObjectIdentifier(oid)
2692 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2693 @given(oid_strategy())
2694 def test_validness(self, oid):
2695 obj = ObjectIdentifier(oid)
2696 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2699 pprint(obj, big_blobs=True, with_decode_path=True)
2701 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2703 oid_values_strategy(),
2705 integers(min_value=1).map(tag_ctxc),
2706 integers(min_value=0),
2709 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
2710 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2711 _, _, _, default, optional, _decoded = values
2720 pprint(obj, big_blobs=True, with_decode_path=True)
2721 self.assertFalse(obj.expled)
2722 obj_encoded = obj.encode()
2723 obj_expled = obj(value, expl=tag_expl)
2724 self.assertTrue(obj_expled.expled)
2726 list(obj_expled.pps())
2727 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2728 obj_expled_encoded = obj_expled.encode()
2729 ctx_copied = deepcopy(ctx_dummy)
2730 obj_decoded, tail = obj_expled.decode(
2731 obj_expled_encoded + tail_junk,
2735 self.assertDictEqual(ctx_copied, ctx_dummy)
2737 list(obj_decoded.pps())
2738 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2739 self.assertEqual(tail, tail_junk)
2740 self.assertEqual(obj_decoded, obj_expled)
2741 self.assertNotEqual(obj_decoded, obj)
2742 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
2743 self.assertEqual(tuple(obj_decoded), tuple(obj))
2744 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2745 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2746 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2748 obj_decoded.expl_llen,
2749 len(len_encode(len(obj_encoded))),
2751 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2752 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2755 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2757 self.assertEqual(obj_decoded.expl_offset, offset)
2758 assert_exceeding_data(
2760 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2765 oid_strategy().map(ObjectIdentifier),
2766 oid_strategy().map(ObjectIdentifier),
2768 def test_add(self, oid1, oid2):
2769 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
2770 for oid_to_add in (oid2, tuple(oid2)):
2771 self.assertEqual(oid1 + oid_to_add, oid_expect)
2772 with self.assertRaises(InvalidValueType):
2775 def test_go_vectors_valid(self):
2776 for data, expect in (
2778 (b"\x55\x02", (2, 5, 2)),
2779 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
2780 (b"\x81\x34\x03", (2, 100, 3)),
2783 ObjectIdentifier().decode(b"".join((
2784 ObjectIdentifier.tag_default,
2785 len_encode(len(data)),
2791 def test_go_vectors_invalid(self):
2792 data = b"\x55\x02\xc0\x80\x80\x80\x80"
2793 with self.assertRaises(DecodeError):
2794 ObjectIdentifier().decode(b"".join((
2795 Integer.tag_default,
2796 len_encode(len(data)),
2800 def test_x690_vector(self):
2802 ObjectIdentifier().decode(hexdec("0603883703"))[0],
2803 ObjectIdentifier((2, 999, 3)),
2806 def test_nonnormalized_first_arc(self):
2808 ObjectIdentifier.tag_default +
2811 ObjectIdentifier((1, 0)).encode()[-1:]
2813 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
2814 self.assertTrue(obj.ber_encoded)
2815 self.assertTrue(obj.bered)
2817 self.assertTrue(obj.ber_encoded)
2818 self.assertTrue(obj.bered)
2819 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
2820 ObjectIdentifier().decode(tampered)
2822 @given(data_strategy())
2823 def test_negative_arcs(self, d):
2824 oid = list(d.draw(oid_strategy()))
2827 idx = d.draw(integers(min_value=3, max_value=len(oid)))
2829 if oid[idx - 1] == 0:
2831 with self.assertRaises(InvalidOID):
2832 ObjectIdentifier(tuple(oid))
2833 with self.assertRaises(InvalidOID):
2834 ObjectIdentifier(".".join(str(i) for i in oid))
2836 @given(data_strategy())
2837 def test_plused_arcs(self, d):
2838 oid = [str(arc) for arc in d.draw(oid_strategy())]
2839 idx = d.draw(integers(min_value=0, max_value=len(oid)))
2840 oid[idx - 1] = "+" + oid[idx - 1]
2841 with self.assertRaises(InvalidOID):
2842 ObjectIdentifier(".".join(str(i) for i in oid))
2844 @given(data_strategy())
2845 def test_nonnormalized_arcs(self, d):
2846 arcs = d.draw(lists(
2847 integers(min_value=0, max_value=100),
2851 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
2852 _, _, lv = tag_strip(dered)
2853 _, _, v = len_decode(lv)
2854 v_no_first_arc = v[1:]
2855 idx_for_tamper = d.draw(integers(
2857 max_value=len(v_no_first_arc) - 1,
2859 tampered = list(bytearray(v_no_first_arc))
2860 for _ in range(d.draw(integers(min_value=1, max_value=3))):
2861 tampered.insert(idx_for_tamper, 0x80)
2862 tampered = bytes(bytearray(tampered))
2864 ObjectIdentifier.tag_default +
2865 len_encode(len(tampered)) +
2868 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
2869 self.assertTrue(obj.ber_encoded)
2870 self.assertTrue(obj.bered)
2872 self.assertTrue(obj.ber_encoded)
2873 self.assertTrue(obj.bered)
2874 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
2875 ObjectIdentifier().decode(tampered)
2879 def enumerated_values_strategy(draw, schema=None, do_expl=False):
2881 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
2882 values = list(draw(sets(
2884 min_size=len(schema),
2885 max_size=len(schema),
2887 schema = list(zip(schema, values))
2888 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
2892 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2894 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2895 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
2896 optional = draw(one_of(none(), booleans()))
2898 draw(integers(min_value=0)),
2899 draw(integers(min_value=0)),
2900 draw(integers(min_value=0)),
2902 return (schema, value, impl, expl, default, optional, _decoded)
2905 class TestEnumerated(CommonMixin, TestCase):
2906 class EWhatever(Enumerated):
2907 schema = (("whatever", 0),)
2909 base_klass = EWhatever
2911 def test_schema_required(self):
2912 with assertRaisesRegex(self, ValueError, "schema must be specified"):
2915 def test_invalid_value_type(self):
2916 with self.assertRaises(InvalidValueType) as err:
2917 self.base_klass((1, 2))
2920 @given(sets(text_letters(), min_size=2))
2921 def test_unknown_name(self, schema_input):
2922 missing = schema_input.pop()
2924 class E(Enumerated):
2925 schema = [(n, 123) for n in schema_input]
2926 with self.assertRaises(ObjUnknown) as err:
2931 sets(text_letters(), min_size=2),
2932 sets(integers(), min_size=2),
2934 def test_unknown_value(self, schema_input, values_input):
2936 missing_value = values_input.pop()
2937 _input = list(zip(schema_input, values_input))
2939 class E(Enumerated):
2941 with self.assertRaises(DecodeError) as err:
2946 def test_optional(self, optional):
2947 obj = self.base_klass(default="whatever", optional=optional)
2948 self.assertTrue(obj.optional)
2950 def test_ready(self):
2951 obj = self.base_klass()
2952 self.assertFalse(obj.ready)
2955 pprint(obj, big_blobs=True, with_decode_path=True)
2956 with self.assertRaises(ObjNotReady) as err:
2959 obj = self.base_klass("whatever")
2960 self.assertTrue(obj.ready)
2963 pprint(obj, big_blobs=True, with_decode_path=True)
2965 @given(integers(), integers(), binary(), binary())
2966 def test_comparison(self, value1, value2, tag1, tag2):
2967 class E(Enumerated):
2969 ("whatever0", value1),
2970 ("whatever1", value2),
2973 class EInherited(E):
2975 for klass in (E, EInherited):
2976 obj1 = klass(value1)
2977 obj2 = klass(value2)
2978 self.assertEqual(obj1 == obj2, value1 == value2)
2979 self.assertEqual(obj1 != obj2, value1 != value2)
2980 self.assertEqual(obj1 == int(obj2), value1 == value2)
2981 obj1 = klass(value1, impl=tag1)
2982 obj2 = klass(value1, impl=tag2)
2983 self.assertEqual(obj1 == obj2, tag1 == tag2)
2984 self.assertEqual(obj1 != obj2, tag1 != tag2)
2986 @given(data_strategy())
2987 def test_call(self, d):
2996 ) = d.draw(enumerated_values_strategy())
2998 class E(Enumerated):
2999 schema = schema_initial
3001 value=value_initial,
3004 default=default_initial,
3005 optional=optional_initial or False,
3006 _decoded=_decoded_initial,
3016 ) = d.draw(enumerated_values_strategy(
3017 schema=schema_initial,
3018 do_expl=impl_initial is None,
3028 value_expected = default if value is None else value
3030 default_initial if value_expected is None
3035 dict(schema_initial).get(value_expected, value_expected),
3037 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3038 self.assertEqual(obj.expl_tag, expl or expl_initial)
3041 default_initial if default is None else default,
3043 if obj.default is None:
3044 optional = optional_initial if optional is None else optional
3045 optional = False if optional is None else optional
3048 self.assertEqual(obj.optional, optional)
3049 self.assertEqual(obj.specs, dict(schema_initial))
3051 @given(enumerated_values_strategy())
3052 def test_copy(self, values):
3053 schema_input, value, impl, expl, default, optional, _decoded = values
3055 class E(Enumerated):
3056 schema = schema_input
3066 for copy_func in copy_funcs:
3067 obj_copied = copy_func(obj)
3068 self.assert_copied_basic_fields(obj, obj_copied)
3069 self.assertEqual(obj.specs, obj_copied.specs)
3071 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3072 @given(data_strategy())
3073 def test_symmetric(self, d):
3074 schema_input, _, _, _, default, optional, _decoded = d.draw(
3075 enumerated_values_strategy(),
3077 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3078 offset = d.draw(integers(min_value=0))
3079 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3080 tail_junk = d.draw(binary(max_size=5))
3082 class E(Enumerated):
3083 schema = schema_input
3092 pprint(obj, big_blobs=True, with_decode_path=True)
3093 self.assertFalse(obj.expled)
3094 obj_encoded = obj.encode()
3095 obj_expled = obj(value, expl=tag_expl)
3096 self.assertTrue(obj_expled.expled)
3098 list(obj_expled.pps())
3099 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3100 obj_expled_encoded = obj_expled.encode()
3101 ctx_copied = deepcopy(ctx_dummy)
3102 obj_decoded, tail = obj_expled.decode(
3103 obj_expled_encoded + tail_junk,
3107 self.assertDictEqual(ctx_copied, ctx_dummy)
3109 list(obj_decoded.pps())
3110 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3111 self.assertEqual(tail, tail_junk)
3112 self.assertEqual(obj_decoded, obj_expled)
3113 self.assertNotEqual(obj_decoded, obj)
3114 self.assertEqual(int(obj_decoded), int(obj_expled))
3115 self.assertEqual(int(obj_decoded), int(obj))
3116 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3117 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3118 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3120 obj_decoded.expl_llen,
3121 len(len_encode(len(obj_encoded))),
3123 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3124 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3127 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3129 self.assertEqual(obj_decoded.expl_offset, offset)
3130 assert_exceeding_data(
3132 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3138 def string_values_strategy(draw, alphabet, do_expl=False):
3139 bound_min, bound_max = sorted(draw(sets(
3140 integers(min_value=0, max_value=1 << 7),
3144 value = draw(one_of(
3146 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3148 default = draw(one_of(
3150 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3153 if draw(booleans()):
3154 bounds = (bound_min, bound_max)
3158 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3160 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3161 optional = draw(one_of(none(), booleans()))
3163 draw(integers(min_value=0)),
3164 draw(integers(min_value=0)),
3165 draw(integers(min_value=0)),
3167 return (value, bounds, impl, expl, default, optional, _decoded)
3170 class StringMixin(object):
3171 def test_invalid_value_type(self):
3172 with self.assertRaises(InvalidValueType) as err:
3173 self.base_klass((1, 2))
3176 def text_alphabet(self):
3177 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
3178 return printable + whitespace
3182 def test_optional(self, optional):
3183 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3184 self.assertTrue(obj.optional)
3186 @given(data_strategy())
3187 def test_ready(self, d):
3188 obj = self.base_klass()
3189 self.assertFalse(obj.ready)
3192 pprint(obj, big_blobs=True, with_decode_path=True)
3194 with self.assertRaises(ObjNotReady) as err:
3197 value = d.draw(text(alphabet=self.text_alphabet()))
3198 obj = self.base_klass(value)
3199 self.assertTrue(obj.ready)
3202 pprint(obj, big_blobs=True, with_decode_path=True)
3205 @given(data_strategy())
3206 def test_comparison(self, d):
3207 value1 = d.draw(text(alphabet=self.text_alphabet()))
3208 value2 = d.draw(text(alphabet=self.text_alphabet()))
3209 tag1 = d.draw(binary(min_size=1))
3210 tag2 = d.draw(binary(min_size=1))
3211 obj1 = self.base_klass(value1)
3212 obj2 = self.base_klass(value2)
3213 self.assertEqual(obj1 == obj2, value1 == value2)
3214 self.assertEqual(obj1 != obj2, value1 != value2)
3215 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3216 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3217 obj1 = self.base_klass(value1, impl=tag1)
3218 obj2 = self.base_klass(value1, impl=tag2)
3219 self.assertEqual(obj1 == obj2, tag1 == tag2)
3220 self.assertEqual(obj1 != obj2, tag1 != tag2)
3222 @given(data_strategy())
3223 def test_bounds_satisfied(self, d):
3224 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3225 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3226 value = d.draw(text(
3227 alphabet=self.text_alphabet(),
3231 self.base_klass(value=value, bounds=(bound_min, bound_max))
3233 @given(data_strategy())
3234 def test_bounds_unsatisfied(self, d):
3235 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3236 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3237 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3238 with self.assertRaises(BoundsError) as err:
3239 self.base_klass(value=value, bounds=(bound_min, bound_max))
3241 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3242 self.base_klass(bounds=(bound_min, bound_max)).decode(
3243 self.base_klass(value).encode()
3246 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3247 with self.assertRaises(BoundsError) as err:
3248 self.base_klass(value=value, bounds=(bound_min, bound_max))
3250 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3251 self.base_klass(bounds=(bound_min, bound_max)).decode(
3252 self.base_klass(value).encode()
3256 @given(data_strategy())
3257 def test_call(self, d):
3266 ) = d.draw(string_values_strategy(self.text_alphabet()))
3267 obj_initial = self.base_klass(
3273 optional_initial or False,
3284 ) = d.draw(string_values_strategy(
3285 self.text_alphabet(),
3286 do_expl=impl_initial is None,
3288 if (default is None) and (obj_initial.default is not None):
3291 (bounds is None) and
3292 (value is not None) and
3293 (bounds_initial is not None) and
3294 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3298 (bounds is None) and
3299 (default is not None) and
3300 (bounds_initial is not None) and
3301 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3304 obj = obj_initial(value, bounds, impl, expl, default, optional)
3306 value_expected = default if value is None else value
3308 default_initial if value_expected is None
3311 self.assertEqual(obj, value_expected)
3312 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3313 self.assertEqual(obj.expl_tag, expl or expl_initial)
3316 default_initial if default is None else default,
3318 if obj.default is None:
3319 optional = optional_initial if optional is None else optional
3320 optional = False if optional is None else optional
3323 self.assertEqual(obj.optional, optional)
3325 (obj._bound_min, obj._bound_max),
3326 bounds or bounds_initial or (0, float("+inf")),
3329 @given(data_strategy())
3330 def test_copy(self, d):
3331 values = d.draw(string_values_strategy(self.text_alphabet()))
3332 obj = self.base_klass(*values)
3333 for copy_func in copy_funcs:
3334 obj_copied = copy_func(obj)
3335 self.assert_copied_basic_fields(obj, obj_copied)
3336 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3337 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3338 self.assertEqual(obj._value, obj_copied._value)
3340 @given(data_strategy())
3341 def test_stripped(self, d):
3342 value = d.draw(text(alphabet=self.text_alphabet()))
3343 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3344 obj = self.base_klass(value, impl=tag_impl)
3345 with self.assertRaises(NotEnoughData):
3346 obj.decode(obj.encode()[:-1])
3348 @given(data_strategy())
3349 def test_stripped_expl(self, d):
3350 value = d.draw(text(alphabet=self.text_alphabet()))
3351 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3352 obj = self.base_klass(value, expl=tag_expl)
3353 with self.assertRaises(NotEnoughData):
3354 obj.decode(obj.encode()[:-1])
3357 integers(min_value=31),
3358 integers(min_value=0),
3361 def test_bad_tag(self, tag, offset, decode_path):
3362 with self.assertRaises(DecodeError) as err:
3363 self.base_klass().decode(
3364 tag_encode(tag)[:-1],
3366 decode_path=decode_path,
3369 self.assertEqual(err.exception.offset, offset)
3370 self.assertEqual(err.exception.decode_path, decode_path)
3373 integers(min_value=128),
3374 integers(min_value=0),
3377 def test_bad_len(self, l, offset, decode_path):
3378 with self.assertRaises(DecodeError) as err:
3379 self.base_klass().decode(
3380 self.base_klass.tag_default + len_encode(l)[:-1],
3382 decode_path=decode_path,
3385 self.assertEqual(err.exception.offset, offset)
3386 self.assertEqual(err.exception.decode_path, decode_path)
3389 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3390 integers(min_value=0),
3393 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3394 value, bound_min = list(sorted(ints))
3396 class String(self.base_klass):
3397 # Multiply this value by four, to satisfy UTF-32 bounds
3398 # (4 bytes per character) validation
3399 bounds = (bound_min * 4, bound_min * 4)
3400 with self.assertRaises(DecodeError) as err:
3402 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3404 decode_path=decode_path,
3407 self.assertEqual(err.exception.offset, offset)
3408 self.assertEqual(err.exception.decode_path, decode_path)
3410 @given(data_strategy())
3411 def test_symmetric(self, d):
3412 values = d.draw(string_values_strategy(self.text_alphabet()))
3413 value = d.draw(text(alphabet=self.text_alphabet()))
3414 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3415 offset = d.draw(integers(min_value=0))
3416 tail_junk = d.draw(binary(max_size=5))
3417 _, _, _, _, default, optional, _decoded = values
3418 obj = self.base_klass(
3426 pprint(obj, big_blobs=True, with_decode_path=True)
3427 self.assertFalse(obj.expled)
3428 obj_encoded = obj.encode()
3429 obj_expled = obj(value, expl=tag_expl)
3430 self.assertTrue(obj_expled.expled)
3432 list(obj_expled.pps())
3433 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3434 obj_expled_encoded = obj_expled.encode()
3435 ctx_copied = deepcopy(ctx_dummy)
3436 obj_decoded, tail = obj_expled.decode(
3437 obj_expled_encoded + tail_junk,
3441 self.assertDictEqual(ctx_copied, ctx_dummy)
3443 list(obj_decoded.pps())
3444 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3445 self.assertEqual(tail, tail_junk)
3446 self.assertEqual(obj_decoded, obj_expled)
3447 self.assertNotEqual(obj_decoded, obj)
3448 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3449 self.assertEqual(bytes(obj_decoded), bytes(obj))
3450 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3451 self.assertEqual(text_type(obj_decoded), text_type(obj))
3452 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3453 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3454 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3456 obj_decoded.expl_llen,
3457 len(len_encode(len(obj_encoded))),
3459 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3460 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3463 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3465 self.assertEqual(obj_decoded.expl_offset, offset)
3466 assert_exceeding_data(
3468 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3473 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3474 base_klass = UTF8String
3477 cyrillic_letters = text(
3478 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3484 class UnicodeDecodeErrorMixin(object):
3485 @given(cyrillic_letters)
3486 def test_unicode_decode_error(self, cyrillic_text):
3487 with self.assertRaises(DecodeError):
3488 self.base_klass(cyrillic_text)
3491 class TestNumericString(StringMixin, CommonMixin, TestCase):
3492 base_klass = NumericString
3494 def text_alphabet(self):
3497 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3498 def test_non_numeric(self, non_numeric_text):
3499 with assertRaisesRegex(self, DecodeError, "non-numeric"):
3500 self.base_klass(non_numeric_text)
3503 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3504 integers(min_value=0),
3507 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3508 value, bound_min = list(sorted(ints))
3510 class String(self.base_klass):
3511 bounds = (bound_min, bound_min)
3512 with self.assertRaises(DecodeError) as err:
3514 self.base_klass(b"1" * value).encode(),
3516 decode_path=decode_path,
3519 self.assertEqual(err.exception.offset, offset)
3520 self.assertEqual(err.exception.decode_path, decode_path)
3523 class TestPrintableString(
3524 UnicodeDecodeErrorMixin,
3529 base_klass = PrintableString
3531 def text_alphabet(self):
3532 return ascii_letters + digits + " '()+,-./:=?"
3534 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3535 def test_non_printable(self, non_printable_text):
3536 with assertRaisesRegex(self, DecodeError, "non-printable"):
3537 self.base_klass(non_printable_text)
3540 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3541 integers(min_value=0),
3544 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3545 value, bound_min = list(sorted(ints))
3547 class String(self.base_klass):
3548 bounds = (bound_min, bound_min)
3549 with self.assertRaises(DecodeError) as err:
3551 self.base_klass(b"1" * value).encode(),
3553 decode_path=decode_path,
3556 self.assertEqual(err.exception.offset, offset)
3557 self.assertEqual(err.exception.decode_path, decode_path)
3559 def test_allowable_invalid_chars(self):
3561 ("*", {"allow_asterisk": True}),
3562 ("&", {"allow_ampersand": True}),
3563 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3566 obj = self.base_klass(s)
3567 for prop in kwargs.keys():
3568 self.assertFalse(getattr(obj, prop))
3570 with assertRaisesRegex(self, DecodeError, "non-printable"):
3572 self.base_klass(s, **kwargs)
3573 klass = self.base_klass(**kwargs)
3575 for prop in kwargs.keys():
3576 self.assertTrue(getattr(obj, prop))
3579 for prop in kwargs.keys():
3580 self.assertTrue(getattr(obj, prop))
3583 class TestTeletexString(
3584 UnicodeDecodeErrorMixin,
3589 base_klass = TeletexString
3592 class TestVideotexString(
3593 UnicodeDecodeErrorMixin,
3598 base_klass = VideotexString
3601 class TestIA5String(
3602 UnicodeDecodeErrorMixin,
3607 base_klass = IA5String
3610 class TestGraphicString(
3611 UnicodeDecodeErrorMixin,
3616 base_klass = GraphicString
3619 class TestVisibleString(
3620 UnicodeDecodeErrorMixin,
3625 base_klass = VisibleString
3627 def test_x690_vector(self):
3628 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3629 self.assertSequenceEqual(tail, b"")
3630 self.assertEqual(str(obj), "Jones")
3631 self.assertFalse(obj.ber_encoded)
3632 self.assertFalse(obj.lenindef)
3633 self.assertFalse(obj.bered)
3635 obj, tail = VisibleString().decode(
3636 hexdec("3A0904034A6F6E04026573"),
3637 ctx={"bered": True},
3639 self.assertSequenceEqual(tail, b"")
3640 self.assertEqual(str(obj), "Jones")
3641 self.assertTrue(obj.ber_encoded)
3642 self.assertFalse(obj.lenindef)
3643 self.assertTrue(obj.bered)
3645 self.assertTrue(obj.ber_encoded)
3646 self.assertFalse(obj.lenindef)
3647 self.assertTrue(obj.bered)
3649 obj, tail = VisibleString().decode(
3650 hexdec("3A8004034A6F6E040265730000"),
3651 ctx={"bered": True},
3653 self.assertSequenceEqual(tail, b"")
3654 self.assertEqual(str(obj), "Jones")
3655 self.assertTrue(obj.ber_encoded)
3656 self.assertTrue(obj.lenindef)
3657 self.assertTrue(obj.bered)
3659 self.assertTrue(obj.ber_encoded)
3660 self.assertTrue(obj.lenindef)
3661 self.assertTrue(obj.bered)
3664 class TestGeneralString(
3665 UnicodeDecodeErrorMixin,
3670 base_klass = GeneralString
3673 class TestUniversalString(StringMixin, CommonMixin, TestCase):
3674 base_klass = UniversalString
3677 class TestBMPString(StringMixin, CommonMixin, TestCase):
3678 base_klass = BMPString
3682 def generalized_time_values_strategy(
3690 if draw(booleans()):
3691 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
3693 value = value.replace(microsecond=0)
3695 if draw(booleans()):
3696 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
3698 default = default.replace(microsecond=0)
3702 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3704 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3705 optional = draw(one_of(none(), booleans()))
3707 draw(integers(min_value=0)),
3708 draw(integers(min_value=0)),
3709 draw(integers(min_value=0)),
3711 return (value, impl, expl, default, optional, _decoded)
3714 class TimeMixin(object):
3715 def test_invalid_value_type(self):
3716 with self.assertRaises(InvalidValueType) as err:
3717 self.base_klass(datetime.now().timetuple())
3720 @given(data_strategy())
3721 def test_optional(self, d):
3722 default = d.draw(datetimes(
3723 min_value=self.min_datetime,
3724 max_value=self.max_datetime,
3726 optional = d.draw(booleans())
3727 obj = self.base_klass(default=default, optional=optional)
3728 self.assertTrue(obj.optional)
3730 @given(data_strategy())
3731 def test_ready(self, d):
3732 obj = self.base_klass()
3733 self.assertFalse(obj.ready)
3736 pprint(obj, big_blobs=True, with_decode_path=True)
3737 with self.assertRaises(ObjNotReady) as err:
3740 value = d.draw(datetimes(
3741 min_value=self.min_datetime,
3742 max_value=self.max_datetime,
3744 obj = self.base_klass(value)
3745 self.assertTrue(obj.ready)
3748 pprint(obj, big_blobs=True, with_decode_path=True)
3750 @given(data_strategy())
3751 def test_comparison(self, d):
3752 value1 = d.draw(datetimes(
3753 min_value=self.min_datetime,
3754 max_value=self.max_datetime,
3756 value2 = d.draw(datetimes(
3757 min_value=self.min_datetime,
3758 max_value=self.max_datetime,
3760 tag1 = d.draw(binary(min_size=1))
3761 tag2 = d.draw(binary(min_size=1))
3763 value1 = value1.replace(microsecond=0)
3764 value2 = value2.replace(microsecond=0)
3765 obj1 = self.base_klass(value1)
3766 obj2 = self.base_klass(value2)
3767 self.assertEqual(obj1 == obj2, value1 == value2)
3768 self.assertEqual(obj1 != obj2, value1 != value2)
3769 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
3770 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3771 obj1 = self.base_klass(value1, impl=tag1)
3772 obj2 = self.base_klass(value1, impl=tag2)
3773 self.assertEqual(obj1 == obj2, tag1 == tag2)
3774 self.assertEqual(obj1 != obj2, tag1 != tag2)
3776 @given(data_strategy())
3777 def test_call(self, d):
3785 ) = d.draw(generalized_time_values_strategy(
3786 min_datetime=self.min_datetime,
3787 max_datetime=self.max_datetime,
3788 omit_ms=self.omit_ms,
3790 obj_initial = self.base_klass(
3791 value=value_initial,
3794 default=default_initial,
3795 optional=optional_initial or False,
3796 _decoded=_decoded_initial,
3805 ) = d.draw(generalized_time_values_strategy(
3806 min_datetime=self.min_datetime,
3807 max_datetime=self.max_datetime,
3808 omit_ms=self.omit_ms,
3809 do_expl=impl_initial is None,
3819 value_expected = default if value is None else value
3821 default_initial if value_expected is None
3824 self.assertEqual(obj, value_expected)
3825 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3826 self.assertEqual(obj.expl_tag, expl or expl_initial)
3829 default_initial if default is None else default,
3831 if obj.default is None:
3832 optional = optional_initial if optional is None else optional
3833 optional = False if optional is None else optional
3836 self.assertEqual(obj.optional, optional)
3838 @given(data_strategy())
3839 def test_copy(self, d):
3840 values = d.draw(generalized_time_values_strategy(
3841 min_datetime=self.min_datetime,
3842 max_datetime=self.max_datetime,
3844 obj = self.base_klass(*values)
3845 for copy_func in copy_funcs:
3846 obj_copied = copy_func(obj)
3847 self.assert_copied_basic_fields(obj, obj_copied)
3848 self.assertEqual(obj._value, obj_copied._value)
3850 @given(data_strategy())
3851 def test_stripped(self, d):
3852 value = d.draw(datetimes(
3853 min_value=self.min_datetime,
3854 max_value=self.max_datetime,
3856 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3857 obj = self.base_klass(value, impl=tag_impl)
3858 with self.assertRaises(NotEnoughData):
3859 obj.decode(obj.encode()[:-1])
3861 @given(data_strategy())
3862 def test_stripped_expl(self, d):
3863 value = d.draw(datetimes(
3864 min_value=self.min_datetime,
3865 max_value=self.max_datetime,
3867 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3868 obj = self.base_klass(value, expl=tag_expl)
3869 with self.assertRaises(NotEnoughData):
3870 obj.decode(obj.encode()[:-1])
3872 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3873 @given(data_strategy())
3874 def test_symmetric(self, d):
3875 values = d.draw(generalized_time_values_strategy(
3876 min_datetime=self.min_datetime,
3877 max_datetime=self.max_datetime,
3879 value = d.draw(datetimes(
3880 min_value=self.min_datetime,
3881 max_value=self.max_datetime,
3883 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3884 offset = d.draw(integers(min_value=0))
3885 tail_junk = d.draw(binary(max_size=5))
3886 _, _, _, default, optional, _decoded = values
3887 obj = self.base_klass(
3895 pprint(obj, big_blobs=True, with_decode_path=True)
3896 self.assertFalse(obj.expled)
3897 obj_encoded = obj.encode()
3898 self.additional_symmetric_check(value, obj_encoded)
3899 obj_expled = obj(value, expl=tag_expl)
3900 self.assertTrue(obj_expled.expled)
3902 list(obj_expled.pps())
3903 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3904 obj_expled_encoded = obj_expled.encode()
3905 ctx_copied = deepcopy(ctx_dummy)
3906 obj_decoded, tail = obj_expled.decode(
3907 obj_expled_encoded + tail_junk,
3911 self.assertDictEqual(ctx_copied, ctx_dummy)
3913 list(obj_decoded.pps())
3914 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3915 self.assertEqual(tail, tail_junk)
3916 self.assertEqual(obj_decoded, obj_expled)
3917 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
3918 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
3919 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3920 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3921 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3923 obj_decoded.expl_llen,
3924 len(len_encode(len(obj_encoded))),
3926 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3927 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3930 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3932 self.assertEqual(obj_decoded.expl_offset, offset)
3933 assert_exceeding_data(
3935 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3940 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
3941 base_klass = GeneralizedTime
3943 min_datetime = datetime(1900, 1, 1)
3944 max_datetime = datetime(9999, 12, 31)
3946 def additional_symmetric_check(self, value, obj_encoded):
3947 if value.microsecond > 0:
3948 self.assertFalse(obj_encoded.endswith(b"0Z"))
3950 def test_x690_vector_valid(self):
3954 b"19920722132100.3Z",
3956 GeneralizedTime(data)
3958 def test_x690_vector_invalid(self):
3961 b"19920622123421.0Z",
3962 b"19920722132100.30Z",
3964 with self.assertRaises(DecodeError) as err:
3965 GeneralizedTime(data)
3968 def test_go_vectors_invalid(self):
3980 b"-20100102030410Z",
3981 b"2010-0102030410Z",
3982 b"2010-0002030410Z",
3983 b"201001-02030410Z",
3984 b"20100102-030410Z",
3985 b"2010010203-0410Z",
3986 b"201001020304-10Z",
3987 # These ones are INVALID in *DER*, but accepted
3988 # by Go's encoding/asn1
3989 b"20100102030405+0607",
3990 b"20100102030405-0607",
3992 with self.assertRaises(DecodeError) as err:
3993 GeneralizedTime(data)
3996 def test_go_vectors_valid(self):
3998 GeneralizedTime(b"20100102030405Z").todatetime(),
3999 datetime(2010, 1, 2, 3, 4, 5, 0),
4004 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4005 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4007 binary(min_size=1, max_size=1),
4009 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4010 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4013 def test_junk(self, part0, part1, part2):
4014 junk = part0 + part1 + part2
4015 assume(not (set(junk) <= set(digits.encode("ascii"))))
4016 with self.assertRaises(DecodeError):
4017 GeneralizedTime().decode(
4018 GeneralizedTime.tag_default +
4019 len_encode(len(junk)) +
4025 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4026 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4028 binary(min_size=1, max_size=1),
4030 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4031 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4034 def test_junk_dm(self, part0, part1, part2):
4035 junk = part0 + part1 + part2
4036 assume(not (set(junk) <= set(digits.encode("ascii"))))
4037 with self.assertRaises(DecodeError):
4038 GeneralizedTime().decode(
4039 GeneralizedTime.tag_default +
4040 len_encode(len(junk)) +
4044 def test_ns_fractions(self):
4045 GeneralizedTime(b"20010101000000.000001Z")
4046 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4047 GeneralizedTime(b"20010101000000.0000001Z")
4050 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4051 base_klass = UTCTime
4053 min_datetime = datetime(2000, 1, 1)
4054 max_datetime = datetime(2049, 12, 31)
4056 def additional_symmetric_check(self, value, obj_encoded):
4059 def test_x690_vector_valid(self):
4067 def test_x690_vector_invalid(self):
4072 with self.assertRaises(DecodeError) as err:
4076 def test_go_vectors_invalid(self):
4102 # These ones are INVALID in *DER*, but accepted
4103 # by Go's encoding/asn1
4104 b"910506164540-0700",
4105 b"910506164540+0730",
4109 with self.assertRaises(DecodeError) as err:
4113 def test_go_vectors_valid(self):
4115 UTCTime(b"910506234540Z").todatetime(),
4116 datetime(1991, 5, 6, 23, 45, 40, 0),
4119 @given(integers(min_value=0, max_value=49))
4120 def test_pre50(self, year):
4122 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4126 @given(integers(min_value=50, max_value=99))
4127 def test_post50(self, year):
4129 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4135 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4136 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4138 binary(min_size=1, max_size=1),
4140 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4141 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4144 def test_junk(self, part0, part1, part2):
4145 junk = part0 + part1 + part2
4146 assume(not (set(junk) <= set(digits.encode("ascii"))))
4147 with self.assertRaises(DecodeError):
4149 UTCTime.tag_default +
4150 len_encode(len(junk)) +
4156 def any_values_strategy(draw, do_expl=False):
4157 value = draw(one_of(none(), binary()))
4160 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4161 optional = draw(one_of(none(), booleans()))
4163 draw(integers(min_value=0)),
4164 draw(integers(min_value=0)),
4165 draw(integers(min_value=0)),
4167 return (value, expl, optional, _decoded)
4170 class AnyInherited(Any):
4174 class TestAny(CommonMixin, TestCase):
4177 def test_invalid_value_type(self):
4178 with self.assertRaises(InvalidValueType) as err:
4183 def test_optional(self, optional):
4184 obj = Any(optional=optional)
4185 self.assertEqual(obj.optional, optional)
4188 def test_ready(self, value):
4190 self.assertFalse(obj.ready)
4193 pprint(obj, big_blobs=True, with_decode_path=True)
4194 with self.assertRaises(ObjNotReady) as err:
4198 self.assertTrue(obj.ready)
4201 pprint(obj, big_blobs=True, with_decode_path=True)
4204 def test_basic(self, value):
4205 integer_encoded = Integer(value).encode()
4207 Any(integer_encoded),
4208 Any(Integer(value)),
4209 Any(Any(Integer(value))),
4211 self.assertSequenceEqual(bytes(obj), integer_encoded)
4213 obj.decode(obj.encode())[0].vlen,
4214 len(integer_encoded),
4218 pprint(obj, big_blobs=True, with_decode_path=True)
4219 self.assertSequenceEqual(obj.encode(), integer_encoded)
4221 @given(binary(), binary())
4222 def test_comparison(self, value1, value2):
4223 for klass in (Any, AnyInherited):
4224 obj1 = klass(value1)
4225 obj2 = klass(value2)
4226 self.assertEqual(obj1 == obj2, value1 == value2)
4227 self.assertEqual(obj1 != obj2, value1 != value2)
4228 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4230 @given(data_strategy())
4231 def test_call(self, d):
4232 for klass in (Any, AnyInherited):
4238 ) = d.draw(any_values_strategy())
4239 obj_initial = klass(
4242 optional_initial or False,
4250 ) = d.draw(any_values_strategy(do_expl=True))
4251 obj = obj_initial(value, expl, optional)
4253 value_expected = None if value is None else value
4254 self.assertEqual(obj, value_expected)
4255 self.assertEqual(obj.expl_tag, expl or expl_initial)
4256 if obj.default is None:
4257 optional = optional_initial if optional is None else optional
4258 optional = False if optional is None else optional
4259 self.assertEqual(obj.optional, optional)
4261 def test_simultaneous_impl_expl(self):
4262 # override it, as Any does not have implicit tag
4265 def test_decoded(self):
4266 # override it, as Any does not have implicit tag
4269 @given(any_values_strategy())
4270 def test_copy(self, values):
4271 for klass in (Any, AnyInherited):
4272 obj = klass(*values)
4273 for copy_func in copy_funcs:
4274 obj_copied = copy_func(obj)
4275 self.assert_copied_basic_fields(obj, obj_copied)
4276 self.assertEqual(obj._value, obj_copied._value)
4278 @given(binary().map(OctetString))
4279 def test_stripped(self, value):
4281 with self.assertRaises(NotEnoughData):
4282 obj.decode(obj.encode()[:-1])
4286 integers(min_value=1).map(tag_ctxc),
4288 def test_stripped_expl(self, value, tag_expl):
4289 obj = Any(value, expl=tag_expl)
4290 with self.assertRaises(NotEnoughData):
4291 obj.decode(obj.encode()[:-1])
4294 integers(min_value=31),
4295 integers(min_value=0),
4298 def test_bad_tag(self, tag, offset, decode_path):
4299 with self.assertRaises(DecodeError) as err:
4301 tag_encode(tag)[:-1],
4303 decode_path=decode_path,
4306 self.assertEqual(err.exception.offset, offset)
4307 self.assertEqual(err.exception.decode_path, decode_path)
4310 integers(min_value=128),
4311 integers(min_value=0),
4314 def test_bad_len(self, l, offset, decode_path):
4315 with self.assertRaises(DecodeError) as err:
4317 Any.tag_default + len_encode(l)[:-1],
4319 decode_path=decode_path,
4322 self.assertEqual(err.exception.offset, offset)
4323 self.assertEqual(err.exception.decode_path, decode_path)
4325 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4327 any_values_strategy(),
4328 integers().map(lambda x: Integer(x).encode()),
4329 integers(min_value=1).map(tag_ctxc),
4330 integers(min_value=0),
4333 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
4334 for klass in (Any, AnyInherited):
4335 _, _, optional, _decoded = values
4336 obj = klass(value=value, optional=optional, _decoded=_decoded)
4339 pprint(obj, big_blobs=True, with_decode_path=True)
4340 self.assertFalse(obj.expled)
4341 obj_encoded = obj.encode()
4342 obj_expled = obj(value, expl=tag_expl)
4343 self.assertTrue(obj_expled.expled)
4345 list(obj_expled.pps())
4346 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4347 obj_expled_encoded = obj_expled.encode()
4348 ctx_copied = deepcopy(ctx_dummy)
4349 obj_decoded, tail = obj_expled.decode(
4350 obj_expled_encoded + tail_junk,
4354 self.assertDictEqual(ctx_copied, ctx_dummy)
4356 list(obj_decoded.pps())
4357 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4358 self.assertEqual(tail, tail_junk)
4359 self.assertEqual(obj_decoded, obj_expled)
4360 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
4361 self.assertEqual(bytes(obj_decoded), bytes(obj))
4362 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4363 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4364 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4366 obj_decoded.expl_llen,
4367 len(len_encode(len(obj_encoded))),
4369 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4370 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4373 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4375 self.assertEqual(obj_decoded.expl_offset, offset)
4376 self.assertEqual(obj_decoded.tlen, 0)
4377 self.assertEqual(obj_decoded.llen, 0)
4378 self.assertEqual(obj_decoded.vlen, len(value))
4379 assert_exceeding_data(
4381 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4386 integers(min_value=1).map(tag_ctxc),
4387 integers(min_value=0, max_value=3),
4388 integers(min_value=0),
4392 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
4393 chunk = Boolean(False, expl=expl).encode()
4395 OctetString.tag_default +
4397 b"".join([chunk] * chunks) +
4400 with self.assertRaises(LenIndefForm):
4404 decode_path=decode_path,
4406 obj, tail = Any().decode(
4409 decode_path=decode_path,
4410 ctx={"bered": True},
4412 self.assertSequenceEqual(tail, junk)
4413 self.assertEqual(obj.offset, offset)
4414 self.assertEqual(obj.tlvlen, len(encoded))
4415 self.assertTrue(obj.lenindef)
4416 self.assertFalse(obj.ber_encoded)
4417 self.assertTrue(obj.bered)
4419 self.assertTrue(obj.lenindef)
4420 self.assertFalse(obj.ber_encoded)
4421 self.assertTrue(obj.bered)
4424 pprint(obj, big_blobs=True, with_decode_path=True)
4425 with self.assertRaises(NotEnoughData) as err:
4429 decode_path=decode_path,
4430 ctx={"bered": True},
4432 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
4433 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
4435 class SeqOf(SequenceOf):
4436 schema = Boolean(expl=expl)
4438 class Seq(Sequence):
4440 ("type", ObjectIdentifier(defines=((("value",), {
4441 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
4446 ("type", ObjectIdentifier("1.2.3")),
4447 ("value", Any(encoded)),
4449 seq_encoded = seq.encode()
4450 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
4451 self.assertIsNotNone(seq_decoded["value"].defined)
4453 list(seq_decoded.pps())
4454 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
4455 self.assertTrue(seq_decoded.bered)
4456 self.assertFalse(seq_decoded["type"].bered)
4457 self.assertTrue(seq_decoded["value"].bered)
4459 chunk = chunk[:-1] + b"\x01"
4460 chunks = b"".join([chunk] * (chunks + 1))
4461 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
4463 ("type", ObjectIdentifier("1.2.3")),
4464 ("value", Any(encoded)),
4466 seq_encoded = seq.encode()
4467 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
4468 self.assertIsNotNone(seq_decoded["value"].defined)
4470 list(seq_decoded.pps())
4471 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
4472 self.assertTrue(seq_decoded.bered)
4473 self.assertFalse(seq_decoded["type"].bered)
4474 self.assertTrue(seq_decoded["value"].bered)
4478 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
4480 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
4481 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
4483 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
4484 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
4486 min_size=len(names),
4487 max_size=len(names),
4490 (name, Integer(**tag_kwargs))
4491 for name, tag_kwargs in zip(names, tags)
4494 if value_required or draw(booleans()):
4495 value = draw(tuples(
4496 sampled_from([name for name, _ in schema]),
4497 integers().map(Integer),
4501 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4502 default = draw(one_of(
4504 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
4506 optional = draw(one_of(none(), booleans()))
4508 draw(integers(min_value=0)),
4509 draw(integers(min_value=0)),
4510 draw(integers(min_value=0)),
4512 return (schema, value, expl, default, optional, _decoded)
4515 class ChoiceInherited(Choice):
4519 class TestChoice(CommonMixin, TestCase):
4521 schema = (("whatever", Boolean()),)
4524 def test_schema_required(self):
4525 with assertRaisesRegex(self, ValueError, "schema must be specified"):
4528 def test_impl_forbidden(self):
4529 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
4530 Choice(impl=b"whatever")
4532 def test_invalid_value_type(self):
4533 with self.assertRaises(InvalidValueType) as err:
4534 self.base_klass(123)
4536 with self.assertRaises(ObjUnknown) as err:
4537 self.base_klass(("whenever", Boolean(False)))
4539 with self.assertRaises(InvalidValueType) as err:
4540 self.base_klass(("whatever", Integer(123)))
4544 def test_optional(self, optional):
4545 obj = self.base_klass(
4546 default=self.base_klass(("whatever", Boolean(False))),
4549 self.assertTrue(obj.optional)
4552 def test_ready(self, value):
4553 obj = self.base_klass()
4554 self.assertFalse(obj.ready)
4557 pprint(obj, big_blobs=True, with_decode_path=True)
4558 self.assertIsNone(obj["whatever"])
4559 with self.assertRaises(ObjNotReady) as err:
4562 obj["whatever"] = Boolean()
4563 self.assertFalse(obj.ready)
4566 pprint(obj, big_blobs=True, with_decode_path=True)
4567 obj["whatever"] = Boolean(value)
4568 self.assertTrue(obj.ready)
4571 pprint(obj, big_blobs=True, with_decode_path=True)
4573 @given(booleans(), booleans())
4574 def test_comparison(self, value1, value2):
4575 class WahlInherited(self.base_klass):
4577 for klass in (self.base_klass, WahlInherited):
4578 obj1 = klass(("whatever", Boolean(value1)))
4579 obj2 = klass(("whatever", Boolean(value2)))
4580 self.assertEqual(obj1 == obj2, value1 == value2)
4581 self.assertEqual(obj1 != obj2, value1 != value2)
4582 self.assertEqual(obj1 == obj2._value, value1 == value2)
4583 self.assertFalse(obj1 == obj2._value[1])
4585 @given(data_strategy())
4586 def test_call(self, d):
4587 for klass in (Choice, ChoiceInherited):
4595 ) = d.draw(choice_values_strategy())
4598 schema = schema_initial
4600 value=value_initial,
4602 default=default_initial,
4603 optional=optional_initial or False,
4604 _decoded=_decoded_initial,
4613 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
4614 obj = obj_initial(value, expl, default, optional)
4616 value_expected = default if value is None else value
4618 default_initial if value_expected is None
4621 self.assertEqual(obj.choice, value_expected[0])
4622 self.assertEqual(obj.value, int(value_expected[1]))
4623 self.assertEqual(obj.expl_tag, expl or expl_initial)
4624 default_expect = default_initial if default is None else default
4625 if default_expect is not None:
4626 self.assertEqual(obj.default.choice, default_expect[0])
4627 self.assertEqual(obj.default.value, int(default_expect[1]))
4628 if obj.default is None:
4629 optional = optional_initial if optional is None else optional
4630 optional = False if optional is None else optional
4633 self.assertEqual(obj.optional, optional)
4634 self.assertEqual(obj.specs, obj_initial.specs)
4636 def test_simultaneous_impl_expl(self):
4637 # override it, as Any does not have implicit tag
4640 def test_decoded(self):
4641 # override it, as Any does not have implicit tag
4644 @given(choice_values_strategy())
4645 def test_copy(self, values):
4646 _schema, value, expl, default, optional, _decoded = values
4648 class Wahl(self.base_klass):
4650 register_class(Wahl)
4655 optional=optional or False,
4658 for copy_func in copy_funcs:
4659 obj_copied = copy_func(obj)
4660 self.assertIsNone(obj.tag)
4661 self.assertIsNone(obj_copied.tag)
4662 # hack for assert_copied_basic_fields
4663 obj.tag = "whatever"
4664 obj_copied.tag = "whatever"
4665 self.assert_copied_basic_fields(obj, obj_copied)
4667 self.assertEqual(obj._value, obj_copied._value)
4668 self.assertEqual(obj.specs, obj_copied.specs)
4671 def test_stripped(self, value):
4672 obj = self.base_klass(("whatever", Boolean(value)))
4673 with self.assertRaises(NotEnoughData):
4674 obj.decode(obj.encode()[:-1])
4678 integers(min_value=1).map(tag_ctxc),
4680 def test_stripped_expl(self, value, tag_expl):
4681 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
4682 with self.assertRaises(NotEnoughData):
4683 obj.decode(obj.encode()[:-1])
4685 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4686 @given(data_strategy())
4687 def test_symmetric(self, d):
4688 _schema, value, _, default, optional, _decoded = d.draw(
4689 choice_values_strategy(value_required=True)
4691 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4692 offset = d.draw(integers(min_value=0))
4693 tail_junk = d.draw(binary(max_size=5))
4695 class Wahl(self.base_klass):
4705 pprint(obj, big_blobs=True, with_decode_path=True)
4706 self.assertFalse(obj.expled)
4707 obj_encoded = obj.encode()
4708 obj_expled = obj(value, expl=tag_expl)
4709 self.assertTrue(obj_expled.expled)
4711 list(obj_expled.pps())
4712 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4713 obj_expled_encoded = obj_expled.encode()
4714 ctx_copied = deepcopy(ctx_dummy)
4715 obj_decoded, tail = obj_expled.decode(
4716 obj_expled_encoded + tail_junk,
4720 self.assertDictEqual(ctx_copied, ctx_dummy)
4722 list(obj_decoded.pps())
4723 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4724 self.assertEqual(tail, tail_junk)
4725 self.assertEqual(obj_decoded, obj_expled)
4726 self.assertEqual(obj_decoded.choice, obj_expled.choice)
4727 self.assertEqual(obj_decoded.value, obj_expled.value)
4728 self.assertEqual(obj_decoded.choice, obj.choice)
4729 self.assertEqual(obj_decoded.value, obj.value)
4730 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4731 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4732 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4734 obj_decoded.expl_llen,
4735 len(len_encode(len(obj_encoded))),
4737 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4738 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4741 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4743 self.assertEqual(obj_decoded.expl_offset, offset)
4744 self.assertSequenceEqual(
4746 obj_decoded.value.fulloffset - offset:
4747 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
4751 assert_exceeding_data(
4753 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4758 def test_set_get(self, value):
4761 ("erste", Boolean()),
4762 ("zweite", Integer()),
4765 with self.assertRaises(ObjUnknown) as err:
4766 obj["whatever"] = "whenever"
4767 with self.assertRaises(InvalidValueType) as err:
4768 obj["zweite"] = Boolean(False)
4769 obj["zweite"] = Integer(value)
4771 with self.assertRaises(ObjUnknown) as err:
4774 self.assertIsNone(obj["erste"])
4775 self.assertEqual(obj["zweite"], Integer(value))
4777 def test_tag_mismatch(self):
4780 ("erste", Boolean()),
4782 int_encoded = Integer(123).encode()
4783 bool_encoded = Boolean(False).encode()
4785 obj.decode(bool_encoded)
4786 with self.assertRaises(TagMismatch):
4787 obj.decode(int_encoded)
4789 def test_tag_mismatch_underlying(self):
4790 class SeqOfBoolean(SequenceOf):
4793 class SeqOfInteger(SequenceOf):
4798 ("erste", SeqOfBoolean()),
4801 int_encoded = SeqOfInteger((Integer(123),)).encode()
4802 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
4804 obj.decode(bool_encoded)
4805 with self.assertRaises(TagMismatch) as err:
4806 obj.decode(int_encoded)
4807 self.assertEqual(err.exception.decode_path, ("erste", "0"))
4811 def seq_values_strategy(draw, seq_klass, do_expl=False):
4813 if draw(booleans()):
4815 value._value = draw(dictionaries(
4818 booleans().map(Boolean),
4819 integers().map(Integer),
4823 if draw(booleans()):
4824 schema = list(draw(dictionaries(
4827 booleans().map(Boolean),
4828 integers().map(Integer),
4834 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4836 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4838 if draw(booleans()):
4839 default = seq_klass()
4840 default._value = draw(dictionaries(
4843 booleans().map(Boolean),
4844 integers().map(Integer),
4847 optional = draw(one_of(none(), booleans()))
4849 draw(integers(min_value=0)),
4850 draw(integers(min_value=0)),
4851 draw(integers(min_value=0)),
4853 return (value, schema, impl, expl, default, optional, _decoded)
4857 def sequence_strategy(draw, seq_klass):
4858 inputs = draw(lists(
4860 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
4861 tuples(just(Integer), integers(), one_of(none(), integers())),
4866 integers(min_value=1),
4867 min_size=len(inputs),
4868 max_size=len(inputs),
4871 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
4872 for tag, expled in zip(tags, draw(lists(
4874 min_size=len(inputs),
4875 max_size=len(inputs),
4879 for i, optional in enumerate(draw(lists(
4880 sampled_from(("required", "optional", "empty")),
4881 min_size=len(inputs),
4882 max_size=len(inputs),
4884 if optional in ("optional", "empty"):
4885 inits[i]["optional"] = True
4886 if optional == "empty":
4888 empties = set(empties)
4889 names = list(draw(sets(
4891 min_size=len(inputs),
4892 max_size=len(inputs),
4895 for i, (klass, value, default) in enumerate(inputs):
4896 schema.append((names[i], klass(default=default, **inits[i])))
4897 seq_name = draw(text_letters())
4898 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
4901 for i, (klass, value, default) in enumerate(inputs):
4908 "default_value": None if spec.default is None else default,
4912 expect["optional"] = True
4914 expect["presented"] = True
4915 expect["value"] = value
4917 expect["optional"] = True
4918 if default is not None and default == value:
4919 expect["presented"] = False
4920 seq[name] = klass(value)
4921 expects.append(expect)
4926 def sequences_strategy(draw, seq_klass):
4927 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
4929 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
4930 for tag, expled in zip(tags, draw(lists(
4937 i for i, is_default in enumerate(draw(lists(
4943 names = list(draw(sets(
4948 seq_expectses = draw(lists(
4949 sequence_strategy(seq_klass=seq_klass),
4953 seqs = [seq for seq, _ in seq_expectses]
4955 for i, (name, seq) in enumerate(zip(names, seqs)):
4958 seq(default=(seq if i in defaulted else None), **inits[i]),
4960 seq_name = draw(text_letters())
4961 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
4964 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
4967 "expects": expects_inner,
4970 seq_outer[name] = seq_inner
4971 if seq_outer.specs[name].default is None:
4972 expect["presented"] = True
4973 expect_outers.append(expect)
4974 return seq_outer, expect_outers
4977 class SeqMixing(object):
4978 def test_invalid_value_type(self):
4979 with self.assertRaises(InvalidValueType) as err:
4980 self.base_klass(123)
4983 def test_invalid_value_type_set(self):
4984 class Seq(self.base_klass):
4985 schema = (("whatever", Boolean()),)
4987 with self.assertRaises(InvalidValueType) as err:
4988 seq["whatever"] = Integer(123)
4992 def test_optional(self, optional):
4993 obj = self.base_klass(default=self.base_klass(), optional=optional)
4994 self.assertTrue(obj.optional)
4996 @given(data_strategy())
4997 def test_ready(self, d):
4999 str(i): v for i, v in enumerate(d.draw(lists(
5006 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5013 for name in d.draw(permutations(
5014 list(ready.keys()) + list(non_ready.keys()),
5016 schema_input.append((name, Boolean()))
5018 class Seq(self.base_klass):
5019 schema = tuple(schema_input)
5021 for name in ready.keys():
5023 seq[name] = Boolean()
5024 self.assertFalse(seq.ready)
5027 pprint(seq, big_blobs=True, with_decode_path=True)
5028 for name, value in ready.items():
5029 seq[name] = Boolean(value)
5030 self.assertFalse(seq.ready)
5033 pprint(seq, big_blobs=True, with_decode_path=True)
5034 with self.assertRaises(ObjNotReady) as err:
5037 for name, value in non_ready.items():
5038 seq[name] = Boolean(value)
5039 self.assertTrue(seq.ready)
5042 pprint(seq, big_blobs=True, with_decode_path=True)
5044 @given(data_strategy())
5045 def test_call(self, d):
5046 class SeqInherited(self.base_klass):
5048 for klass in (self.base_klass, SeqInherited):
5057 ) = d.draw(seq_values_strategy(seq_klass=klass))
5058 obj_initial = klass(
5064 optional_initial or False,
5075 ) = d.draw(seq_values_strategy(
5077 do_expl=impl_initial is None,
5079 obj = obj_initial(value, impl, expl, default, optional)
5080 value_expected = default if value is None else value
5082 default_initial if value_expected is None
5085 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
5086 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
5087 self.assertEqual(obj.expl_tag, expl or expl_initial)
5089 {} if obj.default is None else obj.default._value,
5090 getattr(default_initial if default is None else default, "_value", {}),
5092 if obj.default is None:
5093 optional = optional_initial if optional is None else optional
5094 optional = False if optional is None else optional
5097 self.assertEqual(list(obj.specs.items()), schema_initial or [])
5098 self.assertEqual(obj.optional, optional)
5100 @given(data_strategy())
5101 def test_copy(self, d):
5102 class SeqInherited(self.base_klass):
5104 register_class(SeqInherited)
5105 for klass in (self.base_klass, SeqInherited):
5106 values = d.draw(seq_values_strategy(seq_klass=klass))
5107 obj = klass(*values)
5108 for copy_func in copy_funcs:
5109 obj_copied = copy_func(obj)
5110 self.assert_copied_basic_fields(obj, obj_copied)
5111 self.assertEqual(obj.specs, obj_copied.specs)
5112 self.assertEqual(obj._value, obj_copied._value)
5114 @given(data_strategy())
5115 def test_stripped(self, d):
5116 value = d.draw(integers())
5117 tag_impl = tag_encode(d.draw(integers(min_value=1)))
5119 class Seq(self.base_klass):
5121 schema = (("whatever", Integer()),)
5123 seq["whatever"] = Integer(value)
5124 with self.assertRaises(NotEnoughData):
5125 seq.decode(seq.encode()[:-1])
5127 @given(data_strategy())
5128 def test_stripped_expl(self, d):
5129 value = d.draw(integers())
5130 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5132 class Seq(self.base_klass):
5134 schema = (("whatever", Integer()),)
5136 seq["whatever"] = Integer(value)
5137 with self.assertRaises(NotEnoughData):
5138 seq.decode(seq.encode()[:-1])
5140 @given(binary(min_size=2))
5141 def test_non_tag_mismatch_raised(self, junk):
5143 _, _, len_encoded = tag_strip(memoryview(junk))
5144 len_decode(len_encoded)
5150 class Seq(self.base_klass):
5152 ("whatever", Integer()),
5154 ("whenever", Integer()),
5157 seq["whatever"] = Integer(123)
5158 seq["junk"] = Any(junk)
5159 seq["whenever"] = Integer(123)
5160 with self.assertRaises(DecodeError):
5161 seq.decode(seq.encode())
5164 integers(min_value=31),
5165 integers(min_value=0),
5168 def test_bad_tag(self, tag, offset, decode_path):
5169 with self.assertRaises(DecodeError) as err:
5170 self.base_klass().decode(
5171 tag_encode(tag)[:-1],
5173 decode_path=decode_path,
5176 self.assertEqual(err.exception.offset, offset)
5177 self.assertEqual(err.exception.decode_path, decode_path)
5180 integers(min_value=128),
5181 integers(min_value=0),
5184 def test_bad_len(self, l, offset, decode_path):
5185 with self.assertRaises(DecodeError) as err:
5186 self.base_klass().decode(
5187 self.base_klass.tag_default + len_encode(l)[:-1],
5189 decode_path=decode_path,
5192 self.assertEqual(err.exception.offset, offset)
5193 self.assertEqual(err.exception.decode_path, decode_path)
5195 def _assert_expects(self, seq, expects):
5196 for expect in expects:
5198 seq.specs[expect["name"]].optional,
5201 if expect["default_value"] is not None:
5203 seq.specs[expect["name"]].default,
5204 expect["default_value"],
5206 if expect["presented"]:
5207 self.assertIn(expect["name"], seq)
5208 self.assertEqual(seq[expect["name"]], expect["value"])
5210 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5211 @given(data_strategy())
5212 def test_symmetric(self, d):
5213 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
5214 tail_junk = d.draw(binary(max_size=5))
5215 self.assertTrue(seq.ready)
5216 self.assertFalse(seq.decoded)
5217 self._assert_expects(seq, expects)
5220 pprint(seq, big_blobs=True, with_decode_path=True)
5221 self.assertTrue(seq.ready)
5222 seq_encoded = seq.encode()
5223 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
5224 self.assertFalse(seq_decoded.lenindef)
5225 self.assertFalse(seq_decoded.ber_encoded)
5226 self.assertFalse(seq_decoded.bered)
5228 t, _, lv = tag_strip(seq_encoded)
5229 _, _, v = len_decode(lv)
5230 seq_encoded_lenindef = t + LENINDEF + v + EOC
5231 ctx_copied = deepcopy(ctx_dummy)
5232 ctx_copied["bered"] = True
5233 seq_decoded_lenindef, tail_lenindef = seq.decode(
5234 seq_encoded_lenindef + tail_junk,
5237 del ctx_copied["bered"]
5238 self.assertDictEqual(ctx_copied, ctx_dummy)
5239 self.assertTrue(seq_decoded_lenindef.lenindef)
5240 self.assertTrue(seq_decoded_lenindef.bered)
5241 seq_decoded_lenindef = copy(seq_decoded_lenindef)
5242 self.assertTrue(seq_decoded_lenindef.lenindef)
5243 self.assertTrue(seq_decoded_lenindef.bered)
5244 with self.assertRaises(DecodeError):
5245 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
5246 with self.assertRaises(DecodeError):
5247 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
5248 repr(seq_decoded_lenindef)
5249 list(seq_decoded_lenindef.pps())
5250 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
5251 self.assertTrue(seq_decoded_lenindef.ready)
5253 for decoded, decoded_tail, encoded in (
5254 (seq_decoded, tail, seq_encoded),
5255 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
5257 self.assertEqual(decoded_tail, tail_junk)
5258 self._assert_expects(decoded, expects)
5259 self.assertEqual(seq, decoded)
5260 self.assertEqual(decoded.encode(), seq_encoded)
5261 self.assertEqual(decoded.tlvlen, len(encoded))
5262 for expect in expects:
5263 if not expect["presented"]:
5264 self.assertNotIn(expect["name"], decoded)
5266 self.assertIn(expect["name"], decoded)
5267 obj = decoded[expect["name"]]
5268 self.assertTrue(obj.decoded)
5269 offset = obj.expl_offset if obj.expled else obj.offset
5270 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
5271 self.assertSequenceEqual(
5272 seq_encoded[offset:offset + tlvlen],
5276 assert_exceeding_data(
5278 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
5282 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5283 @given(data_strategy())
5284 def test_symmetric_with_seq(self, d):
5285 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
5286 self.assertTrue(seq.ready)
5287 seq_encoded = seq.encode()
5288 seq_decoded, tail = seq.decode(seq_encoded)
5289 self.assertEqual(tail, b"")
5290 self.assertTrue(seq.ready)
5291 self.assertEqual(seq, seq_decoded)
5292 self.assertEqual(seq_decoded.encode(), seq_encoded)
5293 for expect_outer in expect_outers:
5294 if not expect_outer["presented"]:
5295 self.assertNotIn(expect_outer["name"], seq_decoded)
5297 self.assertIn(expect_outer["name"], seq_decoded)
5298 obj = seq_decoded[expect_outer["name"]]
5299 self.assertTrue(obj.decoded)
5300 offset = obj.expl_offset if obj.expled else obj.offset
5301 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
5302 self.assertSequenceEqual(
5303 seq_encoded[offset:offset + tlvlen],
5306 self._assert_expects(obj, expect_outer["expects"])
5308 @given(data_strategy())
5309 def test_default_disappears(self, d):
5310 _schema = list(d.draw(dictionaries(
5312 sets(integers(), min_size=2, max_size=2),
5316 class Seq(self.base_klass):
5318 (n, Integer(default=d))
5319 for n, (_, d) in _schema
5322 for name, (value, _) in _schema:
5323 seq[name] = Integer(value)
5324 self.assertEqual(len(seq._value), len(_schema))
5325 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
5326 self.assertGreater(len(seq.encode()), len(empty_seq))
5327 for name, (_, default) in _schema:
5328 seq[name] = Integer(default)
5329 self.assertEqual(len(seq._value), 0)
5330 self.assertSequenceEqual(seq.encode(), empty_seq)
5332 @given(data_strategy())
5333 def test_encoded_default_not_accepted(self, d):
5334 _schema = list(d.draw(dictionaries(
5339 tags = [tag_encode(tag) for tag in d.draw(sets(
5340 integers(min_value=0),
5341 min_size=len(_schema),
5342 max_size=len(_schema),
5345 class SeqWithoutDefault(self.base_klass):
5347 (n, Integer(impl=t))
5348 for (n, _), t in zip(_schema, tags)
5350 seq_without_default = SeqWithoutDefault()
5351 for name, value in _schema:
5352 seq_without_default[name] = Integer(value)
5353 seq_encoded = seq_without_default.encode()
5355 class SeqWithDefault(self.base_klass):
5357 (n, Integer(default=v, impl=t))
5358 for (n, v), t in zip(_schema, tags)
5360 seq_with_default = SeqWithDefault()
5361 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
5362 seq_with_default.decode(seq_encoded)
5363 for ctx in ({"bered": True}, {"allow_default_values": True}):
5364 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
5365 self.assertTrue(seq_decoded.ber_encoded)
5366 self.assertTrue(seq_decoded.bered)
5367 seq_decoded = copy(seq_decoded)
5368 self.assertTrue(seq_decoded.ber_encoded)
5369 self.assertTrue(seq_decoded.bered)
5370 for name, value in _schema:
5371 self.assertEqual(seq_decoded[name], seq_with_default[name])
5372 self.assertEqual(seq_decoded[name], value)
5374 @given(data_strategy())
5375 def test_missing_from_spec(self, d):
5376 names = list(d.draw(sets(text_letters(), min_size=2)))
5377 tags = [tag_encode(tag) for tag in d.draw(sets(
5378 integers(min_value=0),
5379 min_size=len(names),
5380 max_size=len(names),
5382 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
5384 class SeqFull(self.base_klass):
5385 schema = [(n, Integer(impl=t)) for n, t in names_tags]
5386 seq_full = SeqFull()
5387 for i, name in enumerate(names):
5388 seq_full[name] = Integer(i)
5389 seq_encoded = seq_full.encode()
5390 altered = names_tags[:-2] + names_tags[-1:]
5392 class SeqMissing(self.base_klass):
5393 schema = [(n, Integer(impl=t)) for n, t in altered]
5394 seq_missing = SeqMissing()
5395 with self.assertRaises(TagMismatch):
5396 seq_missing.decode(seq_encoded)
5398 def test_bered(self):
5399 class Seq(self.base_klass):
5400 schema = (("underlying", Boolean()),)
5401 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
5402 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
5403 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
5404 self.assertFalse(decoded.ber_encoded)
5405 self.assertFalse(decoded.lenindef)
5406 self.assertTrue(decoded.bered)
5407 decoded = copy(decoded)
5408 self.assertFalse(decoded.ber_encoded)
5409 self.assertFalse(decoded.lenindef)
5410 self.assertTrue(decoded.bered)
5412 class Seq(self.base_klass):
5413 schema = (("underlying", OctetString()),)
5415 tag_encode(form=TagFormConstructed, num=4) +
5417 OctetString(b"whatever").encode() +
5420 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
5421 with self.assertRaises(DecodeError):
5422 Seq().decode(encoded)
5423 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
5424 self.assertFalse(decoded.ber_encoded)
5425 self.assertFalse(decoded.lenindef)
5426 self.assertTrue(decoded.bered)
5427 decoded = copy(decoded)
5428 self.assertFalse(decoded.ber_encoded)
5429 self.assertFalse(decoded.lenindef)
5430 self.assertTrue(decoded.bered)
5433 class TestSequence(SeqMixing, CommonMixin, TestCase):
5434 base_klass = Sequence
5440 def test_remaining(self, value, junk):
5441 class Seq(Sequence):
5443 ("whatever", Integer()),
5445 int_encoded = Integer(value).encode()
5447 Sequence.tag_default,
5448 len_encode(len(int_encoded + junk)),
5451 with assertRaisesRegex(self, DecodeError, "remaining"):
5452 Seq().decode(junked)
5454 @given(sets(text_letters(), min_size=2))
5455 def test_obj_unknown(self, names):
5456 missing = names.pop()
5458 class Seq(Sequence):
5459 schema = [(n, Boolean()) for n in names]
5461 with self.assertRaises(ObjUnknown) as err:
5464 with self.assertRaises(ObjUnknown) as err:
5465 seq[missing] = Boolean()
5468 def test_x690_vector(self):
5469 class Seq(Sequence):
5471 ("name", IA5String()),
5474 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
5475 self.assertEqual(seq["name"], "Smith")
5476 self.assertEqual(seq["ok"], True)
5479 class TestSet(SeqMixing, CommonMixin, TestCase):
5482 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5483 @given(data_strategy())
5484 def test_sorted(self, d):
5486 tag_encode(tag) for tag in
5487 d.draw(sets(integers(min_value=1), min_size=1, max_size=10))
5491 schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
5493 for name, _ in Seq.schema:
5494 seq[name] = OctetString(b"")
5495 seq_encoded = seq.encode()
5496 seq_decoded, _ = seq.decode(seq_encoded)
5497 self.assertSequenceEqual(
5498 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
5499 b"".join(sorted([seq[name].encode() for name, _ in Seq.schema])),
5502 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5503 @given(data_strategy())
5504 def test_unsorted(self, d):
5506 tag_encode(tag) for tag in
5507 d.draw(sets(integers(min_value=1), min_size=2, max_size=5))
5509 tags = d.draw(permutations(tags))
5510 assume(tags != sorted(tags))
5511 encoded = b"".join(OctetString(t, impl=t).encode() for t in tags)
5512 seq_encoded = b"".join((
5514 len_encode(len(encoded)),
5519 schema = [(str(i), OctetString(impl=t)) for i, t in enumerate(tags)]
5521 with assertRaisesRegex(self, DecodeError, "unordered SET"):
5522 seq.decode(seq_encoded)
5523 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
5524 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
5525 self.assertTrue(seq_decoded.ber_encoded)
5526 self.assertTrue(seq_decoded.bered)
5527 seq_decoded = copy(seq_decoded)
5528 self.assertTrue(seq_decoded.ber_encoded)
5529 self.assertTrue(seq_decoded.bered)
5530 self.assertSequenceEqual(
5531 [bytes(seq_decoded[str(i)]) for i, t in enumerate(tags)],
5537 def seqof_values_strategy(draw, schema=None, do_expl=False):
5539 schema = draw(sampled_from((Boolean(), Integer())))
5540 bound_min, bound_max = sorted(draw(sets(
5541 integers(min_value=0, max_value=10),
5545 if isinstance(schema, Boolean):
5546 values_generator = booleans().map(Boolean)
5547 elif isinstance(schema, Integer):
5548 values_generator = integers().map(Integer)
5549 values_generator = lists(
5554 values = draw(one_of(none(), values_generator))
5558 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5560 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5561 default = draw(one_of(none(), values_generator))
5562 optional = draw(one_of(none(), booleans()))
5564 draw(integers(min_value=0)),
5565 draw(integers(min_value=0)),
5566 draw(integers(min_value=0)),
5571 (bound_min, bound_max),
5580 class SeqOfMixing(object):
5581 def test_invalid_value_type(self):
5582 with self.assertRaises(InvalidValueType) as err:
5583 self.base_klass(123)
5586 def test_invalid_values_type(self):
5587 class SeqOf(self.base_klass):
5589 with self.assertRaises(InvalidValueType) as err:
5590 SeqOf([Integer(123), Boolean(False), Integer(234)])
5593 def test_schema_required(self):
5594 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5595 self.base_klass.__mro__[1]()
5597 @given(booleans(), booleans(), binary(), binary())
5598 def test_comparison(self, value1, value2, tag1, tag2):
5599 class SeqOf(self.base_klass):
5601 obj1 = SeqOf([Boolean(value1)])
5602 obj2 = SeqOf([Boolean(value2)])
5603 self.assertEqual(obj1 == obj2, value1 == value2)
5604 self.assertEqual(obj1 != obj2, value1 != value2)
5605 self.assertEqual(obj1 == list(obj2), value1 == value2)
5606 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
5607 obj1 = SeqOf([Boolean(value1)], impl=tag1)
5608 obj2 = SeqOf([Boolean(value1)], impl=tag2)
5609 self.assertEqual(obj1 == obj2, tag1 == tag2)
5610 self.assertEqual(obj1 != obj2, tag1 != tag2)
5612 @given(lists(booleans()))
5613 def test_iter(self, values):
5614 class SeqOf(self.base_klass):
5616 obj = SeqOf([Boolean(value) for value in values])
5617 self.assertEqual(len(obj), len(values))
5618 for i, value in enumerate(obj):
5619 self.assertEqual(value, values[i])
5621 @given(data_strategy())
5622 def test_ready(self, d):
5623 ready = [Integer(v) for v in d.draw(lists(
5630 range(d.draw(integers(min_value=1, max_value=5)))
5633 class SeqOf(self.base_klass):
5635 values = d.draw(permutations(ready + non_ready))
5637 for value in values:
5639 self.assertFalse(seqof.ready)
5642 pprint(seqof, big_blobs=True, with_decode_path=True)
5643 with self.assertRaises(ObjNotReady) as err:
5646 for i, value in enumerate(values):
5647 self.assertEqual(seqof[i], value)
5648 if not seqof[i].ready:
5649 seqof[i] = Integer(i)
5650 self.assertTrue(seqof.ready)
5653 pprint(seqof, big_blobs=True, with_decode_path=True)
5655 def test_spec_mismatch(self):
5656 class SeqOf(self.base_klass):
5659 seqof.append(Integer(123))
5660 with self.assertRaises(ValueError):
5661 seqof.append(Boolean(False))
5662 with self.assertRaises(ValueError):
5663 seqof[0] = Boolean(False)
5665 @given(data_strategy())
5666 def test_bounds_satisfied(self, d):
5667 class SeqOf(self.base_klass):
5669 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
5670 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
5671 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
5672 SeqOf(value=value, bounds=(bound_min, bound_max))
5674 @given(data_strategy())
5675 def test_bounds_unsatisfied(self, d):
5676 class SeqOf(self.base_klass):
5678 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
5679 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
5680 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
5681 with self.assertRaises(BoundsError) as err:
5682 SeqOf(value=value, bounds=(bound_min, bound_max))
5684 with assertRaisesRegex(self, DecodeError, "bounds") as err:
5685 SeqOf(bounds=(bound_min, bound_max)).decode(
5686 SeqOf(value).encode()
5689 value = [Boolean(True)] * d.draw(integers(
5690 min_value=bound_max + 1,
5691 max_value=bound_max + 10,
5693 with self.assertRaises(BoundsError) as err:
5694 SeqOf(value=value, bounds=(bound_min, bound_max))
5696 with assertRaisesRegex(self, DecodeError, "bounds") as err:
5697 SeqOf(bounds=(bound_min, bound_max)).decode(
5698 SeqOf(value).encode()
5702 @given(integers(min_value=1, max_value=10))
5703 def test_out_of_bounds(self, bound_max):
5704 class SeqOf(self.base_klass):
5706 bounds = (0, bound_max)
5708 for _ in range(bound_max):
5709 seqof.append(Integer(123))
5710 with self.assertRaises(BoundsError):
5711 seqof.append(Integer(123))
5713 @given(data_strategy())
5714 def test_call(self, d):
5724 ) = d.draw(seqof_values_strategy())
5726 class SeqOf(self.base_klass):
5727 schema = schema_initial
5728 obj_initial = SeqOf(
5729 value=value_initial,
5730 bounds=bounds_initial,
5733 default=default_initial,
5734 optional=optional_initial or False,
5735 _decoded=_decoded_initial,
5746 ) = d.draw(seqof_values_strategy(
5747 schema=schema_initial,
5748 do_expl=impl_initial is None,
5750 if (default is None) and (obj_initial.default is not None):
5753 (bounds is None) and
5754 (value is not None) and
5755 (bounds_initial is not None) and
5756 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
5760 (bounds is None) and
5761 (default is not None) and
5762 (bounds_initial is not None) and
5763 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
5775 value_expected = default if value is None else value
5777 default_initial if value_expected is None
5780 value_expected = () if value_expected is None else value_expected
5781 self.assertEqual(obj, value_expected)
5782 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
5783 self.assertEqual(obj.expl_tag, expl or expl_initial)
5786 default_initial if default is None else default,
5788 if obj.default is None:
5789 optional = optional_initial if optional is None else optional
5790 optional = False if optional is None else optional
5793 self.assertEqual(obj.optional, optional)
5795 (obj._bound_min, obj._bound_max),
5796 bounds or bounds_initial or (0, float("+inf")),
5799 @given(seqof_values_strategy())
5800 def test_copy(self, values):
5801 _schema, value, bounds, impl, expl, default, optional, _decoded = values
5803 class SeqOf(self.base_klass):
5805 register_class(SeqOf)
5812 optional=optional or False,
5815 for copy_func in copy_funcs:
5816 obj_copied = copy_func(obj)
5817 self.assert_copied_basic_fields(obj, obj_copied)
5818 self.assertEqual(obj._bound_min, obj_copied._bound_min)
5819 self.assertEqual(obj._bound_max, obj_copied._bound_max)
5820 self.assertEqual(obj._value, obj_copied._value)
5824 integers(min_value=1).map(tag_encode),
5826 def test_stripped(self, values, tag_impl):
5827 class SeqOf(self.base_klass):
5828 schema = OctetString()
5829 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
5830 with self.assertRaises(NotEnoughData):
5831 obj.decode(obj.encode()[:-1])
5835 integers(min_value=1).map(tag_ctxc),
5837 def test_stripped_expl(self, values, tag_expl):
5838 class SeqOf(self.base_klass):
5839 schema = OctetString()
5840 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
5841 with self.assertRaises(NotEnoughData):
5842 obj.decode(obj.encode()[:-1])
5845 integers(min_value=31),
5846 integers(min_value=0),
5849 def test_bad_tag(self, tag, offset, decode_path):
5850 with self.assertRaises(DecodeError) as err:
5851 self.base_klass().decode(
5852 tag_encode(tag)[:-1],
5854 decode_path=decode_path,
5857 self.assertEqual(err.exception.offset, offset)
5858 self.assertEqual(err.exception.decode_path, decode_path)
5861 integers(min_value=128),
5862 integers(min_value=0),
5865 def test_bad_len(self, l, offset, decode_path):
5866 with self.assertRaises(DecodeError) as err:
5867 self.base_klass().decode(
5868 self.base_klass.tag_default + len_encode(l)[:-1],
5870 decode_path=decode_path,
5873 self.assertEqual(err.exception.offset, offset)
5874 self.assertEqual(err.exception.decode_path, decode_path)
5876 @given(binary(min_size=1))
5877 def test_tag_mismatch(self, impl):
5878 assume(impl != self.base_klass.tag_default)
5879 with self.assertRaises(TagMismatch):
5880 self.base_klass(impl=impl).decode(self.base_klass().encode())
5882 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5884 seqof_values_strategy(schema=Integer()),
5885 lists(integers().map(Integer)),
5886 integers(min_value=1).map(tag_ctxc),
5887 integers(min_value=0),
5890 def test_symmetric(self, values, value, tag_expl, offset, tail_junk):
5891 _, _, _, _, _, default, optional, _decoded = values
5893 class SeqOf(self.base_klass):
5903 pprint(obj, big_blobs=True, with_decode_path=True)
5904 self.assertFalse(obj.expled)
5905 obj_encoded = obj.encode()
5906 obj_expled = obj(value, expl=tag_expl)
5907 self.assertTrue(obj_expled.expled)
5909 list(obj_expled.pps())
5910 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5911 obj_expled_encoded = obj_expled.encode()
5912 ctx_copied = deepcopy(ctx_dummy)
5913 obj_decoded, tail = obj_expled.decode(
5914 obj_expled_encoded + tail_junk,
5918 self.assertDictEqual(ctx_copied, ctx_dummy)
5920 list(obj_decoded.pps())
5921 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5922 self.assertEqual(tail, tail_junk)
5923 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
5924 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5925 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5926 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5928 obj_decoded.expl_llen,
5929 len(len_encode(len(obj_encoded))),
5931 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5932 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5935 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5937 self.assertEqual(obj_decoded.expl_offset, offset)
5938 for obj_inner in obj_decoded:
5939 self.assertIn(obj_inner, obj_decoded)
5940 self.assertSequenceEqual(
5943 obj_inner.offset - offset:
5944 obj_inner.offset + obj_inner.tlvlen - offset
5948 t, _, lv = tag_strip(obj_encoded)
5949 _, _, v = len_decode(lv)
5950 obj_encoded_lenindef = t + LENINDEF + v + EOC
5951 obj_decoded_lenindef, tail_lenindef = obj.decode(
5952 obj_encoded_lenindef + tail_junk,
5953 ctx={"bered": True},
5955 self.assertTrue(obj_decoded_lenindef.lenindef)
5956 self.assertTrue(obj_decoded_lenindef.bered)
5957 obj_decoded_lenindef = copy(obj_decoded_lenindef)
5958 self.assertTrue(obj_decoded_lenindef.lenindef)
5959 self.assertTrue(obj_decoded_lenindef.bered)
5960 repr(obj_decoded_lenindef)
5961 list(obj_decoded_lenindef.pps())
5962 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
5963 self.assertEqual(tail_lenindef, tail_junk)
5964 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
5965 with self.assertRaises(DecodeError):
5966 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
5967 with self.assertRaises(DecodeError):
5968 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
5970 assert_exceeding_data(
5972 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5976 def test_bered(self):
5977 class SeqOf(self.base_klass):
5979 encoded = Boolean(False).encode()
5980 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
5981 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
5982 with self.assertRaises(DecodeError):
5983 SeqOf().decode(encoded)
5984 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
5985 self.assertFalse(decoded.ber_encoded)
5986 self.assertFalse(decoded.lenindef)
5987 self.assertTrue(decoded.bered)
5988 decoded = copy(decoded)
5989 self.assertFalse(decoded.ber_encoded)
5990 self.assertFalse(decoded.lenindef)
5991 self.assertTrue(decoded.bered)
5993 class SeqOf(self.base_klass):
5994 schema = OctetString()
5995 encoded = OctetString(b"whatever").encode()
5997 tag_encode(form=TagFormConstructed, num=4) +
5999 OctetString(b"whatever").encode() +
6002 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
6003 with self.assertRaises(DecodeError):
6004 SeqOf().decode(encoded)
6005 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
6006 self.assertFalse(decoded.ber_encoded)
6007 self.assertFalse(decoded.lenindef)
6008 self.assertTrue(decoded.bered)
6009 decoded = copy(decoded)
6010 self.assertFalse(decoded.ber_encoded)
6011 self.assertFalse(decoded.lenindef)
6012 self.assertTrue(decoded.bered)
6015 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
6016 class SeqOf(SequenceOf):
6020 def _test_symmetric_compare_objs(self, obj1, obj2):
6021 self.assertEqual(obj1, obj2)
6022 self.assertSequenceEqual(list(obj1), list(obj2))
6025 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
6030 def _test_symmetric_compare_objs(self, obj1, obj2):
6031 self.assertSetEqual(
6032 set(int(v) for v in obj1),
6033 set(int(v) for v in obj2),
6036 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6037 @given(data_strategy())
6038 def test_sorted(self, d):
6039 values = [OctetString(v) for v in d.draw(lists(binary()))]
6042 schema = OctetString()
6044 seq_encoded = seq.encode()
6045 seq_decoded, _ = seq.decode(seq_encoded)
6046 self.assertSequenceEqual(
6047 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6048 b"".join(sorted([v.encode() for v in values])),
6051 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6052 @given(data_strategy())
6053 def test_unsorted(self, d):
6054 values = [OctetString(v).encode() for v in d.draw(sets(
6055 binary(min_size=1, max_size=5),
6059 values = d.draw(permutations(values))
6060 assume(values != sorted(values))
6061 encoded = b"".join(values)
6062 seq_encoded = b"".join((
6064 len_encode(len(encoded)),
6069 schema = OctetString()
6071 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
6072 seq.decode(seq_encoded)
6074 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6075 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6076 self.assertTrue(seq_decoded.ber_encoded)
6077 self.assertTrue(seq_decoded.bered)
6078 seq_decoded = copy(seq_decoded)
6079 self.assertTrue(seq_decoded.ber_encoded)
6080 self.assertTrue(seq_decoded.bered)
6081 self.assertSequenceEqual(
6082 [obj.encode() for obj in seq_decoded],
6087 class TestGoMarshalVectors(TestCase):
6089 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
6090 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
6091 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
6092 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
6093 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
6095 class Seq(Sequence):
6097 ("erste", Integer()),
6098 ("zweite", Integer(optional=True))
6101 seq["erste"] = Integer(64)
6102 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
6103 seq["erste"] = Integer(0x123456)
6104 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
6105 seq["erste"] = Integer(64)
6106 seq["zweite"] = Integer(65)
6107 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
6109 class NestedSeq(Sequence):
6113 seq["erste"] = Integer(127)
6114 seq["zweite"] = None
6115 nested = NestedSeq()
6116 nested["nest"] = seq
6117 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
6119 self.assertSequenceEqual(
6120 OctetString(b"\x01\x02\x03").encode(),
6121 hexdec("0403010203"),
6124 class Seq(Sequence):
6126 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
6129 seq["erste"] = Integer(64)
6130 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
6132 class Seq(Sequence):
6134 ("erste", Integer(expl=tag_ctxc(5))),
6137 seq["erste"] = Integer(64)
6138 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
6140 class Seq(Sequence):
6143 impl=tag_encode(0, klass=TagClassContext),
6148 seq["erste"] = Null()
6149 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
6151 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
6153 self.assertSequenceEqual(
6154 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
6155 hexdec("170d3730303130313030303030305a"),
6157 self.assertSequenceEqual(
6158 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
6159 hexdec("170d3039313131353232353631365a"),
6161 self.assertSequenceEqual(
6162 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
6163 hexdec("180f32313030303430353132303130315a"),
6166 class Seq(Sequence):
6168 ("erste", GeneralizedTime()),
6171 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
6172 self.assertSequenceEqual(
6174 hexdec("3011180f32303039313131353232353631365a"),
6177 self.assertSequenceEqual(
6178 BitString((1, b"\x80")).encode(),
6181 self.assertSequenceEqual(
6182 BitString((12, b"\x81\xF0")).encode(),
6183 hexdec("03030481f0"),
6186 self.assertSequenceEqual(
6187 ObjectIdentifier("1.2.3.4").encode(),
6188 hexdec("06032a0304"),
6190 self.assertSequenceEqual(
6191 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
6192 hexdec("06092a864888932d010105"),
6194 self.assertSequenceEqual(
6195 ObjectIdentifier("2.100.3").encode(),
6196 hexdec("0603813403"),
6199 self.assertSequenceEqual(
6200 PrintableString("test").encode(),
6201 hexdec("130474657374"),
6203 self.assertSequenceEqual(
6204 PrintableString("x" * 127).encode(),
6205 hexdec("137F" + "78" * 127),
6207 self.assertSequenceEqual(
6208 PrintableString("x" * 128).encode(),
6209 hexdec("138180" + "78" * 128),
6211 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
6213 class Seq(Sequence):
6215 ("erste", IA5String()),
6218 seq["erste"] = IA5String("test")
6219 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
6221 class Seq(Sequence):
6223 ("erste", PrintableString()),
6226 seq["erste"] = PrintableString("test")
6227 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
6228 # Asterisk is actually not allowable
6229 PrintableString._allowable_chars |= set(b"*")
6230 seq["erste"] = PrintableString("test*")
6231 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
6232 PrintableString._allowable_chars -= set(b"*")
6234 class Seq(Sequence):
6236 ("erste", Any(optional=True)),
6237 ("zweite", Integer()),
6240 seq["zweite"] = Integer(64)
6241 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
6246 seq.append(Integer(10))
6247 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
6249 class _SeqOf(SequenceOf):
6250 schema = PrintableString()
6252 class SeqOf(SequenceOf):
6255 _seqof.append(PrintableString("1"))
6257 seqof.append(_seqof)
6258 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
6260 class Seq(Sequence):
6262 ("erste", Integer(default=1)),
6265 seq["erste"] = Integer(0)
6266 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
6267 seq["erste"] = Integer(1)
6268 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
6269 seq["erste"] = Integer(2)
6270 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
6273 class TestPP(TestCase):
6274 @given(data_strategy())
6275 def test_oid_printing(self, d):
6277 str(ObjectIdentifier(k)): v * 2
6278 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
6280 chosen = d.draw(sampled_from(sorted(oids)))
6281 chosen_id = oids[chosen]
6282 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
6283 self.assertNotIn(chosen_id, pp_console_row(pp))
6286 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
6290 class TestAutoAddSlots(TestCase):
6292 class Inher(Integer):
6295 with self.assertRaises(AttributeError):
6297 inher.unexistent = "whatever"
6300 class TestOIDDefines(TestCase):
6301 @given(data_strategy())
6302 def runTest(self, d):
6303 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
6304 value_name_chosen = d.draw(sampled_from(value_names))
6306 ObjectIdentifier(oid)
6307 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
6309 oid_chosen = d.draw(sampled_from(oids))
6310 values = d.draw(lists(
6312 min_size=len(value_names),
6313 max_size=len(value_names),
6316 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
6317 oid: Integer() for oid in oids[:-1]
6320 for i, value_name in enumerate(value_names):
6321 _schema.append((value_name, Any(expl=tag_ctxp(i))))
6323 class Seq(Sequence):
6326 for value_name, value in zip(value_names, values):
6327 seq[value_name] = Any(Integer(value).encode())
6328 seq["type"] = oid_chosen
6329 seq, _ = Seq().decode(seq.encode())
6330 for value_name in value_names:
6331 if value_name == value_name_chosen:
6333 self.assertIsNone(seq[value_name].defined)
6334 if value_name_chosen in oids[:-1]:
6335 self.assertIsNotNone(seq[value_name_chosen].defined)
6336 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
6337 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
6340 pprint(seq, big_blobs=True, with_decode_path=True)
6343 class TestDefinesByPath(TestCase):
6344 def test_generated(self):
6345 class Seq(Sequence):
6347 ("type", ObjectIdentifier()),
6348 ("value", OctetString(expl=tag_ctxc(123))),
6351 class SeqInner(Sequence):
6353 ("typeInner", ObjectIdentifier()),
6354 ("valueInner", Any()),
6357 class PairValue(SetOf):
6360 class Pair(Sequence):
6362 ("type", ObjectIdentifier()),
6363 ("value", PairValue()),
6366 class Pairs(SequenceOf):
6373 type_octet_stringed,
6375 ObjectIdentifier(oid)
6376 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
6378 seq_integered = Seq()
6379 seq_integered["type"] = type_integered
6380 seq_integered["value"] = OctetString(Integer(123).encode())
6381 seq_integered_raw = seq_integered.encode()
6385 (type_octet_stringed, OctetString(b"whatever")),
6386 (type_integered, Integer(123)),
6387 (type_octet_stringed, OctetString(b"whenever")),
6388 (type_integered, Integer(234)),
6390 for t, v in pairs_input:
6393 pair["value"] = PairValue((Any(v),))
6395 seq_inner = SeqInner()
6396 seq_inner["typeInner"] = type_innered
6397 seq_inner["valueInner"] = Any(pairs)
6398 seq_sequenced = Seq()
6399 seq_sequenced["type"] = type_sequenced
6400 seq_sequenced["value"] = OctetString(seq_inner.encode())
6401 seq_sequenced_raw = seq_sequenced.encode()
6403 list(seq_sequenced.pps())
6404 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
6406 defines_by_path = []
6407 ctx_copied = deepcopy(ctx_dummy)
6408 seq_integered, _ = Seq().decode(
6412 self.assertDictEqual(ctx_copied, ctx_dummy)
6413 self.assertIsNone(seq_integered["value"].defined)
6414 defines_by_path.append(
6415 (("type",), ((("value",), {
6416 type_integered: Integer(),
6417 type_sequenced: SeqInner(),
6420 ctx_copied["defines_by_path"] = defines_by_path
6421 seq_integered, _ = Seq().decode(
6425 del ctx_copied["defines_by_path"]
6426 self.assertDictEqual(ctx_copied, ctx_dummy)
6427 self.assertIsNotNone(seq_integered["value"].defined)
6428 self.assertEqual(seq_integered["value"].defined[0], type_integered)
6429 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
6430 self.assertTrue(seq_integered_raw[
6431 seq_integered["value"].defined[1].offset:
6432 ].startswith(Integer(123).encode()))
6434 list(seq_integered.pps())
6435 pprint(seq_integered, big_blobs=True, with_decode_path=True)
6437 ctx_copied["defines_by_path"] = defines_by_path
6438 seq_sequenced, _ = Seq().decode(
6442 del ctx_copied["defines_by_path"]
6443 self.assertDictEqual(ctx_copied, ctx_dummy)
6444 self.assertIsNotNone(seq_sequenced["value"].defined)
6445 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
6446 seq_inner = seq_sequenced["value"].defined[1]
6447 self.assertIsNone(seq_inner["valueInner"].defined)
6449 list(seq_sequenced.pps())
6450 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
6452 defines_by_path.append((
6453 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
6454 ((("valueInner",), {type_innered: Pairs()}),),
6456 ctx_copied["defines_by_path"] = defines_by_path
6457 seq_sequenced, _ = Seq().decode(
6461 del ctx_copied["defines_by_path"]
6462 self.assertDictEqual(ctx_copied, ctx_dummy)
6463 self.assertIsNotNone(seq_sequenced["value"].defined)
6464 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
6465 seq_inner = seq_sequenced["value"].defined[1]
6466 self.assertIsNotNone(seq_inner["valueInner"].defined)
6467 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
6468 pairs = seq_inner["valueInner"].defined[1]
6470 self.assertIsNone(pair["value"][0].defined)
6472 list(seq_sequenced.pps())
6473 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
6475 defines_by_path.append((
6478 DecodePathDefBy(type_sequenced),
6480 DecodePathDefBy(type_innered),
6485 type_integered: Integer(),
6486 type_octet_stringed: OctetString(),
6489 ctx_copied["defines_by_path"] = defines_by_path
6490 seq_sequenced, _ = Seq().decode(
6494 del ctx_copied["defines_by_path"]
6495 self.assertDictEqual(ctx_copied, ctx_dummy)
6496 self.assertIsNotNone(seq_sequenced["value"].defined)
6497 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
6498 seq_inner = seq_sequenced["value"].defined[1]
6499 self.assertIsNotNone(seq_inner["valueInner"].defined)
6500 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
6501 pairs_got = seq_inner["valueInner"].defined[1]
6502 for pair_input, pair_got in zip(pairs_input, pairs_got):
6503 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
6504 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
6506 list(seq_sequenced.pps())
6507 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
6509 @given(oid_strategy(), integers())
6510 def test_simple(self, oid, tgt):
6511 class Inner(Sequence):
6513 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
6514 ObjectIdentifier(oid): Integer(),
6518 class Outer(Sequence):
6521 ("tgt", OctetString()),
6525 inner["oid"] = ObjectIdentifier(oid)
6527 outer["inner"] = inner
6528 outer["tgt"] = OctetString(Integer(tgt).encode())
6529 decoded, _ = Outer().decode(outer.encode())
6530 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
6533 class TestAbsDecodePath(TestCase):
6535 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
6536 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
6538 def test_concat(self, decode_path, rel_path):
6539 self.assertSequenceEqual(
6540 abs_decode_path(decode_path, rel_path),
6541 decode_path + rel_path,
6545 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
6546 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
6548 def test_abs(self, decode_path, rel_path):
6549 self.assertSequenceEqual(
6550 abs_decode_path(decode_path, ("/",) + rel_path),
6555 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
6556 integers(min_value=1, max_value=3),
6557 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
6559 def test_dots(self, decode_path, number_of_dots, rel_path):
6560 self.assertSequenceEqual(
6561 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
6562 decode_path[:-number_of_dots] + rel_path,
6566 class TestStrictDefaultExistence(TestCase):
6567 @given(data_strategy())
6568 def runTest(self, d):
6569 count = d.draw(integers(min_value=1, max_value=10))
6570 chosen = d.draw(integers(min_value=0, max_value=count - 1))
6572 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
6573 for i in range(count)
6575 for klass in (Sequence, Set):
6579 for i in range(count):
6580 seq["int%d" % i] = Integer(123)
6582 chosen_choice = "int%d" % chosen
6583 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
6584 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6586 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
6587 self.assertTrue(decoded.ber_encoded)
6588 self.assertTrue(decoded.bered)
6589 decoded = copy(decoded)
6590 self.assertTrue(decoded.ber_encoded)
6591 self.assertTrue(decoded.bered)
6592 decoded, _ = seq.decode(raw, ctx={"bered": True})
6593 self.assertTrue(decoded.ber_encoded)
6594 self.assertTrue(decoded.bered)
6595 decoded = copy(decoded)
6596 self.assertTrue(decoded.ber_encoded)
6597 self.assertTrue(decoded.bered)
6600 class TestX690PrefixedType(TestCase):
6602 self.assertSequenceEqual(
6603 VisibleString("Jones").encode(),
6604 hexdec("1A054A6F6E6573"),
6606 self.assertSequenceEqual(
6609 impl=tag_encode(3, klass=TagClassApplication),
6611 hexdec("43054A6F6E6573"),
6613 self.assertSequenceEqual(
6617 impl=tag_encode(3, klass=TagClassApplication),
6621 hexdec("A20743054A6F6E6573"),
6623 self.assertSequenceEqual(
6627 impl=tag_encode(3, klass=TagClassApplication),
6629 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
6631 hexdec("670743054A6F6E6573"),
6633 self.assertSequenceEqual(
6634 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
6635 hexdec("82054A6F6E6573"),
6639 class TestExplOOB(TestCase):
6641 expl = tag_ctxc(123)
6642 raw = Integer(123).encode() + Integer(234).encode()
6643 raw = b"".join((expl, len_encode(len(raw)), raw))
6644 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
6645 Integer(expl=expl).decode(raw)
6646 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
6649 class TestPickleDifferentVersion(TestCase):
6651 pickled = pickle_dumps(Integer(123), pickle_proto)
6653 version_orig = pyderasn.__version__
6654 pyderasn.__version__ += "different"
6655 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
6656 pickle_loads(pickled)
6657 pyderasn.__version__ = version_orig
6658 pickle_loads(pickled)