2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2020 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this program. If not, see
16 # <http://www.gnu.org/licenses/>.
19 from copy import deepcopy
20 from datetime import datetime
21 from datetime import timedelta
22 from importlib import import_module
23 from io import BytesIO
24 from operator import attrgetter
25 from os import environ
26 from os import urandom
27 from random import random
28 from string import ascii_letters
29 from string import digits
30 from string import printable
31 from string import whitespace
32 from time import mktime
34 from unittest import TestCase
36 from hypothesis import assume
37 from hypothesis import given
38 from hypothesis import settings
39 from hypothesis.strategies import binary
40 from hypothesis.strategies import booleans
41 from hypothesis.strategies import composite
42 from hypothesis.strategies import data as data_strategy
43 from hypothesis.strategies import datetimes
44 from hypothesis.strategies import dictionaries
45 from hypothesis.strategies import integers
46 from hypothesis.strategies import just
47 from hypothesis.strategies import lists
48 from hypothesis.strategies import none
49 from hypothesis.strategies import one_of
50 from hypothesis.strategies import permutations
51 from hypothesis.strategies import sampled_from
52 from hypothesis.strategies import sets
53 from hypothesis.strategies import text
54 from hypothesis.strategies import tuples
55 from six import assertRaisesRegex
56 from six import binary_type
57 from six import byte2int
58 from six import indexbytes
59 from six import int2byte
60 from six import iterbytes
62 from six import text_type
63 from six import unichr as six_unichr
64 from six.moves import xrange as six_xrange
65 from six.moves.cPickle import dumps as pickle_dumps
66 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
67 from six.moves.cPickle import loads as pickle_loads
69 from pyderasn import _pp
70 from pyderasn import abs_decode_path
71 from pyderasn import Any
72 from pyderasn import BitString
73 from pyderasn import BMPString
74 from pyderasn import Boolean
75 from pyderasn import BoundsError
76 from pyderasn import Choice
77 from pyderasn import DecodeError
78 from pyderasn import DecodePathDefBy
79 from pyderasn import encode2pass
80 from pyderasn import encode_cer
81 from pyderasn import Enumerated
82 from pyderasn import EOC
83 from pyderasn import EOC_LEN
84 from pyderasn import ExceedingData
85 from pyderasn import GeneralizedTime
86 from pyderasn import GeneralString
87 from pyderasn import GraphicString
88 from pyderasn import hexdec
89 from pyderasn import hexenc
90 from pyderasn import IA5String
91 from pyderasn import Integer
92 from pyderasn import InvalidLength
93 from pyderasn import InvalidOID
94 from pyderasn import InvalidValueType
95 from pyderasn import len_decode
96 from pyderasn import len_encode
97 from pyderasn import LEN_YYMMDDHHMMSSZ
98 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
99 from pyderasn import LEN_YYYYMMDDHHMMSSZ
100 from pyderasn import LENINDEF
101 from pyderasn import LenIndefForm
102 from pyderasn import NotEnoughData
103 from pyderasn import Null
104 from pyderasn import NumericString
105 from pyderasn import ObjectIdentifier
106 from pyderasn import ObjNotReady
107 from pyderasn import ObjUnknown
108 from pyderasn import OctetString
109 from pyderasn import pp_console_row
110 from pyderasn import pprint
111 from pyderasn import PrintableString
112 from pyderasn import Sequence
113 from pyderasn import SequenceOf
114 from pyderasn import Set
115 from pyderasn import SetOf
116 from pyderasn import tag_ctxc
117 from pyderasn import tag_ctxp
118 from pyderasn import tag_decode
119 from pyderasn import tag_encode
120 from pyderasn import tag_strip
121 from pyderasn import TagClassApplication
122 from pyderasn import TagClassContext
123 from pyderasn import TagClassPrivate
124 from pyderasn import TagClassUniversal
125 from pyderasn import TagFormConstructed
126 from pyderasn import TagFormPrimitive
127 from pyderasn import TagMismatch
128 from pyderasn import TeletexString
129 from pyderasn import UniversalString
130 from pyderasn import UTCTime
131 from pyderasn import UTF8String
132 from pyderasn import VideotexString
133 from pyderasn import VisibleString
136 max_examples = environ.get("MAX_EXAMPLES")
137 settings.register_profile("local", settings(
139 **({"max_examples": int(max_examples)} if max_examples else {})
141 settings.load_profile("local")
142 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
144 tag_classes = sampled_from((
150 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
151 decode_path_strat = lists(integers(), max_size=3).map(
152 lambda decode_path: tuple(str(dp) for dp in decode_path)
154 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
157 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
159 self_module = import_module(__name__)
162 def register_class(klass):
163 klassname = klass.__name__ + str(time()).replace(".", "")
164 klass.__name__ = klassname
165 klass.__qualname__ = klassname
166 setattr(self_module, klassname, klass)
169 def assert_exceeding_data(self, call, junk):
172 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
177 class TestHex(TestCase):
179 def test_symmetric(self, data):
180 self.assertEqual(hexdec(hexenc(data)), data)
183 class TestTagCoder(TestCase):
184 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
188 integers(min_value=0, max_value=30),
191 def test_short(self, klass, form, num, junk):
192 raw = tag_encode(klass=klass, form=form, num=num)
193 self.assertEqual(tag_decode(raw), (klass, form, num))
194 self.assertEqual(len(raw), 1)
196 byte2int(tag_encode(klass=klass, form=form, num=0)),
197 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
199 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
200 self.assertSequenceEqual(stripped.tobytes(), raw)
201 self.assertEqual(tlen, len(raw))
202 self.assertSequenceEqual(tail, junk)
204 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
208 integers(min_value=31),
211 def test_long(self, klass, form, num, junk):
212 raw = tag_encode(klass=klass, form=form, num=num)
213 self.assertEqual(tag_decode(raw), (klass, form, num))
214 self.assertGreater(len(raw), 1)
216 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
219 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
220 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
221 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
222 self.assertSequenceEqual(stripped.tobytes(), raw)
223 self.assertEqual(tlen, len(raw))
224 self.assertSequenceEqual(tail, junk)
226 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
227 @given(integers(min_value=31))
228 def test_unfinished_tag(self, num):
229 raw = bytearray(tag_encode(num=num))
230 for i in range(1, len(raw)):
232 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
233 tag_strip(bytes(raw))
235 def test_go_vectors_valid(self):
236 for data, (eklass, etag, elen, eform) in (
237 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
238 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
239 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
240 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
241 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
242 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
243 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
244 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
245 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
246 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
248 tag, _, len_encoded = tag_strip(memoryview(data))
249 klass, form, num = tag_decode(tag)
250 _len, _, tail = len_decode(len_encoded)
251 self.assertSequenceEqual(tail, b"")
252 self.assertEqual(klass, eklass)
253 self.assertEqual(num, etag)
254 self.assertEqual(_len, elen)
255 self.assertEqual(form, eform)
257 def test_go_vectors_invalid(self):
265 with self.assertRaises(DecodeError):
266 _, _, len_encoded = tag_strip(memoryview(data))
267 len_decode(len_encoded)
270 integers(min_value=0, max_value=127),
271 integers(min_value=0, max_value=2),
273 def test_long_instead_of_short(self, l, dummy_num):
274 octets = (b"\x00" * dummy_num) + int2byte(l)
275 octets = int2byte((dummy_num + 1) | 0x80) + octets
276 with self.assertRaises(DecodeError):
280 class TestLenCoder(TestCase):
281 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
283 integers(min_value=0, max_value=127),
286 def test_short(self, l, junk):
287 raw = len_encode(l) + junk
288 decoded, llen, tail = len_decode(memoryview(raw))
289 self.assertEqual(decoded, l)
290 self.assertEqual(llen, 1)
291 self.assertEqual(len(raw), 1 + len(junk))
292 self.assertEqual(tail.tobytes(), junk)
294 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
296 integers(min_value=128),
299 def test_long(self, l, junk):
300 raw = len_encode(l) + junk
301 decoded, llen, tail = len_decode(memoryview(raw))
302 self.assertEqual(decoded, l)
303 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
304 self.assertEqual(llen, len(raw) - len(junk))
305 self.assertNotEqual(indexbytes(raw, 1), 0)
306 self.assertSequenceEqual(tail.tobytes(), junk)
308 def test_empty(self):
309 with self.assertRaises(NotEnoughData):
312 @given(integers(min_value=128))
313 def test_stripped(self, _len):
314 with self.assertRaises(NotEnoughData):
315 len_decode(len_encode(_len)[:-1])
318 text_printable = text(alphabet=printable, min_size=1)
322 def text_letters(draw):
323 result = draw(text(alphabet=ascii_letters, min_size=1))
325 result = result.encode("ascii")
329 class CommonMixin(object):
330 def test_tag_default(self):
331 obj = self.base_klass()
332 self.assertEqual(obj.tag, obj.tag_default)
334 def test_simultaneous_impl_expl(self):
335 with self.assertRaises(ValueError):
336 self.base_klass(impl=b"whatever", expl=b"whenever")
338 @given(binary(min_size=1), integers(), integers(), integers())
339 def test_decoded(self, impl, offset, llen, vlen):
340 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
341 self.assertEqual(obj.offset, offset)
342 self.assertEqual(obj.llen, llen)
343 self.assertEqual(obj.vlen, vlen)
344 self.assertEqual(obj.tlen, len(impl))
345 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
347 @given(binary(min_size=1))
348 def test_impl_inherited(self, impl_tag):
349 class Inherited(self.base_klass):
352 self.assertSequenceEqual(obj.impl, impl_tag)
353 self.assertFalse(obj.expled)
355 tag_class, _, tag_num = tag_decode(impl_tag)
356 self.assertEqual(obj.tag_order, (tag_class, tag_num))
358 @given(binary(min_size=1))
359 def test_expl_inherited(self, expl_tag):
360 class Inherited(self.base_klass):
363 self.assertSequenceEqual(obj.expl, expl_tag)
364 self.assertTrue(obj.expled)
366 tag_class, _, tag_num = tag_decode(expl_tag)
367 self.assertEqual(obj.tag_order, (tag_class, tag_num))
369 def assert_copied_basic_fields(self, obj, obj_copied):
370 self.assertEqual(obj, obj_copied)
371 self.assertSequenceEqual(obj.tag, obj_copied.tag)
372 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
373 self.assertEqual(obj.default, obj_copied.default)
374 self.assertEqual(obj.optional, obj_copied.optional)
375 self.assertEqual(obj.offset, obj_copied.offset)
376 self.assertEqual(obj.llen, obj_copied.llen)
377 self.assertEqual(obj.vlen, obj_copied.vlen)
379 self.assertEqual(obj.tag_order, obj_copied.tag_order)
383 def boolean_values_strategy(draw, do_expl=False):
384 value = draw(one_of(none(), booleans()))
388 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
390 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
391 default = draw(one_of(none(), booleans()))
392 optional = draw(one_of(none(), booleans()))
394 draw(integers(min_value=0)),
395 draw(integers(min_value=0)),
396 draw(integers(min_value=0)),
398 return (value, impl, expl, default, optional, _decoded)
401 class BooleanInherited(Boolean):
405 class TestBoolean(CommonMixin, TestCase):
408 def test_invalid_value_type(self):
409 with self.assertRaises(InvalidValueType) as err:
414 def test_optional(self, optional):
415 obj = Boolean(default=Boolean(False), optional=optional)
416 self.assertTrue(obj.optional)
419 def test_ready(self, value):
421 self.assertFalse(obj.ready)
424 pprint(obj, big_blobs=True, with_decode_path=True)
425 with self.assertRaises(ObjNotReady) as err:
427 with self.assertRaises(ObjNotReady) as err:
431 self.assertTrue(obj.ready)
434 pprint(obj, big_blobs=True, with_decode_path=True)
436 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
437 def test_comparison(self, value1, value2, tag1, tag2):
438 for klass in (Boolean, BooleanInherited):
441 self.assertEqual(obj1 == obj2, value1 == value2)
442 self.assertEqual(obj1 != obj2, value1 != value2)
443 self.assertEqual(obj1 == bool(obj2), value1 == value2)
444 obj1 = klass(value1, impl=tag1)
445 obj2 = klass(value1, impl=tag2)
446 self.assertEqual(obj1 == obj2, tag1 == tag2)
447 self.assertEqual(obj1 != obj2, tag1 != tag2)
449 @given(data_strategy())
450 def test_call(self, d):
451 for klass in (Boolean, BooleanInherited):
459 ) = d.draw(boolean_values_strategy())
465 optional_initial or False,
475 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
476 obj = obj_initial(value, impl, expl, default, optional)
478 value_expected = default if value is None else value
480 default_initial if value_expected is None
483 self.assertEqual(obj, value_expected)
484 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
485 self.assertEqual(obj.expl_tag, expl or expl_initial)
488 default_initial if default is None else default,
490 if obj.default is None:
491 optional = optional_initial if optional is None else optional
492 optional = False if optional is None else optional
495 self.assertEqual(obj.optional, optional)
497 @given(boolean_values_strategy())
498 def test_copy(self, values):
499 for klass in (Boolean, BooleanInherited):
501 for copy_func in copy_funcs:
502 obj_copied = copy_func(obj)
503 self.assert_copied_basic_fields(obj, obj_copied)
507 integers(min_value=1).map(tag_encode),
509 def test_stripped(self, value, tag_impl):
510 obj = Boolean(value, impl=tag_impl)
511 with self.assertRaises(NotEnoughData):
512 obj.decode(obj.encode()[:-1])
513 with self.assertRaises(NotEnoughData):
514 obj.decode(encode2pass(obj)[:-1])
518 integers(min_value=1).map(tag_ctxc),
520 def test_stripped_expl(self, value, tag_expl):
521 obj = Boolean(value, expl=tag_expl)
522 with self.assertRaises(NotEnoughData):
523 obj.decode(obj.encode()[:-1])
524 with self.assertRaises(NotEnoughData):
525 obj.decode(encode2pass(obj)[:-1])
528 integers(min_value=31),
529 integers(min_value=0),
532 def test_bad_tag(self, tag, offset, decode_path):
533 with self.assertRaises(DecodeError) as err:
535 tag_encode(tag)[:-1],
537 decode_path=decode_path,
540 self.assertEqual(err.exception.offset, offset)
541 self.assertEqual(err.exception.decode_path, decode_path)
544 integers(min_value=31),
545 integers(min_value=0),
548 def test_bad_expl_tag(self, tag, offset, decode_path):
549 with self.assertRaises(DecodeError) as err:
550 Boolean(expl=Boolean.tag_default).decode(
551 tag_encode(tag)[:-1],
553 decode_path=decode_path,
556 self.assertEqual(err.exception.offset, offset)
557 self.assertEqual(err.exception.decode_path, decode_path)
560 integers(min_value=128),
561 integers(min_value=0),
564 def test_bad_len(self, l, offset, decode_path):
565 with self.assertRaises(DecodeError) as err:
567 Boolean.tag_default + len_encode(l)[:-1],
569 decode_path=decode_path,
572 self.assertEqual(err.exception.offset, offset)
573 self.assertEqual(err.exception.decode_path, decode_path)
576 integers(min_value=128),
577 integers(min_value=0),
580 def test_bad_expl_len(self, l, offset, decode_path):
581 with self.assertRaises(DecodeError) as err:
582 Boolean(expl=Boolean.tag_default).decode(
583 Boolean.tag_default + len_encode(l)[:-1],
585 decode_path=decode_path,
588 self.assertEqual(err.exception.offset, offset)
589 self.assertEqual(err.exception.decode_path, decode_path)
591 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
593 boolean_values_strategy(),
595 integers(min_value=1).map(tag_ctxc),
596 integers(min_value=0),
600 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
601 for klass in (Boolean, BooleanInherited):
602 _, _, _, default, optional, _decoded = values
611 pprint(obj, big_blobs=True, with_decode_path=True)
612 self.assertFalse(obj.expled)
613 obj_encoded = obj.encode()
614 self.assertEqual(encode2pass(obj), obj_encoded)
615 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
616 obj_expled = obj(value, expl=tag_expl)
617 self.assertTrue(obj_expled.expled)
619 list(obj_expled.pps())
620 pprint(obj_expled, big_blobs=True, with_decode_path=True)
621 obj_expled_cer = encode_cer(obj_expled)
622 self.assertNotEqual(obj_expled_cer, obj_encoded)
623 self.assertSequenceEqual(
624 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
627 obj_expled_hex_encoded = obj_expled.hexencode()
628 ctx_copied = deepcopy(ctx_dummy)
629 obj_decoded, tail = obj_expled.hexdecode(
630 obj_expled_hex_encoded + hexenc(tail_junk),
634 self.assertDictEqual(ctx_copied, ctx_dummy)
636 list(obj_decoded.pps())
637 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
638 self.assertEqual(tail, tail_junk)
639 self.assertEqual(obj_decoded, obj_expled)
640 self.assertNotEqual(obj_decoded, obj)
641 self.assertEqual(bool(obj_decoded), bool(obj_expled))
642 self.assertEqual(bool(obj_decoded), bool(obj))
643 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
644 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
645 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
647 obj_decoded.expl_llen,
648 len(len_encode(len(obj_encoded))),
650 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
651 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
654 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
656 self.assertEqual(obj_decoded.expl_offset, offset)
657 assert_exceeding_data(
659 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
663 evgens = list(obj_expled.decode_evgen(
664 hexdec(obj_expled_hex_encoded) + tail_junk,
666 decode_path=decode_path,
669 self.assertEqual(len(evgens), 1)
670 _decode_path, obj, tail = evgens[0]
671 self.assertSequenceEqual(tail, tail_junk)
672 self.assertEqual(_decode_path, decode_path)
673 self.assertEqual(obj, obj_decoded)
674 self.assertEqual(obj.expl_offset, offset)
678 @given(integers(min_value=2))
679 def test_invalid_len(self, l):
680 with self.assertRaises(InvalidLength):
681 Boolean().decode(b"".join((
687 @given(integers(min_value=0 + 1, max_value=255 - 1))
688 def test_ber_value(self, value):
689 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
690 Boolean().decode(b"".join((
700 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
701 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
702 self.assertTrue(bool(obj))
703 self.assertTrue(obj.ber_encoded)
704 self.assertFalse(obj.lenindef)
705 self.assertTrue(obj.bered)
707 self.assertTrue(obj.ber_encoded)
708 self.assertFalse(obj.lenindef)
709 self.assertTrue(obj.bered)
712 integers(min_value=1).map(tag_ctxc),
713 binary().filter(lambda x: not x.startswith(EOC)),
715 def test_ber_expl_no_eoc(self, expl, junk):
716 encoded = expl + LENINDEF + Boolean(False).encode()
717 with self.assertRaises(LenIndefForm):
718 Boolean(expl=expl).decode(encoded + junk)
719 with assertRaisesRegex(self, DecodeError, "no EOC"):
720 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
721 obj, tail = Boolean(expl=expl).decode(
722 encoded + EOC + junk,
725 self.assertTrue(obj.expl_lenindef)
726 self.assertFalse(obj.lenindef)
727 self.assertFalse(obj.ber_encoded)
728 self.assertTrue(obj.bered)
730 self.assertTrue(obj.expl_lenindef)
731 self.assertFalse(obj.lenindef)
732 self.assertFalse(obj.ber_encoded)
733 self.assertTrue(obj.bered)
734 self.assertSequenceEqual(tail, junk)
737 pprint(obj, big_blobs=True, with_decode_path=True)
740 integers(min_value=1).map(tag_ctxc),
747 def test_ber_expl(self, expl, values):
753 Boolean(value).encode() +
756 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
758 class SeqOf(SequenceOf):
759 schema = Boolean(expl=expl)
760 with self.assertRaises(LenIndefForm):
761 SeqOf().decode(encoded)
762 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
763 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
764 self.assertSequenceEqual(tail, b"")
765 self.assertSequenceEqual([bool(v) for v in seqof], values)
781 len(expl) + 1 + 3 + EOC_LEN,
792 pprint(seqof, big_blobs=True, with_decode_path=True)
796 def integer_values_strategy(draw, do_expl=False):
797 bound_min, value, default, bound_max = sorted(draw(sets(
806 _specs = draw(sets(text_letters()))
809 min_size=len(_specs),
810 max_size=len(_specs),
812 _specs = list(zip(_specs, values))
815 bounds = (bound_min, bound_max)
819 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
821 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
824 optional = draw(one_of(none(), booleans()))
826 draw(integers(min_value=0)),
827 draw(integers(min_value=0)),
828 draw(integers(min_value=0)),
830 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
833 class IntegerInherited(Integer):
837 class TestInteger(CommonMixin, TestCase):
840 def test_invalid_value_type(self):
841 with self.assertRaises(InvalidValueType) as err:
845 @given(sets(text_letters(), min_size=2))
846 def test_unknown_name(self, names_input):
847 missing = names_input.pop()
850 schema = [(n, 123) for n in names_input]
851 with self.assertRaises(ObjUnknown) as err:
855 @given(sets(text_letters(), min_size=2))
856 def test_known_name(self, names_input):
858 schema = [(n, 123) for n in names_input]
859 Int(names_input.pop())
862 def test_optional(self, optional):
863 obj = Integer(default=Integer(0), optional=optional)
864 self.assertTrue(obj.optional)
867 def test_ready(self, value):
869 self.assertFalse(obj.ready)
872 pprint(obj, big_blobs=True, with_decode_path=True)
873 with self.assertRaises(ObjNotReady) as err:
875 with self.assertRaises(ObjNotReady) as err:
879 self.assertTrue(obj.ready)
882 pprint(obj, big_blobs=True, with_decode_path=True)
885 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
886 def test_comparison(self, value1, value2, tag1, tag2):
887 for klass in (Integer, IntegerInherited):
890 self.assertEqual(obj1 == obj2, value1 == value2)
891 self.assertEqual(obj1 != obj2, value1 != value2)
892 self.assertEqual(obj1 == int(obj2), value1 == value2)
893 obj1 = klass(value1, impl=tag1)
894 obj2 = klass(value1, impl=tag2)
895 self.assertEqual(obj1 == obj2, tag1 == tag2)
896 self.assertEqual(obj1 != obj2, tag1 != tag2)
898 @given(lists(integers()))
899 def test_sorted_works(self, values):
900 self.assertSequenceEqual(
901 [int(v) for v in sorted(Integer(v) for v in values)],
905 @given(data_strategy())
906 def test_named(self, d):
907 names_input = list(d.draw(sets(text_letters(), min_size=1)))
908 values_input = list(d.draw(sets(
910 min_size=len(names_input),
911 max_size=len(names_input),
913 chosen_name = d.draw(sampled_from(names_input))
914 names_input = dict(zip(names_input, values_input))
918 _int = Int(chosen_name)
919 self.assertEqual(_int.named, chosen_name)
920 self.assertEqual(int(_int), names_input[chosen_name])
922 @given(integers(), integers(min_value=0), integers(min_value=0))
923 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
924 value = bound_min + value_delta
925 bound_max = value + bound_delta
926 Integer(value=value, bounds=(bound_min, bound_max))
928 @given(sets(integers(), min_size=3, max_size=3))
929 def test_bounds_unsatisfied(self, values):
930 values = sorted(values)
931 with self.assertRaises(BoundsError) as err:
932 Integer(value=values[0], bounds=(values[1], values[2]))
934 with assertRaisesRegex(self, DecodeError, "bounds") as err:
935 Integer(bounds=(values[1], values[2])).decode(
936 Integer(values[0]).encode()
939 with assertRaisesRegex(self, DecodeError, "bounds") as err:
940 Integer(bounds=(values[1], values[2])).decode(
941 encode2pass(Integer(values[0]))
943 with self.assertRaises(BoundsError) as err:
944 Integer(value=values[2], bounds=(values[0], values[1]))
946 with assertRaisesRegex(self, DecodeError, "bounds") as err:
947 Integer(bounds=(values[0], values[1])).decode(
948 Integer(values[2]).encode()
951 with assertRaisesRegex(self, DecodeError, "bounds") as err:
952 Integer(bounds=(values[0], values[1])).decode(
953 encode2pass(Integer(values[2]))
956 @given(data_strategy())
957 def test_call(self, d):
958 for klass in (Integer, IntegerInherited):
968 ) = d.draw(integer_values_strategy())
975 optional_initial or False,
988 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
989 if (default is None) and (obj_initial.default is not None):
993 (value is not None) and
994 (bounds_initial is not None) and
995 not (bounds_initial[0] <= value <= bounds_initial[1])
1000 (default is not None) and
1001 (bounds_initial is not None) and
1002 not (bounds_initial[0] <= default <= bounds_initial[1])
1005 obj = obj_initial(value, bounds, impl, expl, default, optional)
1007 value_expected = default if value is None else value
1009 default_initial if value_expected is None
1012 self.assertEqual(obj, value_expected)
1013 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1014 self.assertEqual(obj.expl_tag, expl or expl_initial)
1017 default_initial if default is None else default,
1019 if obj.default is None:
1020 optional = optional_initial if optional is None else optional
1021 optional = False if optional is None else optional
1024 self.assertEqual(obj.optional, optional)
1026 (obj._bound_min, obj._bound_max),
1027 bounds or bounds_initial or (float("-inf"), float("+inf")),
1031 {} if _specs_initial is None else dict(_specs_initial),
1034 @given(integer_values_strategy())
1035 def test_copy(self, values):
1036 for klass in (Integer, IntegerInherited):
1037 obj = klass(*values)
1038 for copy_func in copy_funcs:
1039 obj_copied = copy_func(obj)
1040 self.assert_copied_basic_fields(obj, obj_copied)
1041 self.assertEqual(obj.specs, obj_copied.specs)
1042 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1043 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1044 self.assertEqual(obj._value, obj_copied._value)
1048 integers(min_value=1).map(tag_encode),
1050 def test_stripped(self, value, tag_impl):
1051 obj = Integer(value, impl=tag_impl)
1052 with self.assertRaises(NotEnoughData):
1053 obj.decode(obj.encode()[:-1])
1057 integers(min_value=1).map(tag_ctxc),
1059 def test_stripped_expl(self, value, tag_expl):
1060 obj = Integer(value, expl=tag_expl)
1061 with self.assertRaises(NotEnoughData):
1062 obj.decode(obj.encode()[:-1])
1064 def test_zero_len(self):
1065 with self.assertRaises(NotEnoughData):
1066 Integer().decode(b"".join((
1067 Integer.tag_default,
1072 integers(min_value=31),
1073 integers(min_value=0),
1076 def test_bad_tag(self, tag, offset, decode_path):
1077 with self.assertRaises(DecodeError) as err:
1079 tag_encode(tag)[:-1],
1081 decode_path=decode_path,
1084 self.assertEqual(err.exception.offset, offset)
1085 self.assertEqual(err.exception.decode_path, decode_path)
1088 integers(min_value=128),
1089 integers(min_value=0),
1092 def test_bad_len(self, l, offset, decode_path):
1093 with self.assertRaises(DecodeError) as err:
1095 Integer.tag_default + len_encode(l)[:-1],
1097 decode_path=decode_path,
1100 self.assertEqual(err.exception.offset, offset)
1101 self.assertEqual(err.exception.decode_path, decode_path)
1104 sets(integers(), min_size=2, max_size=2),
1105 integers(min_value=0),
1108 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1109 value, bound_min = list(sorted(ints))
1112 bounds = (bound_min, bound_min)
1113 with self.assertRaises(DecodeError) as err:
1115 Integer(value).encode(),
1117 decode_path=decode_path,
1120 self.assertEqual(err.exception.offset, offset)
1121 self.assertEqual(err.exception.decode_path, decode_path)
1123 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1125 integer_values_strategy(),
1127 integers(min_value=1).map(tag_ctxc),
1128 integers(min_value=0),
1132 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1133 for klass in (Integer, IntegerInherited):
1134 _, _, _, _, default, optional, _, _decoded = values
1143 pprint(obj, big_blobs=True, with_decode_path=True)
1144 self.assertFalse(obj.expled)
1145 obj_encoded = obj.encode()
1146 self.assertEqual(encode2pass(obj), obj_encoded)
1147 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1148 obj_expled = obj(value, expl=tag_expl)
1149 self.assertTrue(obj_expled.expled)
1151 list(obj_expled.pps())
1152 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1153 obj_expled_encoded = obj_expled.encode()
1154 obj_expled_cer = encode_cer(obj_expled)
1155 self.assertNotEqual(obj_expled_cer, obj_encoded)
1156 self.assertSequenceEqual(
1157 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1160 ctx_copied = deepcopy(ctx_dummy)
1161 obj_decoded, tail = obj_expled.decode(
1162 obj_expled_encoded + tail_junk,
1166 self.assertDictEqual(ctx_copied, ctx_dummy)
1168 list(obj_decoded.pps())
1169 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1170 self.assertEqual(tail, tail_junk)
1171 self.assertEqual(obj_decoded, obj_expled)
1172 self.assertNotEqual(obj_decoded, obj)
1173 self.assertEqual(int(obj_decoded), int(obj_expled))
1174 self.assertEqual(int(obj_decoded), int(obj))
1175 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1176 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1177 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1179 obj_decoded.expl_llen,
1180 len(len_encode(len(obj_encoded))),
1182 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1183 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1186 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1188 self.assertEqual(obj_decoded.expl_offset, offset)
1189 assert_exceeding_data(
1191 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1195 evgens = list(obj_expled.decode_evgen(
1196 obj_expled_encoded + tail_junk,
1198 decode_path=decode_path,
1201 self.assertEqual(len(evgens), 1)
1202 _decode_path, obj, tail = evgens[0]
1203 self.assertSequenceEqual(tail, tail_junk)
1204 self.assertEqual(_decode_path, decode_path)
1205 self.assertEqual(obj, obj_decoded)
1206 self.assertEqual(obj.expl_offset, offset)
1210 def test_go_vectors_valid(self):
1211 for data, expect in ((
1215 (b"\xff\x7f", -129),
1219 (b"\xff\x00", -256),
1223 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1224 (b"\x80\x00\x00\x00", -2147483648),
1227 Integer().decode(b"".join((
1228 Integer.tag_default,
1229 len_encode(len(data)),
1235 def test_go_vectors_invalid(self):
1240 with self.assertRaises(DecodeError):
1241 Integer().decode(b"".join((
1242 Integer.tag_default,
1243 len_encode(len(data)),
1249 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1252 if draw(booleans()):
1253 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1255 integers(min_value=0, max_value=255),
1256 min_size=len(schema),
1257 max_size=len(schema),
1259 schema = list(zip(schema, bits))
1261 def _value(value_required):
1262 if not value_required and draw(booleans()):
1264 generation_choice = 0
1266 generation_choice = draw(sampled_from((1, 2, 3)))
1267 if generation_choice == 1 or draw(booleans()):
1268 return "'%s'B" % "".join(draw(lists(
1269 sampled_from(("0", "1")),
1270 max_size=len(schema),
1272 if generation_choice == 2 or draw(booleans()):
1273 return draw(binary(max_size=len(schema) // 8))
1274 if generation_choice == 3 or draw(booleans()):
1275 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1277 value = _value(value_required)
1278 default = _value(value_required=False)
1282 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1284 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1285 optional = draw(one_of(none(), booleans()))
1287 draw(integers(min_value=0)),
1288 draw(integers(min_value=0)),
1289 draw(integers(min_value=0)),
1291 return (schema, value, impl, expl, default, optional, _decoded)
1294 class BitStringInherited(BitString):
1298 class TestBitString(CommonMixin, TestCase):
1299 base_klass = BitString
1301 @given(lists(booleans()))
1302 def test_b_encoding(self, bits):
1303 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1304 self.assertEqual(obj.bit_len, len(bits))
1305 self.assertSequenceEqual(list(obj), bits)
1306 for i, bit in enumerate(bits):
1307 self.assertEqual(obj[i], bit)
1309 @given(lists(booleans()))
1310 def test_out_of_bounds_bits(self, bits):
1311 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1312 for i in range(len(bits), len(bits) * 2):
1313 self.assertFalse(obj[i])
1315 def test_bad_b_encoding(self):
1316 with self.assertRaises(ValueError):
1317 BitString("'010120101'B")
1320 integers(min_value=1, max_value=255),
1321 integers(min_value=1, max_value=255),
1323 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1324 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1325 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1326 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1328 class BS(BitString):
1329 schema = (("whatever", 0),)
1330 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1331 self.assertEqual(obj.bit_len, leading_zeros + 1)
1332 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1334 def test_zero_len(self):
1335 with self.assertRaises(NotEnoughData):
1336 BitString().decode(b"".join((
1337 BitString.tag_default,
1341 def test_invalid_value_type(self):
1342 with self.assertRaises(InvalidValueType) as err:
1345 with self.assertRaises(InvalidValueType) as err:
1349 def test_obj_unknown(self):
1350 with self.assertRaises(ObjUnknown) as err:
1351 BitString(b"whatever")["whenever"]
1354 def test_get_invalid_type(self):
1355 with self.assertRaises(InvalidValueType) as err:
1356 BitString(b"whatever")[(1, 2, 3)]
1359 @given(data_strategy())
1360 def test_unknown_name(self, d):
1361 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1362 missing = _schema.pop()
1364 class BS(BitString):
1365 schema = [(n, i) for i, n in enumerate(_schema)]
1366 with self.assertRaises(ObjUnknown) as err:
1371 def test_optional(self, optional):
1372 obj = BitString(default=BitString(b""), optional=optional)
1373 self.assertTrue(obj.optional)
1376 def test_ready(self, value):
1378 self.assertFalse(obj.ready)
1381 pprint(obj, big_blobs=True, with_decode_path=True)
1382 with self.assertRaises(ObjNotReady) as err:
1385 with self.assertRaises(ObjNotReady) as err:
1387 obj = BitString(value)
1388 self.assertTrue(obj.ready)
1391 pprint(obj, big_blobs=True, with_decode_path=True)
1394 tuples(integers(min_value=0), binary()),
1395 tuples(integers(min_value=0), binary()),
1399 def test_comparison(self, value1, value2, tag1, tag2):
1400 for klass in (BitString, BitStringInherited):
1401 obj1 = klass(value1)
1402 obj2 = klass(value2)
1403 self.assertEqual(obj1 == obj2, value1 == value2)
1404 self.assertEqual(obj1 != obj2, value1 != value2)
1405 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1406 obj1 = klass(value1, impl=tag1)
1407 obj2 = klass(value1, impl=tag2)
1408 self.assertEqual(obj1 == obj2, tag1 == tag2)
1409 self.assertEqual(obj1 != obj2, tag1 != tag2)
1411 @given(data_strategy())
1412 def test_call(self, d):
1413 for klass in (BitString, BitStringInherited):
1422 ) = d.draw(bit_string_values_strategy())
1425 schema = schema_initial
1427 value=value_initial,
1430 default=default_initial,
1431 optional=optional_initial or False,
1432 _decoded=_decoded_initial,
1442 ) = d.draw(bit_string_values_strategy(
1443 schema=schema_initial,
1444 do_expl=impl_initial is None,
1453 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1454 self.assertEqual(obj.expl_tag, expl or expl_initial)
1455 if obj.default is None:
1456 optional = optional_initial if optional is None else optional
1457 optional = False if optional is None else optional
1460 self.assertEqual(obj.optional, optional)
1461 self.assertEqual(obj.specs, obj_initial.specs)
1463 @given(bit_string_values_strategy())
1464 def test_copy(self, values):
1465 for klass in (BitString, BitStringInherited):
1466 _schema, value, impl, expl, default, optional, _decoded = values
1476 optional=optional or False,
1479 for copy_func in copy_funcs:
1480 obj_copied = copy_func(obj)
1481 self.assert_copied_basic_fields(obj, obj_copied)
1482 self.assertEqual(obj.specs, obj_copied.specs)
1483 self.assertEqual(obj._value, obj_copied._value)
1487 integers(min_value=1).map(tag_encode),
1489 def test_stripped(self, value, tag_impl):
1490 obj = BitString(value, impl=tag_impl)
1491 with self.assertRaises(NotEnoughData):
1492 obj.decode(obj.encode()[:-1])
1496 integers(min_value=1).map(tag_ctxc),
1498 def test_stripped_expl(self, value, tag_expl):
1499 obj = BitString(value, expl=tag_expl)
1500 with self.assertRaises(NotEnoughData):
1501 obj.decode(obj.encode()[:-1])
1504 integers(min_value=31),
1505 integers(min_value=0),
1508 def test_bad_tag(self, tag, offset, decode_path):
1509 with self.assertRaises(DecodeError) as err:
1511 tag_encode(tag)[:-1],
1513 decode_path=decode_path,
1516 self.assertEqual(err.exception.offset, offset)
1517 self.assertEqual(err.exception.decode_path, decode_path)
1520 integers(min_value=128),
1521 integers(min_value=0),
1524 def test_bad_len(self, l, offset, decode_path):
1525 with self.assertRaises(DecodeError) as err:
1527 BitString.tag_default + len_encode(l)[:-1],
1529 decode_path=decode_path,
1532 self.assertEqual(err.exception.offset, offset)
1533 self.assertEqual(err.exception.decode_path, decode_path)
1535 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1536 @given(data_strategy())
1537 def test_symmetric(self, d):
1546 ) = d.draw(bit_string_values_strategy(value_required=True))
1547 tail_junk = d.draw(binary(max_size=5))
1548 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1549 offset = d.draw(integers(min_value=0))
1550 decode_path = d.draw(decode_path_strat)
1551 for klass in (BitString, BitStringInherited):
1562 pprint(obj, big_blobs=True, with_decode_path=True)
1563 self.assertFalse(obj.expled)
1564 obj_encoded = obj.encode()
1565 self.assertEqual(encode2pass(obj), obj_encoded)
1566 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1567 obj_expled = obj(value, expl=tag_expl)
1568 self.assertTrue(obj_expled.expled)
1570 list(obj_expled.pps())
1571 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1572 obj_expled_encoded = obj_expled.encode()
1573 obj_expled_cer = encode_cer(obj_expled)
1574 self.assertNotEqual(obj_expled_cer, obj_encoded)
1575 self.assertSequenceEqual(
1576 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1579 ctx_copied = deepcopy(ctx_dummy)
1580 obj_decoded, tail = obj_expled.decode(
1581 obj_expled_encoded + tail_junk,
1585 self.assertDictEqual(ctx_copied, ctx_dummy)
1587 list(obj_decoded.pps())
1588 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1589 self.assertEqual(tail, tail_junk)
1590 self.assertEqual(obj_decoded, obj_expled)
1591 self.assertNotEqual(obj_decoded, obj)
1592 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1593 self.assertEqual(bytes(obj_decoded), bytes(obj))
1594 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1595 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1596 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1598 obj_decoded.expl_llen,
1599 len(len_encode(len(obj_encoded))),
1601 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1602 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1605 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1607 self.assertEqual(obj_decoded.expl_offset, offset)
1608 if isinstance(value, tuple):
1609 self.assertSetEqual(set(value), set(obj_decoded.named))
1612 assert_exceeding_data(
1614 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1618 evgens = list(obj_expled.decode_evgen(
1619 obj_expled_encoded + tail_junk,
1621 decode_path=decode_path,
1624 self.assertEqual(len(evgens), 1)
1625 _decode_path, obj, tail = evgens[0]
1626 self.assertSequenceEqual(tail, tail_junk)
1627 self.assertEqual(_decode_path, decode_path)
1628 self.assertEqual(obj.expl_offset, offset)
1632 @given(integers(min_value=1, max_value=255))
1633 def test_bad_zero_value(self, pad_size):
1634 with self.assertRaises(DecodeError):
1635 BitString().decode(b"".join((
1636 BitString.tag_default,
1641 def test_go_vectors_invalid(self):
1647 with self.assertRaises(DecodeError):
1648 BitString().decode(b"".join((
1649 BitString.tag_default,
1654 def test_go_vectors_valid(self):
1655 obj, _ = BitString().decode(b"".join((
1656 BitString.tag_default,
1660 self.assertEqual(bytes(obj), b"")
1661 self.assertEqual(obj.bit_len, 0)
1663 obj, _ = BitString().decode(b"".join((
1664 BitString.tag_default,
1668 self.assertEqual(bytes(obj), b"\x00")
1669 self.assertEqual(obj.bit_len, 1)
1671 obj = BitString((16, b"\x82\x40"))
1672 self.assertTrue(obj[0])
1673 self.assertFalse(obj[1])
1674 self.assertTrue(obj[6])
1675 self.assertTrue(obj[9])
1676 self.assertFalse(obj[17])
1678 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1680 integers(min_value=1, max_value=30),
1683 binary(min_size=1, max_size=5),
1685 binary(min_size=1, max_size=5),
1693 lists(booleans(), min_size=1),
1697 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1698 def chunk_constructed(contents):
1700 tag_encode(form=TagFormConstructed, num=3) +
1702 b"".join(BitString(content).encode() for content in contents) +
1706 chunks_len_expected = []
1707 payload_expected = b""
1708 bit_len_expected = 0
1709 for chunk_input in chunk_inputs:
1710 if isinstance(chunk_input, binary_type):
1711 chunks.append(BitString(chunk_input).encode())
1712 payload_expected += chunk_input
1713 bit_len_expected += len(chunk_input) * 8
1714 chunks_len_expected.append(len(chunk_input) + 1)
1716 chunks.append(chunk_constructed(chunk_input))
1717 payload = b"".join(chunk_input)
1718 payload_expected += payload
1719 bit_len_expected += len(payload) * 8
1720 for c in chunk_input:
1721 chunks_len_expected.append(len(c) + 1)
1722 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1723 chunk_last = BitString("'%s'B" % "".join(
1724 "1" if bit else "0" for bit in chunk_last_bits
1726 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1727 payload_expected += bytes(chunk_last)
1728 bit_len_expected += chunk_last.bit_len
1729 encoded_indefinite = (
1730 tag_encode(form=TagFormConstructed, num=impl) +
1733 chunk_last.encode() +
1736 encoded_definite = (
1737 tag_encode(form=TagFormConstructed, num=impl) +
1738 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1742 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1743 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1744 for lenindef_expected, encoded in (
1745 (True, encoded_indefinite),
1746 (False, encoded_definite),
1748 obj, tail = BitString(impl=tag_encode(impl)).decode(
1750 ctx={"bered": True},
1752 self.assertSequenceEqual(tail, junk)
1753 self.assertEqual(obj.bit_len, bit_len_expected)
1754 self.assertSequenceEqual(bytes(obj), payload_expected)
1755 self.assertTrue(obj.ber_encoded)
1756 self.assertEqual(obj.lenindef, lenindef_expected)
1757 self.assertTrue(obj.bered)
1759 self.assertTrue(obj.ber_encoded)
1760 self.assertEqual(obj.lenindef, lenindef_expected)
1761 self.assertTrue(obj.bered)
1762 self.assertEqual(len(encoded), obj.tlvlen)
1765 pprint(obj, big_blobs=True, with_decode_path=True)
1767 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1769 decode_path=decode_path,
1770 ctx={"bered": True},
1772 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1773 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1774 self.assertGreater(len(dp), len(decode_path))
1775 self.assertEqual(obj.vlen, chunk_len_expected)
1778 integers(min_value=0),
1781 def test_ber_definite_too_short(self, offset, decode_path):
1782 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1784 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1786 decode_path=decode_path,
1787 ctx={"bered": True},
1789 self.assertEqual(err.exception.decode_path, decode_path)
1790 self.assertEqual(err.exception.offset, offset)
1793 integers(min_value=0),
1796 def test_ber_definite_no_data(self, offset, decode_path):
1797 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1799 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1801 decode_path=decode_path,
1802 ctx={"bered": True},
1804 self.assertEqual(err.exception.decode_path, decode_path)
1805 self.assertEqual(err.exception.offset, offset)
1808 integers(min_value=0),
1810 integers(min_value=1, max_value=3),
1812 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1813 bs = BitString(b"data").encode()
1814 with self.assertRaises(NotEnoughData) as err:
1816 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1818 decode_path=decode_path,
1819 ctx={"bered": True},
1821 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1822 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1825 integers(min_value=0),
1827 integers(min_value=1, max_value=3),
1829 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1830 bs = BitString(b"data").encode()
1831 bs_longer = BitString(b"data-longer").encode()
1832 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1835 tag_encode(3, form=TagFormConstructed) +
1836 len_encode((chunks + 1) * len(bs)) +
1841 decode_path=decode_path,
1842 ctx={"bered": True},
1844 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1845 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1848 integers(min_value=0),
1851 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1852 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1854 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1856 decode_path=decode_path,
1857 ctx={"bered": True},
1859 self.assertEqual(err.exception.decode_path, decode_path)
1860 self.assertEqual(err.exception.offset, offset)
1862 @given(data_strategy())
1863 def test_ber_indefinite_not_multiple(self, d):
1864 bs_short = BitString("'A'H").encode()
1865 bs_full = BitString("'AA'H").encode()
1866 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1867 chunks.append(bs_short)
1868 d.draw(permutations(chunks))
1869 chunks.append(bs_short)
1870 offset = d.draw(integers(min_value=0))
1871 decode_path = d.draw(decode_path_strat)
1872 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1875 tag_encode(3, form=TagFormConstructed) +
1881 decode_path=decode_path,
1882 ctx={"bered": True},
1885 err.exception.decode_path,
1886 decode_path + (str(chunks.index(bs_short)),),
1889 err.exception.offset,
1890 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1893 def test_x690_vector(self):
1894 vector = BitString("'0A3B5F291CD'H")
1895 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1896 self.assertSequenceEqual(tail, b"")
1897 self.assertEqual(obj, vector)
1898 obj, tail = BitString().decode(
1899 hexdec("23800303000A3B0305045F291CD00000"),
1900 ctx={"bered": True},
1902 self.assertSequenceEqual(tail, b"")
1903 self.assertEqual(obj, vector)
1904 self.assertTrue(obj.ber_encoded)
1905 self.assertTrue(obj.lenindef)
1906 self.assertTrue(obj.bered)
1908 self.assertTrue(obj.ber_encoded)
1909 self.assertTrue(obj.lenindef)
1910 self.assertTrue(obj.bered)
1912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1913 @given(integers(min_value=1000, max_value=3000))
1914 def test_cer(self, data_len):
1915 data = urandom(data_len)
1916 encoded = encode_cer(BitString(data))
1917 ctx = {"bered": True}
1918 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1919 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1920 evgens_expected = data_len // 999
1921 if evgens_expected * 999 != data_len:
1922 evgens_expected += 1
1923 evgens_expected += 1
1924 self.assertEqual(len(evgens), evgens_expected)
1925 for (_, obj, _) in evgens[:-2]:
1926 self.assertEqual(obj.vlen, 1000)
1927 _, obj, _ = evgens[-2]
1928 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1932 def octet_string_values_strategy(draw, do_expl=False):
1933 bound_min, bound_max = sorted(draw(sets(
1934 integers(min_value=0, max_value=1 << 7),
1938 value = draw(one_of(
1940 binary(min_size=bound_min, max_size=bound_max),
1942 default = draw(one_of(
1944 binary(min_size=bound_min, max_size=bound_max),
1947 if draw(booleans()):
1948 bounds = (bound_min, bound_max)
1952 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1954 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1955 optional = draw(one_of(none(), booleans()))
1957 draw(integers(min_value=0)),
1958 draw(integers(min_value=0)),
1959 draw(integers(min_value=0)),
1961 return (value, bounds, impl, expl, default, optional, _decoded)
1964 class OctetStringInherited(OctetString):
1968 class TestOctetString(CommonMixin, TestCase):
1969 base_klass = OctetString
1971 def test_invalid_value_type(self):
1972 with self.assertRaises(InvalidValueType) as err:
1973 OctetString(text_type(123))
1977 def test_optional(self, optional):
1978 obj = OctetString(default=OctetString(b""), optional=optional)
1979 self.assertTrue(obj.optional)
1982 def test_ready(self, value):
1984 self.assertFalse(obj.ready)
1987 pprint(obj, big_blobs=True, with_decode_path=True)
1988 with self.assertRaises(ObjNotReady) as err:
1991 with self.assertRaises(ObjNotReady) as err:
1993 obj = OctetString(value)
1994 self.assertTrue(obj.ready)
1997 pprint(obj, big_blobs=True, with_decode_path=True)
1999 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2000 def test_comparison(self, value1, value2, tag1, tag2):
2001 for klass in (OctetString, OctetStringInherited):
2002 obj1 = klass(value1)
2003 obj2 = klass(value2)
2004 self.assertEqual(obj1 == obj2, value1 == value2)
2005 self.assertEqual(obj1 != obj2, value1 != value2)
2006 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2007 obj1 = klass(value1, impl=tag1)
2008 obj2 = klass(value1, impl=tag2)
2009 self.assertEqual(obj1 == obj2, tag1 == tag2)
2010 self.assertEqual(obj1 != obj2, tag1 != tag2)
2012 @given(lists(binary()))
2013 def test_sorted_works(self, values):
2014 self.assertSequenceEqual(
2015 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2019 @given(data_strategy())
2020 def test_bounds_satisfied(self, d):
2021 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2022 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2023 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2024 OctetString(value=value, bounds=(bound_min, bound_max))
2026 @given(data_strategy())
2027 def test_bounds_unsatisfied(self, d):
2028 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2029 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2030 value = d.draw(binary(max_size=bound_min - 1))
2031 with self.assertRaises(BoundsError) as err:
2032 OctetString(value=value, bounds=(bound_min, bound_max))
2034 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2035 OctetString(bounds=(bound_min, bound_max)).decode(
2036 OctetString(value).encode()
2039 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2040 OctetString(bounds=(bound_min, bound_max)).decode(
2041 encode2pass(OctetString(value))
2043 value = d.draw(binary(min_size=bound_max + 1))
2044 with self.assertRaises(BoundsError) as err:
2045 OctetString(value=value, bounds=(bound_min, bound_max))
2047 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2048 OctetString(bounds=(bound_min, bound_max)).decode(
2049 OctetString(value).encode()
2052 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2053 OctetString(bounds=(bound_min, bound_max)).decode(
2054 encode2pass(OctetString(value))
2057 @given(data_strategy())
2058 def test_call(self, d):
2059 for klass in (OctetString, OctetStringInherited):
2068 ) = d.draw(octet_string_values_strategy())
2069 obj_initial = klass(
2075 optional_initial or False,
2086 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2087 if (default is None) and (obj_initial.default is not None):
2090 (bounds is None) and
2091 (value is not None) and
2092 (bounds_initial is not None) and
2093 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2097 (bounds is None) and
2098 (default is not None) and
2099 (bounds_initial is not None) and
2100 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2103 obj = obj_initial(value, bounds, impl, expl, default, optional)
2105 value_expected = default if value is None else value
2107 default_initial if value_expected is None
2110 self.assertEqual(obj, value_expected)
2111 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2112 self.assertEqual(obj.expl_tag, expl or expl_initial)
2115 default_initial if default is None else default,
2117 if obj.default is None:
2118 optional = optional_initial if optional is None else optional
2119 optional = False if optional is None else optional
2122 self.assertEqual(obj.optional, optional)
2124 (obj._bound_min, obj._bound_max),
2125 bounds or bounds_initial or (0, float("+inf")),
2128 @given(octet_string_values_strategy())
2129 def test_copy(self, values):
2130 for klass in (OctetString, OctetStringInherited):
2131 obj = klass(*values)
2132 for copy_func in copy_funcs:
2133 obj_copied = copy_func(obj)
2134 self.assert_copied_basic_fields(obj, obj_copied)
2135 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2136 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2137 self.assertEqual(obj._value, obj_copied._value)
2141 integers(min_value=1).map(tag_encode),
2143 def test_stripped(self, value, tag_impl):
2144 obj = OctetString(value, impl=tag_impl)
2145 with self.assertRaises(NotEnoughData):
2146 obj.decode(obj.encode()[:-1])
2150 integers(min_value=1).map(tag_ctxc),
2152 def test_stripped_expl(self, value, tag_expl):
2153 obj = OctetString(value, expl=tag_expl)
2154 with self.assertRaises(NotEnoughData):
2155 obj.decode(obj.encode()[:-1])
2158 integers(min_value=31),
2159 integers(min_value=0),
2162 def test_bad_tag(self, tag, offset, decode_path):
2163 with self.assertRaises(DecodeError) as err:
2164 OctetString().decode(
2165 tag_encode(tag)[:-1],
2167 decode_path=decode_path,
2170 self.assertEqual(err.exception.offset, offset)
2171 self.assertEqual(err.exception.decode_path, decode_path)
2174 integers(min_value=128),
2175 integers(min_value=0),
2178 def test_bad_len(self, l, offset, decode_path):
2179 with self.assertRaises(DecodeError) as err:
2180 OctetString().decode(
2181 OctetString.tag_default + len_encode(l)[:-1],
2183 decode_path=decode_path,
2186 self.assertEqual(err.exception.offset, offset)
2187 self.assertEqual(err.exception.decode_path, decode_path)
2190 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2191 integers(min_value=0),
2194 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2195 value, bound_min = list(sorted(ints))
2197 class String(OctetString):
2198 bounds = (bound_min, bound_min)
2199 with self.assertRaises(DecodeError) as err:
2201 OctetString(b"\x00" * value).encode(),
2203 decode_path=decode_path,
2206 self.assertEqual(err.exception.offset, offset)
2207 self.assertEqual(err.exception.decode_path, decode_path)
2209 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2211 octet_string_values_strategy(),
2213 integers(min_value=1).map(tag_ctxc),
2214 integers(min_value=0),
2218 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2219 for klass in (OctetString, OctetStringInherited):
2220 _, _, _, _, default, optional, _decoded = values
2229 pprint(obj, big_blobs=True, with_decode_path=True)
2230 self.assertFalse(obj.expled)
2231 obj_encoded = obj.encode()
2232 self.assertEqual(encode2pass(obj), obj_encoded)
2233 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2234 obj_expled = obj(value, expl=tag_expl)
2235 self.assertTrue(obj_expled.expled)
2237 list(obj_expled.pps())
2238 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2239 obj_expled_encoded = obj_expled.encode()
2240 obj_expled_cer = encode_cer(obj_expled)
2241 self.assertNotEqual(obj_expled_cer, obj_encoded)
2242 self.assertSequenceEqual(
2243 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2246 ctx_copied = deepcopy(ctx_dummy)
2247 obj_decoded, tail = obj_expled.decode(
2248 obj_expled_encoded + tail_junk,
2252 self.assertDictEqual(ctx_copied, ctx_dummy)
2254 list(obj_decoded.pps())
2255 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2256 self.assertEqual(tail, tail_junk)
2257 self.assertEqual(obj_decoded, obj_expled)
2258 self.assertNotEqual(obj_decoded, obj)
2259 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2260 self.assertEqual(bytes(obj_decoded), bytes(obj))
2261 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2262 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2263 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2265 obj_decoded.expl_llen,
2266 len(len_encode(len(obj_encoded))),
2268 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2269 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2272 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2274 self.assertEqual(obj_decoded.expl_offset, offset)
2275 assert_exceeding_data(
2277 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2281 evgens = list(obj_expled.decode_evgen(
2282 obj_expled_encoded + tail_junk,
2284 decode_path=decode_path,
2287 self.assertEqual(len(evgens), 1)
2288 _decode_path, obj, tail = evgens[0]
2289 self.assertSequenceEqual(tail, tail_junk)
2290 self.assertEqual(_decode_path, decode_path)
2291 self.assertEqual(obj.expl_offset, offset)
2295 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2297 integers(min_value=1, max_value=30),
2300 binary(min_size=1, max_size=5),
2302 binary(min_size=1, max_size=5),
2313 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2314 def chunk_constructed(contents):
2316 tag_encode(form=TagFormConstructed, num=4) +
2318 b"".join(OctetString(content).encode() for content in contents) +
2322 chunks_len_expected = []
2323 payload_expected = b""
2324 for chunk_input in chunk_inputs:
2325 if isinstance(chunk_input, binary_type):
2326 chunks.append(OctetString(chunk_input).encode())
2327 payload_expected += chunk_input
2328 chunks_len_expected.append(len(chunk_input))
2330 chunks.append(chunk_constructed(chunk_input))
2331 payload = b"".join(chunk_input)
2332 payload_expected += payload
2333 for c in chunk_input:
2334 chunks_len_expected.append(len(c))
2335 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2336 encoded_indefinite = (
2337 tag_encode(form=TagFormConstructed, num=impl) +
2342 encoded_definite = (
2343 tag_encode(form=TagFormConstructed, num=impl) +
2344 len_encode(len(b"".join(chunks))) +
2347 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2348 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2349 for lenindef_expected, encoded in (
2350 (True, encoded_indefinite),
2351 (False, encoded_definite),
2353 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2355 ctx={"bered": True},
2357 self.assertSequenceEqual(tail, junk)
2358 self.assertSequenceEqual(bytes(obj), payload_expected)
2359 self.assertTrue(obj.ber_encoded)
2360 self.assertEqual(obj.lenindef, lenindef_expected)
2361 self.assertTrue(obj.bered)
2363 self.assertTrue(obj.ber_encoded)
2364 self.assertEqual(obj.lenindef, lenindef_expected)
2365 self.assertTrue(obj.bered)
2366 self.assertEqual(len(encoded), obj.tlvlen)
2369 pprint(obj, big_blobs=True, with_decode_path=True)
2371 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2373 decode_path=decode_path,
2374 ctx={"bered": True},
2376 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2377 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2378 self.assertGreater(len(dp), len(decode_path))
2379 self.assertEqual(obj.vlen, chunk_len_expected)
2382 integers(min_value=0),
2385 def test_ber_definite_too_short(self, offset, decode_path):
2386 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2387 OctetString().decode(
2388 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2390 decode_path=decode_path,
2391 ctx={"bered": True},
2393 self.assertEqual(err.exception.decode_path, decode_path)
2394 self.assertEqual(err.exception.offset, offset)
2397 integers(min_value=0),
2399 integers(min_value=1, max_value=3),
2401 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2402 bs = OctetString(b"data").encode()
2403 with self.assertRaises(NotEnoughData) as err:
2404 OctetString().decode(
2405 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2407 decode_path=decode_path,
2408 ctx={"bered": True},
2410 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2411 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2414 integers(min_value=0),
2416 integers(min_value=1, max_value=3),
2418 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2419 bs = OctetString(b"data").encode()
2420 bs_longer = OctetString(b"data-longer").encode()
2421 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2422 OctetString().decode(
2424 tag_encode(4, form=TagFormConstructed) +
2425 len_encode((chunks + 1) * len(bs)) +
2430 decode_path=decode_path,
2431 ctx={"bered": True},
2433 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2434 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2436 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2437 @given(integers(min_value=1001, max_value=3000))
2438 def test_cer(self, data_len):
2439 data = urandom(data_len)
2440 encoded = encode_cer(OctetString(data))
2441 ctx = {"bered": True}
2442 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2443 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2444 evgens_expected = data_len // 1000
2445 if evgens_expected * 1000 != data_len:
2446 evgens_expected += 1
2447 evgens_expected += 1
2448 self.assertEqual(len(evgens), evgens_expected)
2449 for (_, obj, _) in evgens[:-2]:
2450 self.assertEqual(obj.vlen, 1000)
2451 _, obj, _ = evgens[-2]
2452 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2456 def null_values_strategy(draw, do_expl=False):
2460 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2462 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2463 optional = draw(one_of(none(), booleans()))
2465 draw(integers(min_value=0)),
2466 draw(integers(min_value=0)),
2467 draw(integers(min_value=0)),
2469 return (impl, expl, optional, _decoded)
2472 class NullInherited(Null):
2476 class TestNull(CommonMixin, TestCase):
2479 def test_ready(self):
2481 self.assertTrue(obj.ready)
2484 pprint(obj, big_blobs=True, with_decode_path=True)
2486 @given(binary(min_size=1), binary(min_size=1))
2487 def test_comparison(self, tag1, tag2):
2488 for klass in (Null, NullInherited):
2489 obj1 = klass(impl=tag1)
2490 obj2 = klass(impl=tag2)
2491 self.assertEqual(obj1 == obj2, tag1 == tag2)
2492 self.assertEqual(obj1 != obj2, tag1 != tag2)
2493 self.assertNotEqual(obj1, tag2)
2495 @given(data_strategy())
2496 def test_call(self, d):
2497 for klass in (Null, NullInherited):
2503 ) = d.draw(null_values_strategy())
2504 obj_initial = klass(
2507 optional=optional_initial or False,
2508 _decoded=_decoded_initial,
2515 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2516 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2517 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2518 self.assertEqual(obj.expl_tag, expl or expl_initial)
2519 optional = optional_initial if optional is None else optional
2520 optional = False if optional is None else optional
2521 self.assertEqual(obj.optional, optional)
2523 @given(null_values_strategy())
2524 def test_copy(self, values):
2525 for klass in (Null, NullInherited):
2526 impl, expl, optional, _decoded = values
2530 optional=optional or False,
2533 for copy_func in copy_funcs:
2534 obj_copied = copy_func(obj)
2535 self.assert_copied_basic_fields(obj, obj_copied)
2537 @given(integers(min_value=1).map(tag_encode))
2538 def test_stripped(self, tag_impl):
2539 obj = Null(impl=tag_impl)
2540 with self.assertRaises(NotEnoughData):
2541 obj.decode(obj.encode()[:-1])
2543 @given(integers(min_value=1).map(tag_ctxc))
2544 def test_stripped_expl(self, tag_expl):
2545 obj = Null(expl=tag_expl)
2546 with self.assertRaises(NotEnoughData):
2547 obj.decode(obj.encode()[:-1])
2550 integers(min_value=31),
2551 integers(min_value=0),
2554 def test_bad_tag(self, tag, offset, decode_path):
2555 with self.assertRaises(DecodeError) as err:
2557 tag_encode(tag)[:-1],
2559 decode_path=decode_path,
2562 self.assertEqual(err.exception.offset, offset)
2563 self.assertEqual(err.exception.decode_path, decode_path)
2566 integers(min_value=128),
2567 integers(min_value=0),
2570 def test_bad_len(self, l, offset, decode_path):
2571 with self.assertRaises(DecodeError) as err:
2573 Null.tag_default + len_encode(l)[:-1],
2575 decode_path=decode_path,
2578 self.assertEqual(err.exception.offset, offset)
2579 self.assertEqual(err.exception.decode_path, decode_path)
2581 @given(binary(min_size=1))
2582 def test_tag_mismatch(self, impl):
2583 assume(impl != Null.tag_default)
2584 with self.assertRaises(TagMismatch):
2585 Null(impl=impl).decode(Null().encode())
2588 null_values_strategy(),
2589 integers(min_value=1).map(tag_ctxc),
2590 integers(min_value=0),
2594 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2595 for klass in (Null, NullInherited):
2596 _, _, optional, _decoded = values
2597 obj = klass(optional=optional, _decoded=_decoded)
2600 pprint(obj, big_blobs=True, with_decode_path=True)
2601 self.assertFalse(obj.expled)
2602 obj_encoded = obj.encode()
2603 self.assertEqual(encode2pass(obj), obj_encoded)
2604 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2605 obj_expled = obj(expl=tag_expl)
2606 self.assertTrue(obj_expled.expled)
2608 list(obj_expled.pps())
2609 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2610 obj_expled_encoded = obj_expled.encode()
2611 obj_expled_cer = encode_cer(obj_expled)
2612 self.assertNotEqual(obj_expled_cer, obj_encoded)
2613 self.assertSequenceEqual(
2614 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2617 ctx_copied = deepcopy(ctx_dummy)
2618 obj_decoded, tail = obj_expled.decode(
2619 obj_expled_encoded + tail_junk,
2623 self.assertDictEqual(ctx_copied, ctx_dummy)
2625 list(obj_decoded.pps())
2626 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2627 self.assertEqual(tail, tail_junk)
2628 self.assertEqual(obj_decoded, obj_expled)
2629 self.assertNotEqual(obj_decoded, obj)
2630 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2631 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2632 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2634 obj_decoded.expl_llen,
2635 len(len_encode(len(obj_encoded))),
2637 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2638 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2641 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2643 self.assertEqual(obj_decoded.expl_offset, offset)
2644 assert_exceeding_data(
2646 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2650 evgens = list(obj_expled.decode_evgen(
2651 obj_expled_encoded + tail_junk,
2653 decode_path=decode_path,
2656 self.assertEqual(len(evgens), 1)
2657 _decode_path, obj, tail = evgens[0]
2658 self.assertSequenceEqual(tail, tail_junk)
2659 self.assertEqual(_decode_path, decode_path)
2660 self.assertEqual(obj, obj_decoded)
2661 self.assertEqual(obj.expl_offset, offset)
2665 @given(integers(min_value=1))
2666 def test_invalid_len(self, l):
2667 with self.assertRaises(InvalidLength):
2668 Null().decode(b"".join((
2675 def oid_strategy(draw):
2676 first_arc = draw(integers(min_value=0, max_value=2))
2678 if first_arc in (0, 1):
2679 second_arc = draw(integers(min_value=0, max_value=39))
2681 second_arc = draw(integers(min_value=0))
2682 other_arcs = draw(lists(integers(min_value=0)))
2683 return tuple([first_arc, second_arc] + other_arcs)
2687 def oid_values_strategy(draw, do_expl=False):
2688 value = draw(one_of(none(), oid_strategy()))
2692 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2694 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2695 default = draw(one_of(none(), oid_strategy()))
2696 optional = draw(one_of(none(), booleans()))
2698 draw(integers(min_value=0)),
2699 draw(integers(min_value=0)),
2700 draw(integers(min_value=0)),
2702 return (value, impl, expl, default, optional, _decoded)
2705 class ObjectIdentifierInherited(ObjectIdentifier):
2709 class TestObjectIdentifier(CommonMixin, TestCase):
2710 base_klass = ObjectIdentifier
2712 def test_invalid_value_type(self):
2713 with self.assertRaises(InvalidValueType) as err:
2714 ObjectIdentifier(123)
2718 def test_optional(self, optional):
2719 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2720 self.assertTrue(obj.optional)
2722 @given(oid_strategy())
2723 def test_ready(self, value):
2724 obj = ObjectIdentifier()
2725 self.assertFalse(obj.ready)
2728 pprint(obj, big_blobs=True, with_decode_path=True)
2729 with self.assertRaises(ObjNotReady) as err:
2732 with self.assertRaises(ObjNotReady) as err:
2734 obj = ObjectIdentifier(value)
2735 self.assertTrue(obj.ready)
2736 self.assertFalse(obj.ber_encoded)
2739 pprint(obj, big_blobs=True, with_decode_path=True)
2742 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2743 def test_comparison(self, value1, value2, tag1, tag2):
2744 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2745 obj1 = klass(value1)
2746 obj2 = klass(value2)
2747 self.assertEqual(obj1 == obj2, value1 == value2)
2748 self.assertEqual(obj1 != obj2, value1 != value2)
2749 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2750 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2751 obj1 = klass(value1, impl=tag1)
2752 obj2 = klass(value1, impl=tag2)
2753 self.assertEqual(obj1 == obj2, tag1 == tag2)
2754 self.assertEqual(obj1 != obj2, tag1 != tag2)
2756 @given(lists(oid_strategy()))
2757 def test_sorted_works(self, values):
2758 self.assertSequenceEqual(
2759 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2763 @given(data_strategy())
2764 def test_call(self, d):
2765 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2773 ) = d.draw(oid_values_strategy())
2774 obj_initial = klass(
2775 value=value_initial,
2778 default=default_initial,
2779 optional=optional_initial or False,
2780 _decoded=_decoded_initial,
2789 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2798 value_expected = default if value is None else value
2800 default_initial if value_expected is None
2803 self.assertEqual(obj, value_expected)
2804 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2805 self.assertEqual(obj.expl_tag, expl or expl_initial)
2808 default_initial if default is None else default,
2810 if obj.default is None:
2811 optional = optional_initial if optional is None else optional
2812 optional = False if optional is None else optional
2815 self.assertEqual(obj.optional, optional)
2817 @given(oid_values_strategy())
2818 def test_copy(self, values):
2819 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2836 for copy_func in copy_funcs:
2837 obj_copied = copy_func(obj)
2838 self.assert_copied_basic_fields(obj, obj_copied)
2839 self.assertEqual(obj._value, obj_copied._value)
2841 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2844 integers(min_value=1).map(tag_encode),
2846 def test_stripped(self, value, tag_impl):
2847 obj = ObjectIdentifier(value, impl=tag_impl)
2848 with self.assertRaises(NotEnoughData):
2849 obj.decode(obj.encode()[:-1])
2853 integers(min_value=1).map(tag_ctxc),
2855 def test_stripped_expl(self, value, tag_expl):
2856 obj = ObjectIdentifier(value, expl=tag_expl)
2857 with self.assertRaises(NotEnoughData):
2858 obj.decode(obj.encode()[:-1])
2861 integers(min_value=31),
2862 integers(min_value=0),
2865 def test_bad_tag(self, tag, offset, decode_path):
2866 with self.assertRaises(DecodeError) as err:
2867 ObjectIdentifier().decode(
2868 tag_encode(tag)[:-1],
2870 decode_path=decode_path,
2873 self.assertEqual(err.exception.offset, offset)
2874 self.assertEqual(err.exception.decode_path, decode_path)
2877 integers(min_value=128),
2878 integers(min_value=0),
2881 def test_bad_len(self, l, offset, decode_path):
2882 with self.assertRaises(DecodeError) as err:
2883 ObjectIdentifier().decode(
2884 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2886 decode_path=decode_path,
2889 self.assertEqual(err.exception.offset, offset)
2890 self.assertEqual(err.exception.decode_path, decode_path)
2892 def test_zero_oid(self):
2893 with self.assertRaises(NotEnoughData):
2894 ObjectIdentifier().decode(
2895 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2898 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2899 @given(oid_strategy())
2900 def test_unfinished_oid(self, value):
2901 assume(list(value)[-1] > 255)
2902 obj_encoded = ObjectIdentifier(value).encode()
2903 obj, _ = ObjectIdentifier().decode(obj_encoded)
2904 data = obj_encoded[obj.tlen + obj.llen:-1]
2906 ObjectIdentifier.tag_default,
2907 len_encode(len(data)),
2910 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2913 @given(integers(min_value=0))
2914 def test_invalid_short(self, value):
2915 with self.assertRaises(InvalidOID):
2916 ObjectIdentifier((value,))
2917 with self.assertRaises(InvalidOID):
2918 ObjectIdentifier("%d" % value)
2920 @given(integers(min_value=3), integers(min_value=0))
2921 def test_invalid_first_arc(self, first_arc, second_arc):
2922 with self.assertRaises(InvalidOID):
2923 ObjectIdentifier((first_arc, second_arc))
2924 with self.assertRaises(InvalidOID):
2925 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2927 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2928 def test_invalid_second_arc(self, first_arc, second_arc):
2929 with self.assertRaises(InvalidOID):
2930 ObjectIdentifier((first_arc, second_arc))
2931 with self.assertRaises(InvalidOID):
2932 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2934 @given(text(alphabet=ascii_letters + ".", min_size=1))
2935 def test_junk(self, oid):
2936 with self.assertRaises(InvalidOID):
2937 ObjectIdentifier(oid)
2939 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2940 @given(oid_strategy())
2941 def test_validness(self, oid):
2942 obj = ObjectIdentifier(oid)
2943 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2946 pprint(obj, big_blobs=True, with_decode_path=True)
2948 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2950 oid_values_strategy(),
2952 integers(min_value=1).map(tag_ctxc),
2953 integers(min_value=0),
2957 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2958 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2959 _, _, _, default, optional, _decoded = values
2968 pprint(obj, big_blobs=True, with_decode_path=True)
2969 self.assertFalse(obj.expled)
2970 obj_encoded = obj.encode()
2971 self.assertEqual(encode2pass(obj), obj_encoded)
2972 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2973 obj_expled = obj(value, expl=tag_expl)
2974 self.assertTrue(obj_expled.expled)
2976 list(obj_expled.pps())
2977 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2978 obj_expled_encoded = obj_expled.encode()
2979 obj_expled_cer = encode_cer(obj_expled)
2980 self.assertNotEqual(obj_expled_cer, obj_encoded)
2981 self.assertSequenceEqual(
2982 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2985 ctx_copied = deepcopy(ctx_dummy)
2986 obj_decoded, tail = obj_expled.decode(
2987 obj_expled_encoded + tail_junk,
2991 self.assertDictEqual(ctx_copied, ctx_dummy)
2993 list(obj_decoded.pps())
2994 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2995 self.assertEqual(tail, tail_junk)
2996 self.assertEqual(obj_decoded, obj_expled)
2997 self.assertNotEqual(obj_decoded, obj)
2998 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
2999 self.assertEqual(tuple(obj_decoded), tuple(obj))
3000 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3001 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3002 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3004 obj_decoded.expl_llen,
3005 len(len_encode(len(obj_encoded))),
3007 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3008 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3011 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3013 self.assertEqual(obj_decoded.expl_offset, offset)
3014 assert_exceeding_data(
3016 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3020 evgens = list(obj_expled.decode_evgen(
3021 obj_expled_encoded + tail_junk,
3023 decode_path=decode_path,
3026 self.assertEqual(len(evgens), 1)
3027 _decode_path, obj, tail = evgens[0]
3028 self.assertSequenceEqual(tail, tail_junk)
3029 self.assertEqual(_decode_path, decode_path)
3030 self.assertEqual(obj, obj_decoded)
3031 self.assertEqual(obj.expl_offset, offset)
3036 oid_strategy().map(ObjectIdentifier),
3037 oid_strategy().map(ObjectIdentifier),
3039 def test_add(self, oid1, oid2):
3040 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3041 for oid_to_add in (oid2, tuple(oid2)):
3042 self.assertEqual(oid1 + oid_to_add, oid_expect)
3043 with self.assertRaises(InvalidValueType):
3046 def test_go_vectors_valid(self):
3047 for data, expect in (
3049 (b"\x55\x02", (2, 5, 2)),
3050 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3051 (b"\x81\x34\x03", (2, 100, 3)),
3054 ObjectIdentifier().decode(b"".join((
3055 ObjectIdentifier.tag_default,
3056 len_encode(len(data)),
3062 def test_go_vectors_invalid(self):
3063 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3064 with self.assertRaises(DecodeError):
3065 ObjectIdentifier().decode(b"".join((
3066 Integer.tag_default,
3067 len_encode(len(data)),
3071 def test_x690_vector(self):
3073 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3074 ObjectIdentifier((2, 999, 3)),
3077 def test_nonnormalized_first_arc(self):
3079 ObjectIdentifier.tag_default +
3082 ObjectIdentifier((1, 0)).encode()[-1:]
3084 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3085 self.assertTrue(obj.ber_encoded)
3086 self.assertTrue(obj.bered)
3088 self.assertTrue(obj.ber_encoded)
3089 self.assertTrue(obj.bered)
3090 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3091 ObjectIdentifier().decode(tampered)
3093 @given(data_strategy())
3094 def test_negative_arcs(self, d):
3095 oid = list(d.draw(oid_strategy()))
3098 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3100 if oid[idx - 1] == 0:
3102 with self.assertRaises(InvalidOID):
3103 ObjectIdentifier(tuple(oid))
3104 with self.assertRaises(InvalidOID):
3105 ObjectIdentifier(".".join(str(i) for i in oid))
3107 @given(data_strategy())
3108 def test_plused_arcs(self, d):
3109 oid = [str(arc) for arc in d.draw(oid_strategy())]
3110 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3111 oid[idx - 1] = "+" + oid[idx - 1]
3112 with self.assertRaises(InvalidOID):
3113 ObjectIdentifier(".".join(str(i) for i in oid))
3115 @given(data_strategy())
3116 def test_nonnormalized_arcs(self, d):
3117 arcs = d.draw(lists(
3118 integers(min_value=0, max_value=100),
3122 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3123 _, _, lv = tag_strip(dered)
3124 _, _, v = len_decode(lv)
3125 v_no_first_arc = v[1:]
3126 idx_for_tamper = d.draw(integers(
3128 max_value=len(v_no_first_arc) - 1,
3130 tampered = list(bytearray(v_no_first_arc))
3131 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3132 tampered.insert(idx_for_tamper, 0x80)
3133 tampered = bytes(bytearray(tampered))
3135 ObjectIdentifier.tag_default +
3136 len_encode(len(tampered)) +
3139 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3140 self.assertTrue(obj.ber_encoded)
3141 self.assertTrue(obj.bered)
3143 self.assertTrue(obj.ber_encoded)
3144 self.assertTrue(obj.bered)
3145 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3146 ObjectIdentifier().decode(tampered)
3150 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3152 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3153 values = list(draw(sets(
3155 min_size=len(schema),
3156 max_size=len(schema),
3158 schema = list(zip(schema, values))
3159 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3163 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3165 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3166 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3167 optional = draw(one_of(none(), booleans()))
3169 draw(integers(min_value=0)),
3170 draw(integers(min_value=0)),
3171 draw(integers(min_value=0)),
3173 return (schema, value, impl, expl, default, optional, _decoded)
3176 class TestEnumerated(CommonMixin, TestCase):
3177 class EWhatever(Enumerated):
3178 schema = (("whatever", 0),)
3180 base_klass = EWhatever
3182 def test_schema_required(self):
3183 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3186 def test_invalid_value_type(self):
3187 with self.assertRaises(InvalidValueType) as err:
3188 self.base_klass((1, 2))
3191 @given(sets(text_letters(), min_size=2))
3192 def test_unknown_name(self, schema_input):
3193 missing = schema_input.pop()
3195 class E(Enumerated):
3196 schema = [(n, 123) for n in schema_input]
3197 with self.assertRaises(ObjUnknown) as err:
3202 sets(text_letters(), min_size=2),
3203 sets(integers(), min_size=2),
3205 def test_unknown_value(self, schema_input, values_input):
3207 missing_value = values_input.pop()
3208 _input = list(zip(schema_input, values_input))
3210 class E(Enumerated):
3212 with self.assertRaises(DecodeError) as err:
3217 def test_optional(self, optional):
3218 obj = self.base_klass(default="whatever", optional=optional)
3219 self.assertTrue(obj.optional)
3221 def test_ready(self):
3222 obj = self.base_klass()
3223 self.assertFalse(obj.ready)
3226 pprint(obj, big_blobs=True, with_decode_path=True)
3227 with self.assertRaises(ObjNotReady) as err:
3230 obj = self.base_klass("whatever")
3231 self.assertTrue(obj.ready)
3234 pprint(obj, big_blobs=True, with_decode_path=True)
3236 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3237 def test_comparison(self, value1, value2, tag1, tag2):
3238 class E(Enumerated):
3240 ("whatever0", value1),
3241 ("whatever1", value2),
3244 class EInherited(E):
3246 for klass in (E, EInherited):
3247 obj1 = klass(value1)
3248 obj2 = klass(value2)
3249 self.assertEqual(obj1 == obj2, value1 == value2)
3250 self.assertEqual(obj1 != obj2, value1 != value2)
3251 self.assertEqual(obj1 == int(obj2), value1 == value2)
3252 obj1 = klass(value1, impl=tag1)
3253 obj2 = klass(value1, impl=tag2)
3254 self.assertEqual(obj1 == obj2, tag1 == tag2)
3255 self.assertEqual(obj1 != obj2, tag1 != tag2)
3257 @given(data_strategy())
3258 def test_call(self, d):
3267 ) = d.draw(enumerated_values_strategy())
3269 class E(Enumerated):
3270 schema = schema_initial
3272 value=value_initial,
3275 default=default_initial,
3276 optional=optional_initial or False,
3277 _decoded=_decoded_initial,
3287 ) = d.draw(enumerated_values_strategy(
3288 schema=schema_initial,
3289 do_expl=impl_initial is None,
3299 value_expected = default if value is None else value
3301 default_initial if value_expected is None
3306 dict(schema_initial).get(value_expected, value_expected),
3308 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3309 self.assertEqual(obj.expl_tag, expl or expl_initial)
3312 default_initial if default is None else default,
3314 if obj.default is None:
3315 optional = optional_initial if optional is None else optional
3316 optional = False if optional is None else optional
3319 self.assertEqual(obj.optional, optional)
3320 self.assertEqual(obj.specs, dict(schema_initial))
3322 @given(enumerated_values_strategy())
3323 def test_copy(self, values):
3324 schema_input, value, impl, expl, default, optional, _decoded = values
3326 class E(Enumerated):
3327 schema = schema_input
3337 for copy_func in copy_funcs:
3338 obj_copied = copy_func(obj)
3339 self.assert_copied_basic_fields(obj, obj_copied)
3340 self.assertEqual(obj.specs, obj_copied.specs)
3342 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3343 @given(data_strategy())
3344 def test_symmetric(self, d):
3345 schema_input, _, _, _, default, optional, _decoded = d.draw(
3346 enumerated_values_strategy(),
3348 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3349 offset = d.draw(integers(min_value=0))
3350 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3351 tail_junk = d.draw(binary(max_size=5))
3352 decode_path = d.draw(decode_path_strat)
3354 class E(Enumerated):
3355 schema = schema_input
3364 pprint(obj, big_blobs=True, with_decode_path=True)
3365 self.assertFalse(obj.expled)
3366 obj_encoded = obj.encode()
3367 self.assertEqual(encode2pass(obj), obj_encoded)
3368 obj_expled = obj(value, expl=tag_expl)
3369 self.assertTrue(obj_expled.expled)
3371 list(obj_expled.pps())
3372 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3373 obj_expled_encoded = obj_expled.encode()
3374 ctx_copied = deepcopy(ctx_dummy)
3375 obj_decoded, tail = obj_expled.decode(
3376 obj_expled_encoded + tail_junk,
3380 self.assertDictEqual(ctx_copied, ctx_dummy)
3382 list(obj_decoded.pps())
3383 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3384 self.assertEqual(tail, tail_junk)
3385 self.assertEqual(obj_decoded, obj_expled)
3386 self.assertNotEqual(obj_decoded, obj)
3387 self.assertEqual(int(obj_decoded), int(obj_expled))
3388 self.assertEqual(int(obj_decoded), int(obj))
3389 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3390 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3391 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3393 obj_decoded.expl_llen,
3394 len(len_encode(len(obj_encoded))),
3396 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3397 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3400 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3402 self.assertEqual(obj_decoded.expl_offset, offset)
3403 assert_exceeding_data(
3405 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3409 evgens = list(obj_expled.decode_evgen(
3410 obj_expled_encoded + tail_junk,
3412 decode_path=decode_path,
3415 self.assertEqual(len(evgens), 1)
3416 _decode_path, obj, tail = evgens[0]
3417 self.assertSequenceEqual(tail, tail_junk)
3418 self.assertEqual(_decode_path, decode_path)
3419 self.assertEqual(obj, obj_decoded)
3420 self.assertEqual(obj.expl_offset, offset)
3426 def string_values_strategy(draw, alphabet, do_expl=False):
3427 bound_min, bound_max = sorted(draw(sets(
3428 integers(min_value=0, max_value=1 << 7),
3432 value = draw(one_of(
3434 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3436 default = draw(one_of(
3438 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3441 if draw(booleans()):
3442 bounds = (bound_min, bound_max)
3446 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3448 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3449 optional = draw(one_of(none(), booleans()))
3451 draw(integers(min_value=0)),
3452 draw(integers(min_value=0)),
3453 draw(integers(min_value=0)),
3455 return (value, bounds, impl, expl, default, optional, _decoded)
3458 class StringMixin(object):
3459 def test_invalid_value_type(self):
3460 with self.assertRaises(InvalidValueType) as err:
3461 self.base_klass((1, 2))
3464 def text_alphabet(self):
3465 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
3466 return printable + whitespace
3470 def test_optional(self, optional):
3471 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3472 self.assertTrue(obj.optional)
3474 @given(data_strategy())
3475 def test_ready(self, d):
3476 obj = self.base_klass()
3477 self.assertFalse(obj.ready)
3480 pprint(obj, big_blobs=True, with_decode_path=True)
3482 with self.assertRaises(ObjNotReady) as err:
3485 with self.assertRaises(ObjNotReady) as err:
3487 value = d.draw(text(alphabet=self.text_alphabet()))
3488 obj = self.base_klass(value)
3489 self.assertTrue(obj.ready)
3492 pprint(obj, big_blobs=True, with_decode_path=True)
3495 @given(data_strategy())
3496 def test_comparison(self, d):
3497 value1 = d.draw(text(alphabet=self.text_alphabet()))
3498 value2 = d.draw(text(alphabet=self.text_alphabet()))
3499 tag1 = d.draw(binary(min_size=1))
3500 tag2 = d.draw(binary(min_size=1))
3501 obj1 = self.base_klass(value1)
3502 obj2 = self.base_klass(value2)
3503 self.assertEqual(obj1 == obj2, value1 == value2)
3504 self.assertEqual(obj1 != obj2, value1 != value2)
3505 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3506 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3507 obj1 = self.base_klass(value1, impl=tag1)
3508 obj2 = self.base_klass(value1, impl=tag2)
3509 self.assertEqual(obj1 == obj2, tag1 == tag2)
3510 self.assertEqual(obj1 != obj2, tag1 != tag2)
3512 @given(data_strategy())
3513 def test_bounds_satisfied(self, d):
3514 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3515 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3516 value = d.draw(text(
3517 alphabet=self.text_alphabet(),
3521 self.base_klass(value=value, bounds=(bound_min, bound_max))
3523 @given(data_strategy())
3524 def test_bounds_unsatisfied(self, d):
3525 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3526 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3527 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3528 with self.assertRaises(BoundsError) as err:
3529 self.base_klass(value=value, bounds=(bound_min, bound_max))
3531 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3532 self.base_klass(bounds=(bound_min, bound_max)).decode(
3533 self.base_klass(value).encode()
3536 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3537 self.base_klass(bounds=(bound_min, bound_max)).decode(
3538 encode2pass(self.base_klass(value))
3540 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3541 with self.assertRaises(BoundsError) as err:
3542 self.base_klass(value=value, bounds=(bound_min, bound_max))
3544 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3545 self.base_klass(bounds=(bound_min, bound_max)).decode(
3546 self.base_klass(value).encode()
3549 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3550 self.base_klass(bounds=(bound_min, bound_max)).decode(
3551 encode2pass(self.base_klass(value))
3554 @given(data_strategy())
3555 def test_call(self, d):
3564 ) = d.draw(string_values_strategy(self.text_alphabet()))
3565 obj_initial = self.base_klass(
3571 optional_initial or False,
3582 ) = d.draw(string_values_strategy(
3583 self.text_alphabet(),
3584 do_expl=impl_initial is None,
3586 if (default is None) and (obj_initial.default is not None):
3589 (bounds is None) and
3590 (value is not None) and
3591 (bounds_initial is not None) and
3592 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3596 (bounds is None) and
3597 (default is not None) and
3598 (bounds_initial is not None) and
3599 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3602 obj = obj_initial(value, bounds, impl, expl, default, optional)
3604 value_expected = default if value is None else value
3606 default_initial if value_expected is None
3609 self.assertEqual(obj, value_expected)
3610 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3611 self.assertEqual(obj.expl_tag, expl or expl_initial)
3614 default_initial if default is None else default,
3616 if obj.default is None:
3617 optional = optional_initial if optional is None else optional
3618 optional = False if optional is None else optional
3621 self.assertEqual(obj.optional, optional)
3623 (obj._bound_min, obj._bound_max),
3624 bounds or bounds_initial or (0, float("+inf")),
3627 @given(data_strategy())
3628 def test_copy(self, d):
3629 values = d.draw(string_values_strategy(self.text_alphabet()))
3630 obj = self.base_klass(*values)
3631 for copy_func in copy_funcs:
3632 obj_copied = copy_func(obj)
3633 self.assert_copied_basic_fields(obj, obj_copied)
3634 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3635 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3636 self.assertEqual(obj._value, obj_copied._value)
3638 @given(data_strategy())
3639 def test_stripped(self, d):
3640 value = d.draw(text(alphabet=self.text_alphabet()))
3641 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3642 obj = self.base_klass(value, impl=tag_impl)
3643 with self.assertRaises(NotEnoughData):
3644 obj.decode(obj.encode()[:-1])
3646 @given(data_strategy())
3647 def test_stripped_expl(self, d):
3648 value = d.draw(text(alphabet=self.text_alphabet()))
3649 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3650 obj = self.base_klass(value, expl=tag_expl)
3651 with self.assertRaises(NotEnoughData):
3652 obj.decode(obj.encode()[:-1])
3655 integers(min_value=31),
3656 integers(min_value=0),
3659 def test_bad_tag(self, tag, offset, decode_path):
3660 with self.assertRaises(DecodeError) as err:
3661 self.base_klass().decode(
3662 tag_encode(tag)[:-1],
3664 decode_path=decode_path,
3667 self.assertEqual(err.exception.offset, offset)
3668 self.assertEqual(err.exception.decode_path, decode_path)
3671 integers(min_value=128),
3672 integers(min_value=0),
3675 def test_bad_len(self, l, offset, decode_path):
3676 with self.assertRaises(DecodeError) as err:
3677 self.base_klass().decode(
3678 self.base_klass.tag_default + len_encode(l)[:-1],
3680 decode_path=decode_path,
3683 self.assertEqual(err.exception.offset, offset)
3684 self.assertEqual(err.exception.decode_path, decode_path)
3687 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3688 integers(min_value=0),
3691 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3692 value, bound_min = list(sorted(ints))
3694 class String(self.base_klass):
3695 # Multiply this value by four, to satisfy UTF-32 bounds
3696 # (4 bytes per character) validation
3697 bounds = (bound_min * 4, bound_min * 4)
3698 with self.assertRaises(DecodeError) as err:
3700 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3702 decode_path=decode_path,
3705 self.assertEqual(err.exception.offset, offset)
3706 self.assertEqual(err.exception.decode_path, decode_path)
3708 @given(data_strategy())
3709 def test_symmetric(self, d):
3710 values = d.draw(string_values_strategy(self.text_alphabet()))
3711 value = d.draw(text(alphabet=self.text_alphabet()))
3712 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3713 offset = d.draw(integers(min_value=0))
3714 tail_junk = d.draw(binary(max_size=5))
3715 decode_path = d.draw(decode_path_strat)
3716 _, _, _, _, default, optional, _decoded = values
3717 obj = self.base_klass(
3725 pprint(obj, big_blobs=True, with_decode_path=True)
3726 self.assertFalse(obj.expled)
3727 obj_encoded = obj.encode()
3728 self.assertEqual(encode2pass(obj), obj_encoded)
3729 obj_expled = obj(value, expl=tag_expl)
3730 self.assertTrue(obj_expled.expled)
3732 list(obj_expled.pps())
3733 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3734 obj_expled_encoded = obj_expled.encode()
3735 ctx_copied = deepcopy(ctx_dummy)
3736 obj_decoded, tail = obj_expled.decode(
3737 obj_expled_encoded + tail_junk,
3741 self.assertDictEqual(ctx_copied, ctx_dummy)
3743 list(obj_decoded.pps())
3744 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3745 self.assertEqual(tail, tail_junk)
3746 self.assertEqual(obj_decoded, obj_expled)
3747 self.assertNotEqual(obj_decoded, obj)
3748 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3749 self.assertEqual(bytes(obj_decoded), bytes(obj))
3750 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3751 self.assertEqual(text_type(obj_decoded), text_type(obj))
3752 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3753 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3754 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3756 obj_decoded.expl_llen,
3757 len(len_encode(len(obj_encoded))),
3759 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3760 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3763 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3765 self.assertEqual(obj_decoded.expl_offset, offset)
3766 assert_exceeding_data(
3768 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3772 evgens = list(obj_expled.decode_evgen(
3773 obj_expled_encoded + tail_junk,
3775 decode_path=decode_path,
3778 self.assertEqual(len(evgens), 1)
3779 _decode_path, obj, tail = evgens[0]
3780 self.assertSequenceEqual(tail, tail_junk)
3781 self.assertEqual(_decode_path, decode_path)
3782 if not getattr(self, "evgen_mode_skip_value", True):
3783 self.assertEqual(obj, obj_decoded)
3784 self.assertEqual(obj.expl_offset, offset)
3789 cyrillic_letters = text(
3790 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3796 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3797 base_klass = UTF8String
3799 @given(cyrillic_letters)
3800 def test_byte_per_primitive(self, chars):
3802 char_raw = char.encode("utf-8")
3803 encoded = b"".join((
3804 self.base_klass().tag_constructed,
3806 OctetString(char_raw[:1]).encode(),
3807 OctetString(char_raw[1:2]).encode(),
3811 self.base_klass().decod(encoded, ctx={"bered": True}),
3816 class UnicodeDecodeErrorMixin(object):
3817 @given(cyrillic_letters)
3818 def test_unicode_decode_error(self, cyrillic_text):
3819 with self.assertRaises(DecodeError):
3820 self.base_klass(cyrillic_text)
3823 class TestNumericString(StringMixin, CommonMixin, TestCase):
3824 base_klass = NumericString
3826 def text_alphabet(self):
3829 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3830 def test_non_numeric(self, non_numeric_text):
3831 with assertRaisesRegex(self, DecodeError, "non-numeric"):
3832 self.base_klass(non_numeric_text)
3835 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3836 integers(min_value=0),
3839 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3840 value, bound_min = list(sorted(ints))
3842 class String(self.base_klass):
3843 bounds = (bound_min, bound_min)
3844 with self.assertRaises(DecodeError) as err:
3846 self.base_klass(b"1" * value).encode(),
3848 decode_path=decode_path,
3851 self.assertEqual(err.exception.offset, offset)
3852 self.assertEqual(err.exception.decode_path, decode_path)
3854 def test_byte_per_primitive(self):
3855 encoded = b"".join((
3856 self.base_klass().tag_constructed,
3858 OctetString(b"1").encode(),
3859 OctetString(b"2").encode(),
3863 self.base_klass().decod(encoded, ctx={"bered": True}),
3868 class TestPrintableString(
3869 UnicodeDecodeErrorMixin,
3874 base_klass = PrintableString
3876 def text_alphabet(self):
3877 return ascii_letters + digits + " '()+,-./:=?"
3879 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3880 def test_non_printable(self, non_printable_text):
3881 with assertRaisesRegex(self, DecodeError, "non-printable"):
3882 self.base_klass(non_printable_text)
3885 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3886 integers(min_value=0),
3889 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3890 value, bound_min = list(sorted(ints))
3892 class String(self.base_klass):
3893 bounds = (bound_min, bound_min)
3894 with self.assertRaises(DecodeError) as err:
3896 self.base_klass(b"1" * value).encode(),
3898 decode_path=decode_path,
3901 self.assertEqual(err.exception.offset, offset)
3902 self.assertEqual(err.exception.decode_path, decode_path)
3904 def test_allowable_invalid_chars(self):
3906 ("*", {"allow_asterisk": True}),
3907 ("&", {"allow_ampersand": True}),
3908 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3911 obj = self.base_klass(s)
3912 for prop in kwargs.keys():
3913 self.assertFalse(getattr(obj, prop))
3915 with assertRaisesRegex(self, DecodeError, "non-printable"):
3917 self.base_klass(s, **kwargs)
3918 klass = self.base_klass(**kwargs)
3920 for prop in kwargs.keys():
3921 self.assertTrue(getattr(obj, prop))
3924 for prop in kwargs.keys():
3925 self.assertTrue(getattr(obj, prop))
3928 class TestTeletexString(
3929 UnicodeDecodeErrorMixin,
3934 base_klass = TeletexString
3937 class TestVideotexString(
3938 UnicodeDecodeErrorMixin,
3943 base_klass = VideotexString
3946 class TestIA5String(
3947 UnicodeDecodeErrorMixin,
3952 base_klass = IA5String
3955 class TestGraphicString(
3956 UnicodeDecodeErrorMixin,
3961 base_klass = GraphicString
3964 class TestVisibleString(
3965 UnicodeDecodeErrorMixin,
3970 base_klass = VisibleString
3972 def test_x690_vector(self):
3973 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3974 self.assertSequenceEqual(tail, b"")
3975 self.assertEqual(str(obj), "Jones")
3976 self.assertFalse(obj.ber_encoded)
3977 self.assertFalse(obj.lenindef)
3978 self.assertFalse(obj.bered)
3980 obj, tail = VisibleString().decode(
3981 hexdec("3A0904034A6F6E04026573"),
3982 ctx={"bered": True},
3984 self.assertSequenceEqual(tail, b"")
3985 self.assertEqual(str(obj), "Jones")
3986 self.assertTrue(obj.ber_encoded)
3987 self.assertFalse(obj.lenindef)
3988 self.assertTrue(obj.bered)
3990 self.assertTrue(obj.ber_encoded)
3991 self.assertFalse(obj.lenindef)
3992 self.assertTrue(obj.bered)
3994 obj, tail = VisibleString().decode(
3995 hexdec("3A8004034A6F6E040265730000"),
3996 ctx={"bered": True},
3998 self.assertSequenceEqual(tail, b"")
3999 self.assertEqual(str(obj), "Jones")
4000 self.assertTrue(obj.ber_encoded)
4001 self.assertTrue(obj.lenindef)
4002 self.assertTrue(obj.bered)
4004 self.assertTrue(obj.ber_encoded)
4005 self.assertTrue(obj.lenindef)
4006 self.assertTrue(obj.bered)
4009 class TestGeneralString(
4010 UnicodeDecodeErrorMixin,
4015 base_klass = GeneralString
4018 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4019 base_klass = UniversalString
4022 class TestBMPString(StringMixin, CommonMixin, TestCase):
4023 base_klass = BMPString
4027 def generalized_time_values_strategy(
4035 if draw(booleans()):
4036 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4038 value = value.replace(microsecond=0)
4040 if draw(booleans()):
4041 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4043 default = default.replace(microsecond=0)
4047 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4049 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4050 optional = draw(one_of(none(), booleans()))
4052 draw(integers(min_value=0)),
4053 draw(integers(min_value=0)),
4054 draw(integers(min_value=0)),
4056 return (value, impl, expl, default, optional, _decoded)
4059 class TimeMixin(object):
4060 def test_invalid_value_type(self):
4061 with self.assertRaises(InvalidValueType) as err:
4062 self.base_klass(datetime.now().timetuple())
4065 @given(data_strategy())
4066 def test_optional(self, d):
4067 default = d.draw(datetimes(
4068 min_value=self.min_datetime,
4069 max_value=self.max_datetime,
4071 optional = d.draw(booleans())
4072 obj = self.base_klass(default=default, optional=optional)
4073 self.assertTrue(obj.optional)
4075 @given(data_strategy())
4076 def test_ready(self, d):
4077 obj = self.base_klass()
4078 self.assertFalse(obj.ready)
4081 pprint(obj, big_blobs=True, with_decode_path=True)
4082 with self.assertRaises(ObjNotReady) as err:
4085 with self.assertRaises(ObjNotReady) as err:
4087 value = d.draw(datetimes(
4088 min_value=self.min_datetime,
4089 max_value=self.max_datetime,
4091 obj = self.base_klass(value)
4092 self.assertTrue(obj.ready)
4095 pprint(obj, big_blobs=True, with_decode_path=True)
4097 @given(data_strategy())
4098 def test_comparison(self, d):
4099 value1 = d.draw(datetimes(
4100 min_value=self.min_datetime,
4101 max_value=self.max_datetime,
4103 value2 = d.draw(datetimes(
4104 min_value=self.min_datetime,
4105 max_value=self.max_datetime,
4107 tag1 = d.draw(binary(min_size=1))
4108 tag2 = d.draw(binary(min_size=1))
4110 value1 = value1.replace(microsecond=0)
4111 value2 = value2.replace(microsecond=0)
4112 obj1 = self.base_klass(value1)
4113 obj2 = self.base_klass(value2)
4114 self.assertEqual(obj1 == obj2, value1 == value2)
4115 self.assertEqual(obj1 != obj2, value1 != value2)
4116 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4117 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4118 obj1 = self.base_klass(value1, impl=tag1)
4119 obj2 = self.base_klass(value1, impl=tag2)
4120 self.assertEqual(obj1 == obj2, tag1 == tag2)
4121 self.assertEqual(obj1 != obj2, tag1 != tag2)
4123 @given(data_strategy())
4124 def test_call(self, d):
4132 ) = d.draw(generalized_time_values_strategy(
4133 min_datetime=self.min_datetime,
4134 max_datetime=self.max_datetime,
4135 omit_ms=self.omit_ms,
4137 obj_initial = self.base_klass(
4138 value=value_initial,
4141 default=default_initial,
4142 optional=optional_initial or False,
4143 _decoded=_decoded_initial,
4152 ) = d.draw(generalized_time_values_strategy(
4153 min_datetime=self.min_datetime,
4154 max_datetime=self.max_datetime,
4155 omit_ms=self.omit_ms,
4156 do_expl=impl_initial is None,
4166 value_expected = default if value is None else value
4168 default_initial if value_expected is None
4171 self.assertEqual(obj, value_expected)
4172 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4173 self.assertEqual(obj.expl_tag, expl or expl_initial)
4176 default_initial if default is None else default,
4178 if obj.default is None:
4179 optional = optional_initial if optional is None else optional
4180 optional = False if optional is None else optional
4183 self.assertEqual(obj.optional, optional)
4185 @given(data_strategy())
4186 def test_copy(self, d):
4187 values = d.draw(generalized_time_values_strategy(
4188 min_datetime=self.min_datetime,
4189 max_datetime=self.max_datetime,
4191 obj = self.base_klass(*values)
4192 for copy_func in copy_funcs:
4193 obj_copied = copy_func(obj)
4194 self.assert_copied_basic_fields(obj, obj_copied)
4195 self.assertEqual(obj._value, obj_copied._value)
4197 @given(data_strategy())
4198 def test_stripped(self, d):
4199 value = d.draw(datetimes(
4200 min_value=self.min_datetime,
4201 max_value=self.max_datetime,
4203 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4204 obj = self.base_klass(value, impl=tag_impl)
4205 with self.assertRaises(NotEnoughData):
4206 obj.decode(obj.encode()[:-1])
4208 @given(data_strategy())
4209 def test_stripped_expl(self, d):
4210 value = d.draw(datetimes(
4211 min_value=self.min_datetime,
4212 max_value=self.max_datetime,
4214 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4215 obj = self.base_klass(value, expl=tag_expl)
4216 with self.assertRaises(NotEnoughData):
4217 obj.decode(obj.encode()[:-1])
4219 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4220 @given(data_strategy())
4221 def test_symmetric(self, d):
4222 values = d.draw(generalized_time_values_strategy(
4223 min_datetime=self.min_datetime,
4224 max_datetime=self.max_datetime,
4226 value = d.draw(datetimes(
4227 min_value=self.min_datetime,
4228 max_value=self.max_datetime,
4230 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4231 offset = d.draw(integers(min_value=0))
4232 tail_junk = d.draw(binary(max_size=5))
4233 _, _, _, default, optional, _decoded = values
4234 obj = self.base_klass(
4242 pprint(obj, big_blobs=True, with_decode_path=True)
4243 self.assertFalse(obj.expled)
4244 obj_encoded = obj.encode()
4245 self.assertEqual(encode2pass(obj), obj_encoded)
4246 self.additional_symmetric_check(value, obj_encoded)
4247 obj_expled = obj(value, expl=tag_expl)
4248 self.assertTrue(obj_expled.expled)
4250 list(obj_expled.pps())
4251 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4252 obj_expled_encoded = obj_expled.encode()
4253 ctx_copied = deepcopy(ctx_dummy)
4254 obj_decoded, tail = obj_expled.decode(
4255 obj_expled_encoded + tail_junk,
4259 self.assertDictEqual(ctx_copied, ctx_dummy)
4261 list(obj_decoded.pps())
4262 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4263 self.assertEqual(tail, tail_junk)
4264 self.assertEqual(obj_decoded, obj_expled)
4265 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4266 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4267 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4268 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4269 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4271 obj_decoded.expl_llen,
4272 len(len_encode(len(obj_encoded))),
4274 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4275 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4278 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4280 self.assertEqual(obj_decoded.expl_offset, offset)
4281 assert_exceeding_data(
4283 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4288 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4289 base_klass = GeneralizedTime
4291 min_datetime = datetime(1900, 1, 1)
4292 max_datetime = datetime(9999, 12, 31)
4293 evgen_mode_skip_value = False
4295 def additional_symmetric_check(self, value, obj_encoded):
4296 if value.microsecond > 0:
4297 self.assertFalse(obj_encoded.endswith(b"0Z"))
4299 def test_repr_not_ready(self):
4300 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4301 repr(GeneralizedTime())
4303 def test_x690_vector_valid(self):
4307 b"19920722132100.3Z",
4309 GeneralizedTime(data)
4311 def test_x690_vector_invalid(self):
4314 b"19920622123421.0Z",
4315 b"19920722132100.30Z",
4317 with self.assertRaises(DecodeError) as err:
4318 GeneralizedTime(data)
4321 def test_go_vectors_invalid(self):
4333 b"-20100102030410Z",
4334 b"2010-0102030410Z",
4335 b"2010-0002030410Z",
4336 b"201001-02030410Z",
4337 b"20100102-030410Z",
4338 b"2010010203-0410Z",
4339 b"201001020304-10Z",
4340 # These ones are INVALID in *DER*, but accepted
4341 # by Go's encoding/asn1
4342 b"20100102030405+0607",
4343 b"20100102030405-0607",
4345 with self.assertRaises(DecodeError) as err:
4346 GeneralizedTime(data)
4349 def test_go_vectors_valid(self):
4351 GeneralizedTime(b"20100102030405Z").todatetime(),
4352 datetime(2010, 1, 2, 3, 4, 5, 0),
4355 def test_go_vectors_valid_ber(self):
4357 b"20100102030405+0607",
4358 b"20100102030405-0607",
4360 GeneralizedTime(data, ctx={"bered": True})
4362 def test_utc_offsets(self):
4363 """Some know equal UTC offsets
4366 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4370 "200101011130-0700",
4371 "200101011500-03:30",
4374 self.assertEqual(dts[0], dts[1])
4375 self.assertEqual(dts[0], dts[2])
4376 self.assertEqual(dts[0], dts[3])
4378 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4379 @given(data_strategy())
4380 def test_valid_ber(self, d):
4381 min_year = 1901 if PY2 else 2
4382 year = d.draw(integers(min_value=min_year, max_value=9999))
4383 month = d.draw(integers(min_value=1, max_value=12))
4384 day = d.draw(integers(min_value=1, max_value=28))
4385 hours = d.draw(integers(min_value=0, max_value=23))
4386 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4387 dt = datetime(year, month, day, hours)
4388 fractions_sign = d.draw(sampled_from(" ,."))
4390 if fractions_sign != " ":
4391 fractions = random()
4392 if d.draw(booleans()):
4393 minutes = d.draw(integers(min_value=0, max_value=59))
4394 data += "%02d" % minutes
4395 dt += timedelta(seconds=60 * minutes)
4396 if d.draw(booleans()):
4397 seconds = d.draw(integers(min_value=0, max_value=59))
4398 data += "%02d" % seconds
4399 dt += timedelta(seconds=seconds)
4400 if fractions is not None:
4401 dt += timedelta(microseconds=10**6 * fractions)
4402 elif fractions is not None:
4403 dt += timedelta(seconds=60 * fractions)
4404 elif fractions is not None:
4405 dt += timedelta(seconds=3600 * fractions)
4406 if fractions is not None:
4407 data += fractions_sign + str(fractions)[2:]
4408 if d.draw(booleans()):
4410 elif d.draw(booleans()):
4411 offset_hour = d.draw(integers(min_value=0, max_value=13))
4413 if d.draw(booleans()):
4418 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4419 data += "%02d" % offset_hour
4420 minutes_separator = d.draw(sampled_from((None, "", ":")))
4421 if minutes_separator is not None:
4422 offset_minute = d.draw(integers(min_value=0, max_value=59))
4423 dt -= timedelta(seconds=sign * 60 * offset_minute)
4424 data += "%s%02d" % (minutes_separator, offset_minute)
4425 data = data.encode("ascii")
4426 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4428 GeneralizedTime().decod(data_der)
4433 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4436 mktime(obj.todatetime().timetuple()),
4437 mktime(dt.timetuple()),
4440 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4441 self.assertEqual(obj.ber_encoded, not dered)
4442 self.assertEqual(obj.bered, not dered)
4443 self.assertEqual(obj.ber_raw, None if dered else data)
4444 self.assertEqual(obj.encode() == data_der, dered)
4449 def test_invalid_ber(self):
4451 # "00010203040506.07",
4452 "-0010203040506.07",
4453 "0001-203040506.07",
4454 "000102-3040506.07",
4455 "00010203-40506.07",
4456 "0001020304-506.07",
4457 "000102030405-6.07",
4458 "00010203040506.-7",
4459 "+0010203040506.07",
4460 "0001+203040506.07",
4461 "000102+3040506.07",
4462 "00010203+40506.07",
4463 "0001020304+506.07",
4464 "000102030405+6.07",
4465 "00010203040506.+7",
4466 " 0010203040506.07",
4467 "0001 203040506.07",
4468 "000102 3040506.07",
4469 "00010203 40506.07",
4470 "0001020304 506.07",
4471 "000102030405 6.07",
4472 "00010203040506. 7",
4473 "001 0203040506.07",
4474 "00012 03040506.07",
4475 "0001023 040506.07",
4476 "000102034 0506.07",
4477 "00010203045 06.07",
4478 "0001020304056 .07",
4479 "00010203040506.7 ",
4559 "00010203040506.07+15",
4560 "00010203040506.07-15",
4561 "00010203040506.07+14:60",
4562 "00010203040506.07+1460",
4563 "00010203040506.07-1460",
4564 "00010203040506.07+00:60",
4565 "00010203040506.07-00:60",
4567 "00010203040506+15",
4568 "00010203040506-15",
4569 "00010203040506+14:60",
4570 "00010203040506+1460",
4571 "00010203040506-1460",
4572 "00010203040506+00:60",
4573 "00010203040506-00:60",
4582 with self.assertRaises(DecodeError):
4583 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4584 data = data.replace(".", ",")
4585 with self.assertRaises(DecodeError):
4586 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4590 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4591 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4593 binary(min_size=1, max_size=1),
4595 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4596 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4599 def test_junk(self, part0, part1, part2):
4600 junk = part0 + part1 + part2
4601 assume(not (set(junk) <= set(digits.encode("ascii"))))
4602 with self.assertRaises(DecodeError):
4603 GeneralizedTime().decode(
4604 GeneralizedTime.tag_default +
4605 len_encode(len(junk)) +
4611 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4612 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4614 binary(min_size=1, max_size=1),
4616 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4617 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4620 def test_junk_dm(self, part0, part1, part2):
4621 junk = part0 + part1 + part2
4622 assume(not (set(junk) <= set(digits.encode("ascii"))))
4623 with self.assertRaises(DecodeError):
4624 GeneralizedTime().decode(
4625 GeneralizedTime.tag_default +
4626 len_encode(len(junk)) +
4630 def test_ns_fractions(self):
4631 GeneralizedTime(b"20010101000000.000001Z")
4632 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4633 GeneralizedTime(b"20010101000000.0000001Z")
4635 def test_non_pure_integers(self):
4637 # b"20000102030405Z,
4644 b"20000102030405.+6Z",
4645 b"20000102030405.-6Z",
4652 b"20000102030405._6Z",
4653 b"20000102030405.6_Z",
4660 b"20000102030405. 6Z",
4667 b"20000102030405.6 Z",
4669 with self.assertRaises(DecodeError):
4670 GeneralizedTime(data)
4673 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4674 base_klass = UTCTime
4676 min_datetime = datetime(2000, 1, 1)
4677 max_datetime = datetime(2049, 12, 31)
4678 evgen_mode_skip_value = False
4680 def additional_symmetric_check(self, value, obj_encoded):
4683 def test_repr_not_ready(self):
4684 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4687 def test_x690_vector_valid(self):
4695 def test_x690_vector_invalid(self):
4700 with self.assertRaises(DecodeError) as err:
4704 def test_go_vectors_invalid(self):
4730 # These ones are INVALID in *DER*, but accepted
4731 # by Go's encoding/asn1
4732 b"910506164540-0700",
4733 b"910506164540+0730",
4737 with self.assertRaises(DecodeError) as err:
4741 def test_go_vectors_valid(self):
4743 UTCTime(b"910506234540Z").todatetime(),
4744 datetime(1991, 5, 6, 23, 45, 40, 0),
4747 def test_non_pure_integers(self):
4776 with self.assertRaises(DecodeError):
4779 def test_x680_vector_valid_ber(self):
4781 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4782 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4783 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4784 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4786 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4787 obj = UTCTime().decod(data_der, ctx={"bered": True})
4788 self.assertEqual(obj, dt)
4789 self.assertEqual(obj.todatetime(), dt)
4790 self.assertTrue(obj.ber_encoded)
4791 self.assertTrue(obj.bered)
4792 self.assertEqual(obj.ber_raw, data)
4793 self.assertNotEqual(obj.encode(), data_der)
4796 def test_go_vectors_valid_ber(self):
4798 b"910506164540-0700",
4799 b"910506164540+0730",
4803 data = UTCTime.tag_default + len_encode(len(data)) + data
4804 obj = UTCTime().decod(data, ctx={"bered": True})
4805 self.assertTrue(obj.ber_encoded)
4806 self.assertTrue(obj.bered)
4807 self.assertNotEqual(obj.encode(), data)
4810 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4811 @given(data_strategy())
4812 def test_valid_ber(self, d):
4813 year = d.draw(integers(min_value=0, max_value=99))
4814 month = d.draw(integers(min_value=1, max_value=12))
4815 day = d.draw(integers(min_value=1, max_value=28))
4816 hours = d.draw(integers(min_value=0, max_value=23))
4817 minute = d.draw(integers(min_value=0, max_value=59))
4818 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4820 year + (2000 if year < 50 else 1900),
4827 if d.draw(booleans()):
4829 seconds = d.draw(integers(min_value=0, max_value=59))
4830 data += "%02d" % seconds
4831 dt += timedelta(seconds=seconds)
4832 if d.draw(booleans()):
4836 offset_hour = d.draw(integers(min_value=0, max_value=13))
4837 offset_minute = d.draw(integers(min_value=0, max_value=59))
4838 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4839 if d.draw(booleans()):
4845 data += "%02d%02d" % (offset_hour, offset_minute)
4846 data = data.encode("ascii")
4847 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4848 obj = UTCTime().decod(data_der, ctx={"bered": True})
4849 self.assertEqual(obj, dt)
4850 self.assertEqual(obj.todatetime(), dt)
4851 self.assertEqual(obj.ber_encoded, not dered)
4852 self.assertEqual(obj.bered, not dered)
4853 self.assertEqual(obj.ber_raw, None if dered else data)
4854 self.assertEqual(obj.encode() == data_der, dered)
4859 def test_invalid_ber(self):
4900 b"0001020304+0000Z",
4909 with self.assertRaises(DecodeError):
4910 UTCTime(data, ctx={"bered": True})
4911 data = data[:8] + data[8+2:]
4912 with self.assertRaises(DecodeError):
4913 UTCTime(data, ctx={"bered": True})
4958 b"000102030405+000",
4959 b"000102030405+000Z",
4960 b"000102030405+0000Z",
4961 b"000102030405+-101",
4962 b"000102030405+01-1",
4963 b"000102030405+0060",
4964 b"000102030405+1401",
4965 b"500101000002+0003",
4967 with self.assertRaises(DecodeError):
4968 UTCTime(data, ctx={"bered": True})
4970 @given(integers(min_value=0, max_value=49))
4971 def test_pre50(self, year):
4973 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4977 @given(integers(min_value=50, max_value=99))
4978 def test_post50(self, year):
4980 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4986 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4987 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4989 binary(min_size=1, max_size=1),
4991 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4992 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4995 def test_junk(self, part0, part1, part2):
4996 junk = part0 + part1 + part2
4997 assume(not (set(junk) <= set(digits.encode("ascii"))))
4998 with self.assertRaises(DecodeError):
5000 UTCTime.tag_default +
5001 len_encode(len(junk)) +
5007 def tlv_value_strategy(draw):
5008 tag_num = draw(integers(min_value=1))
5009 data = draw(binary())
5010 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5014 def any_values_strategy(draw, do_expl=False):
5015 value = draw(one_of(none(), tlv_value_strategy()))
5018 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5019 optional = draw(one_of(none(), booleans()))
5021 draw(integers(min_value=0)),
5022 draw(integers(min_value=0)),
5023 draw(integers(min_value=0)),
5025 return (value, expl, optional, _decoded)
5028 class AnyInherited(Any):
5032 class TestAny(CommonMixin, TestCase):
5035 def test_invalid_value_type(self):
5036 with self.assertRaises(InvalidValueType) as err:
5041 def test_optional(self, optional):
5042 obj = Any(optional=optional)
5043 self.assertEqual(obj.optional, optional)
5045 @given(tlv_value_strategy())
5046 def test_ready(self, value):
5048 self.assertFalse(obj.ready)
5051 pprint(obj, big_blobs=True, with_decode_path=True)
5052 with self.assertRaises(ObjNotReady) as err:
5055 with self.assertRaises(ObjNotReady) as err:
5058 self.assertTrue(obj.ready)
5061 pprint(obj, big_blobs=True, with_decode_path=True)
5064 def test_basic(self, value):
5065 integer_encoded = Integer(value).encode()
5067 Any(integer_encoded),
5068 Any(Integer(value)),
5069 Any(Any(Integer(value))),
5071 self.assertSequenceEqual(bytes(obj), integer_encoded)
5073 obj.decode(obj.encode())[0].vlen,
5074 len(integer_encoded),
5078 pprint(obj, big_blobs=True, with_decode_path=True)
5079 self.assertSequenceEqual(obj.encode(), integer_encoded)
5081 @given(tlv_value_strategy(), tlv_value_strategy())
5082 def test_comparison(self, value1, value2):
5083 for klass in (Any, AnyInherited):
5084 obj1 = klass(value1)
5085 obj2 = klass(value2)
5086 self.assertEqual(obj1 == obj2, value1 == value2)
5087 self.assertEqual(obj1 != obj2, value1 != value2)
5088 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5090 @given(data_strategy())
5091 def test_call(self, d):
5092 for klass in (Any, AnyInherited):
5098 ) = d.draw(any_values_strategy())
5099 obj_initial = klass(
5102 optional_initial or False,
5110 ) = d.draw(any_values_strategy(do_expl=True))
5111 obj = obj_initial(value, expl, optional)
5113 value_expected = None if value is None else value
5114 self.assertEqual(obj, value_expected)
5115 self.assertEqual(obj.expl_tag, expl or expl_initial)
5116 if obj.default is None:
5117 optional = optional_initial if optional is None else optional
5118 optional = False if optional is None else optional
5119 self.assertEqual(obj.optional, optional)
5121 def test_simultaneous_impl_expl(self):
5122 # override it, as Any does not have implicit tag
5125 def test_decoded(self):
5126 # override it, as Any does not have implicit tag
5129 @given(any_values_strategy())
5130 def test_copy(self, values):
5131 for klass in (Any, AnyInherited):
5132 obj = klass(*values)
5133 for copy_func in copy_funcs:
5134 obj_copied = copy_func(obj)
5135 self.assert_copied_basic_fields(obj, obj_copied)
5136 self.assertEqual(obj._value, obj_copied._value)
5138 @given(binary().map(OctetString))
5139 def test_stripped(self, value):
5141 with self.assertRaises(NotEnoughData):
5142 obj.decode(obj.encode()[:-1])
5145 tlv_value_strategy(),
5146 integers(min_value=1).map(tag_ctxc),
5148 def test_stripped_expl(self, value, tag_expl):
5149 obj = Any(value, expl=tag_expl)
5150 with self.assertRaises(NotEnoughData):
5151 obj.decode(obj.encode()[:-1])
5154 integers(min_value=31),
5155 integers(min_value=0),
5158 def test_bad_tag(self, tag, offset, decode_path):
5159 with self.assertRaises(DecodeError) as err:
5161 tag_encode(tag)[:-1],
5163 decode_path=decode_path,
5166 self.assertEqual(err.exception.offset, offset)
5167 self.assertEqual(err.exception.decode_path, decode_path)
5170 integers(min_value=128),
5171 integers(min_value=0),
5174 def test_bad_len(self, l, offset, decode_path):
5175 with self.assertRaises(DecodeError) as err:
5177 Any.tag_default + len_encode(l)[:-1],
5179 decode_path=decode_path,
5182 self.assertEqual(err.exception.offset, offset)
5183 self.assertEqual(err.exception.decode_path, decode_path)
5185 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5187 any_values_strategy(),
5188 integers().map(lambda x: Integer(x).encode()),
5189 integers(min_value=1).map(tag_ctxc),
5190 integers(min_value=0),
5194 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5195 for klass in (Any, AnyInherited):
5196 _, _, optional, _decoded = values
5197 obj = klass(value=value, optional=optional, _decoded=_decoded)
5200 pprint(obj, big_blobs=True, with_decode_path=True)
5201 self.assertFalse(obj.expled)
5202 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5203 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5204 obj_encoded = obj.encode()
5205 self.assertEqual(encode2pass(obj), obj_encoded)
5206 obj_expled = obj(value, expl=tag_expl)
5207 self.assertTrue(obj_expled.expled)
5208 tag_class, _, tag_num = tag_decode(tag_expl)
5209 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5211 list(obj_expled.pps())
5212 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5213 obj_expled_encoded = obj_expled.encode()
5214 ctx_copied = deepcopy(ctx_dummy)
5215 obj_decoded, tail = obj_expled.decode(
5216 obj_expled_encoded + tail_junk,
5220 self.assertDictEqual(ctx_copied, ctx_dummy)
5222 list(obj_decoded.pps())
5223 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5224 self.assertEqual(tail, tail_junk)
5225 self.assertEqual(obj_decoded, obj_expled)
5226 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5227 self.assertEqual(bytes(obj_decoded), bytes(obj))
5228 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5229 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5230 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5232 obj_decoded.expl_llen,
5233 len(len_encode(len(obj_encoded))),
5235 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5236 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5239 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5241 self.assertEqual(obj_decoded.expl_offset, offset)
5242 self.assertEqual(obj_decoded.tlen, 0)
5243 self.assertEqual(obj_decoded.llen, 0)
5244 self.assertEqual(obj_decoded.vlen, len(value))
5245 assert_exceeding_data(
5247 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5251 evgens = list(obj_expled.decode_evgen(
5252 obj_expled_encoded + tail_junk,
5254 decode_path=decode_path,
5257 self.assertEqual(len(evgens), 1)
5258 _decode_path, obj, tail = evgens[0]
5259 self.assertSequenceEqual(tail, tail_junk)
5260 self.assertEqual(_decode_path, decode_path)
5261 self.assertEqual(obj.expl_offset, offset)
5266 integers(min_value=1).map(tag_ctxc),
5267 integers(min_value=0, max_value=3),
5268 integers(min_value=0),
5272 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5273 chunk = Boolean(False, expl=expl).encode()
5275 OctetString.tag_default +
5277 b"".join([chunk] * chunks) +
5280 with self.assertRaises(LenIndefForm):
5284 decode_path=decode_path,
5286 obj, tail = Any().decode(
5289 decode_path=decode_path,
5290 ctx={"bered": True},
5292 self.assertSequenceEqual(tail, junk)
5293 self.assertEqual(obj.offset, offset)
5294 self.assertEqual(obj.tlvlen, len(encoded))
5295 self.assertTrue(obj.lenindef)
5296 self.assertFalse(obj.ber_encoded)
5297 self.assertTrue(obj.bered)
5299 self.assertTrue(obj.lenindef)
5300 self.assertFalse(obj.ber_encoded)
5301 self.assertTrue(obj.bered)
5304 pprint(obj, big_blobs=True, with_decode_path=True)
5305 with self.assertRaises(NotEnoughData) as err:
5309 decode_path=decode_path,
5310 ctx={"bered": True},
5312 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5313 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5315 class SeqOf(SequenceOf):
5316 schema = Boolean(expl=expl)
5318 class Seq(Sequence):
5320 ("type", ObjectIdentifier(defines=((("value",), {
5321 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5326 ("type", ObjectIdentifier("1.2.3")),
5327 ("value", Any(encoded)),
5329 seq_encoded = seq.encode()
5330 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5331 self.assertIsNotNone(seq_decoded["value"].defined)
5333 list(seq_decoded.pps())
5334 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5335 self.assertTrue(seq_decoded.bered)
5336 self.assertFalse(seq_decoded["type"].bered)
5337 self.assertTrue(seq_decoded["value"].bered)
5339 chunk = chunk[:-1] + b"\x01"
5340 chunks = b"".join([chunk] * (chunks + 1))
5341 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5343 ("type", ObjectIdentifier("1.2.3")),
5344 ("value", Any(encoded)),
5346 seq_encoded = seq.encode()
5347 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5348 self.assertIsNotNone(seq_decoded["value"].defined)
5350 list(seq_decoded.pps())
5351 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5352 self.assertTrue(seq_decoded.bered)
5353 self.assertFalse(seq_decoded["type"].bered)
5354 self.assertTrue(seq_decoded["value"].bered)
5358 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5360 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5361 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5363 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5364 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5366 min_size=len(names),
5367 max_size=len(names),
5370 (name, Integer(**tag_kwargs))
5371 for name, tag_kwargs in zip(names, tags)
5374 if value_required or draw(booleans()):
5375 value = draw(tuples(
5376 sampled_from([name for name, _ in schema]),
5377 integers().map(Integer),
5381 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5382 default = draw(one_of(
5384 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5386 optional = draw(one_of(none(), booleans()))
5388 draw(integers(min_value=0)),
5389 draw(integers(min_value=0)),
5390 draw(integers(min_value=0)),
5392 return (schema, value, expl, default, optional, _decoded)
5395 class ChoiceInherited(Choice):
5399 class TestChoice(CommonMixin, TestCase):
5401 schema = (("whatever", Boolean()),)
5404 def test_schema_required(self):
5405 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5408 def test_impl_forbidden(self):
5409 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5410 Choice(impl=b"whatever")
5412 def test_invalid_value_type(self):
5413 with self.assertRaises(InvalidValueType) as err:
5414 self.base_klass(123)
5416 with self.assertRaises(ObjUnknown) as err:
5417 self.base_klass(("whenever", Boolean(False)))
5419 with self.assertRaises(InvalidValueType) as err:
5420 self.base_klass(("whatever", Integer(123)))
5424 def test_optional(self, optional):
5425 obj = self.base_klass(
5426 default=self.base_klass(("whatever", Boolean(False))),
5429 self.assertTrue(obj.optional)
5432 def test_ready(self, value):
5433 obj = self.base_klass()
5434 self.assertFalse(obj.ready)
5437 pprint(obj, big_blobs=True, with_decode_path=True)
5438 self.assertIsNone(obj["whatever"])
5439 with self.assertRaises(ObjNotReady) as err:
5442 with self.assertRaises(ObjNotReady) as err:
5444 obj["whatever"] = Boolean()
5445 self.assertFalse(obj.ready)
5448 pprint(obj, big_blobs=True, with_decode_path=True)
5449 obj["whatever"] = Boolean(value)
5450 self.assertTrue(obj.ready)
5453 pprint(obj, big_blobs=True, with_decode_path=True)
5455 @given(booleans(), booleans())
5456 def test_comparison(self, value1, value2):
5457 class WahlInherited(self.base_klass):
5459 for klass in (self.base_klass, WahlInherited):
5460 obj1 = klass(("whatever", Boolean(value1)))
5461 obj2 = klass(("whatever", Boolean(value2)))
5462 self.assertEqual(obj1 == obj2, value1 == value2)
5463 self.assertEqual(obj1 != obj2, value1 != value2)
5464 self.assertEqual(obj1 == obj2._value, value1 == value2)
5465 self.assertFalse(obj1 == obj2._value[1])
5467 @given(data_strategy())
5468 def test_call(self, d):
5469 for klass in (Choice, ChoiceInherited):
5477 ) = d.draw(choice_values_strategy())
5480 schema = schema_initial
5482 value=value_initial,
5484 default=default_initial,
5485 optional=optional_initial or False,
5486 _decoded=_decoded_initial,
5495 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5496 obj = obj_initial(value, expl, default, optional)
5498 value_expected = default if value is None else value
5500 default_initial if value_expected is None
5503 self.assertEqual(obj.choice, value_expected[0])
5504 self.assertEqual(obj.value, int(value_expected[1]))
5505 self.assertEqual(obj.expl_tag, expl or expl_initial)
5506 default_expect = default_initial if default is None else default
5507 if default_expect is not None:
5508 self.assertEqual(obj.default.choice, default_expect[0])
5509 self.assertEqual(obj.default.value, int(default_expect[1]))
5510 if obj.default is None:
5511 optional = optional_initial if optional is None else optional
5512 optional = False if optional is None else optional
5515 self.assertEqual(obj.optional, optional)
5516 self.assertEqual(obj.specs, obj_initial.specs)
5518 def test_simultaneous_impl_expl(self):
5519 # override it, as Any does not have implicit tag
5522 def test_decoded(self):
5523 # override it, as Any does not have implicit tag
5526 @given(choice_values_strategy())
5527 def test_copy(self, values):
5528 _schema, value, expl, default, optional, _decoded = values
5530 class Wahl(self.base_klass):
5532 register_class(Wahl)
5537 optional=optional or False,
5540 for copy_func in copy_funcs:
5541 obj_copied = copy_func(obj)
5542 self.assertIsNone(obj.tag)
5543 self.assertIsNone(obj_copied.tag)
5544 # hack for assert_copied_basic_fields
5545 obj.tag = "whatever"
5546 obj_copied.tag = "whatever"
5547 self.assert_copied_basic_fields(obj, obj_copied)
5549 self.assertEqual(obj._value, obj_copied._value)
5550 self.assertEqual(obj.specs, obj_copied.specs)
5553 def test_stripped(self, value):
5554 obj = self.base_klass(("whatever", Boolean(value)))
5555 with self.assertRaises(NotEnoughData):
5556 obj.decode(obj.encode()[:-1])
5560 integers(min_value=1).map(tag_ctxc),
5562 def test_stripped_expl(self, value, tag_expl):
5563 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5564 with self.assertRaises(NotEnoughData):
5565 obj.decode(obj.encode()[:-1])
5567 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5568 @given(data_strategy())
5569 def test_symmetric(self, d):
5570 _schema, value, _, default, optional, _decoded = d.draw(
5571 choice_values_strategy(value_required=True)
5573 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5574 offset = d.draw(integers(min_value=0))
5575 tail_junk = d.draw(binary(max_size=5))
5576 decode_path = d.draw(decode_path_strat)
5578 class Wahl(self.base_klass):
5588 pprint(obj, big_blobs=True, with_decode_path=True)
5589 self.assertFalse(obj.expled)
5590 self.assertEqual(obj.tag_order, obj.value.tag_order)
5591 obj_encoded = obj.encode()
5592 self.assertEqual(encode2pass(obj), obj_encoded)
5593 obj_expled = obj(value, expl=tag_expl)
5594 self.assertTrue(obj_expled.expled)
5595 tag_class, _, tag_num = tag_decode(tag_expl)
5596 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5598 list(obj_expled.pps())
5599 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5600 obj_expled_encoded = obj_expled.encode()
5601 ctx_copied = deepcopy(ctx_dummy)
5602 obj_decoded, tail = obj_expled.decode(
5603 obj_expled_encoded + tail_junk,
5607 self.assertDictEqual(ctx_copied, ctx_dummy)
5609 list(obj_decoded.pps())
5610 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5611 self.assertEqual(tail, tail_junk)
5612 self.assertEqual(obj_decoded, obj_expled)
5613 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5614 self.assertEqual(obj_decoded.value, obj_expled.value)
5615 self.assertEqual(obj_decoded.choice, obj.choice)
5616 self.assertEqual(obj_decoded.value, obj.value)
5617 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5618 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5619 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5621 obj_decoded.expl_llen,
5622 len(len_encode(len(obj_encoded))),
5624 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5625 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5628 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5630 self.assertEqual(obj_decoded.expl_offset, offset)
5631 self.assertSequenceEqual(
5633 obj_decoded.value.fulloffset - offset:
5634 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5638 assert_exceeding_data(
5640 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5644 evgens = list(obj_expled.decode_evgen(
5645 obj_expled_encoded + tail_junk,
5647 decode_path=decode_path,
5650 self.assertEqual(len(evgens), 2)
5651 _decode_path, obj, tail = evgens[0]
5652 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5653 _decode_path, obj, tail = evgens[1]
5654 self.assertSequenceEqual(tail, tail_junk)
5655 self.assertEqual(_decode_path, decode_path)
5656 self.assertEqual(obj.expl_offset, offset)
5661 def test_set_get(self, value):
5664 ("erste", Boolean()),
5665 ("zweite", Integer()),
5668 with self.assertRaises(ObjUnknown) as err:
5669 obj["whatever"] = "whenever"
5670 with self.assertRaises(InvalidValueType) as err:
5671 obj["zweite"] = Boolean(False)
5672 obj["zweite"] = Integer(value)
5674 with self.assertRaises(ObjUnknown) as err:
5677 self.assertIsNone(obj["erste"])
5678 self.assertEqual(obj["zweite"], Integer(value))
5680 def test_tag_mismatch(self):
5683 ("erste", Boolean()),
5685 int_encoded = Integer(123).encode()
5686 bool_encoded = Boolean(False).encode()
5688 obj.decode(bool_encoded)
5689 with self.assertRaises(TagMismatch):
5690 obj.decode(int_encoded)
5692 def test_tag_mismatch_underlying(self):
5693 class SeqOfBoolean(SequenceOf):
5696 class SeqOfInteger(SequenceOf):
5701 ("erste", SeqOfBoolean()),
5704 int_encoded = SeqOfInteger((Integer(123),)).encode()
5705 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5707 obj.decode(bool_encoded)
5708 with self.assertRaises(TagMismatch) as err:
5709 obj.decode(int_encoded)
5710 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5714 def seq_values_strategy(draw, seq_klass, do_expl=False):
5716 if draw(booleans()):
5718 value._value = draw(dictionaries(
5721 booleans().map(Boolean),
5722 integers().map(Integer),
5726 if draw(booleans()):
5727 schema = list(draw(dictionaries(
5730 booleans().map(Boolean),
5731 integers().map(Integer),
5737 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5739 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5741 if draw(booleans()):
5742 default = seq_klass()
5743 default._value = draw(dictionaries(
5746 booleans().map(Boolean),
5747 integers().map(Integer),
5750 optional = draw(one_of(none(), booleans()))
5752 draw(integers(min_value=0)),
5753 draw(integers(min_value=0)),
5754 draw(integers(min_value=0)),
5756 return (value, schema, impl, expl, default, optional, _decoded)
5760 def sequence_strategy(draw, seq_klass):
5761 inputs = draw(lists(
5763 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5764 tuples(just(Integer), integers(), one_of(none(), integers())),
5769 integers(min_value=1),
5770 min_size=len(inputs),
5771 max_size=len(inputs),
5774 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5775 for tag, expled in zip(tags, draw(lists(
5777 min_size=len(inputs),
5778 max_size=len(inputs),
5782 for i, optional in enumerate(draw(lists(
5783 sampled_from(("required", "optional", "empty")),
5784 min_size=len(inputs),
5785 max_size=len(inputs),
5787 if optional in ("optional", "empty"):
5788 inits[i]["optional"] = True
5789 if optional == "empty":
5791 empties = set(empties)
5792 names = list(draw(sets(
5794 min_size=len(inputs),
5795 max_size=len(inputs),
5798 for i, (klass, value, default) in enumerate(inputs):
5799 schema.append((names[i], klass(default=default, **inits[i])))
5800 seq_name = draw(text_letters())
5801 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5804 for i, (klass, value, default) in enumerate(inputs):
5811 "default_value": None if spec.default is None else default,
5815 expect["optional"] = True
5817 expect["presented"] = True
5818 expect["value"] = value
5820 expect["optional"] = True
5821 if default is not None and default == value:
5822 expect["presented"] = False
5823 seq[name] = klass(value)
5824 expects.append(expect)
5829 def sequences_strategy(draw, seq_klass):
5830 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5832 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5833 for tag, expled in zip(tags, draw(lists(
5840 i for i, is_default in enumerate(draw(lists(
5846 names = list(draw(sets(
5851 seq_expectses = draw(lists(
5852 sequence_strategy(seq_klass=seq_klass),
5856 seqs = [seq for seq, _ in seq_expectses]
5858 for i, (name, seq) in enumerate(zip(names, seqs)):
5861 seq(default=(seq if i in defaulted else None), **inits[i]),
5863 seq_name = draw(text_letters())
5864 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5867 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5870 "expects": expects_inner,
5873 seq_outer[name] = seq_inner
5874 if seq_outer.specs[name].default is None:
5875 expect["presented"] = True
5876 expect_outers.append(expect)
5877 return seq_outer, expect_outers
5880 class SeqMixing(object):
5881 def test_invalid_value_type(self):
5882 with self.assertRaises(InvalidValueType) as err:
5883 self.base_klass(123)
5886 def test_invalid_value_type_set(self):
5887 class Seq(self.base_klass):
5888 schema = (("whatever", Boolean()),)
5890 with self.assertRaises(InvalidValueType) as err:
5891 seq["whatever"] = Integer(123)
5895 def test_optional(self, optional):
5896 obj = self.base_klass(default=self.base_klass(), optional=optional)
5897 self.assertTrue(obj.optional)
5899 @given(data_strategy())
5900 def test_ready(self, d):
5902 str(i): v for i, v in enumerate(d.draw(lists(
5909 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5916 for name in d.draw(permutations(
5917 list(ready.keys()) + list(non_ready.keys()),
5919 schema_input.append((name, Boolean()))
5921 class Seq(self.base_klass):
5922 schema = tuple(schema_input)
5924 for name in ready.keys():
5926 seq[name] = Boolean()
5927 self.assertFalse(seq.ready)
5930 pprint(seq, big_blobs=True, with_decode_path=True)
5931 for name, value in ready.items():
5932 seq[name] = Boolean(value)
5933 self.assertFalse(seq.ready)
5936 pprint(seq, big_blobs=True, with_decode_path=True)
5937 with self.assertRaises(ObjNotReady) as err:
5940 with self.assertRaises(ObjNotReady) as err:
5942 for name, value in non_ready.items():
5943 seq[name] = Boolean(value)
5944 self.assertTrue(seq.ready)
5947 pprint(seq, big_blobs=True, with_decode_path=True)
5949 @given(data_strategy())
5950 def test_call(self, d):
5951 class SeqInherited(self.base_klass):
5953 for klass in (self.base_klass, SeqInherited):
5962 ) = d.draw(seq_values_strategy(seq_klass=klass))
5963 obj_initial = klass(
5969 optional_initial or False,
5980 ) = d.draw(seq_values_strategy(
5982 do_expl=impl_initial is None,
5984 obj = obj_initial(value, impl, expl, default, optional)
5985 value_expected = default if value is None else value
5987 default_initial if value_expected is None
5990 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
5991 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
5992 self.assertEqual(obj.expl_tag, expl or expl_initial)
5994 {} if obj.default is None else obj.default._value,
5995 getattr(default_initial if default is None else default, "_value", {}),
5997 if obj.default is None:
5998 optional = optional_initial if optional is None else optional
5999 optional = False if optional is None else optional
6002 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6003 self.assertEqual(obj.optional, optional)
6005 @given(data_strategy())
6006 def test_copy(self, d):
6007 class SeqInherited(self.base_klass):
6009 register_class(SeqInherited)
6010 for klass in (self.base_klass, SeqInherited):
6011 values = d.draw(seq_values_strategy(seq_klass=klass))
6012 obj = klass(*values)
6013 for copy_func in copy_funcs:
6014 obj_copied = copy_func(obj)
6015 self.assert_copied_basic_fields(obj, obj_copied)
6016 self.assertEqual(obj.specs, obj_copied.specs)
6017 self.assertEqual(obj._value, obj_copied._value)
6019 @given(data_strategy())
6020 def test_stripped(self, d):
6021 value = d.draw(integers())
6022 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6024 class Seq(self.base_klass):
6026 schema = (("whatever", Integer()),)
6028 seq["whatever"] = Integer(value)
6029 with self.assertRaises(NotEnoughData):
6030 seq.decode(seq.encode()[:-1])
6032 @given(data_strategy())
6033 def test_stripped_expl(self, d):
6034 value = d.draw(integers())
6035 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6037 class Seq(self.base_klass):
6039 schema = (("whatever", Integer()),)
6041 seq["whatever"] = Integer(value)
6042 with self.assertRaises(NotEnoughData):
6043 seq.decode(seq.encode()[:-1])
6045 @given(integers(min_value=3), binary(min_size=2))
6046 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6047 junk = tag_encode(junk_tag_num) + junk
6049 _, _, len_encoded = tag_strip(memoryview(junk))
6050 len_decode(len_encoded)
6056 class Seq(self.base_klass):
6058 ("whatever", Integer()),
6060 ("whenever", Integer()),
6063 seq["whatever"] = Integer(123)
6064 seq["junk"] = Any(junk)
6065 seq["whenever"] = Integer(123)
6066 with self.assertRaises(DecodeError):
6067 seq.decode(seq.encode())
6070 integers(min_value=31),
6071 integers(min_value=0),
6074 def test_bad_tag(self, tag, offset, decode_path):
6075 with self.assertRaises(DecodeError) as err:
6076 self.base_klass().decode(
6077 tag_encode(tag)[:-1],
6079 decode_path=decode_path,
6082 self.assertEqual(err.exception.offset, offset)
6083 self.assertEqual(err.exception.decode_path, decode_path)
6086 integers(min_value=128),
6087 integers(min_value=0),
6090 def test_bad_len(self, l, offset, decode_path):
6091 with self.assertRaises(DecodeError) as err:
6092 self.base_klass().decode(
6093 self.base_klass.tag_default + len_encode(l)[:-1],
6095 decode_path=decode_path,
6098 self.assertEqual(err.exception.offset, offset)
6099 self.assertEqual(err.exception.decode_path, decode_path)
6101 def _assert_expects(self, seq, expects):
6102 for expect in expects:
6104 seq.specs[expect["name"]].optional,
6107 if expect["default_value"] is not None:
6109 seq.specs[expect["name"]].default,
6110 expect["default_value"],
6112 if expect["presented"]:
6113 self.assertIn(expect["name"], seq)
6114 self.assertEqual(seq[expect["name"]], expect["value"])
6116 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6117 @given(data_strategy())
6118 def test_symmetric(self, d):
6119 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6120 tail_junk = d.draw(binary(max_size=5))
6121 decode_path = d.draw(decode_path_strat)
6122 self.assertTrue(seq.ready)
6123 self.assertFalse(seq.decoded)
6124 self._assert_expects(seq, expects)
6127 pprint(seq, big_blobs=True, with_decode_path=True)
6128 self.assertTrue(seq.ready)
6129 seq_encoded = seq.encode()
6130 self.assertEqual(encode2pass(seq), seq_encoded)
6131 seq_encoded_cer = encode_cer(seq)
6132 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6133 self.assertSequenceEqual(
6134 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6137 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6138 self.assertFalse(seq_decoded.lenindef)
6139 self.assertFalse(seq_decoded.ber_encoded)
6140 self.assertFalse(seq_decoded.bered)
6142 t, _, lv = tag_strip(seq_encoded)
6143 _, _, v = len_decode(lv)
6144 seq_encoded_lenindef = t + LENINDEF + v + EOC
6145 with self.assertRaises(DecodeError):
6146 seq.decode(seq_encoded_lenindef)
6147 ctx_copied = deepcopy(ctx_dummy)
6148 ctx_copied["bered"] = True
6149 seq_decoded_lenindef, tail_lenindef = seq.decode(
6150 seq_encoded_lenindef + tail_junk,
6153 del ctx_copied["bered"]
6154 self.assertDictEqual(ctx_copied, ctx_dummy)
6155 self.assertTrue(seq_decoded_lenindef.lenindef)
6156 self.assertTrue(seq_decoded_lenindef.bered)
6157 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6158 self.assertTrue(seq_decoded_lenindef.lenindef)
6159 self.assertTrue(seq_decoded_lenindef.bered)
6160 with self.assertRaises(DecodeError):
6161 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6162 with self.assertRaises(DecodeError):
6163 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6164 repr(seq_decoded_lenindef)
6165 list(seq_decoded_lenindef.pps())
6166 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6167 self.assertTrue(seq_decoded_lenindef.ready)
6169 for decoded, decoded_tail, encoded in (
6170 (seq_decoded, tail, seq_encoded),
6171 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6173 self.assertEqual(decoded_tail, tail_junk)
6174 self._assert_expects(decoded, expects)
6175 self.assertEqual(seq, decoded)
6176 self.assertEqual(decoded.encode(), seq_encoded)
6177 self.assertEqual(decoded.tlvlen, len(encoded))
6178 for expect in expects:
6179 if not expect["presented"]:
6180 self.assertNotIn(expect["name"], decoded)
6182 self.assertIn(expect["name"], decoded)
6183 obj = decoded[expect["name"]]
6184 self.assertTrue(obj.decoded)
6185 offset = obj.expl_offset if obj.expled else obj.offset
6186 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6187 self.assertSequenceEqual(
6188 seq_encoded[offset:offset + tlvlen],
6192 evgens = list(seq.decode_evgen(
6193 encoded + decoded_tail,
6194 decode_path=decode_path,
6195 ctx={"bered": True},
6197 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6198 for _decode_path, obj, _ in evgens[:-1]:
6199 self.assertEqual(_decode_path[:-1], decode_path)
6202 _decode_path, obj, tail = evgens[-1]
6203 self.assertEqual(_decode_path, decode_path)
6207 assert_exceeding_data(
6209 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6213 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6214 @given(data_strategy())
6215 def test_symmetric_with_seq(self, d):
6216 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6217 self.assertTrue(seq.ready)
6218 seq_encoded = seq.encode()
6219 self.assertEqual(encode2pass(seq), seq_encoded)
6220 seq_decoded, tail = seq.decode(seq_encoded)
6221 self.assertEqual(tail, b"")
6222 self.assertTrue(seq.ready)
6223 self.assertEqual(seq, seq_decoded)
6224 self.assertEqual(seq_decoded.encode(), seq_encoded)
6225 for expect_outer in expect_outers:
6226 if not expect_outer["presented"]:
6227 self.assertNotIn(expect_outer["name"], seq_decoded)
6229 self.assertIn(expect_outer["name"], seq_decoded)
6230 obj = seq_decoded[expect_outer["name"]]
6231 self.assertTrue(obj.decoded)
6232 offset = obj.expl_offset if obj.expled else obj.offset
6233 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6234 self.assertSequenceEqual(
6235 seq_encoded[offset:offset + tlvlen],
6238 self._assert_expects(obj, expect_outer["expects"])
6240 @given(data_strategy())
6241 def test_default_disappears(self, d):
6242 _schema = list(d.draw(dictionaries(
6244 sets(integers(), min_size=2, max_size=2),
6248 class Seq(self.base_klass):
6250 (n, Integer(default=d))
6251 for n, (_, d) in _schema
6254 for name, (value, _) in _schema:
6255 seq[name] = Integer(value)
6256 self.assertEqual(len(seq._value), len(_schema))
6257 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6258 self.assertGreater(len(seq.encode()), len(empty_seq))
6259 for name, (_, default) in _schema:
6260 seq[name] = Integer(default)
6261 self.assertEqual(len(seq._value), 0)
6262 self.assertSequenceEqual(seq.encode(), empty_seq)
6264 @given(data_strategy())
6265 def test_encoded_default_not_accepted(self, d):
6266 _schema = list(d.draw(dictionaries(
6271 tags = [tag_encode(tag) for tag in d.draw(sets(
6272 integers(min_value=1),
6273 min_size=len(_schema),
6274 max_size=len(_schema),
6278 schema = (("int", Integer()),)
6280 class SeqWithoutDefault(self.base_klass):
6283 for (n, _), t in zip(_schema, tags)
6285 seq_without_default = SeqWithoutDefault()
6286 for name, value in _schema:
6287 seq_without_default[name] = Wahl(("int", Integer(value)))
6288 seq_encoded = seq_without_default.encode()
6289 seq_without_default.decode(seq_encoded)
6291 len(list(seq_without_default.decode_evgen(seq_encoded))),
6292 len(_schema) * 2 + 1,
6295 class SeqWithDefault(self.base_klass):
6297 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6298 for (n, v), t in zip(_schema, tags)
6300 seq_with_default = SeqWithDefault()
6301 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6302 seq_with_default.decode(seq_encoded)
6303 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6304 list(seq_with_default.decode_evgen(seq_encoded))
6305 for ctx in ({"bered": True}, {"allow_default_values": True}):
6306 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6307 self.assertTrue(seq_decoded.ber_encoded)
6308 self.assertTrue(seq_decoded.bered)
6309 seq_decoded = copy(seq_decoded)
6310 self.assertTrue(seq_decoded.ber_encoded)
6311 self.assertTrue(seq_decoded.bered)
6312 for name, value in _schema:
6313 self.assertEqual(seq_decoded[name], seq_with_default[name])
6314 self.assertEqual(seq_decoded[name].value, value)
6316 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6320 seq_without_default = SeqWithoutDefault()
6321 for name, value in _schema:
6322 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6323 seq_encoded = seq_without_default.encode()
6324 seq_with_default.decode(seq_encoded)
6326 len(list(seq_with_default.decode_evgen(seq_encoded))),
6330 @given(data_strategy())
6331 def test_missing_from_spec(self, d):
6332 names = list(d.draw(sets(text_letters(), min_size=2)))
6333 tags = [tag_encode(tag) for tag in d.draw(sets(
6334 integers(min_value=1),
6335 min_size=len(names),
6336 max_size=len(names),
6338 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6340 class SeqFull(self.base_klass):
6341 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6342 seq_full = SeqFull()
6343 for i, name in enumerate(names):
6344 seq_full[name] = Integer(i)
6345 seq_encoded = seq_full.encode()
6346 altered = names_tags[:-2] + names_tags[-1:]
6348 class SeqMissing(self.base_klass):
6349 schema = [(n, Integer(impl=t)) for n, t in altered]
6350 seq_missing = SeqMissing()
6351 with self.assertRaises(TagMismatch):
6352 seq_missing.decode(seq_encoded)
6353 with self.assertRaises(TagMismatch):
6354 list(seq_missing.decode_evgen(seq_encoded))
6356 def test_bered(self):
6357 class Seq(self.base_klass):
6358 schema = (("underlying", Boolean()),)
6359 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6360 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6361 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6362 self.assertFalse(decoded.ber_encoded)
6363 self.assertFalse(decoded.lenindef)
6364 self.assertTrue(decoded.bered)
6365 decoded = copy(decoded)
6366 self.assertFalse(decoded.ber_encoded)
6367 self.assertFalse(decoded.lenindef)
6368 self.assertTrue(decoded.bered)
6370 class Seq(self.base_klass):
6371 schema = (("underlying", OctetString()),)
6373 tag_encode(form=TagFormConstructed, num=4) +
6375 OctetString(b"whatever").encode() +
6378 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6379 with self.assertRaises(DecodeError):
6380 Seq().decode(encoded)
6381 with self.assertRaises(DecodeError):
6382 list(Seq().decode_evgen(encoded))
6383 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6384 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6385 self.assertFalse(decoded.ber_encoded)
6386 self.assertFalse(decoded.lenindef)
6387 self.assertTrue(decoded.bered)
6388 decoded = copy(decoded)
6389 self.assertFalse(decoded.ber_encoded)
6390 self.assertFalse(decoded.lenindef)
6391 self.assertTrue(decoded.bered)
6394 class TestSequence(SeqMixing, CommonMixin, TestCase):
6395 base_klass = Sequence
6401 def test_remaining(self, value, junk):
6402 class Seq(Sequence):
6404 ("whatever", Integer()),
6406 int_encoded = Integer(value).encode()
6408 Sequence.tag_default,
6409 len_encode(len(int_encoded + junk)),
6412 with assertRaisesRegex(self, DecodeError, "remaining"):
6413 Seq().decode(junked)
6415 @given(sets(text_letters(), min_size=2))
6416 def test_obj_unknown(self, names):
6417 missing = names.pop()
6419 class Seq(Sequence):
6420 schema = [(n, Boolean()) for n in names]
6422 with self.assertRaises(ObjUnknown) as err:
6425 with self.assertRaises(ObjUnknown) as err:
6426 seq[missing] = Boolean()
6429 def test_x690_vector(self):
6430 class Seq(Sequence):
6432 ("name", IA5String()),
6435 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6436 self.assertEqual(seq["name"], "Smith")
6437 self.assertEqual(seq["ok"], True)
6440 class TestSet(SeqMixing, CommonMixin, TestCase):
6443 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6444 @given(data_strategy())
6445 def test_sorted(self, d):
6446 class DummySeq(Sequence):
6447 schema = (("null", Null()),)
6449 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6450 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6451 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6452 tag_nums -= set([dummy_seq_tag_num])
6453 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6454 _schema.append(("seq", DummySeq()))
6457 schema = d.draw(permutations(_schema))
6459 for name, _ in _schema:
6461 seq[name] = OctetString(name.encode("ascii"))
6462 seq["seq"] = DummySeq((("null", Null()),))
6464 seq_encoded = seq.encode()
6465 seq_decoded, _ = seq.decode(seq_encoded)
6466 seq_encoded_expected = []
6467 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6468 if tag_num == dummy_seq_tag_num:
6469 seq_encoded_expected.append(seq["seq"].encode())
6471 seq_encoded_expected.append(seq[str(tag_num)].encode())
6472 self.assertSequenceEqual(
6473 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6474 b"".join(seq_encoded_expected),
6477 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6478 encoded += seq["seq"].encode()
6479 seq_encoded = b"".join((
6481 len_encode(len(encoded)),
6484 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6485 seq.decode(seq_encoded)
6486 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6487 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6488 self.assertTrue(seq_decoded.ber_encoded)
6489 self.assertTrue(seq_decoded.bered)
6490 seq_decoded = copy(seq_decoded)
6491 self.assertTrue(seq_decoded.ber_encoded)
6492 self.assertTrue(seq_decoded.bered)
6494 def test_same_value_twice(self):
6497 ("bool", Boolean()),
6501 encoded = b"".join((
6502 Integer(123).encode(),
6503 Integer(234).encode(),
6504 Boolean(True).encode(),
6506 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6507 with self.assertRaises(TagMismatch):
6508 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6512 def seqof_values_strategy(draw, schema=None, do_expl=False):
6514 schema = draw(sampled_from((Boolean(), Integer())))
6515 bound_min, bound_max = sorted(draw(sets(
6516 integers(min_value=0, max_value=10),
6520 if isinstance(schema, Boolean):
6521 values_generator = booleans().map(Boolean)
6522 elif isinstance(schema, Integer):
6523 values_generator = integers().map(Integer)
6524 values_generator = lists(
6529 values = draw(one_of(none(), values_generator))
6533 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6535 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6536 default = draw(one_of(none(), values_generator))
6537 optional = draw(one_of(none(), booleans()))
6539 draw(integers(min_value=0)),
6540 draw(integers(min_value=0)),
6541 draw(integers(min_value=0)),
6546 (bound_min, bound_max),
6555 class SeqOfMixing(object):
6556 def test_invalid_value_type(self):
6557 with self.assertRaises(InvalidValueType) as err:
6558 self.base_klass(123)
6561 def test_invalid_values_type(self):
6562 class SeqOf(self.base_klass):
6564 with self.assertRaises(InvalidValueType) as err:
6565 SeqOf([Integer(123), Boolean(False), Integer(234)])
6568 def test_schema_required(self):
6569 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6570 self.base_klass.__mro__[1]()
6572 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6573 def test_comparison(self, value1, value2, tag1, tag2):
6574 class SeqOf(self.base_klass):
6576 obj1 = SeqOf([Boolean(value1)])
6577 obj2 = SeqOf([Boolean(value2)])
6578 self.assertEqual(obj1 == obj2, value1 == value2)
6579 self.assertEqual(obj1 != obj2, value1 != value2)
6580 self.assertEqual(obj1 == list(obj2), value1 == value2)
6581 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6582 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6583 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6584 self.assertEqual(obj1 == obj2, tag1 == tag2)
6585 self.assertEqual(obj1 != obj2, tag1 != tag2)
6587 @given(lists(booleans()))
6588 def test_iter(self, values):
6589 class SeqOf(self.base_klass):
6591 obj = SeqOf([Boolean(value) for value in values])
6592 self.assertEqual(len(obj), len(values))
6593 for i, value in enumerate(obj):
6594 self.assertEqual(value, values[i])
6596 @given(data_strategy())
6597 def test_ready(self, d):
6598 ready = [Integer(v) for v in d.draw(lists(
6605 range(d.draw(integers(min_value=1, max_value=5)))
6608 class SeqOf(self.base_klass):
6610 values = d.draw(permutations(ready + non_ready))
6612 for value in values:
6614 self.assertFalse(seqof.ready)
6617 pprint(seqof, big_blobs=True, with_decode_path=True)
6618 with self.assertRaises(ObjNotReady) as err:
6621 with self.assertRaises(ObjNotReady) as err:
6623 for i, value in enumerate(values):
6624 self.assertEqual(seqof[i], value)
6625 if not seqof[i].ready:
6626 seqof[i] = Integer(i)
6627 self.assertTrue(seqof.ready)
6630 pprint(seqof, big_blobs=True, with_decode_path=True)
6632 def test_spec_mismatch(self):
6633 class SeqOf(self.base_klass):
6636 seqof.append(Integer(123))
6637 with self.assertRaises(ValueError):
6638 seqof.append(Boolean(False))
6639 with self.assertRaises(ValueError):
6640 seqof[0] = Boolean(False)
6642 @given(data_strategy())
6643 def test_bounds_satisfied(self, d):
6644 class SeqOf(self.base_klass):
6646 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6647 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6648 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6649 SeqOf(value=value, bounds=(bound_min, bound_max))
6651 @given(data_strategy())
6652 def test_bounds_unsatisfied(self, d):
6653 class SeqOf(self.base_klass):
6655 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6656 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6657 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6658 with self.assertRaises(BoundsError) as err:
6659 SeqOf(value=value, bounds=(bound_min, bound_max))
6661 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6662 SeqOf(bounds=(bound_min, bound_max)).decode(
6663 SeqOf(value).encode()
6666 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6667 SeqOf(bounds=(bound_min, bound_max)).decode(
6668 encode2pass(SeqOf(value))
6670 value = [Boolean(True)] * d.draw(integers(
6671 min_value=bound_max + 1,
6672 max_value=bound_max + 10,
6674 with self.assertRaises(BoundsError) as err:
6675 SeqOf(value=value, bounds=(bound_min, bound_max))
6677 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6678 SeqOf(bounds=(bound_min, bound_max)).decode(
6679 SeqOf(value).encode()
6682 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6683 SeqOf(bounds=(bound_min, bound_max)).decode(
6684 encode2pass(SeqOf(value))
6687 @given(integers(min_value=1, max_value=10))
6688 def test_out_of_bounds(self, bound_max):
6689 class SeqOf(self.base_klass):
6691 bounds = (0, bound_max)
6693 for _ in range(bound_max):
6694 seqof.append(Integer(123))
6695 with self.assertRaises(BoundsError):
6696 seqof.append(Integer(123))
6698 @given(data_strategy())
6699 def test_call(self, d):
6709 ) = d.draw(seqof_values_strategy())
6711 class SeqOf(self.base_klass):
6712 schema = schema_initial
6713 obj_initial = SeqOf(
6714 value=value_initial,
6715 bounds=bounds_initial,
6718 default=default_initial,
6719 optional=optional_initial or False,
6720 _decoded=_decoded_initial,
6731 ) = d.draw(seqof_values_strategy(
6732 schema=schema_initial,
6733 do_expl=impl_initial is None,
6735 if (default is None) and (obj_initial.default is not None):
6738 (bounds is None) and
6739 (value is not None) and
6740 (bounds_initial is not None) and
6741 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6745 (bounds is None) and
6746 (default is not None) and
6747 (bounds_initial is not None) and
6748 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6760 value_expected = default if value is None else value
6762 default_initial if value_expected is None
6765 value_expected = () if value_expected is None else value_expected
6766 self.assertEqual(obj, value_expected)
6767 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6768 self.assertEqual(obj.expl_tag, expl or expl_initial)
6771 default_initial if default is None else default,
6773 if obj.default is None:
6774 optional = optional_initial if optional is None else optional
6775 optional = False if optional is None else optional
6778 self.assertEqual(obj.optional, optional)
6780 (obj._bound_min, obj._bound_max),
6781 bounds or bounds_initial or (0, float("+inf")),
6784 @given(seqof_values_strategy())
6785 def test_copy(self, values):
6786 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6788 class SeqOf(self.base_klass):
6790 register_class(SeqOf)
6797 optional=optional or False,
6800 for copy_func in copy_funcs:
6801 obj_copied = copy_func(obj)
6802 self.assert_copied_basic_fields(obj, obj_copied)
6803 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6804 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6805 self.assertEqual(obj._value, obj_copied._value)
6809 integers(min_value=1).map(tag_encode),
6811 def test_stripped(self, values, tag_impl):
6812 class SeqOf(self.base_klass):
6813 schema = OctetString()
6814 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6815 with self.assertRaises(NotEnoughData):
6816 obj.decode(obj.encode()[:-1])
6820 integers(min_value=1).map(tag_ctxc),
6822 def test_stripped_expl(self, values, tag_expl):
6823 class SeqOf(self.base_klass):
6824 schema = OctetString()
6825 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6826 with self.assertRaises(NotEnoughData):
6827 obj.decode(obj.encode()[:-1])
6830 integers(min_value=31),
6831 integers(min_value=0),
6834 def test_bad_tag(self, tag, offset, decode_path):
6835 with self.assertRaises(DecodeError) as err:
6836 self.base_klass().decode(
6837 tag_encode(tag)[:-1],
6839 decode_path=decode_path,
6842 self.assertEqual(err.exception.offset, offset)
6843 self.assertEqual(err.exception.decode_path, decode_path)
6846 integers(min_value=128),
6847 integers(min_value=0),
6850 def test_bad_len(self, l, offset, decode_path):
6851 with self.assertRaises(DecodeError) as err:
6852 self.base_klass().decode(
6853 self.base_klass.tag_default + len_encode(l)[:-1],
6855 decode_path=decode_path,
6858 self.assertEqual(err.exception.offset, offset)
6859 self.assertEqual(err.exception.decode_path, decode_path)
6861 @given(binary(min_size=1))
6862 def test_tag_mismatch(self, impl):
6863 assume(impl != self.base_klass.tag_default)
6864 with self.assertRaises(TagMismatch):
6865 self.base_klass(impl=impl).decode(self.base_klass().encode())
6867 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6869 seqof_values_strategy(schema=Integer()),
6870 lists(integers().map(Integer)),
6871 integers(min_value=1).map(tag_ctxc),
6872 integers(min_value=0),
6876 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6877 _, _, _, _, _, default, optional, _decoded = values
6879 class SeqOf(self.base_klass):
6889 pprint(obj, big_blobs=True, with_decode_path=True)
6890 self.assertFalse(obj.expled)
6891 obj_encoded = obj.encode()
6892 self.assertEqual(encode2pass(obj), obj_encoded)
6893 obj_encoded_cer = encode_cer(obj)
6894 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6895 self.assertSequenceEqual(
6896 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6899 obj_expled = obj(value, expl=tag_expl)
6900 self.assertTrue(obj_expled.expled)
6902 list(obj_expled.pps())
6903 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6904 obj_expled_encoded = obj_expled.encode()
6905 ctx_copied = deepcopy(ctx_dummy)
6906 obj_decoded, tail = obj_expled.decode(
6907 obj_expled_encoded + tail_junk,
6911 self.assertDictEqual(ctx_copied, ctx_dummy)
6913 list(obj_decoded.pps())
6914 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6915 self.assertEqual(tail, tail_junk)
6916 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6917 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6918 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6919 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6921 obj_decoded.expl_llen,
6922 len(len_encode(len(obj_encoded))),
6924 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6925 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6928 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6930 self.assertEqual(obj_decoded.expl_offset, offset)
6931 for obj_inner in obj_decoded:
6932 self.assertIn(obj_inner, obj_decoded)
6933 self.assertSequenceEqual(
6936 obj_inner.offset - offset:
6937 obj_inner.offset + obj_inner.tlvlen - offset
6941 t, _, lv = tag_strip(obj_encoded)
6942 _, _, v = len_decode(lv)
6943 obj_encoded_lenindef = t + LENINDEF + v + EOC
6944 with self.assertRaises(DecodeError):
6945 obj.decode(obj_encoded_lenindef)
6946 obj_decoded_lenindef, tail_lenindef = obj.decode(
6947 obj_encoded_lenindef + tail_junk,
6948 ctx={"bered": True},
6950 self.assertTrue(obj_decoded_lenindef.lenindef)
6951 self.assertTrue(obj_decoded_lenindef.bered)
6952 obj_decoded_lenindef = copy(obj_decoded_lenindef)
6953 self.assertTrue(obj_decoded_lenindef.lenindef)
6954 self.assertTrue(obj_decoded_lenindef.bered)
6955 repr(obj_decoded_lenindef)
6956 list(obj_decoded_lenindef.pps())
6957 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
6958 self.assertEqual(tail_lenindef, tail_junk)
6959 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
6960 with self.assertRaises(DecodeError):
6961 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
6962 with self.assertRaises(DecodeError):
6963 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
6965 evgens = list(obj.decode_evgen(
6966 obj_encoded_lenindef + tail_junk,
6967 decode_path=decode_path,
6968 ctx={"bered": True},
6970 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
6971 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
6972 self.assertEqual(_decode_path, decode_path + (str(i),))
6975 _decode_path, obj, tail = evgens[-1]
6976 self.assertEqual(_decode_path, decode_path)
6980 assert_exceeding_data(
6982 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
6986 def test_bered(self):
6987 class SeqOf(self.base_klass):
6989 encoded = Boolean(False).encode()
6990 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
6991 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
6992 with self.assertRaises(DecodeError):
6993 SeqOf().decode(encoded)
6994 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
6995 self.assertFalse(decoded.ber_encoded)
6996 self.assertFalse(decoded.lenindef)
6997 self.assertTrue(decoded.bered)
6998 decoded = copy(decoded)
6999 self.assertFalse(decoded.ber_encoded)
7000 self.assertFalse(decoded.lenindef)
7001 self.assertTrue(decoded.bered)
7003 class SeqOf(self.base_klass):
7004 schema = OctetString()
7005 encoded = OctetString(b"whatever").encode()
7007 tag_encode(form=TagFormConstructed, num=4) +
7009 OctetString(b"whatever").encode() +
7012 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7013 with self.assertRaises(DecodeError):
7014 SeqOf().decode(encoded)
7015 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7016 self.assertFalse(decoded.ber_encoded)
7017 self.assertFalse(decoded.lenindef)
7018 self.assertTrue(decoded.bered)
7019 decoded = copy(decoded)
7020 self.assertFalse(decoded.ber_encoded)
7021 self.assertFalse(decoded.lenindef)
7022 self.assertTrue(decoded.bered)
7025 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7026 class SeqOf(SequenceOf):
7030 def _test_symmetric_compare_objs(self, obj1, obj2):
7031 self.assertEqual(obj1, obj2)
7032 self.assertSequenceEqual(list(obj1), list(obj2))
7034 def test_iterator_pickling(self):
7035 class SeqOf(SequenceOf):
7037 register_class(SeqOf)
7040 seqof = seqof(iter(six_xrange(10)))
7041 with assertRaisesRegex(self, ValueError, "iterator"):
7044 def test_iterator_bounds(self):
7045 class SeqOf(SequenceOf):
7051 for i in six_xrange(n):
7054 seqof = SeqOf(gen(n))
7055 self.assertTrue(seqof.ready)
7056 with self.assertRaises(BoundsError):
7058 self.assertFalse(seqof.ready)
7059 seqof = seqof(gen(n))
7060 self.assertTrue(seqof.ready)
7061 with self.assertRaises(BoundsError):
7063 self.assertFalse(seqof.ready)
7065 def test_iterator_twice(self):
7066 class SeqOf(SequenceOf):
7068 bounds = (1, float("+inf"))
7071 for i in six_xrange(10):
7073 seqof = SeqOf(gen())
7074 self.assertTrue(seqof.ready)
7076 self.assertFalse(seqof.ready)
7077 register_class(SeqOf)
7080 def test_iterator_2pass(self):
7081 class SeqOf(SequenceOf):
7083 bounds = (1, float("+inf"))
7086 for i in six_xrange(10):
7088 seqof = SeqOf(gen())
7089 self.assertTrue(seqof.ready)
7090 _, state = seqof.encode1st()
7091 self.assertFalse(seqof.ready)
7092 seqof = seqof(gen())
7093 self.assertTrue(seqof.ready)
7095 seqof.encode2nd(buf.write, iter(state))
7096 self.assertSequenceEqual(
7097 [int(i) for i in seqof.decod(buf.getvalue())],
7101 def test_non_ready_bound_min(self):
7102 class SeqOf(SequenceOf):
7104 bounds = (1, float("+inf"))
7106 self.assertFalse(seqof.ready)
7109 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7114 def _test_symmetric_compare_objs(self, obj1, obj2):
7115 self.assertSetEqual(
7116 set(int(v) for v in obj1),
7117 set(int(v) for v in obj2),
7120 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7121 @given(data_strategy())
7122 def test_sorted(self, d):
7123 values = [OctetString(v) for v in d.draw(lists(binary()))]
7126 schema = OctetString()
7128 seq_encoded = seq.encode()
7129 seq_decoded, _ = seq.decode(seq_encoded)
7130 self.assertSequenceEqual(
7131 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7132 b"".join(sorted([v.encode() for v in values])),
7135 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7136 @given(data_strategy())
7137 def test_unsorted(self, d):
7138 values = [OctetString(v).encode() for v in d.draw(sets(
7139 binary(min_size=1, max_size=5),
7143 values = d.draw(permutations(values))
7144 assume(values != sorted(values))
7145 encoded = b"".join(values)
7146 seq_encoded = b"".join((
7148 len_encode(len(encoded)),
7153 schema = OctetString()
7155 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7156 seq.decode(seq_encoded)
7158 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7159 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7160 self.assertTrue(seq_decoded.ber_encoded)
7161 self.assertTrue(seq_decoded.bered)
7162 seq_decoded = copy(seq_decoded)
7163 self.assertTrue(seq_decoded.ber_encoded)
7164 self.assertTrue(seq_decoded.bered)
7165 self.assertSequenceEqual(
7166 [obj.encode() for obj in seq_decoded],
7171 class TestGoMarshalVectors(TestCase):
7173 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7174 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7175 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7176 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7177 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7179 class Seq(Sequence):
7181 ("erste", Integer()),
7182 ("zweite", Integer(optional=True))
7185 seq["erste"] = Integer(64)
7186 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7187 seq["erste"] = Integer(0x123456)
7188 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7189 seq["erste"] = Integer(64)
7190 seq["zweite"] = Integer(65)
7191 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7193 class NestedSeq(Sequence):
7197 seq["erste"] = Integer(127)
7198 seq["zweite"] = None
7199 nested = NestedSeq()
7200 nested["nest"] = seq
7201 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7203 self.assertSequenceEqual(
7204 OctetString(b"\x01\x02\x03").encode(),
7205 hexdec("0403010203"),
7208 class Seq(Sequence):
7210 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7213 seq["erste"] = Integer(64)
7214 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7216 class Seq(Sequence):
7218 ("erste", Integer(expl=tag_ctxc(5))),
7221 seq["erste"] = Integer(64)
7222 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7224 class Seq(Sequence):
7227 impl=tag_encode(0, klass=TagClassContext),
7232 seq["erste"] = Null()
7233 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7235 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7237 self.assertSequenceEqual(
7238 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7239 hexdec("170d3730303130313030303030305a"),
7241 self.assertSequenceEqual(
7242 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7243 hexdec("170d3039313131353232353631365a"),
7245 self.assertSequenceEqual(
7246 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7247 hexdec("180f32313030303430353132303130315a"),
7250 class Seq(Sequence):
7252 ("erste", GeneralizedTime()),
7255 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7256 self.assertSequenceEqual(
7258 hexdec("3011180f32303039313131353232353631365a"),
7261 self.assertSequenceEqual(
7262 BitString((1, b"\x80")).encode(),
7265 self.assertSequenceEqual(
7266 BitString((12, b"\x81\xF0")).encode(),
7267 hexdec("03030481f0"),
7270 self.assertSequenceEqual(
7271 ObjectIdentifier("1.2.3.4").encode(),
7272 hexdec("06032a0304"),
7274 self.assertSequenceEqual(
7275 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7276 hexdec("06092a864888932d010105"),
7278 self.assertSequenceEqual(
7279 ObjectIdentifier("2.100.3").encode(),
7280 hexdec("0603813403"),
7283 self.assertSequenceEqual(
7284 PrintableString("test").encode(),
7285 hexdec("130474657374"),
7287 self.assertSequenceEqual(
7288 PrintableString("x" * 127).encode(),
7289 hexdec("137F" + "78" * 127),
7291 self.assertSequenceEqual(
7292 PrintableString("x" * 128).encode(),
7293 hexdec("138180" + "78" * 128),
7295 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7297 class Seq(Sequence):
7299 ("erste", IA5String()),
7302 seq["erste"] = IA5String("test")
7303 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7305 class Seq(Sequence):
7307 ("erste", PrintableString()),
7310 seq["erste"] = PrintableString("test")
7311 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7312 # Asterisk is actually not allowable
7313 PrintableString._allowable_chars |= set(b"*")
7314 seq["erste"] = PrintableString("test*")
7315 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7316 PrintableString._allowable_chars -= set(b"*")
7318 class Seq(Sequence):
7320 ("erste", Any(optional=True)),
7321 ("zweite", Integer()),
7324 seq["zweite"] = Integer(64)
7325 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7330 seq.append(Integer(10))
7331 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7333 class _SeqOf(SequenceOf):
7334 schema = PrintableString()
7336 class SeqOf(SequenceOf):
7339 _seqof.append(PrintableString("1"))
7341 seqof.append(_seqof)
7342 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7344 class Seq(Sequence):
7346 ("erste", Integer(default=1)),
7349 seq["erste"] = Integer(0)
7350 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7351 seq["erste"] = Integer(1)
7352 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7353 seq["erste"] = Integer(2)
7354 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7357 class TestPP(TestCase):
7358 @given(data_strategy())
7359 def test_oid_printing(self, d):
7361 str(ObjectIdentifier(k)): v * 2
7362 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7364 chosen = d.draw(sampled_from(sorted(oids)))
7365 chosen_id = oids[chosen]
7366 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7367 self.assertNotIn(chosen_id, pp_console_row(pp))
7370 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7374 class TestAutoAddSlots(TestCase):
7376 class Inher(Integer):
7379 with self.assertRaises(AttributeError):
7381 inher.unexistent = "whatever"
7384 class TestOIDDefines(TestCase):
7385 @given(data_strategy())
7386 def runTest(self, d):
7387 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7388 value_name_chosen = d.draw(sampled_from(value_names))
7390 ObjectIdentifier(oid)
7391 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7393 oid_chosen = d.draw(sampled_from(oids))
7394 values = d.draw(lists(
7396 min_size=len(value_names),
7397 max_size=len(value_names),
7399 for definable_class in (Any, OctetString, BitString):
7401 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7402 oid: Integer() for oid in oids[:-1]
7405 for i, value_name in enumerate(value_names):
7406 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7408 class Seq(Sequence):
7411 for value_name, value in zip(value_names, values):
7412 seq[value_name] = definable_class(Integer(value).encode())
7413 seq["type"] = oid_chosen
7414 seq, _ = Seq().decode(seq.encode())
7415 for value_name in value_names:
7416 if value_name == value_name_chosen:
7418 self.assertIsNone(seq[value_name].defined)
7419 if value_name_chosen in oids[:-1]:
7420 self.assertIsNotNone(seq[value_name_chosen].defined)
7421 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7422 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7425 pprint(seq, big_blobs=True, with_decode_path=True)
7428 class TestDefinesByPath(TestCase):
7429 def test_generated(self):
7430 class Seq(Sequence):
7432 ("type", ObjectIdentifier()),
7433 ("value", OctetString(expl=tag_ctxc(123))),
7436 class SeqInner(Sequence):
7438 ("typeInner", ObjectIdentifier()),
7439 ("valueInner", Any()),
7442 class PairValue(SetOf):
7445 class Pair(Sequence):
7447 ("type", ObjectIdentifier()),
7448 ("value", PairValue()),
7451 class Pairs(SequenceOf):
7458 type_octet_stringed,
7460 ObjectIdentifier(oid)
7461 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7463 seq_integered = Seq()
7464 seq_integered["type"] = type_integered
7465 seq_integered["value"] = OctetString(Integer(123).encode())
7466 seq_integered_raw = seq_integered.encode()
7470 (type_octet_stringed, OctetString(b"whatever")),
7471 (type_integered, Integer(123)),
7472 (type_octet_stringed, OctetString(b"whenever")),
7473 (type_integered, Integer(234)),
7475 for t, v in pairs_input:
7478 ("value", PairValue((Any(v),))),
7480 seq_inner = SeqInner()
7481 seq_inner["typeInner"] = type_innered
7482 seq_inner["valueInner"] = Any(pairs)
7483 seq_sequenced = Seq()
7484 seq_sequenced["type"] = type_sequenced
7485 seq_sequenced["value"] = OctetString(seq_inner.encode())
7486 seq_sequenced_raw = seq_sequenced.encode()
7488 list(seq_sequenced.pps())
7489 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7491 defines_by_path = []
7492 ctx_copied = deepcopy(ctx_dummy)
7493 seq_integered, _ = Seq().decode(
7497 self.assertDictEqual(ctx_copied, ctx_dummy)
7498 self.assertIsNone(seq_integered["value"].defined)
7499 defines_by_path.append(
7500 (("type",), ((("value",), {
7501 type_integered: Integer(),
7502 type_sequenced: SeqInner(),
7505 ctx_copied["defines_by_path"] = defines_by_path
7506 seq_integered, _ = Seq().decode(
7510 del ctx_copied["defines_by_path"]
7511 self.assertDictEqual(ctx_copied, ctx_dummy)
7512 self.assertIsNotNone(seq_integered["value"].defined)
7513 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7514 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7515 self.assertTrue(seq_integered_raw[
7516 seq_integered["value"].defined[1].offset:
7517 ].startswith(Integer(123).encode()))
7519 list(seq_integered.pps())
7520 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7522 ctx_copied["defines_by_path"] = defines_by_path
7523 seq_sequenced, _ = Seq().decode(
7527 del ctx_copied["defines_by_path"]
7528 self.assertDictEqual(ctx_copied, ctx_dummy)
7529 self.assertIsNotNone(seq_sequenced["value"].defined)
7530 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7531 seq_inner = seq_sequenced["value"].defined[1]
7532 self.assertIsNone(seq_inner["valueInner"].defined)
7534 list(seq_sequenced.pps())
7535 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7537 defines_by_path.append((
7538 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7539 ((("valueInner",), {type_innered: Pairs()}),),
7541 ctx_copied["defines_by_path"] = defines_by_path
7542 seq_sequenced, _ = Seq().decode(
7546 del ctx_copied["defines_by_path"]
7547 self.assertDictEqual(ctx_copied, ctx_dummy)
7548 self.assertIsNotNone(seq_sequenced["value"].defined)
7549 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7550 seq_inner = seq_sequenced["value"].defined[1]
7551 self.assertIsNotNone(seq_inner["valueInner"].defined)
7552 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7553 pairs = seq_inner["valueInner"].defined[1]
7555 self.assertIsNone(pair["value"][0].defined)
7557 list(seq_sequenced.pps())
7558 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7560 defines_by_path.append((
7563 DecodePathDefBy(type_sequenced),
7565 DecodePathDefBy(type_innered),
7570 type_integered: Integer(),
7571 type_octet_stringed: OctetString(),
7574 ctx_copied["defines_by_path"] = defines_by_path
7575 seq_sequenced, _ = Seq().decode(
7579 del ctx_copied["defines_by_path"]
7580 self.assertDictEqual(ctx_copied, ctx_dummy)
7581 self.assertIsNotNone(seq_sequenced["value"].defined)
7582 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7583 seq_inner = seq_sequenced["value"].defined[1]
7584 self.assertIsNotNone(seq_inner["valueInner"].defined)
7585 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7586 pairs_got = seq_inner["valueInner"].defined[1]
7587 for pair_input, pair_got in zip(pairs_input, pairs_got):
7588 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7589 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7591 list(seq_sequenced.pps())
7592 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7594 @given(oid_strategy(), integers())
7595 def test_simple(self, oid, tgt):
7596 class Inner(Sequence):
7598 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7599 ObjectIdentifier(oid): Integer(),
7603 class Outer(Sequence):
7606 ("tgt", OctetString()),
7610 inner["oid"] = ObjectIdentifier(oid)
7612 outer["inner"] = inner
7613 outer["tgt"] = OctetString(Integer(tgt).encode())
7614 decoded, _ = Outer().decode(outer.encode())
7615 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7617 def test_remaining_data(self):
7618 oid = ObjectIdentifier("1.2.3")
7620 class Seq(Sequence):
7622 ("oid", ObjectIdentifier(defines=((("tgt",), {
7625 ("tgt", OctetString()),
7630 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7632 with assertRaisesRegex(self, DecodeError, "remaining data"):
7633 Seq().decode(seq.encode())
7635 def test_remaining_data_seqof(self):
7636 oid = ObjectIdentifier("1.2.3")
7639 schema = OctetString()
7641 class Seq(Sequence):
7643 ("oid", ObjectIdentifier(defines=((("tgt",), {
7651 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7653 with assertRaisesRegex(self, DecodeError, "remaining data"):
7654 Seq().decode(seq.encode())
7657 class TestAbsDecodePath(TestCase):
7659 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7660 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7662 def test_concat(self, decode_path, rel_path):
7663 dp = abs_decode_path(decode_path, rel_path)
7664 self.assertSequenceEqual(dp, decode_path + rel_path)
7668 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7669 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7671 def test_abs(self, decode_path, rel_path):
7672 self.assertSequenceEqual(
7673 abs_decode_path(decode_path, ("/",) + rel_path),
7678 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7679 integers(min_value=1, max_value=3),
7680 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7682 def test_dots(self, decode_path, number_of_dots, rel_path):
7683 self.assertSequenceEqual(
7684 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7685 decode_path[:-number_of_dots] + rel_path,
7689 class TestStrictDefaultExistence(TestCase):
7690 @given(data_strategy())
7691 def runTest(self, d):
7692 count = d.draw(integers(min_value=1, max_value=10))
7693 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7695 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7696 for i in range(count)
7698 for klass in (Sequence, Set):
7702 for i in range(count):
7703 seq["int%d" % i] = Integer(123)
7705 chosen_choice = "int%d" % chosen
7706 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7707 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7709 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7710 self.assertTrue(decoded.ber_encoded)
7711 self.assertTrue(decoded.bered)
7712 decoded = copy(decoded)
7713 self.assertTrue(decoded.ber_encoded)
7714 self.assertTrue(decoded.bered)
7715 decoded, _ = seq.decode(raw, ctx={"bered": True})
7716 self.assertTrue(decoded.ber_encoded)
7717 self.assertTrue(decoded.bered)
7718 decoded = copy(decoded)
7719 self.assertTrue(decoded.ber_encoded)
7720 self.assertTrue(decoded.bered)
7723 class TestX690PrefixedType(TestCase):
7725 self.assertSequenceEqual(
7726 VisibleString("Jones").encode(),
7727 hexdec("1A054A6F6E6573"),
7731 self.assertSequenceEqual(
7734 impl=tag_encode(3, klass=TagClassApplication),
7736 hexdec("43054A6F6E6573"),
7740 self.assertSequenceEqual(
7744 impl=tag_encode(3, klass=TagClassApplication),
7748 hexdec("A20743054A6F6E6573"),
7752 self.assertSequenceEqual(
7756 impl=tag_encode(3, klass=TagClassApplication),
7758 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7760 hexdec("670743054A6F6E6573"),
7764 self.assertSequenceEqual(
7765 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7766 hexdec("82054A6F6E6573"),
7770 class TestExplOOB(TestCase):
7772 expl = tag_ctxc(123)
7773 raw = Integer(123).encode() + Integer(234).encode()
7774 raw = b"".join((expl, len_encode(len(raw)), raw))
7775 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7776 Integer(expl=expl).decode(raw)
7777 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7780 class TestPickleDifferentVersion(TestCase):
7782 pickled = pickle_dumps(Integer(123), pickle_proto)
7784 version_orig = pyderasn.__version__
7785 pyderasn.__version__ += "different"
7786 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7787 pickle_loads(pickled)
7788 pyderasn.__version__ = version_orig
7789 pickle_loads(pickled)
7792 class TestCERSetOrdering(TestCase):
7793 def test_vectors(self):
7794 """Taken from X.690-201508
7798 ("c", Integer(impl=tag_ctxp(2))),
7799 ("d", Integer(impl=tag_ctxp(4))),
7804 ("g", Integer(impl=tag_ctxp(5))),
7805 ("h", Integer(impl=tag_ctxp(6))),
7810 ("j", Integer(impl=tag_ctxp(0))),
7821 ("a", Integer(impl=tag_ctxp(3))),
7822 ("b", B(expl=tag_ctxc(1))),
7827 ("a", Integer(123)),
7828 ("b", B(("d", Integer(234)))),
7829 ("e", E(("f", F(("g", Integer(345)))))),
7831 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7832 self.assertSequenceEqual(
7833 [i.__class__.__name__ for i in order],
7834 ("E", "B", "Integer"),