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)
2666 @given(integers(min_value=1))
2667 def test_invalid_len(self, l):
2668 with self.assertRaises(InvalidLength):
2669 Null().decode(b"".join((
2676 def oid_strategy(draw):
2677 first_arc = draw(integers(min_value=0, max_value=2))
2679 if first_arc in (0, 1):
2680 second_arc = draw(integers(min_value=0, max_value=39))
2682 second_arc = draw(integers(min_value=0))
2683 other_arcs = draw(lists(integers(min_value=0)))
2684 return tuple([first_arc, second_arc] + other_arcs)
2688 def oid_values_strategy(draw, do_expl=False):
2689 value = draw(one_of(none(), oid_strategy()))
2693 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2695 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2696 default = draw(one_of(none(), oid_strategy()))
2697 optional = draw(one_of(none(), booleans()))
2699 draw(integers(min_value=0)),
2700 draw(integers(min_value=0)),
2701 draw(integers(min_value=0)),
2703 return (value, impl, expl, default, optional, _decoded)
2706 class ObjectIdentifierInherited(ObjectIdentifier):
2710 class TestObjectIdentifier(CommonMixin, TestCase):
2711 base_klass = ObjectIdentifier
2713 def test_invalid_value_type(self):
2714 with self.assertRaises(InvalidValueType) as err:
2715 ObjectIdentifier(123)
2719 def test_optional(self, optional):
2720 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2721 self.assertTrue(obj.optional)
2723 @given(oid_strategy())
2724 def test_ready(self, value):
2725 obj = ObjectIdentifier()
2726 self.assertFalse(obj.ready)
2729 pprint(obj, big_blobs=True, with_decode_path=True)
2730 with self.assertRaises(ObjNotReady) as err:
2733 with self.assertRaises(ObjNotReady) as err:
2735 obj = ObjectIdentifier(value)
2736 self.assertTrue(obj.ready)
2737 self.assertFalse(obj.ber_encoded)
2740 pprint(obj, big_blobs=True, with_decode_path=True)
2743 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2744 def test_comparison(self, value1, value2, tag1, tag2):
2745 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2746 obj1 = klass(value1)
2747 obj2 = klass(value2)
2748 self.assertEqual(obj1 == obj2, value1 == value2)
2749 self.assertEqual(obj1 != obj2, value1 != value2)
2750 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2751 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2752 obj1 = klass(value1, impl=tag1)
2753 obj2 = klass(value1, impl=tag2)
2754 self.assertEqual(obj1 == obj2, tag1 == tag2)
2755 self.assertEqual(obj1 != obj2, tag1 != tag2)
2757 @given(lists(oid_strategy()))
2758 def test_sorted_works(self, values):
2759 self.assertSequenceEqual(
2760 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2764 @given(data_strategy())
2765 def test_call(self, d):
2766 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2774 ) = d.draw(oid_values_strategy())
2775 obj_initial = klass(
2776 value=value_initial,
2779 default=default_initial,
2780 optional=optional_initial or False,
2781 _decoded=_decoded_initial,
2790 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2799 value_expected = default if value is None else value
2801 default_initial if value_expected is None
2804 self.assertEqual(obj, value_expected)
2805 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2806 self.assertEqual(obj.expl_tag, expl or expl_initial)
2809 default_initial if default is None else default,
2811 if obj.default is None:
2812 optional = optional_initial if optional is None else optional
2813 optional = False if optional is None else optional
2816 self.assertEqual(obj.optional, optional)
2818 @given(oid_values_strategy())
2819 def test_copy(self, values):
2820 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2837 for copy_func in copy_funcs:
2838 obj_copied = copy_func(obj)
2839 self.assert_copied_basic_fields(obj, obj_copied)
2840 self.assertEqual(obj._value, obj_copied._value)
2842 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2845 integers(min_value=1).map(tag_encode),
2847 def test_stripped(self, value, tag_impl):
2848 obj = ObjectIdentifier(value, impl=tag_impl)
2849 with self.assertRaises(NotEnoughData):
2850 obj.decode(obj.encode()[:-1])
2854 integers(min_value=1).map(tag_ctxc),
2856 def test_stripped_expl(self, value, tag_expl):
2857 obj = ObjectIdentifier(value, expl=tag_expl)
2858 with self.assertRaises(NotEnoughData):
2859 obj.decode(obj.encode()[:-1])
2862 integers(min_value=31),
2863 integers(min_value=0),
2866 def test_bad_tag(self, tag, offset, decode_path):
2867 with self.assertRaises(DecodeError) as err:
2868 ObjectIdentifier().decode(
2869 tag_encode(tag)[:-1],
2871 decode_path=decode_path,
2874 self.assertEqual(err.exception.offset, offset)
2875 self.assertEqual(err.exception.decode_path, decode_path)
2878 integers(min_value=128),
2879 integers(min_value=0),
2882 def test_bad_len(self, l, offset, decode_path):
2883 with self.assertRaises(DecodeError) as err:
2884 ObjectIdentifier().decode(
2885 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2887 decode_path=decode_path,
2890 self.assertEqual(err.exception.offset, offset)
2891 self.assertEqual(err.exception.decode_path, decode_path)
2893 def test_zero_oid(self):
2894 with self.assertRaises(NotEnoughData):
2895 ObjectIdentifier().decode(
2896 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2899 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2900 @given(oid_strategy())
2901 def test_unfinished_oid(self, value):
2902 assume(list(value)[-1] > 255)
2903 obj_encoded = ObjectIdentifier(value).encode()
2904 obj, _ = ObjectIdentifier().decode(obj_encoded)
2905 data = obj_encoded[obj.tlen + obj.llen:-1]
2907 ObjectIdentifier.tag_default,
2908 len_encode(len(data)),
2911 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2914 @given(integers(min_value=0))
2915 def test_invalid_short(self, value):
2916 with self.assertRaises(InvalidOID):
2917 ObjectIdentifier((value,))
2918 with self.assertRaises(InvalidOID):
2919 ObjectIdentifier("%d" % value)
2921 @given(integers(min_value=3), integers(min_value=0))
2922 def test_invalid_first_arc(self, first_arc, second_arc):
2923 with self.assertRaises(InvalidOID):
2924 ObjectIdentifier((first_arc, second_arc))
2925 with self.assertRaises(InvalidOID):
2926 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2928 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2929 def test_invalid_second_arc(self, first_arc, second_arc):
2930 with self.assertRaises(InvalidOID):
2931 ObjectIdentifier((first_arc, second_arc))
2932 with self.assertRaises(InvalidOID):
2933 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2935 @given(text(alphabet=ascii_letters + ".", min_size=1))
2936 def test_junk(self, oid):
2937 with self.assertRaises(InvalidOID):
2938 ObjectIdentifier(oid)
2940 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2941 @given(oid_strategy())
2942 def test_validness(self, oid):
2943 obj = ObjectIdentifier(oid)
2944 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2947 pprint(obj, big_blobs=True, with_decode_path=True)
2949 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2951 oid_values_strategy(),
2953 integers(min_value=1).map(tag_ctxc),
2954 integers(min_value=0),
2958 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2959 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2960 _, _, _, default, optional, _decoded = values
2969 pprint(obj, big_blobs=True, with_decode_path=True)
2970 self.assertFalse(obj.expled)
2971 obj_encoded = obj.encode()
2972 self.assertEqual(encode2pass(obj), obj_encoded)
2973 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2974 obj_expled = obj(value, expl=tag_expl)
2975 self.assertTrue(obj_expled.expled)
2977 list(obj_expled.pps())
2978 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2979 obj_expled_encoded = obj_expled.encode()
2980 obj_expled_cer = encode_cer(obj_expled)
2981 self.assertNotEqual(obj_expled_cer, obj_encoded)
2982 self.assertSequenceEqual(
2983 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2986 ctx_copied = deepcopy(ctx_dummy)
2987 obj_decoded, tail = obj_expled.decode(
2988 obj_expled_encoded + tail_junk,
2992 self.assertDictEqual(ctx_copied, ctx_dummy)
2994 list(obj_decoded.pps())
2995 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2996 self.assertEqual(tail, tail_junk)
2997 self.assertEqual(obj_decoded, obj_expled)
2998 self.assertNotEqual(obj_decoded, obj)
2999 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
3000 self.assertEqual(tuple(obj_decoded), tuple(obj))
3001 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3002 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3003 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3005 obj_decoded.expl_llen,
3006 len(len_encode(len(obj_encoded))),
3008 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3009 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3012 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3014 self.assertEqual(obj_decoded.expl_offset, offset)
3015 assert_exceeding_data(
3017 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3021 evgens = list(obj_expled.decode_evgen(
3022 obj_expled_encoded + tail_junk,
3024 decode_path=decode_path,
3027 self.assertEqual(len(evgens), 1)
3028 _decode_path, obj, tail = evgens[0]
3029 self.assertSequenceEqual(tail, tail_junk)
3030 self.assertEqual(_decode_path, decode_path)
3031 self.assertEqual(obj, obj_decoded)
3032 self.assertEqual(obj.expl_offset, offset)
3037 oid_strategy().map(ObjectIdentifier),
3038 oid_strategy().map(ObjectIdentifier),
3040 def test_add(self, oid1, oid2):
3041 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3042 for oid_to_add in (oid2, tuple(oid2)):
3043 self.assertEqual(oid1 + oid_to_add, oid_expect)
3044 with self.assertRaises(InvalidValueType):
3047 def test_go_vectors_valid(self):
3048 for data, expect in (
3050 (b"\x55\x02", (2, 5, 2)),
3051 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3052 (b"\x81\x34\x03", (2, 100, 3)),
3055 ObjectIdentifier().decode(b"".join((
3056 ObjectIdentifier.tag_default,
3057 len_encode(len(data)),
3063 def test_go_vectors_invalid(self):
3064 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3065 with self.assertRaises(DecodeError):
3066 ObjectIdentifier().decode(b"".join((
3067 Integer.tag_default,
3068 len_encode(len(data)),
3072 def test_x690_vector(self):
3074 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3075 ObjectIdentifier((2, 999, 3)),
3078 def test_nonnormalized_first_arc(self):
3080 ObjectIdentifier.tag_default +
3083 ObjectIdentifier((1, 0)).encode()[-1:]
3085 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3086 self.assertTrue(obj.ber_encoded)
3087 self.assertTrue(obj.bered)
3089 self.assertTrue(obj.ber_encoded)
3090 self.assertTrue(obj.bered)
3091 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3092 ObjectIdentifier().decode(tampered)
3094 @given(data_strategy())
3095 def test_negative_arcs(self, d):
3096 oid = list(d.draw(oid_strategy()))
3099 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3101 if oid[idx - 1] == 0:
3103 with self.assertRaises(InvalidOID):
3104 ObjectIdentifier(tuple(oid))
3105 with self.assertRaises(InvalidOID):
3106 ObjectIdentifier(".".join(str(i) for i in oid))
3108 @given(data_strategy())
3109 def test_plused_arcs(self, d):
3110 oid = [str(arc) for arc in d.draw(oid_strategy())]
3111 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3112 oid[idx - 1] = "+" + oid[idx - 1]
3113 with self.assertRaises(InvalidOID):
3114 ObjectIdentifier(".".join(str(i) for i in oid))
3116 @given(data_strategy())
3117 def test_nonnormalized_arcs(self, d):
3118 arcs = d.draw(lists(
3119 integers(min_value=0, max_value=100),
3123 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3124 _, _, lv = tag_strip(dered)
3125 _, _, v = len_decode(lv)
3126 v_no_first_arc = v[1:]
3127 idx_for_tamper = d.draw(integers(
3129 max_value=len(v_no_first_arc) - 1,
3131 tampered = list(bytearray(v_no_first_arc))
3132 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3133 tampered.insert(idx_for_tamper, 0x80)
3134 tampered = bytes(bytearray(tampered))
3136 ObjectIdentifier.tag_default +
3137 len_encode(len(tampered)) +
3140 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3141 self.assertTrue(obj.ber_encoded)
3142 self.assertTrue(obj.bered)
3144 self.assertTrue(obj.ber_encoded)
3145 self.assertTrue(obj.bered)
3146 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3147 ObjectIdentifier().decode(tampered)
3151 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3153 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3154 values = list(draw(sets(
3156 min_size=len(schema),
3157 max_size=len(schema),
3159 schema = list(zip(schema, values))
3160 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3164 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3166 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3167 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3168 optional = draw(one_of(none(), booleans()))
3170 draw(integers(min_value=0)),
3171 draw(integers(min_value=0)),
3172 draw(integers(min_value=0)),
3174 return (schema, value, impl, expl, default, optional, _decoded)
3177 class TestEnumerated(CommonMixin, TestCase):
3178 class EWhatever(Enumerated):
3179 schema = (("whatever", 0),)
3181 base_klass = EWhatever
3183 def test_schema_required(self):
3184 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3187 def test_invalid_value_type(self):
3188 with self.assertRaises(InvalidValueType) as err:
3189 self.base_klass((1, 2))
3192 @given(sets(text_letters(), min_size=2))
3193 def test_unknown_name(self, schema_input):
3194 missing = schema_input.pop()
3196 class E(Enumerated):
3197 schema = [(n, 123) for n in schema_input]
3198 with self.assertRaises(ObjUnknown) as err:
3203 sets(text_letters(), min_size=2),
3204 sets(integers(), min_size=2),
3206 def test_unknown_value(self, schema_input, values_input):
3208 missing_value = values_input.pop()
3209 _input = list(zip(schema_input, values_input))
3211 class E(Enumerated):
3213 with self.assertRaises(DecodeError) as err:
3218 def test_optional(self, optional):
3219 obj = self.base_klass(default="whatever", optional=optional)
3220 self.assertTrue(obj.optional)
3222 def test_ready(self):
3223 obj = self.base_klass()
3224 self.assertFalse(obj.ready)
3227 pprint(obj, big_blobs=True, with_decode_path=True)
3228 with self.assertRaises(ObjNotReady) as err:
3231 obj = self.base_klass("whatever")
3232 self.assertTrue(obj.ready)
3235 pprint(obj, big_blobs=True, with_decode_path=True)
3237 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3238 def test_comparison(self, value1, value2, tag1, tag2):
3239 class E(Enumerated):
3241 ("whatever0", value1),
3242 ("whatever1", value2),
3245 class EInherited(E):
3247 for klass in (E, EInherited):
3248 obj1 = klass(value1)
3249 obj2 = klass(value2)
3250 self.assertEqual(obj1 == obj2, value1 == value2)
3251 self.assertEqual(obj1 != obj2, value1 != value2)
3252 self.assertEqual(obj1 == int(obj2), value1 == value2)
3253 obj1 = klass(value1, impl=tag1)
3254 obj2 = klass(value1, impl=tag2)
3255 self.assertEqual(obj1 == obj2, tag1 == tag2)
3256 self.assertEqual(obj1 != obj2, tag1 != tag2)
3258 @given(data_strategy())
3259 def test_call(self, d):
3268 ) = d.draw(enumerated_values_strategy())
3270 class E(Enumerated):
3271 schema = schema_initial
3273 value=value_initial,
3276 default=default_initial,
3277 optional=optional_initial or False,
3278 _decoded=_decoded_initial,
3288 ) = d.draw(enumerated_values_strategy(
3289 schema=schema_initial,
3290 do_expl=impl_initial is None,
3300 value_expected = default if value is None else value
3302 default_initial if value_expected is None
3307 dict(schema_initial).get(value_expected, value_expected),
3309 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3310 self.assertEqual(obj.expl_tag, expl or expl_initial)
3313 default_initial if default is None else default,
3315 if obj.default is None:
3316 optional = optional_initial if optional is None else optional
3317 optional = False if optional is None else optional
3320 self.assertEqual(obj.optional, optional)
3321 self.assertEqual(obj.specs, dict(schema_initial))
3323 @given(enumerated_values_strategy())
3324 def test_copy(self, values):
3325 schema_input, value, impl, expl, default, optional, _decoded = values
3327 class E(Enumerated):
3328 schema = schema_input
3338 for copy_func in copy_funcs:
3339 obj_copied = copy_func(obj)
3340 self.assert_copied_basic_fields(obj, obj_copied)
3341 self.assertEqual(obj.specs, obj_copied.specs)
3343 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3344 @given(data_strategy())
3345 def test_symmetric(self, d):
3346 schema_input, _, _, _, default, optional, _decoded = d.draw(
3347 enumerated_values_strategy(),
3349 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3350 offset = d.draw(integers(min_value=0))
3351 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3352 tail_junk = d.draw(binary(max_size=5))
3353 decode_path = d.draw(decode_path_strat)
3355 class E(Enumerated):
3356 schema = schema_input
3365 pprint(obj, big_blobs=True, with_decode_path=True)
3366 self.assertFalse(obj.expled)
3367 obj_encoded = obj.encode()
3368 self.assertEqual(encode2pass(obj), obj_encoded)
3369 obj_expled = obj(value, expl=tag_expl)
3370 self.assertTrue(obj_expled.expled)
3372 list(obj_expled.pps())
3373 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3374 obj_expled_encoded = obj_expled.encode()
3375 ctx_copied = deepcopy(ctx_dummy)
3376 obj_decoded, tail = obj_expled.decode(
3377 obj_expled_encoded + tail_junk,
3381 self.assertDictEqual(ctx_copied, ctx_dummy)
3383 list(obj_decoded.pps())
3384 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3385 self.assertEqual(tail, tail_junk)
3386 self.assertEqual(obj_decoded, obj_expled)
3387 self.assertNotEqual(obj_decoded, obj)
3388 self.assertEqual(int(obj_decoded), int(obj_expled))
3389 self.assertEqual(int(obj_decoded), int(obj))
3390 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3391 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3392 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3394 obj_decoded.expl_llen,
3395 len(len_encode(len(obj_encoded))),
3397 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3398 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3401 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3403 self.assertEqual(obj_decoded.expl_offset, offset)
3404 assert_exceeding_data(
3406 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3410 evgens = list(obj_expled.decode_evgen(
3411 obj_expled_encoded + tail_junk,
3413 decode_path=decode_path,
3416 self.assertEqual(len(evgens), 1)
3417 _decode_path, obj, tail = evgens[0]
3418 self.assertSequenceEqual(tail, tail_junk)
3419 self.assertEqual(_decode_path, decode_path)
3420 self.assertEqual(obj, obj_decoded)
3421 self.assertEqual(obj.expl_offset, offset)
3427 def string_values_strategy(draw, alphabet, do_expl=False):
3428 bound_min, bound_max = sorted(draw(sets(
3429 integers(min_value=0, max_value=1 << 7),
3433 value = draw(one_of(
3435 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3437 default = draw(one_of(
3439 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3442 if draw(booleans()):
3443 bounds = (bound_min, bound_max)
3447 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3449 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3450 optional = draw(one_of(none(), booleans()))
3452 draw(integers(min_value=0)),
3453 draw(integers(min_value=0)),
3454 draw(integers(min_value=0)),
3456 return (value, bounds, impl, expl, default, optional, _decoded)
3459 class StringMixin(object):
3460 def test_invalid_value_type(self):
3461 with self.assertRaises(InvalidValueType) as err:
3462 self.base_klass((1, 2))
3465 def text_alphabet(self):
3466 if self.base_klass.encoding in ("ascii", "iso-8859-1"):
3467 return printable + whitespace
3471 def test_optional(self, optional):
3472 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3473 self.assertTrue(obj.optional)
3475 @given(data_strategy())
3476 def test_ready(self, d):
3477 obj = self.base_klass()
3478 self.assertFalse(obj.ready)
3481 pprint(obj, big_blobs=True, with_decode_path=True)
3483 with self.assertRaises(ObjNotReady) as err:
3486 with self.assertRaises(ObjNotReady) as err:
3488 value = d.draw(text(alphabet=self.text_alphabet()))
3489 obj = self.base_klass(value)
3490 self.assertTrue(obj.ready)
3493 pprint(obj, big_blobs=True, with_decode_path=True)
3496 @given(data_strategy())
3497 def test_comparison(self, d):
3498 value1 = d.draw(text(alphabet=self.text_alphabet()))
3499 value2 = d.draw(text(alphabet=self.text_alphabet()))
3500 tag1 = d.draw(binary(min_size=1))
3501 tag2 = d.draw(binary(min_size=1))
3502 obj1 = self.base_klass(value1)
3503 obj2 = self.base_klass(value2)
3504 self.assertEqual(obj1 == obj2, value1 == value2)
3505 self.assertEqual(obj1 != obj2, value1 != value2)
3506 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3507 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3508 obj1 = self.base_klass(value1, impl=tag1)
3509 obj2 = self.base_klass(value1, impl=tag2)
3510 self.assertEqual(obj1 == obj2, tag1 == tag2)
3511 self.assertEqual(obj1 != obj2, tag1 != tag2)
3513 @given(data_strategy())
3514 def test_bounds_satisfied(self, d):
3515 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3516 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3517 value = d.draw(text(
3518 alphabet=self.text_alphabet(),
3522 self.base_klass(value=value, bounds=(bound_min, bound_max))
3524 @given(data_strategy())
3525 def test_bounds_unsatisfied(self, d):
3526 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3527 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3528 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3529 with self.assertRaises(BoundsError) as err:
3530 self.base_klass(value=value, bounds=(bound_min, bound_max))
3532 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3533 self.base_klass(bounds=(bound_min, bound_max)).decode(
3534 self.base_klass(value).encode()
3537 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3538 self.base_klass(bounds=(bound_min, bound_max)).decode(
3539 encode2pass(self.base_klass(value))
3541 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3542 with self.assertRaises(BoundsError) as err:
3543 self.base_klass(value=value, bounds=(bound_min, bound_max))
3545 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3546 self.base_klass(bounds=(bound_min, bound_max)).decode(
3547 self.base_klass(value).encode()
3550 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3551 self.base_klass(bounds=(bound_min, bound_max)).decode(
3552 encode2pass(self.base_klass(value))
3555 @given(data_strategy())
3556 def test_call(self, d):
3565 ) = d.draw(string_values_strategy(self.text_alphabet()))
3566 obj_initial = self.base_klass(
3572 optional_initial or False,
3583 ) = d.draw(string_values_strategy(
3584 self.text_alphabet(),
3585 do_expl=impl_initial is None,
3587 if (default is None) and (obj_initial.default is not None):
3590 (bounds is None) and
3591 (value is not None) and
3592 (bounds_initial is not None) and
3593 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3597 (bounds is None) and
3598 (default is not None) and
3599 (bounds_initial is not None) and
3600 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3603 obj = obj_initial(value, bounds, impl, expl, default, optional)
3605 value_expected = default if value is None else value
3607 default_initial if value_expected is None
3610 self.assertEqual(obj, value_expected)
3611 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3612 self.assertEqual(obj.expl_tag, expl or expl_initial)
3615 default_initial if default is None else default,
3617 if obj.default is None:
3618 optional = optional_initial if optional is None else optional
3619 optional = False if optional is None else optional
3622 self.assertEqual(obj.optional, optional)
3624 (obj._bound_min, obj._bound_max),
3625 bounds or bounds_initial or (0, float("+inf")),
3628 @given(data_strategy())
3629 def test_copy(self, d):
3630 values = d.draw(string_values_strategy(self.text_alphabet()))
3631 obj = self.base_klass(*values)
3632 for copy_func in copy_funcs:
3633 obj_copied = copy_func(obj)
3634 self.assert_copied_basic_fields(obj, obj_copied)
3635 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3636 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3637 self.assertEqual(obj._value, obj_copied._value)
3639 @given(data_strategy())
3640 def test_stripped(self, d):
3641 value = d.draw(text(alphabet=self.text_alphabet()))
3642 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3643 obj = self.base_klass(value, impl=tag_impl)
3644 with self.assertRaises(NotEnoughData):
3645 obj.decode(obj.encode()[:-1])
3647 @given(data_strategy())
3648 def test_stripped_expl(self, d):
3649 value = d.draw(text(alphabet=self.text_alphabet()))
3650 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3651 obj = self.base_klass(value, expl=tag_expl)
3652 with self.assertRaises(NotEnoughData):
3653 obj.decode(obj.encode()[:-1])
3656 integers(min_value=31),
3657 integers(min_value=0),
3660 def test_bad_tag(self, tag, offset, decode_path):
3661 with self.assertRaises(DecodeError) as err:
3662 self.base_klass().decode(
3663 tag_encode(tag)[:-1],
3665 decode_path=decode_path,
3668 self.assertEqual(err.exception.offset, offset)
3669 self.assertEqual(err.exception.decode_path, decode_path)
3672 integers(min_value=128),
3673 integers(min_value=0),
3676 def test_bad_len(self, l, offset, decode_path):
3677 with self.assertRaises(DecodeError) as err:
3678 self.base_klass().decode(
3679 self.base_klass.tag_default + len_encode(l)[:-1],
3681 decode_path=decode_path,
3684 self.assertEqual(err.exception.offset, offset)
3685 self.assertEqual(err.exception.decode_path, decode_path)
3688 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3689 integers(min_value=0),
3692 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3693 value, bound_min = list(sorted(ints))
3695 class String(self.base_klass):
3696 # Multiply this value by four, to satisfy UTF-32 bounds
3697 # (4 bytes per character) validation
3698 bounds = (bound_min * 4, bound_min * 4)
3699 with self.assertRaises(DecodeError) as err:
3701 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3703 decode_path=decode_path,
3706 self.assertEqual(err.exception.offset, offset)
3707 self.assertEqual(err.exception.decode_path, decode_path)
3709 @given(data_strategy())
3710 def test_symmetric(self, d):
3711 values = d.draw(string_values_strategy(self.text_alphabet()))
3712 value = d.draw(text(alphabet=self.text_alphabet()))
3713 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3714 offset = d.draw(integers(min_value=0))
3715 tail_junk = d.draw(binary(max_size=5))
3716 decode_path = d.draw(decode_path_strat)
3717 _, _, _, _, default, optional, _decoded = values
3718 obj = self.base_klass(
3726 pprint(obj, big_blobs=True, with_decode_path=True)
3727 self.assertFalse(obj.expled)
3728 obj_encoded = obj.encode()
3729 self.assertEqual(encode2pass(obj), obj_encoded)
3730 obj_expled = obj(value, expl=tag_expl)
3731 self.assertTrue(obj_expled.expled)
3733 list(obj_expled.pps())
3734 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3735 obj_expled_encoded = obj_expled.encode()
3736 ctx_copied = deepcopy(ctx_dummy)
3737 obj_decoded, tail = obj_expled.decode(
3738 obj_expled_encoded + tail_junk,
3742 self.assertDictEqual(ctx_copied, ctx_dummy)
3744 list(obj_decoded.pps())
3745 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3746 self.assertEqual(tail, tail_junk)
3747 self.assertEqual(obj_decoded, obj_expled)
3748 self.assertNotEqual(obj_decoded, obj)
3749 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3750 self.assertEqual(bytes(obj_decoded), bytes(obj))
3751 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3752 self.assertEqual(text_type(obj_decoded), text_type(obj))
3753 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3754 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3755 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3757 obj_decoded.expl_llen,
3758 len(len_encode(len(obj_encoded))),
3760 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3761 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3764 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3766 self.assertEqual(obj_decoded.expl_offset, offset)
3767 assert_exceeding_data(
3769 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3773 evgens = list(obj_expled.decode_evgen(
3774 obj_expled_encoded + tail_junk,
3776 decode_path=decode_path,
3779 self.assertEqual(len(evgens), 1)
3780 _decode_path, obj, tail = evgens[0]
3781 self.assertSequenceEqual(tail, tail_junk)
3782 self.assertEqual(_decode_path, decode_path)
3783 if not getattr(self, "evgen_mode_skip_value", True):
3784 self.assertEqual(obj, obj_decoded)
3785 self.assertEqual(obj.expl_offset, offset)
3790 cyrillic_letters = text(
3791 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3797 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3798 base_klass = UTF8String
3800 @given(cyrillic_letters)
3801 def test_byte_per_primitive(self, chars):
3803 char_raw = char.encode("utf-8")
3804 encoded = b"".join((
3805 self.base_klass().tag_constructed,
3807 OctetString(char_raw[:1]).encode(),
3808 OctetString(char_raw[1:2]).encode(),
3812 self.base_klass().decod(encoded, ctx={"bered": True}),
3817 class UnicodeDecodeErrorMixin(object):
3818 @given(cyrillic_letters)
3819 def test_unicode_decode_error(self, cyrillic_text):
3820 with self.assertRaises(DecodeError):
3821 self.base_klass(cyrillic_text)
3824 class TestNumericString(StringMixin, CommonMixin, TestCase):
3825 base_klass = NumericString
3827 def text_alphabet(self):
3830 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3831 def test_non_numeric(self, non_numeric_text):
3832 with assertRaisesRegex(self, DecodeError, "non-numeric"):
3833 self.base_klass(non_numeric_text)
3836 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3837 integers(min_value=0),
3840 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3841 value, bound_min = list(sorted(ints))
3843 class String(self.base_klass):
3844 bounds = (bound_min, bound_min)
3845 with self.assertRaises(DecodeError) as err:
3847 self.base_klass(b"1" * value).encode(),
3849 decode_path=decode_path,
3852 self.assertEqual(err.exception.offset, offset)
3853 self.assertEqual(err.exception.decode_path, decode_path)
3855 def test_byte_per_primitive(self):
3856 encoded = b"".join((
3857 self.base_klass().tag_constructed,
3859 OctetString(b"1").encode(),
3860 OctetString(b"2").encode(),
3864 self.base_klass().decod(encoded, ctx={"bered": True}),
3869 class TestPrintableString(
3870 UnicodeDecodeErrorMixin,
3875 base_klass = PrintableString
3877 def text_alphabet(self):
3878 return ascii_letters + digits + " '()+,-./:=?"
3880 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3881 def test_non_printable(self, non_printable_text):
3882 with assertRaisesRegex(self, DecodeError, "non-printable"):
3883 self.base_klass(non_printable_text)
3886 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3887 integers(min_value=0),
3890 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3891 value, bound_min = list(sorted(ints))
3893 class String(self.base_klass):
3894 bounds = (bound_min, bound_min)
3895 with self.assertRaises(DecodeError) as err:
3897 self.base_klass(b"1" * value).encode(),
3899 decode_path=decode_path,
3902 self.assertEqual(err.exception.offset, offset)
3903 self.assertEqual(err.exception.decode_path, decode_path)
3905 def test_allowable_invalid_chars(self):
3907 ("*", {"allow_asterisk": True}),
3908 ("&", {"allow_ampersand": True}),
3909 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3912 obj = self.base_klass(s)
3913 for prop in kwargs.keys():
3914 self.assertFalse(getattr(obj, prop))
3916 with assertRaisesRegex(self, DecodeError, "non-printable"):
3918 self.base_klass(s, **kwargs)
3919 klass = self.base_klass(**kwargs)
3921 for prop in kwargs.keys():
3922 self.assertTrue(getattr(obj, prop))
3925 for prop in kwargs.keys():
3926 self.assertTrue(getattr(obj, prop))
3929 class TestTeletexString(
3930 UnicodeDecodeErrorMixin,
3935 base_klass = TeletexString
3938 class TestVideotexString(
3939 UnicodeDecodeErrorMixin,
3944 base_klass = VideotexString
3947 class TestIA5String(
3948 UnicodeDecodeErrorMixin,
3953 base_klass = IA5String
3956 class TestGraphicString(
3957 UnicodeDecodeErrorMixin,
3962 base_klass = GraphicString
3965 class TestVisibleString(
3966 UnicodeDecodeErrorMixin,
3971 base_klass = VisibleString
3973 def test_x690_vector(self):
3974 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3975 self.assertSequenceEqual(tail, b"")
3976 self.assertEqual(str(obj), "Jones")
3977 self.assertFalse(obj.ber_encoded)
3978 self.assertFalse(obj.lenindef)
3979 self.assertFalse(obj.bered)
3981 obj, tail = VisibleString().decode(
3982 hexdec("3A0904034A6F6E04026573"),
3983 ctx={"bered": True},
3985 self.assertSequenceEqual(tail, b"")
3986 self.assertEqual(str(obj), "Jones")
3987 self.assertTrue(obj.ber_encoded)
3988 self.assertFalse(obj.lenindef)
3989 self.assertTrue(obj.bered)
3991 self.assertTrue(obj.ber_encoded)
3992 self.assertFalse(obj.lenindef)
3993 self.assertTrue(obj.bered)
3995 obj, tail = VisibleString().decode(
3996 hexdec("3A8004034A6F6E040265730000"),
3997 ctx={"bered": True},
3999 self.assertSequenceEqual(tail, b"")
4000 self.assertEqual(str(obj), "Jones")
4001 self.assertTrue(obj.ber_encoded)
4002 self.assertTrue(obj.lenindef)
4003 self.assertTrue(obj.bered)
4005 self.assertTrue(obj.ber_encoded)
4006 self.assertTrue(obj.lenindef)
4007 self.assertTrue(obj.bered)
4010 class TestGeneralString(
4011 UnicodeDecodeErrorMixin,
4016 base_klass = GeneralString
4019 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4020 base_klass = UniversalString
4023 class TestBMPString(StringMixin, CommonMixin, TestCase):
4024 base_klass = BMPString
4028 def generalized_time_values_strategy(
4036 if draw(booleans()):
4037 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4039 value = value.replace(microsecond=0)
4041 if draw(booleans()):
4042 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4044 default = default.replace(microsecond=0)
4048 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4050 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4051 optional = draw(one_of(none(), booleans()))
4053 draw(integers(min_value=0)),
4054 draw(integers(min_value=0)),
4055 draw(integers(min_value=0)),
4057 return (value, impl, expl, default, optional, _decoded)
4060 class TimeMixin(object):
4061 def test_invalid_value_type(self):
4062 with self.assertRaises(InvalidValueType) as err:
4063 self.base_klass(datetime.now().timetuple())
4066 @given(data_strategy())
4067 def test_optional(self, d):
4068 default = d.draw(datetimes(
4069 min_value=self.min_datetime,
4070 max_value=self.max_datetime,
4072 optional = d.draw(booleans())
4073 obj = self.base_klass(default=default, optional=optional)
4074 self.assertTrue(obj.optional)
4076 @given(data_strategy())
4077 def test_ready(self, d):
4078 obj = self.base_klass()
4079 self.assertFalse(obj.ready)
4082 pprint(obj, big_blobs=True, with_decode_path=True)
4083 with self.assertRaises(ObjNotReady) as err:
4086 with self.assertRaises(ObjNotReady) as err:
4088 value = d.draw(datetimes(
4089 min_value=self.min_datetime,
4090 max_value=self.max_datetime,
4092 obj = self.base_klass(value)
4093 self.assertTrue(obj.ready)
4096 pprint(obj, big_blobs=True, with_decode_path=True)
4098 @given(data_strategy())
4099 def test_comparison(self, d):
4100 value1 = d.draw(datetimes(
4101 min_value=self.min_datetime,
4102 max_value=self.max_datetime,
4104 value2 = d.draw(datetimes(
4105 min_value=self.min_datetime,
4106 max_value=self.max_datetime,
4108 tag1 = d.draw(binary(min_size=1))
4109 tag2 = d.draw(binary(min_size=1))
4111 value1 = value1.replace(microsecond=0)
4112 value2 = value2.replace(microsecond=0)
4113 obj1 = self.base_klass(value1)
4114 obj2 = self.base_klass(value2)
4115 self.assertEqual(obj1 == obj2, value1 == value2)
4116 self.assertEqual(obj1 != obj2, value1 != value2)
4117 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4118 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4119 obj1 = self.base_klass(value1, impl=tag1)
4120 obj2 = self.base_klass(value1, impl=tag2)
4121 self.assertEqual(obj1 == obj2, tag1 == tag2)
4122 self.assertEqual(obj1 != obj2, tag1 != tag2)
4124 @given(data_strategy())
4125 def test_call(self, d):
4133 ) = d.draw(generalized_time_values_strategy(
4134 min_datetime=self.min_datetime,
4135 max_datetime=self.max_datetime,
4136 omit_ms=self.omit_ms,
4138 obj_initial = self.base_klass(
4139 value=value_initial,
4142 default=default_initial,
4143 optional=optional_initial or False,
4144 _decoded=_decoded_initial,
4153 ) = d.draw(generalized_time_values_strategy(
4154 min_datetime=self.min_datetime,
4155 max_datetime=self.max_datetime,
4156 omit_ms=self.omit_ms,
4157 do_expl=impl_initial is None,
4167 value_expected = default if value is None else value
4169 default_initial if value_expected is None
4172 self.assertEqual(obj, value_expected)
4173 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4174 self.assertEqual(obj.expl_tag, expl or expl_initial)
4177 default_initial if default is None else default,
4179 if obj.default is None:
4180 optional = optional_initial if optional is None else optional
4181 optional = False if optional is None else optional
4184 self.assertEqual(obj.optional, optional)
4186 @given(data_strategy())
4187 def test_copy(self, d):
4188 values = d.draw(generalized_time_values_strategy(
4189 min_datetime=self.min_datetime,
4190 max_datetime=self.max_datetime,
4192 obj = self.base_klass(*values)
4193 for copy_func in copy_funcs:
4194 obj_copied = copy_func(obj)
4195 self.assert_copied_basic_fields(obj, obj_copied)
4196 self.assertEqual(obj._value, obj_copied._value)
4198 @given(data_strategy())
4199 def test_stripped(self, d):
4200 value = d.draw(datetimes(
4201 min_value=self.min_datetime,
4202 max_value=self.max_datetime,
4204 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4205 obj = self.base_klass(value, impl=tag_impl)
4206 with self.assertRaises(NotEnoughData):
4207 obj.decode(obj.encode()[:-1])
4209 @given(data_strategy())
4210 def test_stripped_expl(self, d):
4211 value = d.draw(datetimes(
4212 min_value=self.min_datetime,
4213 max_value=self.max_datetime,
4215 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4216 obj = self.base_klass(value, expl=tag_expl)
4217 with self.assertRaises(NotEnoughData):
4218 obj.decode(obj.encode()[:-1])
4220 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4221 @given(data_strategy())
4222 def test_symmetric(self, d):
4223 values = d.draw(generalized_time_values_strategy(
4224 min_datetime=self.min_datetime,
4225 max_datetime=self.max_datetime,
4227 value = d.draw(datetimes(
4228 min_value=self.min_datetime,
4229 max_value=self.max_datetime,
4231 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4232 offset = d.draw(integers(min_value=0))
4233 tail_junk = d.draw(binary(max_size=5))
4234 _, _, _, default, optional, _decoded = values
4235 obj = self.base_klass(
4243 pprint(obj, big_blobs=True, with_decode_path=True)
4244 self.assertFalse(obj.expled)
4245 obj_encoded = obj.encode()
4246 self.assertEqual(encode2pass(obj), obj_encoded)
4247 self.additional_symmetric_check(value, obj_encoded)
4248 obj_expled = obj(value, expl=tag_expl)
4249 self.assertTrue(obj_expled.expled)
4251 list(obj_expled.pps())
4252 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4253 obj_expled_encoded = obj_expled.encode()
4254 ctx_copied = deepcopy(ctx_dummy)
4255 obj_decoded, tail = obj_expled.decode(
4256 obj_expled_encoded + tail_junk,
4260 self.assertDictEqual(ctx_copied, ctx_dummy)
4262 list(obj_decoded.pps())
4263 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4264 self.assertEqual(tail, tail_junk)
4265 self.assertEqual(obj_decoded, obj_expled)
4266 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4267 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4268 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4269 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4270 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4272 obj_decoded.expl_llen,
4273 len(len_encode(len(obj_encoded))),
4275 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4276 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4279 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4281 self.assertEqual(obj_decoded.expl_offset, offset)
4282 assert_exceeding_data(
4284 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4289 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4290 base_klass = GeneralizedTime
4292 min_datetime = datetime(1900, 1, 1)
4293 max_datetime = datetime(9999, 12, 31)
4294 evgen_mode_skip_value = False
4296 def additional_symmetric_check(self, value, obj_encoded):
4297 if value.microsecond > 0:
4298 self.assertFalse(obj_encoded.endswith(b"0Z"))
4300 def test_repr_not_ready(self):
4301 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4302 repr(GeneralizedTime())
4304 def test_x690_vector_valid(self):
4308 b"19920722132100.3Z",
4310 GeneralizedTime(data)
4312 def test_x690_vector_invalid(self):
4315 b"19920622123421.0Z",
4316 b"19920722132100.30Z",
4318 with self.assertRaises(DecodeError) as err:
4319 GeneralizedTime(data)
4322 def test_go_vectors_invalid(self):
4334 b"-20100102030410Z",
4335 b"2010-0102030410Z",
4336 b"2010-0002030410Z",
4337 b"201001-02030410Z",
4338 b"20100102-030410Z",
4339 b"2010010203-0410Z",
4340 b"201001020304-10Z",
4341 # These ones are INVALID in *DER*, but accepted
4342 # by Go's encoding/asn1
4343 b"20100102030405+0607",
4344 b"20100102030405-0607",
4346 with self.assertRaises(DecodeError) as err:
4347 GeneralizedTime(data)
4350 def test_go_vectors_valid(self):
4352 GeneralizedTime(b"20100102030405Z").todatetime(),
4353 datetime(2010, 1, 2, 3, 4, 5, 0),
4356 def test_go_vectors_valid_ber(self):
4358 b"20100102030405+0607",
4359 b"20100102030405-0607",
4361 GeneralizedTime(data, ctx={"bered": True})
4363 def test_utc_offsets(self):
4364 """Some know equal UTC offsets
4367 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4371 "200101011130-0700",
4372 "200101011500-03:30",
4375 self.assertEqual(dts[0], dts[1])
4376 self.assertEqual(dts[0], dts[2])
4377 self.assertEqual(dts[0], dts[3])
4379 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4380 @given(data_strategy())
4381 def test_valid_ber(self, d):
4382 min_year = 1901 if PY2 else 2
4383 year = d.draw(integers(min_value=min_year, max_value=9999))
4384 month = d.draw(integers(min_value=1, max_value=12))
4385 day = d.draw(integers(min_value=1, max_value=28))
4386 hours = d.draw(integers(min_value=0, max_value=23))
4387 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4388 dt = datetime(year, month, day, hours)
4389 fractions_sign = d.draw(sampled_from(" ,."))
4391 if fractions_sign != " ":
4392 fractions = random()
4393 if d.draw(booleans()):
4394 minutes = d.draw(integers(min_value=0, max_value=59))
4395 data += "%02d" % minutes
4396 dt += timedelta(seconds=60 * minutes)
4397 if d.draw(booleans()):
4398 seconds = d.draw(integers(min_value=0, max_value=59))
4399 data += "%02d" % seconds
4400 dt += timedelta(seconds=seconds)
4401 if fractions is not None:
4402 dt += timedelta(microseconds=10**6 * fractions)
4403 elif fractions is not None:
4404 dt += timedelta(seconds=60 * fractions)
4405 elif fractions is not None:
4406 dt += timedelta(seconds=3600 * fractions)
4407 if fractions is not None:
4408 data += fractions_sign + str(fractions)[2:]
4409 if d.draw(booleans()):
4411 elif d.draw(booleans()):
4412 offset_hour = d.draw(integers(min_value=0, max_value=13))
4414 if d.draw(booleans()):
4419 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4420 data += "%02d" % offset_hour
4421 minutes_separator = d.draw(sampled_from((None, "", ":")))
4422 if minutes_separator is not None:
4423 offset_minute = d.draw(integers(min_value=0, max_value=59))
4424 dt -= timedelta(seconds=sign * 60 * offset_minute)
4425 data += "%s%02d" % (minutes_separator, offset_minute)
4426 data = data.encode("ascii")
4427 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4429 GeneralizedTime().decod(data_der)
4434 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4437 mktime(obj.todatetime().timetuple()),
4438 mktime(dt.timetuple()),
4441 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4442 self.assertEqual(obj.ber_encoded, not dered)
4443 self.assertEqual(obj.bered, not dered)
4444 self.assertEqual(obj.ber_raw, None if dered else data)
4445 self.assertEqual(obj.encode() == data_der, dered)
4450 def test_invalid_ber(self):
4452 # "00010203040506.07",
4453 "-0010203040506.07",
4454 "0001-203040506.07",
4455 "000102-3040506.07",
4456 "00010203-40506.07",
4457 "0001020304-506.07",
4458 "000102030405-6.07",
4459 "00010203040506.-7",
4460 "+0010203040506.07",
4461 "0001+203040506.07",
4462 "000102+3040506.07",
4463 "00010203+40506.07",
4464 "0001020304+506.07",
4465 "000102030405+6.07",
4466 "00010203040506.+7",
4467 " 0010203040506.07",
4468 "0001 203040506.07",
4469 "000102 3040506.07",
4470 "00010203 40506.07",
4471 "0001020304 506.07",
4472 "000102030405 6.07",
4473 "00010203040506. 7",
4474 "001 0203040506.07",
4475 "00012 03040506.07",
4476 "0001023 040506.07",
4477 "000102034 0506.07",
4478 "00010203045 06.07",
4479 "0001020304056 .07",
4480 "00010203040506.7 ",
4560 "00010203040506.07+15",
4561 "00010203040506.07-15",
4562 "00010203040506.07+14:60",
4563 "00010203040506.07+1460",
4564 "00010203040506.07-1460",
4565 "00010203040506.07+00:60",
4566 "00010203040506.07-00:60",
4568 "00010203040506+15",
4569 "00010203040506-15",
4570 "00010203040506+14:60",
4571 "00010203040506+1460",
4572 "00010203040506-1460",
4573 "00010203040506+00:60",
4574 "00010203040506-00:60",
4583 with self.assertRaises(DecodeError):
4584 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4585 data = data.replace(".", ",")
4586 with self.assertRaises(DecodeError):
4587 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4591 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4592 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4594 binary(min_size=1, max_size=1),
4596 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4597 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4600 def test_junk(self, part0, part1, part2):
4601 junk = part0 + part1 + part2
4602 assume(not (set(junk) <= set(digits.encode("ascii"))))
4603 with self.assertRaises(DecodeError):
4604 GeneralizedTime().decode(
4605 GeneralizedTime.tag_default +
4606 len_encode(len(junk)) +
4612 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4613 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4615 binary(min_size=1, max_size=1),
4617 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4618 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4621 def test_junk_dm(self, part0, part1, part2):
4622 junk = part0 + part1 + part2
4623 assume(not (set(junk) <= set(digits.encode("ascii"))))
4624 with self.assertRaises(DecodeError):
4625 GeneralizedTime().decode(
4626 GeneralizedTime.tag_default +
4627 len_encode(len(junk)) +
4631 def test_ns_fractions(self):
4632 GeneralizedTime(b"20010101000000.000001Z")
4633 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4634 GeneralizedTime(b"20010101000000.0000001Z")
4636 def test_non_pure_integers(self):
4638 # b"20000102030405Z,
4645 b"20000102030405.+6Z",
4646 b"20000102030405.-6Z",
4653 b"20000102030405._6Z",
4654 b"20000102030405.6_Z",
4661 b"20000102030405. 6Z",
4668 b"20000102030405.6 Z",
4670 with self.assertRaises(DecodeError):
4671 GeneralizedTime(data)
4674 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4675 base_klass = UTCTime
4677 min_datetime = datetime(2000, 1, 1)
4678 max_datetime = datetime(2049, 12, 31)
4679 evgen_mode_skip_value = False
4681 def additional_symmetric_check(self, value, obj_encoded):
4684 def test_repr_not_ready(self):
4685 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4688 def test_x690_vector_valid(self):
4696 def test_x690_vector_invalid(self):
4701 with self.assertRaises(DecodeError) as err:
4705 def test_go_vectors_invalid(self):
4731 # These ones are INVALID in *DER*, but accepted
4732 # by Go's encoding/asn1
4733 b"910506164540-0700",
4734 b"910506164540+0730",
4738 with self.assertRaises(DecodeError) as err:
4742 def test_go_vectors_valid(self):
4744 UTCTime(b"910506234540Z").todatetime(),
4745 datetime(1991, 5, 6, 23, 45, 40, 0),
4748 def test_non_pure_integers(self):
4777 with self.assertRaises(DecodeError):
4780 def test_x680_vector_valid_ber(self):
4782 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4783 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4784 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4785 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4787 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4788 obj = UTCTime().decod(data_der, ctx={"bered": True})
4789 self.assertEqual(obj, dt)
4790 self.assertEqual(obj.todatetime(), dt)
4791 self.assertTrue(obj.ber_encoded)
4792 self.assertTrue(obj.bered)
4793 self.assertEqual(obj.ber_raw, data)
4794 self.assertNotEqual(obj.encode(), data_der)
4797 def test_go_vectors_valid_ber(self):
4799 b"910506164540-0700",
4800 b"910506164540+0730",
4804 data = UTCTime.tag_default + len_encode(len(data)) + data
4805 obj = UTCTime().decod(data, ctx={"bered": True})
4806 self.assertTrue(obj.ber_encoded)
4807 self.assertTrue(obj.bered)
4808 self.assertNotEqual(obj.encode(), data)
4811 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4812 @given(data_strategy())
4813 def test_valid_ber(self, d):
4814 year = d.draw(integers(min_value=0, max_value=99))
4815 month = d.draw(integers(min_value=1, max_value=12))
4816 day = d.draw(integers(min_value=1, max_value=28))
4817 hours = d.draw(integers(min_value=0, max_value=23))
4818 minute = d.draw(integers(min_value=0, max_value=59))
4819 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4821 year + (2000 if year < 50 else 1900),
4828 if d.draw(booleans()):
4830 seconds = d.draw(integers(min_value=0, max_value=59))
4831 data += "%02d" % seconds
4832 dt += timedelta(seconds=seconds)
4833 if d.draw(booleans()):
4837 offset_hour = d.draw(integers(min_value=0, max_value=13))
4838 offset_minute = d.draw(integers(min_value=0, max_value=59))
4839 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4840 if d.draw(booleans()):
4846 data += "%02d%02d" % (offset_hour, offset_minute)
4847 data = data.encode("ascii")
4848 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4849 obj = UTCTime().decod(data_der, ctx={"bered": True})
4850 self.assertEqual(obj, dt)
4851 self.assertEqual(obj.todatetime(), dt)
4852 self.assertEqual(obj.ber_encoded, not dered)
4853 self.assertEqual(obj.bered, not dered)
4854 self.assertEqual(obj.ber_raw, None if dered else data)
4855 self.assertEqual(obj.encode() == data_der, dered)
4860 def test_invalid_ber(self):
4901 b"0001020304+0000Z",
4910 with self.assertRaises(DecodeError):
4911 UTCTime(data, ctx={"bered": True})
4912 data = data[:8] + data[8+2:]
4913 with self.assertRaises(DecodeError):
4914 UTCTime(data, ctx={"bered": True})
4959 b"000102030405+000",
4960 b"000102030405+000Z",
4961 b"000102030405+0000Z",
4962 b"000102030405+-101",
4963 b"000102030405+01-1",
4964 b"000102030405+0060",
4965 b"000102030405+1401",
4966 b"500101000002+0003",
4968 with self.assertRaises(DecodeError):
4969 UTCTime(data, ctx={"bered": True})
4971 @given(integers(min_value=0, max_value=49))
4972 def test_pre50(self, year):
4974 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4978 @given(integers(min_value=50, max_value=99))
4979 def test_post50(self, year):
4981 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
4987 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4988 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4990 binary(min_size=1, max_size=1),
4992 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4993 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
4996 def test_junk(self, part0, part1, part2):
4997 junk = part0 + part1 + part2
4998 assume(not (set(junk) <= set(digits.encode("ascii"))))
4999 with self.assertRaises(DecodeError):
5001 UTCTime.tag_default +
5002 len_encode(len(junk)) +
5008 def tlv_value_strategy(draw):
5009 tag_num = draw(integers(min_value=1))
5010 data = draw(binary())
5011 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5015 def any_values_strategy(draw, do_expl=False):
5016 value = draw(one_of(none(), tlv_value_strategy()))
5019 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5020 optional = draw(one_of(none(), booleans()))
5022 draw(integers(min_value=0)),
5023 draw(integers(min_value=0)),
5024 draw(integers(min_value=0)),
5026 return (value, expl, optional, _decoded)
5029 class AnyInherited(Any):
5033 class TestAny(CommonMixin, TestCase):
5036 def test_invalid_value_type(self):
5037 with self.assertRaises(InvalidValueType) as err:
5042 def test_optional(self, optional):
5043 obj = Any(optional=optional)
5044 self.assertEqual(obj.optional, optional)
5046 @given(tlv_value_strategy())
5047 def test_ready(self, value):
5049 self.assertFalse(obj.ready)
5052 pprint(obj, big_blobs=True, with_decode_path=True)
5053 with self.assertRaises(ObjNotReady) as err:
5056 with self.assertRaises(ObjNotReady) as err:
5059 self.assertTrue(obj.ready)
5062 pprint(obj, big_blobs=True, with_decode_path=True)
5065 def test_basic(self, value):
5066 integer_encoded = Integer(value).encode()
5068 Any(integer_encoded),
5069 Any(Integer(value)),
5070 Any(Any(Integer(value))),
5072 self.assertSequenceEqual(bytes(obj), integer_encoded)
5074 obj.decode(obj.encode())[0].vlen,
5075 len(integer_encoded),
5079 pprint(obj, big_blobs=True, with_decode_path=True)
5080 self.assertSequenceEqual(obj.encode(), integer_encoded)
5082 @given(tlv_value_strategy(), tlv_value_strategy())
5083 def test_comparison(self, value1, value2):
5084 for klass in (Any, AnyInherited):
5085 obj1 = klass(value1)
5086 obj2 = klass(value2)
5087 self.assertEqual(obj1 == obj2, value1 == value2)
5088 self.assertEqual(obj1 != obj2, value1 != value2)
5089 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5091 @given(data_strategy())
5092 def test_call(self, d):
5093 for klass in (Any, AnyInherited):
5099 ) = d.draw(any_values_strategy())
5100 obj_initial = klass(
5103 optional_initial or False,
5111 ) = d.draw(any_values_strategy(do_expl=True))
5112 obj = obj_initial(value, expl, optional)
5114 value_expected = None if value is None else value
5115 self.assertEqual(obj, value_expected)
5116 self.assertEqual(obj.expl_tag, expl or expl_initial)
5117 if obj.default is None:
5118 optional = optional_initial if optional is None else optional
5119 optional = False if optional is None else optional
5120 self.assertEqual(obj.optional, optional)
5122 def test_simultaneous_impl_expl(self):
5123 # override it, as Any does not have implicit tag
5126 def test_decoded(self):
5127 # override it, as Any does not have implicit tag
5130 @given(any_values_strategy())
5131 def test_copy(self, values):
5132 for klass in (Any, AnyInherited):
5133 obj = klass(*values)
5134 for copy_func in copy_funcs:
5135 obj_copied = copy_func(obj)
5136 self.assert_copied_basic_fields(obj, obj_copied)
5137 self.assertEqual(obj._value, obj_copied._value)
5139 @given(binary().map(OctetString))
5140 def test_stripped(self, value):
5142 with self.assertRaises(NotEnoughData):
5143 obj.decode(obj.encode()[:-1])
5146 tlv_value_strategy(),
5147 integers(min_value=1).map(tag_ctxc),
5149 def test_stripped_expl(self, value, tag_expl):
5150 obj = Any(value, expl=tag_expl)
5151 with self.assertRaises(NotEnoughData):
5152 obj.decode(obj.encode()[:-1])
5155 integers(min_value=31),
5156 integers(min_value=0),
5159 def test_bad_tag(self, tag, offset, decode_path):
5160 with self.assertRaises(DecodeError) as err:
5162 tag_encode(tag)[:-1],
5164 decode_path=decode_path,
5167 self.assertEqual(err.exception.offset, offset)
5168 self.assertEqual(err.exception.decode_path, decode_path)
5171 integers(min_value=128),
5172 integers(min_value=0),
5175 def test_bad_len(self, l, offset, decode_path):
5176 with self.assertRaises(DecodeError) as err:
5178 Any.tag_default + len_encode(l)[:-1],
5180 decode_path=decode_path,
5183 self.assertEqual(err.exception.offset, offset)
5184 self.assertEqual(err.exception.decode_path, decode_path)
5186 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5188 any_values_strategy(),
5189 integers().map(lambda x: Integer(x).encode()),
5190 integers(min_value=1).map(tag_ctxc),
5191 integers(min_value=0),
5195 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5196 for klass in (Any, AnyInherited):
5197 _, _, optional, _decoded = values
5198 obj = klass(value=value, optional=optional, _decoded=_decoded)
5201 pprint(obj, big_blobs=True, with_decode_path=True)
5202 self.assertFalse(obj.expled)
5203 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5204 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5205 obj_encoded = obj.encode()
5206 self.assertEqual(encode2pass(obj), obj_encoded)
5207 obj_expled = obj(value, expl=tag_expl)
5208 self.assertTrue(obj_expled.expled)
5209 tag_class, _, tag_num = tag_decode(tag_expl)
5210 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5212 list(obj_expled.pps())
5213 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5214 obj_expled_encoded = obj_expled.encode()
5215 ctx_copied = deepcopy(ctx_dummy)
5216 obj_decoded, tail = obj_expled.decode(
5217 obj_expled_encoded + tail_junk,
5221 self.assertDictEqual(ctx_copied, ctx_dummy)
5223 list(obj_decoded.pps())
5224 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5225 self.assertEqual(tail, tail_junk)
5226 self.assertEqual(obj_decoded, obj_expled)
5227 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5228 self.assertEqual(bytes(obj_decoded), bytes(obj))
5229 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5230 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5231 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5233 obj_decoded.expl_llen,
5234 len(len_encode(len(obj_encoded))),
5236 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5237 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5240 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5242 self.assertEqual(obj_decoded.expl_offset, offset)
5243 self.assertEqual(obj_decoded.tlen, 0)
5244 self.assertEqual(obj_decoded.llen, 0)
5245 self.assertEqual(obj_decoded.vlen, len(value))
5246 assert_exceeding_data(
5248 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5252 evgens = list(obj_expled.decode_evgen(
5253 obj_expled_encoded + tail_junk,
5255 decode_path=decode_path,
5258 self.assertEqual(len(evgens), 1)
5259 _decode_path, obj, tail = evgens[0]
5260 self.assertSequenceEqual(tail, tail_junk)
5261 self.assertEqual(_decode_path, decode_path)
5262 self.assertEqual(obj.expl_offset, offset)
5267 integers(min_value=1).map(tag_ctxc),
5268 integers(min_value=0, max_value=3),
5269 integers(min_value=0),
5273 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5274 chunk = Boolean(False, expl=expl).encode()
5276 OctetString.tag_default +
5278 b"".join([chunk] * chunks) +
5281 with self.assertRaises(LenIndefForm):
5285 decode_path=decode_path,
5287 obj, tail = Any().decode(
5290 decode_path=decode_path,
5291 ctx={"bered": True},
5293 self.assertSequenceEqual(tail, junk)
5294 self.assertEqual(obj.offset, offset)
5295 self.assertEqual(obj.tlvlen, len(encoded))
5296 self.assertTrue(obj.lenindef)
5297 self.assertFalse(obj.ber_encoded)
5298 self.assertTrue(obj.bered)
5300 self.assertTrue(obj.lenindef)
5301 self.assertFalse(obj.ber_encoded)
5302 self.assertTrue(obj.bered)
5305 pprint(obj, big_blobs=True, with_decode_path=True)
5306 with self.assertRaises(NotEnoughData) as err:
5310 decode_path=decode_path,
5311 ctx={"bered": True},
5313 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5314 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5316 class SeqOf(SequenceOf):
5317 schema = Boolean(expl=expl)
5319 class Seq(Sequence):
5321 ("type", ObjectIdentifier(defines=((("value",), {
5322 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5327 ("type", ObjectIdentifier("1.2.3")),
5328 ("value", Any(encoded)),
5330 seq_encoded = seq.encode()
5331 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5332 self.assertIsNotNone(seq_decoded["value"].defined)
5334 list(seq_decoded.pps())
5335 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5336 self.assertTrue(seq_decoded.bered)
5337 self.assertFalse(seq_decoded["type"].bered)
5338 self.assertTrue(seq_decoded["value"].bered)
5340 chunk = chunk[:-1] + b"\x01"
5341 chunks = b"".join([chunk] * (chunks + 1))
5342 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5344 ("type", ObjectIdentifier("1.2.3")),
5345 ("value", Any(encoded)),
5347 seq_encoded = seq.encode()
5348 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5349 self.assertIsNotNone(seq_decoded["value"].defined)
5351 list(seq_decoded.pps())
5352 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5353 self.assertTrue(seq_decoded.bered)
5354 self.assertFalse(seq_decoded["type"].bered)
5355 self.assertTrue(seq_decoded["value"].bered)
5359 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5361 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5362 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5364 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5365 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5367 min_size=len(names),
5368 max_size=len(names),
5371 (name, Integer(**tag_kwargs))
5372 for name, tag_kwargs in zip(names, tags)
5375 if value_required or draw(booleans()):
5376 value = draw(tuples(
5377 sampled_from([name for name, _ in schema]),
5378 integers().map(Integer),
5382 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5383 default = draw(one_of(
5385 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5387 optional = draw(one_of(none(), booleans()))
5389 draw(integers(min_value=0)),
5390 draw(integers(min_value=0)),
5391 draw(integers(min_value=0)),
5393 return (schema, value, expl, default, optional, _decoded)
5396 class ChoiceInherited(Choice):
5400 class TestChoice(CommonMixin, TestCase):
5402 schema = (("whatever", Boolean()),)
5405 def test_schema_required(self):
5406 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5409 def test_impl_forbidden(self):
5410 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5411 Choice(impl=b"whatever")
5413 def test_invalid_value_type(self):
5414 with self.assertRaises(InvalidValueType) as err:
5415 self.base_klass(123)
5417 with self.assertRaises(ObjUnknown) as err:
5418 self.base_klass(("whenever", Boolean(False)))
5420 with self.assertRaises(InvalidValueType) as err:
5421 self.base_klass(("whatever", Integer(123)))
5425 def test_optional(self, optional):
5426 obj = self.base_klass(
5427 default=self.base_klass(("whatever", Boolean(False))),
5430 self.assertTrue(obj.optional)
5433 def test_ready(self, value):
5434 obj = self.base_klass()
5435 self.assertFalse(obj.ready)
5438 pprint(obj, big_blobs=True, with_decode_path=True)
5439 self.assertIsNone(obj["whatever"])
5440 with self.assertRaises(ObjNotReady) as err:
5443 with self.assertRaises(ObjNotReady) as err:
5445 obj["whatever"] = Boolean()
5446 self.assertFalse(obj.ready)
5449 pprint(obj, big_blobs=True, with_decode_path=True)
5450 obj["whatever"] = Boolean(value)
5451 self.assertTrue(obj.ready)
5454 pprint(obj, big_blobs=True, with_decode_path=True)
5456 @given(booleans(), booleans())
5457 def test_comparison(self, value1, value2):
5458 class WahlInherited(self.base_klass):
5460 for klass in (self.base_klass, WahlInherited):
5461 obj1 = klass(("whatever", Boolean(value1)))
5462 obj2 = klass(("whatever", Boolean(value2)))
5463 self.assertEqual(obj1 == obj2, value1 == value2)
5464 self.assertEqual(obj1 != obj2, value1 != value2)
5465 self.assertEqual(obj1 == obj2._value, value1 == value2)
5466 self.assertFalse(obj1 == obj2._value[1])
5468 @given(data_strategy())
5469 def test_call(self, d):
5470 for klass in (Choice, ChoiceInherited):
5478 ) = d.draw(choice_values_strategy())
5481 schema = schema_initial
5483 value=value_initial,
5485 default=default_initial,
5486 optional=optional_initial or False,
5487 _decoded=_decoded_initial,
5496 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5497 obj = obj_initial(value, expl, default, optional)
5499 value_expected = default if value is None else value
5501 default_initial if value_expected is None
5504 self.assertEqual(obj.choice, value_expected[0])
5505 self.assertEqual(obj.value, int(value_expected[1]))
5506 self.assertEqual(obj.expl_tag, expl or expl_initial)
5507 default_expect = default_initial if default is None else default
5508 if default_expect is not None:
5509 self.assertEqual(obj.default.choice, default_expect[0])
5510 self.assertEqual(obj.default.value, int(default_expect[1]))
5511 if obj.default is None:
5512 optional = optional_initial if optional is None else optional
5513 optional = False if optional is None else optional
5516 self.assertEqual(obj.optional, optional)
5517 self.assertEqual(obj.specs, obj_initial.specs)
5519 def test_simultaneous_impl_expl(self):
5520 # override it, as Any does not have implicit tag
5523 def test_decoded(self):
5524 # override it, as Any does not have implicit tag
5527 @given(choice_values_strategy())
5528 def test_copy(self, values):
5529 _schema, value, expl, default, optional, _decoded = values
5531 class Wahl(self.base_klass):
5533 register_class(Wahl)
5538 optional=optional or False,
5541 for copy_func in copy_funcs:
5542 obj_copied = copy_func(obj)
5543 self.assertIsNone(obj.tag)
5544 self.assertIsNone(obj_copied.tag)
5545 # hack for assert_copied_basic_fields
5546 obj.tag = "whatever"
5547 obj_copied.tag = "whatever"
5548 self.assert_copied_basic_fields(obj, obj_copied)
5550 self.assertEqual(obj._value, obj_copied._value)
5551 self.assertEqual(obj.specs, obj_copied.specs)
5554 def test_stripped(self, value):
5555 obj = self.base_klass(("whatever", Boolean(value)))
5556 with self.assertRaises(NotEnoughData):
5557 obj.decode(obj.encode()[:-1])
5561 integers(min_value=1).map(tag_ctxc),
5563 def test_stripped_expl(self, value, tag_expl):
5564 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5565 with self.assertRaises(NotEnoughData):
5566 obj.decode(obj.encode()[:-1])
5568 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5569 @given(data_strategy())
5570 def test_symmetric(self, d):
5571 _schema, value, _, default, optional, _decoded = d.draw(
5572 choice_values_strategy(value_required=True)
5574 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5575 offset = d.draw(integers(min_value=0))
5576 tail_junk = d.draw(binary(max_size=5))
5577 decode_path = d.draw(decode_path_strat)
5579 class Wahl(self.base_klass):
5589 pprint(obj, big_blobs=True, with_decode_path=True)
5590 self.assertFalse(obj.expled)
5591 self.assertEqual(obj.tag_order, obj.value.tag_order)
5592 obj_encoded = obj.encode()
5593 self.assertEqual(encode2pass(obj), obj_encoded)
5594 obj_expled = obj(value, expl=tag_expl)
5595 self.assertTrue(obj_expled.expled)
5596 tag_class, _, tag_num = tag_decode(tag_expl)
5597 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5599 list(obj_expled.pps())
5600 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5601 obj_expled_encoded = obj_expled.encode()
5602 ctx_copied = deepcopy(ctx_dummy)
5603 obj_decoded, tail = obj_expled.decode(
5604 obj_expled_encoded + tail_junk,
5608 self.assertDictEqual(ctx_copied, ctx_dummy)
5610 list(obj_decoded.pps())
5611 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5612 self.assertEqual(tail, tail_junk)
5613 self.assertEqual(obj_decoded, obj_expled)
5614 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5615 self.assertEqual(obj_decoded.value, obj_expled.value)
5616 self.assertEqual(obj_decoded.choice, obj.choice)
5617 self.assertEqual(obj_decoded.value, obj.value)
5618 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5619 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5620 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5622 obj_decoded.expl_llen,
5623 len(len_encode(len(obj_encoded))),
5625 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5626 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5629 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5631 self.assertEqual(obj_decoded.expl_offset, offset)
5632 self.assertSequenceEqual(
5634 obj_decoded.value.fulloffset - offset:
5635 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5639 assert_exceeding_data(
5641 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5645 evgens = list(obj_expled.decode_evgen(
5646 obj_expled_encoded + tail_junk,
5648 decode_path=decode_path,
5651 self.assertEqual(len(evgens), 2)
5652 _decode_path, obj, tail = evgens[0]
5653 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5654 _decode_path, obj, tail = evgens[1]
5655 self.assertSequenceEqual(tail, tail_junk)
5656 self.assertEqual(_decode_path, decode_path)
5657 self.assertEqual(obj.expl_offset, offset)
5662 def test_set_get(self, value):
5665 ("erste", Boolean()),
5666 ("zweite", Integer()),
5669 with self.assertRaises(ObjUnknown) as err:
5670 obj["whatever"] = "whenever"
5671 with self.assertRaises(InvalidValueType) as err:
5672 obj["zweite"] = Boolean(False)
5673 obj["zweite"] = Integer(value)
5675 with self.assertRaises(ObjUnknown) as err:
5678 self.assertIsNone(obj["erste"])
5679 self.assertEqual(obj["zweite"], Integer(value))
5681 def test_tag_mismatch(self):
5684 ("erste", Boolean()),
5686 int_encoded = Integer(123).encode()
5687 bool_encoded = Boolean(False).encode()
5689 obj.decode(bool_encoded)
5690 with self.assertRaises(TagMismatch):
5691 obj.decode(int_encoded)
5693 def test_tag_mismatch_underlying(self):
5694 class SeqOfBoolean(SequenceOf):
5697 class SeqOfInteger(SequenceOf):
5702 ("erste", SeqOfBoolean()),
5705 int_encoded = SeqOfInteger((Integer(123),)).encode()
5706 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5708 obj.decode(bool_encoded)
5709 with self.assertRaises(TagMismatch) as err:
5710 obj.decode(int_encoded)
5711 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5715 def seq_values_strategy(draw, seq_klass, do_expl=False):
5717 if draw(booleans()):
5719 value._value = draw(dictionaries(
5722 booleans().map(Boolean),
5723 integers().map(Integer),
5727 if draw(booleans()):
5728 schema = list(draw(dictionaries(
5731 booleans().map(Boolean),
5732 integers().map(Integer),
5738 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5740 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5742 if draw(booleans()):
5743 default = seq_klass()
5744 default._value = draw(dictionaries(
5747 booleans().map(Boolean),
5748 integers().map(Integer),
5751 optional = draw(one_of(none(), booleans()))
5753 draw(integers(min_value=0)),
5754 draw(integers(min_value=0)),
5755 draw(integers(min_value=0)),
5757 return (value, schema, impl, expl, default, optional, _decoded)
5761 def sequence_strategy(draw, seq_klass):
5762 inputs = draw(lists(
5764 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5765 tuples(just(Integer), integers(), one_of(none(), integers())),
5770 integers(min_value=1),
5771 min_size=len(inputs),
5772 max_size=len(inputs),
5775 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5776 for tag, expled in zip(tags, draw(lists(
5778 min_size=len(inputs),
5779 max_size=len(inputs),
5783 for i, optional in enumerate(draw(lists(
5784 sampled_from(("required", "optional", "empty")),
5785 min_size=len(inputs),
5786 max_size=len(inputs),
5788 if optional in ("optional", "empty"):
5789 inits[i]["optional"] = True
5790 if optional == "empty":
5792 empties = set(empties)
5793 names = list(draw(sets(
5795 min_size=len(inputs),
5796 max_size=len(inputs),
5799 for i, (klass, value, default) in enumerate(inputs):
5800 schema.append((names[i], klass(default=default, **inits[i])))
5801 seq_name = draw(text_letters())
5802 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5805 for i, (klass, value, default) in enumerate(inputs):
5812 "default_value": None if spec.default is None else default,
5816 expect["optional"] = True
5818 expect["presented"] = True
5819 expect["value"] = value
5821 expect["optional"] = True
5822 if default is not None and default == value:
5823 expect["presented"] = False
5824 seq[name] = klass(value)
5825 expects.append(expect)
5830 def sequences_strategy(draw, seq_klass):
5831 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5833 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5834 for tag, expled in zip(tags, draw(lists(
5841 i for i, is_default in enumerate(draw(lists(
5847 names = list(draw(sets(
5852 seq_expectses = draw(lists(
5853 sequence_strategy(seq_klass=seq_klass),
5857 seqs = [seq for seq, _ in seq_expectses]
5859 for i, (name, seq) in enumerate(zip(names, seqs)):
5862 seq(default=(seq if i in defaulted else None), **inits[i]),
5864 seq_name = draw(text_letters())
5865 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5868 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5871 "expects": expects_inner,
5874 seq_outer[name] = seq_inner
5875 if seq_outer.specs[name].default is None:
5876 expect["presented"] = True
5877 expect_outers.append(expect)
5878 return seq_outer, expect_outers
5881 class SeqMixing(object):
5882 def test_invalid_value_type(self):
5883 with self.assertRaises(InvalidValueType) as err:
5884 self.base_klass(123)
5887 def test_invalid_value_type_set(self):
5888 class Seq(self.base_klass):
5889 schema = (("whatever", Boolean()),)
5891 with self.assertRaises(InvalidValueType) as err:
5892 seq["whatever"] = Integer(123)
5896 def test_optional(self, optional):
5897 obj = self.base_klass(default=self.base_klass(), optional=optional)
5898 self.assertTrue(obj.optional)
5900 @given(data_strategy())
5901 def test_ready(self, d):
5903 str(i): v for i, v in enumerate(d.draw(lists(
5910 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5917 for name in d.draw(permutations(
5918 list(ready.keys()) + list(non_ready.keys()),
5920 schema_input.append((name, Boolean()))
5922 class Seq(self.base_klass):
5923 schema = tuple(schema_input)
5925 for name in ready.keys():
5927 seq[name] = Boolean()
5928 self.assertFalse(seq.ready)
5931 pprint(seq, big_blobs=True, with_decode_path=True)
5932 for name, value in ready.items():
5933 seq[name] = Boolean(value)
5934 self.assertFalse(seq.ready)
5937 pprint(seq, big_blobs=True, with_decode_path=True)
5938 with self.assertRaises(ObjNotReady) as err:
5941 with self.assertRaises(ObjNotReady) as err:
5943 for name, value in non_ready.items():
5944 seq[name] = Boolean(value)
5945 self.assertTrue(seq.ready)
5948 pprint(seq, big_blobs=True, with_decode_path=True)
5950 @given(data_strategy())
5951 def test_call(self, d):
5952 class SeqInherited(self.base_klass):
5954 for klass in (self.base_klass, SeqInherited):
5963 ) = d.draw(seq_values_strategy(seq_klass=klass))
5964 obj_initial = klass(
5970 optional_initial or False,
5981 ) = d.draw(seq_values_strategy(
5983 do_expl=impl_initial is None,
5985 obj = obj_initial(value, impl, expl, default, optional)
5986 value_expected = default if value is None else value
5988 default_initial if value_expected is None
5991 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
5992 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
5993 self.assertEqual(obj.expl_tag, expl or expl_initial)
5995 {} if obj.default is None else obj.default._value,
5996 getattr(default_initial if default is None else default, "_value", {}),
5998 if obj.default is None:
5999 optional = optional_initial if optional is None else optional
6000 optional = False if optional is None else optional
6003 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6004 self.assertEqual(obj.optional, optional)
6006 @given(data_strategy())
6007 def test_copy(self, d):
6008 class SeqInherited(self.base_klass):
6010 register_class(SeqInherited)
6011 for klass in (self.base_klass, SeqInherited):
6012 values = d.draw(seq_values_strategy(seq_klass=klass))
6013 obj = klass(*values)
6014 for copy_func in copy_funcs:
6015 obj_copied = copy_func(obj)
6016 self.assert_copied_basic_fields(obj, obj_copied)
6017 self.assertEqual(obj.specs, obj_copied.specs)
6018 self.assertEqual(obj._value, obj_copied._value)
6020 @given(data_strategy())
6021 def test_stripped(self, d):
6022 value = d.draw(integers())
6023 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6025 class Seq(self.base_klass):
6027 schema = (("whatever", Integer()),)
6029 seq["whatever"] = Integer(value)
6030 with self.assertRaises(NotEnoughData):
6031 seq.decode(seq.encode()[:-1])
6033 @given(data_strategy())
6034 def test_stripped_expl(self, d):
6035 value = d.draw(integers())
6036 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6038 class Seq(self.base_klass):
6040 schema = (("whatever", Integer()),)
6042 seq["whatever"] = Integer(value)
6043 with self.assertRaises(NotEnoughData):
6044 seq.decode(seq.encode()[:-1])
6046 @given(integers(min_value=3), binary(min_size=2))
6047 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6048 junk = tag_encode(junk_tag_num) + junk
6050 _, _, len_encoded = tag_strip(memoryview(junk))
6051 len_decode(len_encoded)
6057 class Seq(self.base_klass):
6059 ("whatever", Integer()),
6061 ("whenever", Integer()),
6064 seq["whatever"] = Integer(123)
6065 seq["junk"] = Any(junk)
6066 seq["whenever"] = Integer(123)
6067 with self.assertRaises(DecodeError):
6068 seq.decode(seq.encode())
6071 integers(min_value=31),
6072 integers(min_value=0),
6075 def test_bad_tag(self, tag, offset, decode_path):
6076 with self.assertRaises(DecodeError) as err:
6077 self.base_klass().decode(
6078 tag_encode(tag)[:-1],
6080 decode_path=decode_path,
6083 self.assertEqual(err.exception.offset, offset)
6084 self.assertEqual(err.exception.decode_path, decode_path)
6087 integers(min_value=128),
6088 integers(min_value=0),
6091 def test_bad_len(self, l, offset, decode_path):
6092 with self.assertRaises(DecodeError) as err:
6093 self.base_klass().decode(
6094 self.base_klass.tag_default + len_encode(l)[:-1],
6096 decode_path=decode_path,
6099 self.assertEqual(err.exception.offset, offset)
6100 self.assertEqual(err.exception.decode_path, decode_path)
6102 def _assert_expects(self, seq, expects):
6103 for expect in expects:
6105 seq.specs[expect["name"]].optional,
6108 if expect["default_value"] is not None:
6110 seq.specs[expect["name"]].default,
6111 expect["default_value"],
6113 if expect["presented"]:
6114 self.assertIn(expect["name"], seq)
6115 self.assertEqual(seq[expect["name"]], expect["value"])
6117 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6118 @given(data_strategy())
6119 def test_symmetric(self, d):
6120 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6121 tail_junk = d.draw(binary(max_size=5))
6122 decode_path = d.draw(decode_path_strat)
6123 self.assertTrue(seq.ready)
6124 self.assertFalse(seq.decoded)
6125 self._assert_expects(seq, expects)
6128 pprint(seq, big_blobs=True, with_decode_path=True)
6129 self.assertTrue(seq.ready)
6130 seq_encoded = seq.encode()
6131 self.assertEqual(encode2pass(seq), seq_encoded)
6132 seq_encoded_cer = encode_cer(seq)
6133 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6134 self.assertSequenceEqual(
6135 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6138 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6139 self.assertFalse(seq_decoded.lenindef)
6140 self.assertFalse(seq_decoded.ber_encoded)
6141 self.assertFalse(seq_decoded.bered)
6143 t, _, lv = tag_strip(seq_encoded)
6144 _, _, v = len_decode(lv)
6145 seq_encoded_lenindef = t + LENINDEF + v + EOC
6146 with self.assertRaises(DecodeError):
6147 seq.decode(seq_encoded_lenindef)
6148 ctx_copied = deepcopy(ctx_dummy)
6149 ctx_copied["bered"] = True
6150 seq_decoded_lenindef, tail_lenindef = seq.decode(
6151 seq_encoded_lenindef + tail_junk,
6154 del ctx_copied["bered"]
6155 self.assertDictEqual(ctx_copied, ctx_dummy)
6156 self.assertTrue(seq_decoded_lenindef.lenindef)
6157 self.assertTrue(seq_decoded_lenindef.bered)
6158 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6159 self.assertTrue(seq_decoded_lenindef.lenindef)
6160 self.assertTrue(seq_decoded_lenindef.bered)
6161 with self.assertRaises(DecodeError):
6162 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6163 with self.assertRaises(DecodeError):
6164 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6165 repr(seq_decoded_lenindef)
6166 list(seq_decoded_lenindef.pps())
6167 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6168 self.assertTrue(seq_decoded_lenindef.ready)
6170 for decoded, decoded_tail, encoded in (
6171 (seq_decoded, tail, seq_encoded),
6172 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6174 self.assertEqual(decoded_tail, tail_junk)
6175 self._assert_expects(decoded, expects)
6176 self.assertEqual(seq, decoded)
6177 self.assertEqual(decoded.encode(), seq_encoded)
6178 self.assertEqual(decoded.tlvlen, len(encoded))
6179 for expect in expects:
6180 if not expect["presented"]:
6181 self.assertNotIn(expect["name"], decoded)
6183 self.assertIn(expect["name"], decoded)
6184 obj = decoded[expect["name"]]
6185 self.assertTrue(obj.decoded)
6186 offset = obj.expl_offset if obj.expled else obj.offset
6187 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6188 self.assertSequenceEqual(
6189 seq_encoded[offset:offset + tlvlen],
6193 evgens = list(seq.decode_evgen(
6194 encoded + decoded_tail,
6195 decode_path=decode_path,
6196 ctx={"bered": True},
6198 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6199 for _decode_path, obj, _ in evgens[:-1]:
6200 self.assertEqual(_decode_path[:-1], decode_path)
6203 _decode_path, obj, tail = evgens[-1]
6204 self.assertEqual(_decode_path, decode_path)
6208 assert_exceeding_data(
6210 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6214 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6215 @given(data_strategy())
6216 def test_symmetric_with_seq(self, d):
6217 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6218 self.assertTrue(seq.ready)
6219 seq_encoded = seq.encode()
6220 self.assertEqual(encode2pass(seq), seq_encoded)
6221 seq_decoded, tail = seq.decode(seq_encoded)
6222 self.assertEqual(tail, b"")
6223 self.assertTrue(seq.ready)
6224 self.assertEqual(seq, seq_decoded)
6225 self.assertEqual(seq_decoded.encode(), seq_encoded)
6226 for expect_outer in expect_outers:
6227 if not expect_outer["presented"]:
6228 self.assertNotIn(expect_outer["name"], seq_decoded)
6230 self.assertIn(expect_outer["name"], seq_decoded)
6231 obj = seq_decoded[expect_outer["name"]]
6232 self.assertTrue(obj.decoded)
6233 offset = obj.expl_offset if obj.expled else obj.offset
6234 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6235 self.assertSequenceEqual(
6236 seq_encoded[offset:offset + tlvlen],
6239 self._assert_expects(obj, expect_outer["expects"])
6241 @given(data_strategy())
6242 def test_default_disappears(self, d):
6243 _schema = list(d.draw(dictionaries(
6245 sets(integers(), min_size=2, max_size=2),
6249 class Seq(self.base_klass):
6251 (n, Integer(default=d))
6252 for n, (_, d) in _schema
6255 for name, (value, _) in _schema:
6256 seq[name] = Integer(value)
6257 self.assertEqual(len(seq._value), len(_schema))
6258 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6259 self.assertGreater(len(seq.encode()), len(empty_seq))
6260 for name, (_, default) in _schema:
6261 seq[name] = Integer(default)
6262 self.assertEqual(len(seq._value), 0)
6263 self.assertSequenceEqual(seq.encode(), empty_seq)
6265 @given(data_strategy())
6266 def test_encoded_default_not_accepted(self, d):
6267 _schema = list(d.draw(dictionaries(
6272 tags = [tag_encode(tag) for tag in d.draw(sets(
6273 integers(min_value=1),
6274 min_size=len(_schema),
6275 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):
7050 for i in six_xrange(n):
7053 seqof = SeqOf(gen(n))
7054 self.assertTrue(seqof.ready)
7055 with self.assertRaises(BoundsError):
7057 self.assertFalse(seqof.ready)
7058 seqof = seqof(gen(n))
7059 self.assertTrue(seqof.ready)
7060 with self.assertRaises(BoundsError):
7062 self.assertFalse(seqof.ready)
7064 def test_iterator_twice(self):
7065 class SeqOf(SequenceOf):
7067 bounds = (1, float("+inf"))
7069 for i in six_xrange(10):
7071 seqof = SeqOf(gen())
7072 self.assertTrue(seqof.ready)
7074 self.assertFalse(seqof.ready)
7075 register_class(SeqOf)
7078 def test_iterator_2pass(self):
7079 class SeqOf(SequenceOf):
7081 bounds = (1, float("+inf"))
7083 for i in six_xrange(10):
7085 seqof = SeqOf(gen())
7086 self.assertTrue(seqof.ready)
7087 _, state = seqof.encode1st()
7088 self.assertFalse(seqof.ready)
7089 seqof = seqof(gen())
7090 self.assertTrue(seqof.ready)
7092 seqof.encode2nd(buf.write, iter(state))
7093 self.assertSequenceEqual(
7094 [int(i) for i in seqof.decod(buf.getvalue())],
7098 def test_non_ready_bound_min(self):
7099 class SeqOf(SequenceOf):
7101 bounds = (1, float("+inf"))
7103 self.assertFalse(seqof.ready)
7106 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7111 def _test_symmetric_compare_objs(self, obj1, obj2):
7112 self.assertSetEqual(
7113 set(int(v) for v in obj1),
7114 set(int(v) for v in obj2),
7117 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7118 @given(data_strategy())
7119 def test_sorted(self, d):
7120 values = [OctetString(v) for v in d.draw(lists(binary()))]
7123 schema = OctetString()
7125 seq_encoded = seq.encode()
7126 seq_decoded, _ = seq.decode(seq_encoded)
7127 self.assertSequenceEqual(
7128 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7129 b"".join(sorted([v.encode() for v in values])),
7132 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7133 @given(data_strategy())
7134 def test_unsorted(self, d):
7135 values = [OctetString(v).encode() for v in d.draw(sets(
7136 binary(min_size=1, max_size=5),
7140 values = d.draw(permutations(values))
7141 assume(values != sorted(values))
7142 encoded = b"".join(values)
7143 seq_encoded = b"".join((
7145 len_encode(len(encoded)),
7150 schema = OctetString()
7152 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7153 seq.decode(seq_encoded)
7155 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7156 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7157 self.assertTrue(seq_decoded.ber_encoded)
7158 self.assertTrue(seq_decoded.bered)
7159 seq_decoded = copy(seq_decoded)
7160 self.assertTrue(seq_decoded.ber_encoded)
7161 self.assertTrue(seq_decoded.bered)
7162 self.assertSequenceEqual(
7163 [obj.encode() for obj in seq_decoded],
7168 class TestGoMarshalVectors(TestCase):
7170 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7171 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7172 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7173 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7174 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7176 class Seq(Sequence):
7178 ("erste", Integer()),
7179 ("zweite", Integer(optional=True))
7182 seq["erste"] = Integer(64)
7183 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7184 seq["erste"] = Integer(0x123456)
7185 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7186 seq["erste"] = Integer(64)
7187 seq["zweite"] = Integer(65)
7188 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7190 class NestedSeq(Sequence):
7194 seq["erste"] = Integer(127)
7195 seq["zweite"] = None
7196 nested = NestedSeq()
7197 nested["nest"] = seq
7198 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7200 self.assertSequenceEqual(
7201 OctetString(b"\x01\x02\x03").encode(),
7202 hexdec("0403010203"),
7205 class Seq(Sequence):
7207 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7210 seq["erste"] = Integer(64)
7211 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7213 class Seq(Sequence):
7215 ("erste", Integer(expl=tag_ctxc(5))),
7218 seq["erste"] = Integer(64)
7219 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7221 class Seq(Sequence):
7224 impl=tag_encode(0, klass=TagClassContext),
7229 seq["erste"] = Null()
7230 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7232 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7234 self.assertSequenceEqual(
7235 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7236 hexdec("170d3730303130313030303030305a"),
7238 self.assertSequenceEqual(
7239 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7240 hexdec("170d3039313131353232353631365a"),
7242 self.assertSequenceEqual(
7243 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7244 hexdec("180f32313030303430353132303130315a"),
7247 class Seq(Sequence):
7249 ("erste", GeneralizedTime()),
7252 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7253 self.assertSequenceEqual(
7255 hexdec("3011180f32303039313131353232353631365a"),
7258 self.assertSequenceEqual(
7259 BitString((1, b"\x80")).encode(),
7262 self.assertSequenceEqual(
7263 BitString((12, b"\x81\xF0")).encode(),
7264 hexdec("03030481f0"),
7267 self.assertSequenceEqual(
7268 ObjectIdentifier("1.2.3.4").encode(),
7269 hexdec("06032a0304"),
7271 self.assertSequenceEqual(
7272 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7273 hexdec("06092a864888932d010105"),
7275 self.assertSequenceEqual(
7276 ObjectIdentifier("2.100.3").encode(),
7277 hexdec("0603813403"),
7280 self.assertSequenceEqual(
7281 PrintableString("test").encode(),
7282 hexdec("130474657374"),
7284 self.assertSequenceEqual(
7285 PrintableString("x" * 127).encode(),
7286 hexdec("137F" + "78" * 127),
7288 self.assertSequenceEqual(
7289 PrintableString("x" * 128).encode(),
7290 hexdec("138180" + "78" * 128),
7292 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7294 class Seq(Sequence):
7296 ("erste", IA5String()),
7299 seq["erste"] = IA5String("test")
7300 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7302 class Seq(Sequence):
7304 ("erste", PrintableString()),
7307 seq["erste"] = PrintableString("test")
7308 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7309 # Asterisk is actually not allowable
7310 PrintableString._allowable_chars |= set(b"*")
7311 seq["erste"] = PrintableString("test*")
7312 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7313 PrintableString._allowable_chars -= set(b"*")
7315 class Seq(Sequence):
7317 ("erste", Any(optional=True)),
7318 ("zweite", Integer()),
7321 seq["zweite"] = Integer(64)
7322 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7327 seq.append(Integer(10))
7328 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7330 class _SeqOf(SequenceOf):
7331 schema = PrintableString()
7333 class SeqOf(SequenceOf):
7336 _seqof.append(PrintableString("1"))
7338 seqof.append(_seqof)
7339 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7341 class Seq(Sequence):
7343 ("erste", Integer(default=1)),
7346 seq["erste"] = Integer(0)
7347 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7348 seq["erste"] = Integer(1)
7349 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7350 seq["erste"] = Integer(2)
7351 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7354 class TestPP(TestCase):
7355 @given(data_strategy())
7356 def test_oid_printing(self, d):
7358 str(ObjectIdentifier(k)): v * 2
7359 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7361 chosen = d.draw(sampled_from(sorted(oids)))
7362 chosen_id = oids[chosen]
7363 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7364 self.assertNotIn(chosen_id, pp_console_row(pp))
7367 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7371 class TestAutoAddSlots(TestCase):
7373 class Inher(Integer):
7376 with self.assertRaises(AttributeError):
7378 inher.unexistent = "whatever"
7381 class TestOIDDefines(TestCase):
7382 @given(data_strategy())
7383 def runTest(self, d):
7384 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7385 value_name_chosen = d.draw(sampled_from(value_names))
7387 ObjectIdentifier(oid)
7388 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7390 oid_chosen = d.draw(sampled_from(oids))
7391 values = d.draw(lists(
7393 min_size=len(value_names),
7394 max_size=len(value_names),
7396 for definable_class in (Any, OctetString, BitString):
7398 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7399 oid: Integer() for oid in oids[:-1]
7402 for i, value_name in enumerate(value_names):
7403 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7405 class Seq(Sequence):
7408 for value_name, value in zip(value_names, values):
7409 seq[value_name] = definable_class(Integer(value).encode())
7410 seq["type"] = oid_chosen
7411 seq, _ = Seq().decode(seq.encode())
7412 for value_name in value_names:
7413 if value_name == value_name_chosen:
7415 self.assertIsNone(seq[value_name].defined)
7416 if value_name_chosen in oids[:-1]:
7417 self.assertIsNotNone(seq[value_name_chosen].defined)
7418 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7419 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7422 pprint(seq, big_blobs=True, with_decode_path=True)
7425 class TestDefinesByPath(TestCase):
7426 def test_generated(self):
7427 class Seq(Sequence):
7429 ("type", ObjectIdentifier()),
7430 ("value", OctetString(expl=tag_ctxc(123))),
7433 class SeqInner(Sequence):
7435 ("typeInner", ObjectIdentifier()),
7436 ("valueInner", Any()),
7439 class PairValue(SetOf):
7442 class Pair(Sequence):
7444 ("type", ObjectIdentifier()),
7445 ("value", PairValue()),
7448 class Pairs(SequenceOf):
7455 type_octet_stringed,
7457 ObjectIdentifier(oid)
7458 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7460 seq_integered = Seq()
7461 seq_integered["type"] = type_integered
7462 seq_integered["value"] = OctetString(Integer(123).encode())
7463 seq_integered_raw = seq_integered.encode()
7467 (type_octet_stringed, OctetString(b"whatever")),
7468 (type_integered, Integer(123)),
7469 (type_octet_stringed, OctetString(b"whenever")),
7470 (type_integered, Integer(234)),
7472 for t, v in pairs_input:
7475 ("value", PairValue((Any(v),))),
7477 seq_inner = SeqInner()
7478 seq_inner["typeInner"] = type_innered
7479 seq_inner["valueInner"] = Any(pairs)
7480 seq_sequenced = Seq()
7481 seq_sequenced["type"] = type_sequenced
7482 seq_sequenced["value"] = OctetString(seq_inner.encode())
7483 seq_sequenced_raw = seq_sequenced.encode()
7485 list(seq_sequenced.pps())
7486 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7488 defines_by_path = []
7489 ctx_copied = deepcopy(ctx_dummy)
7490 seq_integered, _ = Seq().decode(
7494 self.assertDictEqual(ctx_copied, ctx_dummy)
7495 self.assertIsNone(seq_integered["value"].defined)
7496 defines_by_path.append(
7497 (("type",), ((("value",), {
7498 type_integered: Integer(),
7499 type_sequenced: SeqInner(),
7502 ctx_copied["defines_by_path"] = defines_by_path
7503 seq_integered, _ = Seq().decode(
7507 del ctx_copied["defines_by_path"]
7508 self.assertDictEqual(ctx_copied, ctx_dummy)
7509 self.assertIsNotNone(seq_integered["value"].defined)
7510 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7511 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7512 self.assertTrue(seq_integered_raw[
7513 seq_integered["value"].defined[1].offset:
7514 ].startswith(Integer(123).encode()))
7516 list(seq_integered.pps())
7517 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7519 ctx_copied["defines_by_path"] = defines_by_path
7520 seq_sequenced, _ = Seq().decode(
7524 del ctx_copied["defines_by_path"]
7525 self.assertDictEqual(ctx_copied, ctx_dummy)
7526 self.assertIsNotNone(seq_sequenced["value"].defined)
7527 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7528 seq_inner = seq_sequenced["value"].defined[1]
7529 self.assertIsNone(seq_inner["valueInner"].defined)
7531 list(seq_sequenced.pps())
7532 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7534 defines_by_path.append((
7535 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7536 ((("valueInner",), {type_innered: Pairs()}),),
7538 ctx_copied["defines_by_path"] = defines_by_path
7539 seq_sequenced, _ = Seq().decode(
7543 del ctx_copied["defines_by_path"]
7544 self.assertDictEqual(ctx_copied, ctx_dummy)
7545 self.assertIsNotNone(seq_sequenced["value"].defined)
7546 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7547 seq_inner = seq_sequenced["value"].defined[1]
7548 self.assertIsNotNone(seq_inner["valueInner"].defined)
7549 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7550 pairs = seq_inner["valueInner"].defined[1]
7552 self.assertIsNone(pair["value"][0].defined)
7554 list(seq_sequenced.pps())
7555 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7557 defines_by_path.append((
7560 DecodePathDefBy(type_sequenced),
7562 DecodePathDefBy(type_innered),
7567 type_integered: Integer(),
7568 type_octet_stringed: OctetString(),
7571 ctx_copied["defines_by_path"] = defines_by_path
7572 seq_sequenced, _ = Seq().decode(
7576 del ctx_copied["defines_by_path"]
7577 self.assertDictEqual(ctx_copied, ctx_dummy)
7578 self.assertIsNotNone(seq_sequenced["value"].defined)
7579 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7580 seq_inner = seq_sequenced["value"].defined[1]
7581 self.assertIsNotNone(seq_inner["valueInner"].defined)
7582 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7583 pairs_got = seq_inner["valueInner"].defined[1]
7584 for pair_input, pair_got in zip(pairs_input, pairs_got):
7585 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7586 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7588 list(seq_sequenced.pps())
7589 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7591 @given(oid_strategy(), integers())
7592 def test_simple(self, oid, tgt):
7593 class Inner(Sequence):
7595 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7596 ObjectIdentifier(oid): Integer(),
7600 class Outer(Sequence):
7603 ("tgt", OctetString()),
7607 inner["oid"] = ObjectIdentifier(oid)
7609 outer["inner"] = inner
7610 outer["tgt"] = OctetString(Integer(tgt).encode())
7611 decoded, _ = Outer().decode(outer.encode())
7612 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7614 def test_remaining_data(self):
7615 oid = ObjectIdentifier("1.2.3")
7616 class Seq(Sequence):
7618 ("oid", ObjectIdentifier(defines=((("tgt",), {
7621 ("tgt", OctetString()),
7626 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7628 with assertRaisesRegex(self, DecodeError, "remaining data"):
7629 Seq().decode(seq.encode())
7631 def test_remaining_data_seqof(self):
7632 oid = ObjectIdentifier("1.2.3")
7634 schema = OctetString()
7636 class Seq(Sequence):
7638 ("oid", ObjectIdentifier(defines=((("tgt",), {
7646 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7648 with assertRaisesRegex(self, DecodeError, "remaining data"):
7649 Seq().decode(seq.encode())
7652 class TestAbsDecodePath(TestCase):
7654 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7655 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7657 def test_concat(self, decode_path, rel_path):
7658 dp = abs_decode_path(decode_path, rel_path)
7659 self.assertSequenceEqual(dp, decode_path + rel_path)
7663 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7664 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7666 def test_abs(self, decode_path, rel_path):
7667 self.assertSequenceEqual(
7668 abs_decode_path(decode_path, ("/",) + rel_path),
7673 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7674 integers(min_value=1, max_value=3),
7675 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7677 def test_dots(self, decode_path, number_of_dots, rel_path):
7678 self.assertSequenceEqual(
7679 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7680 decode_path[:-number_of_dots] + rel_path,
7684 class TestStrictDefaultExistence(TestCase):
7685 @given(data_strategy())
7686 def runTest(self, d):
7687 count = d.draw(integers(min_value=1, max_value=10))
7688 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7690 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7691 for i in range(count)
7693 for klass in (Sequence, Set):
7697 for i in range(count):
7698 seq["int%d" % i] = Integer(123)
7700 chosen_choice = "int%d" % chosen
7701 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7702 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7704 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7705 self.assertTrue(decoded.ber_encoded)
7706 self.assertTrue(decoded.bered)
7707 decoded = copy(decoded)
7708 self.assertTrue(decoded.ber_encoded)
7709 self.assertTrue(decoded.bered)
7710 decoded, _ = seq.decode(raw, ctx={"bered": True})
7711 self.assertTrue(decoded.ber_encoded)
7712 self.assertTrue(decoded.bered)
7713 decoded = copy(decoded)
7714 self.assertTrue(decoded.ber_encoded)
7715 self.assertTrue(decoded.bered)
7718 class TestX690PrefixedType(TestCase):
7720 self.assertSequenceEqual(
7721 VisibleString("Jones").encode(),
7722 hexdec("1A054A6F6E6573"),
7726 self.assertSequenceEqual(
7729 impl=tag_encode(3, klass=TagClassApplication),
7731 hexdec("43054A6F6E6573"),
7735 self.assertSequenceEqual(
7739 impl=tag_encode(3, klass=TagClassApplication),
7743 hexdec("A20743054A6F6E6573"),
7747 self.assertSequenceEqual(
7751 impl=tag_encode(3, klass=TagClassApplication),
7753 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7755 hexdec("670743054A6F6E6573"),
7759 self.assertSequenceEqual(
7760 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7761 hexdec("82054A6F6E6573"),
7765 class TestExplOOB(TestCase):
7767 expl = tag_ctxc(123)
7768 raw = Integer(123).encode() + Integer(234).encode()
7769 raw = b"".join((expl, len_encode(len(raw)), raw))
7770 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7771 Integer(expl=expl).decode(raw)
7772 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7775 class TestPickleDifferentVersion(TestCase):
7777 pickled = pickle_dumps(Integer(123), pickle_proto)
7779 version_orig = pyderasn.__version__
7780 pyderasn.__version__ += "different"
7781 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7782 pickle_loads(pickled)
7783 pyderasn.__version__ = version_orig
7784 pickle_loads(pickled)
7787 class TestCERSetOrdering(TestCase):
7788 def test_vectors(self):
7789 """Taken from X.690-201508
7793 ("c", Integer(impl=tag_ctxp(2))),
7794 ("d", Integer(impl=tag_ctxp(4))),
7799 ("g", Integer(impl=tag_ctxp(5))),
7800 ("h", Integer(impl=tag_ctxp(6))),
7805 ("j", Integer(impl=tag_ctxp(0))),
7816 ("a", Integer(impl=tag_ctxp(3))),
7817 ("b", B(expl=tag_ctxc(1))),
7822 ("a", Integer(123)),
7823 ("b", B(("d", Integer(234)))),
7824 ("e", E(("f", F(("g", Integer(345)))))),
7826 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7827 self.assertSequenceEqual(
7828 [i.__class__.__name__ for i in order],
7829 ("E", "B", "Integer"),