2 # PyDERASN -- Python ASN.1 DER/CER/BER codec with abstract structures
3 # Copyright (C) 2017-2020 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this program. If not, see
16 # <http://www.gnu.org/licenses/>.
19 from copy import deepcopy
20 from datetime import datetime
21 from datetime import timedelta
22 from importlib import import_module
23 from io import BytesIO
24 from operator import attrgetter
25 from os import environ
26 from os import urandom
27 from random import random
28 from string import ascii_letters
29 from string import digits
30 from string import printable
31 from string import whitespace
32 from time import mktime
34 from unittest import TestCase
36 from hypothesis import assume
37 from hypothesis import given
38 from hypothesis import settings
39 from hypothesis.strategies import binary
40 from hypothesis.strategies import booleans
41 from hypothesis.strategies import composite
42 from hypothesis.strategies import data as data_strategy
43 from hypothesis.strategies import datetimes
44 from hypothesis.strategies import dictionaries
45 from hypothesis.strategies import integers
46 from hypothesis.strategies import just
47 from hypothesis.strategies import lists
48 from hypothesis.strategies import none
49 from hypothesis.strategies import one_of
50 from hypothesis.strategies import permutations
51 from hypothesis.strategies import sampled_from
52 from hypothesis.strategies import sets
53 from hypothesis.strategies import text
54 from hypothesis.strategies import tuples
55 from six import assertRaisesRegex
56 from six import binary_type
57 from six import byte2int
58 from six import indexbytes
59 from six import int2byte
60 from six import iterbytes
62 from six import text_type
63 from six import unichr as six_unichr
64 from six.moves import xrange as six_xrange
65 from six.moves.cPickle import dumps as pickle_dumps
66 from six.moves.cPickle import HIGHEST_PROTOCOL as pickle_proto
67 from six.moves.cPickle import loads as pickle_loads
69 from pyderasn import _pp
70 from pyderasn import abs_decode_path
71 from pyderasn import Any
72 from pyderasn import BitString
73 from pyderasn import BMPString
74 from pyderasn import Boolean
75 from pyderasn import BoundsError
76 from pyderasn import Choice
77 from pyderasn import DecodeError
78 from pyderasn import DecodePathDefBy
79 from pyderasn import encode2pass
80 from pyderasn import encode_cer
81 from pyderasn import Enumerated
82 from pyderasn import EOC
83 from pyderasn import EOC_LEN
84 from pyderasn import ExceedingData
85 from pyderasn import GeneralizedTime
86 from pyderasn import GeneralString
87 from pyderasn import GraphicString
88 from pyderasn import hexdec
89 from pyderasn import hexenc
90 from pyderasn import IA5String
91 from pyderasn import Integer
92 from pyderasn import InvalidLength
93 from pyderasn import InvalidOID
94 from pyderasn import InvalidValueType
95 from pyderasn import len_decode
96 from pyderasn import len_encode
97 from pyderasn import LEN_YYMMDDHHMMSSZ
98 from pyderasn import LEN_YYYYMMDDHHMMSSDMZ
99 from pyderasn import LEN_YYYYMMDDHHMMSSZ
100 from pyderasn import LENINDEF
101 from pyderasn import LenIndefForm
102 from pyderasn import NotEnoughData
103 from pyderasn import Null
104 from pyderasn import NumericString
105 from pyderasn import ObjectIdentifier
106 from pyderasn import ObjNotReady
107 from pyderasn import ObjUnknown
108 from pyderasn import OctetString
109 from pyderasn import pp_console_row
110 from pyderasn import pprint
111 from pyderasn import PrintableString
112 from pyderasn import Sequence
113 from pyderasn import SequenceOf
114 from pyderasn import Set
115 from pyderasn import SetOf
116 from pyderasn import tag_ctxc
117 from pyderasn import tag_ctxp
118 from pyderasn import tag_decode
119 from pyderasn import tag_encode
120 from pyderasn import tag_strip
121 from pyderasn import TagClassApplication
122 from pyderasn import TagClassContext
123 from pyderasn import TagClassPrivate
124 from pyderasn import TagClassUniversal
125 from pyderasn import TagFormConstructed
126 from pyderasn import TagFormPrimitive
127 from pyderasn import TagMismatch
128 from pyderasn import TeletexString
129 from pyderasn import UniversalString
130 from pyderasn import UTCTime
131 from pyderasn import UTF8String
132 from pyderasn import VideotexString
133 from pyderasn import VisibleString
136 max_examples = environ.get("MAX_EXAMPLES")
137 settings.register_profile("local", settings(
139 **({"max_examples": int(max_examples)} if max_examples else {})
141 settings.load_profile("local")
142 LONG_TEST_MAX_EXAMPLES = settings().max_examples * 4
144 tag_classes = sampled_from((
150 tag_forms = sampled_from((TagFormConstructed, TagFormPrimitive))
151 decode_path_strat = lists(integers(), max_size=3).map(
152 lambda decode_path: tuple(str(dp) for dp in decode_path)
154 ctx_dummy = dictionaries(integers(), integers(), min_size=2, max_size=4).example()
157 lambda obj: pickle_loads(pickle_dumps(obj, pickle_proto)),
159 self_module = import_module(__name__)
162 def register_class(klass):
163 klassname = klass.__name__ + str(time()).replace(".", "")
164 klass.__name__ = klassname
165 klass.__qualname__ = klassname
166 setattr(self_module, klassname, klass)
169 def assert_exceeding_data(self, call, junk):
172 with assertRaisesRegex(self, ExceedingData, "%d trailing bytes" % len(junk)) as err:
177 class TestHex(TestCase):
179 def test_symmetric(self, data):
180 self.assertEqual(hexdec(hexenc(data)), data)
183 class TestTagCoder(TestCase):
184 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
188 integers(min_value=0, max_value=30),
191 def test_short(self, klass, form, num, junk):
192 raw = tag_encode(klass=klass, form=form, num=num)
193 self.assertEqual(tag_decode(raw), (klass, form, num))
194 self.assertEqual(len(raw), 1)
196 byte2int(tag_encode(klass=klass, form=form, num=0)),
197 byte2int(raw) & (1 << 7 | 1 << 6 | 1 << 5),
199 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
200 self.assertSequenceEqual(stripped.tobytes(), raw)
201 self.assertEqual(tlen, len(raw))
202 self.assertSequenceEqual(tail, junk)
204 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
208 integers(min_value=31),
211 def test_long(self, klass, form, num, junk):
212 raw = tag_encode(klass=klass, form=form, num=num)
213 self.assertEqual(tag_decode(raw), (klass, form, num))
214 self.assertGreater(len(raw), 1)
216 byte2int(tag_encode(klass=klass, form=form, num=0)) | 31,
219 self.assertEqual(byte2int(raw[-1:]) & 0x80, 0)
220 self.assertTrue(all(b & 0x80 > 0 for b in iterbytes(raw[1:-1])))
221 stripped, tlen, tail = tag_strip(memoryview(raw + junk))
222 self.assertSequenceEqual(stripped.tobytes(), raw)
223 self.assertEqual(tlen, len(raw))
224 self.assertSequenceEqual(tail, junk)
226 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
227 @given(integers(min_value=31))
228 def test_unfinished_tag(self, num):
229 raw = bytearray(tag_encode(num=num))
230 for i in range(1, len(raw)):
232 with assertRaisesRegex(self, DecodeError, "unfinished tag"):
233 tag_strip(bytes(raw))
235 def test_go_vectors_valid(self):
236 for data, (eklass, etag, elen, eform) in (
237 (b"\x80\x01", (TagClassContext, 0, 1, TagFormPrimitive)),
238 (b"\xa0\x01", (TagClassContext, 0, 1, TagFormConstructed)),
239 (b"\x02\x00", (TagClassUniversal, 2, 0, TagFormPrimitive)),
240 (b"\xfe\x00", (TagClassPrivate, 30, 0, TagFormConstructed)),
241 (b"\x1f\x1f\x00", (TagClassUniversal, 31, 0, TagFormPrimitive)),
242 (b"\x1f\x81\x00\x00", (TagClassUniversal, 128, 0, TagFormPrimitive)),
243 (b"\x1f\x81\x80\x01\x00", (TagClassUniversal, 0x4001, 0, TagFormPrimitive)),
244 (b"\x00\x81\x80", (TagClassUniversal, 0, 128, TagFormPrimitive)),
245 (b"\x00\x82\x01\x00", (TagClassUniversal, 0, 256, TagFormPrimitive)),
246 (b"\xa0\x84\x7f\xff\xff\xff", (TagClassContext, 0, 0x7fffffff, TagFormConstructed)),
248 tag, _, len_encoded = tag_strip(memoryview(data))
249 klass, form, num = tag_decode(tag)
250 _len, _, tail = len_decode(len_encoded)
251 self.assertSequenceEqual(tail, b"")
252 self.assertEqual(klass, eklass)
253 self.assertEqual(num, etag)
254 self.assertEqual(_len, elen)
255 self.assertEqual(form, eform)
257 def test_go_vectors_invalid(self):
265 with self.assertRaises(DecodeError):
266 _, _, len_encoded = tag_strip(memoryview(data))
267 len_decode(len_encoded)
270 integers(min_value=0, max_value=127),
271 integers(min_value=0, max_value=2),
273 def test_long_instead_of_short(self, l, dummy_num):
274 octets = (b"\x00" * dummy_num) + int2byte(l)
275 octets = int2byte((dummy_num + 1) | 0x80) + octets
276 with self.assertRaises(DecodeError):
280 class TestLenCoder(TestCase):
281 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
283 integers(min_value=0, max_value=127),
286 def test_short(self, l, junk):
287 raw = len_encode(l) + junk
288 decoded, llen, tail = len_decode(memoryview(raw))
289 self.assertEqual(decoded, l)
290 self.assertEqual(llen, 1)
291 self.assertEqual(len(raw), 1 + len(junk))
292 self.assertEqual(tail.tobytes(), junk)
294 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
296 integers(min_value=128),
299 def test_long(self, l, junk):
300 raw = len_encode(l) + junk
301 decoded, llen, tail = len_decode(memoryview(raw))
302 self.assertEqual(decoded, l)
303 self.assertEqual((llen - 1) | 0x80, byte2int(raw))
304 self.assertEqual(llen, len(raw) - len(junk))
305 self.assertNotEqual(indexbytes(raw, 1), 0)
306 self.assertSequenceEqual(tail.tobytes(), junk)
308 def test_empty(self):
309 with self.assertRaises(NotEnoughData):
312 @given(integers(min_value=128))
313 def test_stripped(self, _len):
314 with self.assertRaises(NotEnoughData):
315 len_decode(len_encode(_len)[:-1])
318 text_printable = text(alphabet=printable, min_size=1)
322 def text_letters(draw):
323 result = draw(text(alphabet=ascii_letters, min_size=1))
325 result = result.encode("ascii")
329 class CommonMixin(object):
330 def test_tag_default(self):
331 obj = self.base_klass()
332 self.assertEqual(obj.tag, obj.tag_default)
334 def test_simultaneous_impl_expl(self):
335 with self.assertRaises(ValueError):
336 self.base_klass(impl=b"whatever", expl=b"whenever")
338 @given(binary(min_size=1), integers(), integers(), integers())
339 def test_decoded(self, impl, offset, llen, vlen):
340 obj = self.base_klass(impl=impl, _decoded=(offset, llen, vlen))
341 self.assertEqual(obj.offset, offset)
342 self.assertEqual(obj.llen, llen)
343 self.assertEqual(obj.vlen, vlen)
344 self.assertEqual(obj.tlen, len(impl))
345 self.assertEqual(obj.tlvlen, obj.tlen + obj.llen + obj.vlen)
347 @given(binary(min_size=1))
348 def test_impl_inherited(self, impl_tag):
349 class Inherited(self.base_klass):
352 self.assertSequenceEqual(obj.impl, impl_tag)
353 self.assertFalse(obj.expled)
355 tag_class, _, tag_num = tag_decode(impl_tag)
356 self.assertEqual(obj.tag_order, (tag_class, tag_num))
358 @given(binary(min_size=1))
359 def test_expl_inherited(self, expl_tag):
360 class Inherited(self.base_klass):
363 self.assertSequenceEqual(obj.expl, expl_tag)
364 self.assertTrue(obj.expled)
366 tag_class, _, tag_num = tag_decode(expl_tag)
367 self.assertEqual(obj.tag_order, (tag_class, tag_num))
369 def assert_copied_basic_fields(self, obj, obj_copied):
370 self.assertEqual(obj, obj_copied)
371 self.assertSequenceEqual(obj.tag, obj_copied.tag)
372 self.assertEqual(obj.expl_tag, obj_copied.expl_tag)
373 self.assertEqual(obj.default, obj_copied.default)
374 self.assertEqual(obj.optional, obj_copied.optional)
375 self.assertEqual(obj.offset, obj_copied.offset)
376 self.assertEqual(obj.llen, obj_copied.llen)
377 self.assertEqual(obj.vlen, obj_copied.vlen)
379 self.assertEqual(obj.tag_order, obj_copied.tag_order)
383 def boolean_values_strategy(draw, do_expl=False):
384 value = draw(one_of(none(), booleans()))
388 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
390 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
391 default = draw(one_of(none(), booleans()))
392 optional = draw(one_of(none(), booleans()))
394 draw(integers(min_value=0)),
395 draw(integers(min_value=0)),
396 draw(integers(min_value=0)),
398 return (value, impl, expl, default, optional, _decoded)
401 class BooleanInherited(Boolean):
405 class TestBoolean(CommonMixin, TestCase):
408 def test_invalid_value_type(self):
409 with self.assertRaises(InvalidValueType) as err:
414 def test_optional(self, optional):
415 obj = Boolean(default=Boolean(False), optional=optional)
416 self.assertTrue(obj.optional)
419 def test_ready(self, value):
421 self.assertFalse(obj.ready)
424 pprint(obj, big_blobs=True, with_decode_path=True)
425 with self.assertRaises(ObjNotReady) as err:
427 with self.assertRaises(ObjNotReady) as err:
431 self.assertTrue(obj.ready)
434 pprint(obj, big_blobs=True, with_decode_path=True)
436 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
437 def test_comparison(self, value1, value2, tag1, tag2):
438 for klass in (Boolean, BooleanInherited):
441 self.assertEqual(obj1 == obj2, value1 == value2)
442 self.assertEqual(obj1 != obj2, value1 != value2)
443 self.assertEqual(obj1 == bool(obj2), value1 == value2)
444 obj1 = klass(value1, impl=tag1)
445 obj2 = klass(value1, impl=tag2)
446 self.assertEqual(obj1 == obj2, tag1 == tag2)
447 self.assertEqual(obj1 != obj2, tag1 != tag2)
449 @given(data_strategy())
450 def test_call(self, d):
451 for klass in (Boolean, BooleanInherited):
459 ) = d.draw(boolean_values_strategy())
465 optional_initial or False,
475 ) = d.draw(boolean_values_strategy(do_expl=impl_initial is None))
476 obj = obj_initial(value, impl, expl, default, optional)
478 value_expected = default if value is None else value
480 default_initial if value_expected is None
483 self.assertEqual(obj, value_expected)
484 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
485 self.assertEqual(obj.expl_tag, expl or expl_initial)
488 default_initial if default is None else default,
490 if obj.default is None:
491 optional = optional_initial if optional is None else optional
492 optional = False if optional is None else optional
495 self.assertEqual(obj.optional, optional)
497 @given(boolean_values_strategy())
498 def test_copy(self, values):
499 for klass in (Boolean, BooleanInherited):
501 for copy_func in copy_funcs:
502 obj_copied = copy_func(obj)
503 self.assert_copied_basic_fields(obj, obj_copied)
507 integers(min_value=1).map(tag_encode),
509 def test_stripped(self, value, tag_impl):
510 obj = Boolean(value, impl=tag_impl)
511 with self.assertRaises(NotEnoughData):
512 obj.decode(obj.encode()[:-1])
513 with self.assertRaises(NotEnoughData):
514 obj.decode(encode2pass(obj)[:-1])
518 integers(min_value=1).map(tag_ctxc),
520 def test_stripped_expl(self, value, tag_expl):
521 obj = Boolean(value, expl=tag_expl)
522 with self.assertRaises(NotEnoughData):
523 obj.decode(obj.encode()[:-1])
524 with self.assertRaises(NotEnoughData):
525 obj.decode(encode2pass(obj)[:-1])
528 integers(min_value=31),
529 integers(min_value=0),
532 def test_bad_tag(self, tag, offset, decode_path):
533 with self.assertRaises(DecodeError) as err:
535 tag_encode(tag)[:-1],
537 decode_path=decode_path,
540 self.assertEqual(err.exception.offset, offset)
541 self.assertEqual(err.exception.decode_path, decode_path)
544 integers(min_value=31),
545 integers(min_value=0),
548 def test_bad_expl_tag(self, tag, offset, decode_path):
549 with self.assertRaises(DecodeError) as err:
550 Boolean(expl=Boolean.tag_default).decode(
551 tag_encode(tag)[:-1],
553 decode_path=decode_path,
556 self.assertEqual(err.exception.offset, offset)
557 self.assertEqual(err.exception.decode_path, decode_path)
560 integers(min_value=128),
561 integers(min_value=0),
564 def test_bad_len(self, l, offset, decode_path):
565 with self.assertRaises(DecodeError) as err:
567 Boolean.tag_default + len_encode(l)[:-1],
569 decode_path=decode_path,
572 self.assertEqual(err.exception.offset, offset)
573 self.assertEqual(err.exception.decode_path, decode_path)
576 integers(min_value=128),
577 integers(min_value=0),
580 def test_bad_expl_len(self, l, offset, decode_path):
581 with self.assertRaises(DecodeError) as err:
582 Boolean(expl=Boolean.tag_default).decode(
583 Boolean.tag_default + len_encode(l)[:-1],
585 decode_path=decode_path,
588 self.assertEqual(err.exception.offset, offset)
589 self.assertEqual(err.exception.decode_path, decode_path)
591 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
593 boolean_values_strategy(),
595 integers(min_value=1).map(tag_ctxc),
596 integers(min_value=0),
600 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
601 for klass in (Boolean, BooleanInherited):
602 _, _, _, default, optional, _decoded = values
611 pprint(obj, big_blobs=True, with_decode_path=True)
612 self.assertFalse(obj.expled)
613 obj_encoded = obj.encode()
614 self.assertEqual(encode2pass(obj), obj_encoded)
615 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
616 obj_expled = obj(value, expl=tag_expl)
617 self.assertTrue(obj_expled.expled)
619 list(obj_expled.pps())
620 pprint(obj_expled, big_blobs=True, with_decode_path=True)
621 obj_expled_cer = encode_cer(obj_expled)
622 self.assertNotEqual(obj_expled_cer, obj_encoded)
623 self.assertSequenceEqual(
624 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
627 obj_expled_hex_encoded = obj_expled.hexencode()
628 ctx_copied = deepcopy(ctx_dummy)
629 obj_decoded, tail = obj_expled.hexdecode(
630 obj_expled_hex_encoded + hexenc(tail_junk),
634 self.assertDictEqual(ctx_copied, ctx_dummy)
636 list(obj_decoded.pps())
637 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
638 self.assertEqual(tail, tail_junk)
639 self.assertEqual(obj_decoded, obj_expled)
640 self.assertNotEqual(obj_decoded, obj)
641 self.assertEqual(bool(obj_decoded), bool(obj_expled))
642 self.assertEqual(bool(obj_decoded), bool(obj))
643 self.assertSequenceEqual(obj_decoded.hexencode(), obj_expled_hex_encoded)
644 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
645 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
647 obj_decoded.expl_llen,
648 len(len_encode(len(obj_encoded))),
650 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
651 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
654 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
656 self.assertEqual(obj_decoded.expl_offset, offset)
657 assert_exceeding_data(
659 lambda: obj_expled.hexdecod(obj_expled_hex_encoded + hexenc(tail_junk)),
663 evgens = list(obj_expled.decode_evgen(
664 hexdec(obj_expled_hex_encoded) + tail_junk,
666 decode_path=decode_path,
669 self.assertEqual(len(evgens), 1)
670 _decode_path, obj, tail = evgens[0]
671 self.assertSequenceEqual(tail, tail_junk)
672 self.assertEqual(_decode_path, decode_path)
673 self.assertEqual(obj, obj_decoded)
674 self.assertEqual(obj.expl_offset, offset)
678 @given(integers(min_value=2))
679 def test_invalid_len(self, l):
680 with self.assertRaises(InvalidLength):
681 Boolean().decode(b"".join((
687 @given(integers(min_value=0 + 1, max_value=255 - 1))
688 def test_ber_value(self, value):
689 with assertRaisesRegex(self, DecodeError, "unacceptable Boolean value"):
690 Boolean().decode(b"".join((
700 obj, _ = Boolean().decode(encoded, ctx={"bered": True})
701 list(Boolean().decode_evgen(encoded, ctx={"bered": True}))
702 self.assertTrue(bool(obj))
703 self.assertTrue(obj.ber_encoded)
704 self.assertFalse(obj.lenindef)
705 self.assertTrue(obj.bered)
707 self.assertTrue(obj.ber_encoded)
708 self.assertFalse(obj.lenindef)
709 self.assertTrue(obj.bered)
712 integers(min_value=1).map(tag_ctxc),
713 binary().filter(lambda x: not x.startswith(EOC)),
715 def test_ber_expl_no_eoc(self, expl, junk):
716 encoded = expl + LENINDEF + Boolean(False).encode()
717 with self.assertRaises(LenIndefForm):
718 Boolean(expl=expl).decode(encoded + junk)
719 with assertRaisesRegex(self, DecodeError, "no EOC"):
720 Boolean(expl=expl).decode(encoded + junk, ctx={"bered": True})
721 obj, tail = Boolean(expl=expl).decode(
722 encoded + EOC + junk,
725 self.assertTrue(obj.expl_lenindef)
726 self.assertFalse(obj.lenindef)
727 self.assertFalse(obj.ber_encoded)
728 self.assertTrue(obj.bered)
730 self.assertTrue(obj.expl_lenindef)
731 self.assertFalse(obj.lenindef)
732 self.assertFalse(obj.ber_encoded)
733 self.assertTrue(obj.bered)
734 self.assertSequenceEqual(tail, junk)
737 pprint(obj, big_blobs=True, with_decode_path=True)
740 integers(min_value=1).map(tag_ctxc),
747 def test_ber_expl(self, expl, values):
753 Boolean(value).encode() +
756 encoded = SequenceOf.tag_default + len_encode(len(encoded)) + encoded
758 class SeqOf(SequenceOf):
759 schema = Boolean(expl=expl)
760 with self.assertRaises(LenIndefForm):
761 SeqOf().decode(encoded)
762 seqof, tail = SeqOf().decode(encoded, ctx={"bered": True})
763 list(SeqOf().decode_evgen(encoded, ctx={"bered": True}))
764 self.assertSequenceEqual(tail, b"")
765 self.assertSequenceEqual([bool(v) for v in seqof], values)
781 len(expl) + 1 + 3 + EOC_LEN,
792 pprint(seqof, big_blobs=True, with_decode_path=True)
796 def integer_values_strategy(draw, do_expl=False):
797 bound_min, value, default, bound_max = sorted(draw(sets(
806 _specs = draw(sets(text_letters()))
809 min_size=len(_specs),
810 max_size=len(_specs),
812 _specs = list(zip(_specs, values))
815 bounds = (bound_min, bound_max)
819 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
821 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
824 optional = draw(one_of(none(), booleans()))
826 draw(integers(min_value=0)),
827 draw(integers(min_value=0)),
828 draw(integers(min_value=0)),
830 return (value, bounds, impl, expl, default, optional, _specs, _decoded)
833 class IntegerInherited(Integer):
837 class TestInteger(CommonMixin, TestCase):
840 def test_invalid_value_type(self):
841 with self.assertRaises(InvalidValueType) as err:
845 @given(sets(text_letters(), min_size=2))
846 def test_unknown_name(self, names_input):
847 missing = names_input.pop()
850 schema = [(n, 123) for n in names_input]
851 with self.assertRaises(ObjUnknown) as err:
855 @given(sets(text_letters(), min_size=2))
856 def test_known_name(self, names_input):
858 schema = [(n, 123) for n in names_input]
859 Int(names_input.pop())
862 def test_optional(self, optional):
863 obj = Integer(default=Integer(0), optional=optional)
864 self.assertTrue(obj.optional)
867 def test_ready(self, value):
869 self.assertFalse(obj.ready)
872 pprint(obj, big_blobs=True, with_decode_path=True)
873 with self.assertRaises(ObjNotReady) as err:
875 with self.assertRaises(ObjNotReady) as err:
879 self.assertTrue(obj.ready)
882 pprint(obj, big_blobs=True, with_decode_path=True)
885 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
886 def test_comparison(self, value1, value2, tag1, tag2):
887 for klass in (Integer, IntegerInherited):
890 self.assertEqual(obj1 == obj2, value1 == value2)
891 self.assertEqual(obj1 != obj2, value1 != value2)
892 self.assertEqual(obj1 == int(obj2), value1 == value2)
893 obj1 = klass(value1, impl=tag1)
894 obj2 = klass(value1, impl=tag2)
895 self.assertEqual(obj1 == obj2, tag1 == tag2)
896 self.assertEqual(obj1 != obj2, tag1 != tag2)
898 @given(lists(integers()))
899 def test_sorted_works(self, values):
900 self.assertSequenceEqual(
901 [int(v) for v in sorted(Integer(v) for v in values)],
905 @given(data_strategy())
906 def test_named(self, d):
907 names_input = list(d.draw(sets(text_letters(), min_size=1)))
908 values_input = list(d.draw(sets(
910 min_size=len(names_input),
911 max_size=len(names_input),
913 chosen_name = d.draw(sampled_from(names_input))
914 names_input = dict(zip(names_input, values_input))
918 _int = Int(chosen_name)
919 self.assertEqual(_int.named, chosen_name)
920 self.assertEqual(int(_int), names_input[chosen_name])
922 @given(integers(), integers(min_value=0), integers(min_value=0))
923 def test_bounds_satisfied(self, bound_min, bound_delta, value_delta):
924 value = bound_min + value_delta
925 bound_max = value + bound_delta
926 Integer(value=value, bounds=(bound_min, bound_max))
928 @given(sets(integers(), min_size=3, max_size=3))
929 def test_bounds_unsatisfied(self, values):
930 values = sorted(values)
931 with self.assertRaises(BoundsError) as err:
932 Integer(value=values[0], bounds=(values[1], values[2]))
934 with assertRaisesRegex(self, DecodeError, "bounds") as err:
935 Integer(bounds=(values[1], values[2])).decode(
936 Integer(values[0]).encode()
939 with assertRaisesRegex(self, DecodeError, "bounds") as err:
940 Integer(bounds=(values[1], values[2])).decode(
941 encode2pass(Integer(values[0]))
943 with self.assertRaises(BoundsError) as err:
944 Integer(value=values[2], bounds=(values[0], values[1]))
946 with assertRaisesRegex(self, DecodeError, "bounds") as err:
947 Integer(bounds=(values[0], values[1])).decode(
948 Integer(values[2]).encode()
951 with assertRaisesRegex(self, DecodeError, "bounds") as err:
952 Integer(bounds=(values[0], values[1])).decode(
953 encode2pass(Integer(values[2]))
956 @given(data_strategy())
957 def test_call(self, d):
958 for klass in (Integer, IntegerInherited):
968 ) = d.draw(integer_values_strategy())
975 optional_initial or False,
988 ) = d.draw(integer_values_strategy(do_expl=impl_initial is None))
989 if (default is None) and (obj_initial.default is not None):
993 (value is not None) and
994 (bounds_initial is not None) and
995 not (bounds_initial[0] <= value <= bounds_initial[1])
1000 (default is not None) and
1001 (bounds_initial is not None) and
1002 not (bounds_initial[0] <= default <= bounds_initial[1])
1005 obj = obj_initial(value, bounds, impl, expl, default, optional)
1007 value_expected = default if value is None else value
1009 default_initial if value_expected is None
1012 self.assertEqual(obj, value_expected)
1013 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1014 self.assertEqual(obj.expl_tag, expl or expl_initial)
1017 default_initial if default is None else default,
1019 if obj.default is None:
1020 optional = optional_initial if optional is None else optional
1021 optional = False if optional is None else optional
1024 self.assertEqual(obj.optional, optional)
1026 (obj._bound_min, obj._bound_max),
1027 bounds or bounds_initial or (float("-inf"), float("+inf")),
1031 {} if _specs_initial is None else dict(_specs_initial),
1034 @given(integer_values_strategy())
1035 def test_copy(self, values):
1036 for klass in (Integer, IntegerInherited):
1037 obj = klass(*values)
1038 for copy_func in copy_funcs:
1039 obj_copied = copy_func(obj)
1040 self.assert_copied_basic_fields(obj, obj_copied)
1041 self.assertEqual(obj.specs, obj_copied.specs)
1042 self.assertEqual(obj._bound_min, obj_copied._bound_min)
1043 self.assertEqual(obj._bound_max, obj_copied._bound_max)
1044 self.assertEqual(obj._value, obj_copied._value)
1048 integers(min_value=1).map(tag_encode),
1050 def test_stripped(self, value, tag_impl):
1051 obj = Integer(value, impl=tag_impl)
1052 with self.assertRaises(NotEnoughData):
1053 obj.decode(obj.encode()[:-1])
1057 integers(min_value=1).map(tag_ctxc),
1059 def test_stripped_expl(self, value, tag_expl):
1060 obj = Integer(value, expl=tag_expl)
1061 with self.assertRaises(NotEnoughData):
1062 obj.decode(obj.encode()[:-1])
1064 def test_zero_len(self):
1065 with self.assertRaises(NotEnoughData):
1066 Integer().decode(b"".join((
1067 Integer.tag_default,
1072 integers(min_value=31),
1073 integers(min_value=0),
1076 def test_bad_tag(self, tag, offset, decode_path):
1077 with self.assertRaises(DecodeError) as err:
1079 tag_encode(tag)[:-1],
1081 decode_path=decode_path,
1084 self.assertEqual(err.exception.offset, offset)
1085 self.assertEqual(err.exception.decode_path, decode_path)
1088 integers(min_value=128),
1089 integers(min_value=0),
1092 def test_bad_len(self, l, offset, decode_path):
1093 with self.assertRaises(DecodeError) as err:
1095 Integer.tag_default + len_encode(l)[:-1],
1097 decode_path=decode_path,
1100 self.assertEqual(err.exception.offset, offset)
1101 self.assertEqual(err.exception.decode_path, decode_path)
1104 sets(integers(), min_size=2, max_size=2),
1105 integers(min_value=0),
1108 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
1109 value, bound_min = list(sorted(ints))
1112 bounds = (bound_min, bound_min)
1113 with self.assertRaises(DecodeError) as err:
1115 Integer(value).encode(),
1117 decode_path=decode_path,
1120 self.assertEqual(err.exception.offset, offset)
1121 self.assertEqual(err.exception.decode_path, decode_path)
1123 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1125 integer_values_strategy(),
1127 integers(min_value=1).map(tag_ctxc),
1128 integers(min_value=0),
1132 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
1133 for klass in (Integer, IntegerInherited):
1134 _, _, _, _, default, optional, _, _decoded = values
1143 pprint(obj, big_blobs=True, with_decode_path=True)
1144 self.assertFalse(obj.expled)
1145 obj_encoded = obj.encode()
1146 self.assertEqual(encode2pass(obj), obj_encoded)
1147 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1148 obj_expled = obj(value, expl=tag_expl)
1149 self.assertTrue(obj_expled.expled)
1151 list(obj_expled.pps())
1152 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1153 obj_expled_encoded = obj_expled.encode()
1154 obj_expled_cer = encode_cer(obj_expled)
1155 self.assertNotEqual(obj_expled_cer, obj_encoded)
1156 self.assertSequenceEqual(
1157 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1160 ctx_copied = deepcopy(ctx_dummy)
1161 obj_decoded, tail = obj_expled.decode(
1162 obj_expled_encoded + tail_junk,
1166 self.assertDictEqual(ctx_copied, ctx_dummy)
1168 list(obj_decoded.pps())
1169 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1170 self.assertEqual(tail, tail_junk)
1171 self.assertEqual(obj_decoded, obj_expled)
1172 self.assertNotEqual(obj_decoded, obj)
1173 self.assertEqual(int(obj_decoded), int(obj_expled))
1174 self.assertEqual(int(obj_decoded), int(obj))
1175 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1176 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1177 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1179 obj_decoded.expl_llen,
1180 len(len_encode(len(obj_encoded))),
1182 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1183 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1186 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1188 self.assertEqual(obj_decoded.expl_offset, offset)
1189 assert_exceeding_data(
1191 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1195 evgens = list(obj_expled.decode_evgen(
1196 obj_expled_encoded + tail_junk,
1198 decode_path=decode_path,
1201 self.assertEqual(len(evgens), 1)
1202 _decode_path, obj, tail = evgens[0]
1203 self.assertSequenceEqual(tail, tail_junk)
1204 self.assertEqual(_decode_path, decode_path)
1205 self.assertEqual(obj, obj_decoded)
1206 self.assertEqual(obj.expl_offset, offset)
1210 def test_go_vectors_valid(self):
1211 for data, expect in ((
1215 (b"\xff\x7f", -129),
1219 (b"\xff\x00", -256),
1223 (b"\x80\x00\x00\x00\x00\x00\x00\x00", -9223372036854775808),
1224 (b"\x80\x00\x00\x00", -2147483648),
1227 Integer().decode(b"".join((
1228 Integer.tag_default,
1229 len_encode(len(data)),
1235 def test_go_vectors_invalid(self):
1240 with self.assertRaises(DecodeError):
1241 Integer().decode(b"".join((
1242 Integer.tag_default,
1243 len_encode(len(data)),
1249 def bit_string_values_strategy(draw, schema=None, value_required=False, do_expl=False):
1252 if draw(booleans()):
1253 schema = draw(sets(text_letters(), min_size=1, max_size=256))
1255 integers(min_value=0, max_value=255),
1256 min_size=len(schema),
1257 max_size=len(schema),
1259 schema = list(zip(schema, bits))
1261 def _value(value_required):
1262 if not value_required and draw(booleans()):
1264 generation_choice = 0
1266 generation_choice = draw(sampled_from((1, 2, 3)))
1267 if generation_choice == 1 or draw(booleans()):
1268 return "'%s'B" % "".join(draw(lists(
1269 sampled_from(("0", "1")),
1270 max_size=len(schema),
1272 if generation_choice == 2 or draw(booleans()):
1273 return draw(binary(max_size=len(schema) // 8))
1274 if generation_choice == 3 or draw(booleans()):
1275 return tuple(draw(lists(sampled_from([name for name, _ in schema]))))
1277 value = _value(value_required)
1278 default = _value(value_required=False)
1282 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1284 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1285 optional = draw(one_of(none(), booleans()))
1287 draw(integers(min_value=0)),
1288 draw(integers(min_value=0)),
1289 draw(integers(min_value=0)),
1291 return (schema, value, impl, expl, default, optional, _decoded)
1294 class BitStringInherited(BitString):
1298 class TestBitString(CommonMixin, TestCase):
1299 base_klass = BitString
1301 @given(lists(booleans()))
1302 def test_b_encoding(self, bits):
1303 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1304 self.assertEqual(obj.bit_len, len(bits))
1305 self.assertSequenceEqual(list(obj), bits)
1306 for i, bit in enumerate(bits):
1307 self.assertEqual(obj[i], bit)
1309 @given(lists(booleans()))
1310 def test_out_of_bounds_bits(self, bits):
1311 obj = BitString("'%s'B" % "".join("1" if bit else "0" for bit in bits))
1312 for i in range(len(bits), len(bits) * 2):
1313 self.assertFalse(obj[i])
1315 def test_bad_b_encoding(self):
1316 with self.assertRaises(ValueError):
1317 BitString("'010120101'B")
1320 integers(min_value=1, max_value=255),
1321 integers(min_value=1, max_value=255),
1323 def test_named_are_stripped(self, leading_zeros, trailing_zeros):
1324 obj = BitString("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1325 self.assertEqual(obj.bit_len, leading_zeros + 1 + trailing_zeros)
1326 self.assertGreater(len(obj.encode()), (leading_zeros + 1 + trailing_zeros) // 8)
1328 class BS(BitString):
1329 schema = (("whatever", 0),)
1330 obj = BS("'%s1%s'B" % (("0" * leading_zeros), ("0" * trailing_zeros)))
1331 self.assertEqual(obj.bit_len, leading_zeros + 1)
1332 self.assertGreater(len(obj.encode()), (leading_zeros + 1) // 8)
1334 def test_zero_len(self):
1335 with self.assertRaises(NotEnoughData):
1336 BitString().decode(b"".join((
1337 BitString.tag_default,
1341 def test_invalid_value_type(self):
1342 with self.assertRaises(InvalidValueType) as err:
1345 with self.assertRaises(InvalidValueType) as err:
1349 def test_obj_unknown(self):
1350 with self.assertRaises(ObjUnknown) as err:
1351 BitString(b"whatever")["whenever"]
1354 def test_get_invalid_type(self):
1355 with self.assertRaises(InvalidValueType) as err:
1356 BitString(b"whatever")[(1, 2, 3)]
1359 @given(data_strategy())
1360 def test_unknown_name(self, d):
1361 _schema = d.draw(sets(text_letters(), min_size=2, max_size=5))
1362 missing = _schema.pop()
1364 class BS(BitString):
1365 schema = [(n, i) for i, n in enumerate(_schema)]
1366 with self.assertRaises(ObjUnknown) as err:
1371 def test_optional(self, optional):
1372 obj = BitString(default=BitString(b""), optional=optional)
1373 self.assertTrue(obj.optional)
1376 def test_ready(self, value):
1378 self.assertFalse(obj.ready)
1381 pprint(obj, big_blobs=True, with_decode_path=True)
1382 with self.assertRaises(ObjNotReady) as err:
1385 with self.assertRaises(ObjNotReady) as err:
1387 obj = BitString(value)
1388 self.assertTrue(obj.ready)
1391 pprint(obj, big_blobs=True, with_decode_path=True)
1394 tuples(integers(min_value=0), binary()),
1395 tuples(integers(min_value=0), binary()),
1399 def test_comparison(self, value1, value2, tag1, tag2):
1400 for klass in (BitString, BitStringInherited):
1401 obj1 = klass(value1)
1402 obj2 = klass(value2)
1403 self.assertEqual(obj1 == obj2, value1 == value2)
1404 self.assertEqual(obj1 != obj2, value1 != value2)
1405 self.assertEqual(obj1 == bytes(obj2), value1[1] == value2[1])
1406 obj1 = klass(value1, impl=tag1)
1407 obj2 = klass(value1, impl=tag2)
1408 self.assertEqual(obj1 == obj2, tag1 == tag2)
1409 self.assertEqual(obj1 != obj2, tag1 != tag2)
1411 @given(data_strategy())
1412 def test_call(self, d):
1413 for klass in (BitString, BitStringInherited):
1422 ) = d.draw(bit_string_values_strategy())
1425 schema = schema_initial
1427 value=value_initial,
1430 default=default_initial,
1431 optional=optional_initial or False,
1432 _decoded=_decoded_initial,
1442 ) = d.draw(bit_string_values_strategy(
1443 schema=schema_initial,
1444 do_expl=impl_initial is None,
1453 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
1454 self.assertEqual(obj.expl_tag, expl or expl_initial)
1455 if obj.default is None:
1456 optional = optional_initial if optional is None else optional
1457 optional = False if optional is None else optional
1460 self.assertEqual(obj.optional, optional)
1461 self.assertEqual(obj.specs, obj_initial.specs)
1463 @given(bit_string_values_strategy())
1464 def test_copy(self, values):
1465 for klass in (BitString, BitStringInherited):
1466 _schema, value, impl, expl, default, optional, _decoded = values
1476 optional=optional or False,
1479 for copy_func in copy_funcs:
1480 obj_copied = copy_func(obj)
1481 self.assert_copied_basic_fields(obj, obj_copied)
1482 self.assertEqual(obj.specs, obj_copied.specs)
1483 self.assertEqual(obj._value, obj_copied._value)
1487 integers(min_value=1).map(tag_encode),
1489 def test_stripped(self, value, tag_impl):
1490 obj = BitString(value, impl=tag_impl)
1491 with self.assertRaises(NotEnoughData):
1492 obj.decode(obj.encode()[:-1])
1496 integers(min_value=1).map(tag_ctxc),
1498 def test_stripped_expl(self, value, tag_expl):
1499 obj = BitString(value, expl=tag_expl)
1500 with self.assertRaises(NotEnoughData):
1501 obj.decode(obj.encode()[:-1])
1504 integers(min_value=31),
1505 integers(min_value=0),
1508 def test_bad_tag(self, tag, offset, decode_path):
1509 with self.assertRaises(DecodeError) as err:
1511 tag_encode(tag)[:-1],
1513 decode_path=decode_path,
1516 self.assertEqual(err.exception.offset, offset)
1517 self.assertEqual(err.exception.decode_path, decode_path)
1520 integers(min_value=128),
1521 integers(min_value=0),
1524 def test_bad_len(self, l, offset, decode_path):
1525 with self.assertRaises(DecodeError) as err:
1527 BitString.tag_default + len_encode(l)[:-1],
1529 decode_path=decode_path,
1532 self.assertEqual(err.exception.offset, offset)
1533 self.assertEqual(err.exception.decode_path, decode_path)
1535 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1536 @given(data_strategy())
1537 def test_symmetric(self, d):
1546 ) = d.draw(bit_string_values_strategy(value_required=True))
1547 tail_junk = d.draw(binary(max_size=5))
1548 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
1549 offset = d.draw(integers(min_value=0))
1550 decode_path = d.draw(decode_path_strat)
1551 for klass in (BitString, BitStringInherited):
1562 pprint(obj, big_blobs=True, with_decode_path=True)
1563 self.assertFalse(obj.expled)
1564 obj_encoded = obj.encode()
1565 self.assertEqual(encode2pass(obj), obj_encoded)
1566 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
1567 obj_expled = obj(value, expl=tag_expl)
1568 self.assertTrue(obj_expled.expled)
1570 list(obj_expled.pps())
1571 pprint(obj_expled, big_blobs=True, with_decode_path=True)
1572 obj_expled_encoded = obj_expled.encode()
1573 obj_expled_cer = encode_cer(obj_expled)
1574 self.assertNotEqual(obj_expled_cer, obj_encoded)
1575 self.assertSequenceEqual(
1576 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
1579 ctx_copied = deepcopy(ctx_dummy)
1580 obj_decoded, tail = obj_expled.decode(
1581 obj_expled_encoded + tail_junk,
1585 self.assertDictEqual(ctx_copied, ctx_dummy)
1587 list(obj_decoded.pps())
1588 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
1589 self.assertEqual(tail, tail_junk)
1590 self.assertEqual(obj_decoded, obj_expled)
1591 self.assertNotEqual(obj_decoded, obj)
1592 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
1593 self.assertEqual(bytes(obj_decoded), bytes(obj))
1594 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
1595 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
1596 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
1598 obj_decoded.expl_llen,
1599 len(len_encode(len(obj_encoded))),
1601 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
1602 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
1605 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
1607 self.assertEqual(obj_decoded.expl_offset, offset)
1608 if isinstance(value, tuple):
1609 self.assertSetEqual(set(value), set(obj_decoded.named))
1612 assert_exceeding_data(
1614 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
1618 evgens = list(obj_expled.decode_evgen(
1619 obj_expled_encoded + tail_junk,
1621 decode_path=decode_path,
1624 self.assertEqual(len(evgens), 1)
1625 _decode_path, obj, tail = evgens[0]
1626 self.assertSequenceEqual(tail, tail_junk)
1627 self.assertEqual(_decode_path, decode_path)
1628 self.assertEqual(obj.expl_offset, offset)
1632 @given(integers(min_value=1, max_value=255))
1633 def test_bad_zero_value(self, pad_size):
1634 with self.assertRaises(DecodeError):
1635 BitString().decode(b"".join((
1636 BitString.tag_default,
1641 def test_go_vectors_invalid(self):
1647 with self.assertRaises(DecodeError):
1648 BitString().decode(b"".join((
1649 BitString.tag_default,
1654 def test_go_vectors_valid(self):
1655 obj, _ = BitString().decode(b"".join((
1656 BitString.tag_default,
1660 self.assertEqual(bytes(obj), b"")
1661 self.assertEqual(obj.bit_len, 0)
1663 obj, _ = BitString().decode(b"".join((
1664 BitString.tag_default,
1668 self.assertEqual(bytes(obj), b"\x00")
1669 self.assertEqual(obj.bit_len, 1)
1671 obj = BitString((16, b"\x82\x40"))
1672 self.assertTrue(obj[0])
1673 self.assertFalse(obj[1])
1674 self.assertTrue(obj[6])
1675 self.assertTrue(obj[9])
1676 self.assertFalse(obj[17])
1678 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1680 integers(min_value=1, max_value=30),
1683 binary(min_size=1, max_size=5),
1685 binary(min_size=1, max_size=5),
1693 lists(booleans(), min_size=1),
1697 def test_constructed(self, impl, chunk_inputs, chunk_last_bits, junk, decode_path):
1698 def chunk_constructed(contents):
1700 tag_encode(form=TagFormConstructed, num=3) +
1702 b"".join(BitString(content).encode() for content in contents) +
1706 chunks_len_expected = []
1707 payload_expected = b""
1708 bit_len_expected = 0
1709 for chunk_input in chunk_inputs:
1710 if isinstance(chunk_input, binary_type):
1711 chunks.append(BitString(chunk_input).encode())
1712 payload_expected += chunk_input
1713 bit_len_expected += len(chunk_input) * 8
1714 chunks_len_expected.append(len(chunk_input) + 1)
1716 chunks.append(chunk_constructed(chunk_input))
1717 payload = b"".join(chunk_input)
1718 payload_expected += payload
1719 bit_len_expected += len(payload) * 8
1720 for c in chunk_input:
1721 chunks_len_expected.append(len(c) + 1)
1722 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
1723 chunk_last = BitString("'%s'B" % "".join(
1724 "1" if bit else "0" for bit in chunk_last_bits
1726 chunks_len_expected.append(BitString().decod(chunk_last.encode()).vlen)
1727 payload_expected += bytes(chunk_last)
1728 bit_len_expected += chunk_last.bit_len
1729 encoded_indefinite = (
1730 tag_encode(form=TagFormConstructed, num=impl) +
1733 chunk_last.encode() +
1736 encoded_definite = (
1737 tag_encode(form=TagFormConstructed, num=impl) +
1738 len_encode(len(b"".join(chunks) + chunk_last.encode())) +
1742 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
1743 BitString(impl=tag_encode(impl)).decode(encoded_indefinite)
1744 for lenindef_expected, encoded in (
1745 (True, encoded_indefinite),
1746 (False, encoded_definite),
1748 obj, tail = BitString(impl=tag_encode(impl)).decode(
1750 ctx={"bered": True},
1752 self.assertSequenceEqual(tail, junk)
1753 self.assertEqual(obj.bit_len, bit_len_expected)
1754 self.assertSequenceEqual(bytes(obj), payload_expected)
1755 self.assertTrue(obj.ber_encoded)
1756 self.assertEqual(obj.lenindef, lenindef_expected)
1757 self.assertTrue(obj.bered)
1759 self.assertTrue(obj.ber_encoded)
1760 self.assertEqual(obj.lenindef, lenindef_expected)
1761 self.assertTrue(obj.bered)
1762 self.assertEqual(len(encoded), obj.tlvlen)
1765 pprint(obj, big_blobs=True, with_decode_path=True)
1767 evgens = list(BitString(impl=tag_encode(impl)).decode_evgen(
1769 decode_path=decode_path,
1770 ctx={"bered": True},
1772 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
1773 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
1774 self.assertGreater(len(dp), len(decode_path))
1775 self.assertEqual(obj.vlen, chunk_len_expected)
1778 integers(min_value=0),
1781 def test_ber_definite_too_short(self, offset, decode_path):
1782 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
1784 tag_encode(3, form=TagFormConstructed) + len_encode(1),
1786 decode_path=decode_path,
1787 ctx={"bered": True},
1789 self.assertEqual(err.exception.decode_path, decode_path)
1790 self.assertEqual(err.exception.offset, offset)
1793 integers(min_value=0),
1796 def test_ber_definite_no_data(self, offset, decode_path):
1797 with assertRaisesRegex(self, DecodeError, "zero length") as err:
1799 tag_encode(3, form=TagFormConstructed) + len_encode(0),
1801 decode_path=decode_path,
1802 ctx={"bered": True},
1804 self.assertEqual(err.exception.decode_path, decode_path)
1805 self.assertEqual(err.exception.offset, offset)
1808 integers(min_value=0),
1810 integers(min_value=1, max_value=3),
1812 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
1813 bs = BitString(b"data").encode()
1814 with self.assertRaises(NotEnoughData) as err:
1816 tag_encode(3, form=TagFormConstructed) + LENINDEF + chunks * bs,
1818 decode_path=decode_path,
1819 ctx={"bered": True},
1821 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1822 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1825 integers(min_value=0),
1827 integers(min_value=1, max_value=3),
1829 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
1830 bs = BitString(b"data").encode()
1831 bs_longer = BitString(b"data-longer").encode()
1832 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
1835 tag_encode(3, form=TagFormConstructed) +
1836 len_encode((chunks + 1) * len(bs)) +
1841 decode_path=decode_path,
1842 ctx={"bered": True},
1844 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
1845 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
1848 integers(min_value=0),
1851 def test_ber_indefinite_no_chunks(self, offset, decode_path):
1852 with assertRaisesRegex(self, DecodeError, "no chunks") as err:
1854 tag_encode(3, form=TagFormConstructed) + LENINDEF + EOC,
1856 decode_path=decode_path,
1857 ctx={"bered": True},
1859 self.assertEqual(err.exception.decode_path, decode_path)
1860 self.assertEqual(err.exception.offset, offset)
1862 @given(data_strategy())
1863 def test_ber_indefinite_not_multiple(self, d):
1864 bs_short = BitString("'A'H").encode()
1865 bs_full = BitString("'AA'H").encode()
1866 chunks = [bs_full for _ in range(d.draw(integers(min_value=0, max_value=3)))]
1867 chunks.append(bs_short)
1868 d.draw(permutations(chunks))
1869 chunks.append(bs_short)
1870 offset = d.draw(integers(min_value=0))
1871 decode_path = d.draw(decode_path_strat)
1872 with assertRaisesRegex(self, DecodeError, "multiple of 8 bits") as err:
1875 tag_encode(3, form=TagFormConstructed) +
1881 decode_path=decode_path,
1882 ctx={"bered": True},
1885 err.exception.decode_path,
1886 decode_path + (str(chunks.index(bs_short)),),
1889 err.exception.offset,
1890 offset + 1 + 1 + chunks.index(bs_short) * len(bs_full),
1893 def test_x690_vector(self):
1894 vector = BitString("'0A3B5F291CD'H")
1895 obj, tail = BitString().decode(hexdec("0307040A3B5F291CD0"))
1896 self.assertSequenceEqual(tail, b"")
1897 self.assertEqual(obj, vector)
1898 obj, tail = BitString().decode(
1899 hexdec("23800303000A3B0305045F291CD00000"),
1900 ctx={"bered": True},
1902 self.assertSequenceEqual(tail, b"")
1903 self.assertEqual(obj, vector)
1904 self.assertTrue(obj.ber_encoded)
1905 self.assertTrue(obj.lenindef)
1906 self.assertTrue(obj.bered)
1908 self.assertTrue(obj.ber_encoded)
1909 self.assertTrue(obj.lenindef)
1910 self.assertTrue(obj.bered)
1912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
1913 @given(integers(min_value=1000, max_value=3000))
1914 def test_cer(self, data_len):
1915 data = urandom(data_len)
1916 encoded = encode_cer(BitString(data))
1917 ctx = {"bered": True}
1918 self.assertSequenceEqual(bytes(BitString().decod(encoded, ctx=ctx)), data)
1919 evgens = list(BitString().decode_evgen(encoded, ctx=ctx))
1920 evgens_expected = data_len // 999
1921 if evgens_expected * 999 != data_len:
1922 evgens_expected += 1
1923 evgens_expected += 1
1924 self.assertEqual(len(evgens), evgens_expected)
1925 for (_, obj, _) in evgens[:-2]:
1926 self.assertEqual(obj.vlen, 1000)
1927 _, obj, _ = evgens[-2]
1928 self.assertEqual(obj.vlen, 1 + data_len - len(evgens[:-2]) * 999)
1932 def octet_string_values_strategy(draw, do_expl=False):
1933 bound_min, bound_max = sorted(draw(sets(
1934 integers(min_value=0, max_value=1 << 7),
1938 value = draw(one_of(
1940 binary(min_size=bound_min, max_size=bound_max),
1942 default = draw(one_of(
1944 binary(min_size=bound_min, max_size=bound_max),
1947 if draw(booleans()):
1948 bounds = (bound_min, bound_max)
1952 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1954 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
1955 optional = draw(one_of(none(), booleans()))
1957 draw(integers(min_value=0)),
1958 draw(integers(min_value=0)),
1959 draw(integers(min_value=0)),
1961 return (value, bounds, impl, expl, default, optional, _decoded)
1964 class OctetStringInherited(OctetString):
1968 class TestOctetString(CommonMixin, TestCase):
1969 base_klass = OctetString
1971 def test_invalid_value_type(self):
1972 with self.assertRaises(InvalidValueType) as err:
1973 OctetString(text_type(123))
1977 def test_optional(self, optional):
1978 obj = OctetString(default=OctetString(b""), optional=optional)
1979 self.assertTrue(obj.optional)
1982 def test_ready(self, value):
1984 self.assertFalse(obj.ready)
1987 pprint(obj, big_blobs=True, with_decode_path=True)
1988 with self.assertRaises(ObjNotReady) as err:
1991 with self.assertRaises(ObjNotReady) as err:
1993 obj = OctetString(value)
1994 self.assertTrue(obj.ready)
1997 pprint(obj, big_blobs=True, with_decode_path=True)
1999 @given(binary(), binary(), binary(min_size=1), binary(min_size=1))
2000 def test_comparison(self, value1, value2, tag1, tag2):
2001 for klass in (OctetString, OctetStringInherited):
2002 obj1 = klass(value1)
2003 obj2 = klass(value2)
2004 self.assertEqual(obj1 == obj2, value1 == value2)
2005 self.assertEqual(obj1 != obj2, value1 != value2)
2006 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
2007 obj1 = klass(value1, impl=tag1)
2008 obj2 = klass(value1, impl=tag2)
2009 self.assertEqual(obj1 == obj2, tag1 == tag2)
2010 self.assertEqual(obj1 != obj2, tag1 != tag2)
2012 @given(lists(binary()))
2013 def test_sorted_works(self, values):
2014 self.assertSequenceEqual(
2015 [bytes(v) for v in sorted(OctetString(v) for v in values)],
2019 @given(data_strategy())
2020 def test_bounds_satisfied(self, d):
2021 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
2022 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2023 value = d.draw(binary(min_size=bound_min, max_size=bound_max))
2024 OctetString(value=value, bounds=(bound_min, bound_max))
2026 @given(data_strategy())
2027 def test_bounds_unsatisfied(self, d):
2028 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
2029 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
2030 value = d.draw(binary(max_size=bound_min - 1))
2031 with self.assertRaises(BoundsError) as err:
2032 OctetString(value=value, bounds=(bound_min, bound_max))
2034 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2035 OctetString(bounds=(bound_min, bound_max)).decode(
2036 OctetString(value).encode()
2039 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2040 OctetString(bounds=(bound_min, bound_max)).decode(
2041 encode2pass(OctetString(value))
2043 value = d.draw(binary(min_size=bound_max + 1))
2044 with self.assertRaises(BoundsError) as err:
2045 OctetString(value=value, bounds=(bound_min, bound_max))
2047 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2048 OctetString(bounds=(bound_min, bound_max)).decode(
2049 OctetString(value).encode()
2052 with assertRaisesRegex(self, DecodeError, "bounds") as err:
2053 OctetString(bounds=(bound_min, bound_max)).decode(
2054 encode2pass(OctetString(value))
2057 @given(data_strategy())
2058 def test_call(self, d):
2059 for klass in (OctetString, OctetStringInherited):
2068 ) = d.draw(octet_string_values_strategy())
2069 obj_initial = klass(
2075 optional_initial or False,
2086 ) = d.draw(octet_string_values_strategy(do_expl=impl_initial is None))
2087 if (default is None) and (obj_initial.default is not None):
2090 (bounds is None) and
2091 (value is not None) and
2092 (bounds_initial is not None) and
2093 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
2097 (bounds is None) and
2098 (default is not None) and
2099 (bounds_initial is not None) and
2100 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
2103 obj = obj_initial(value, bounds, impl, expl, default, optional)
2105 value_expected = default if value is None else value
2107 default_initial if value_expected is None
2110 self.assertEqual(obj, value_expected)
2111 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2112 self.assertEqual(obj.expl_tag, expl or expl_initial)
2115 default_initial if default is None else default,
2117 if obj.default is None:
2118 optional = optional_initial if optional is None else optional
2119 optional = False if optional is None else optional
2122 self.assertEqual(obj.optional, optional)
2124 (obj._bound_min, obj._bound_max),
2125 bounds or bounds_initial or (0, float("+inf")),
2128 @given(octet_string_values_strategy())
2129 def test_copy(self, values):
2130 for klass in (OctetString, OctetStringInherited):
2131 obj = klass(*values)
2132 for copy_func in copy_funcs:
2133 obj_copied = copy_func(obj)
2134 self.assert_copied_basic_fields(obj, obj_copied)
2135 self.assertEqual(obj._bound_min, obj_copied._bound_min)
2136 self.assertEqual(obj._bound_max, obj_copied._bound_max)
2137 self.assertEqual(obj._value, obj_copied._value)
2141 integers(min_value=1).map(tag_encode),
2143 def test_stripped(self, value, tag_impl):
2144 obj = OctetString(value, impl=tag_impl)
2145 with self.assertRaises(NotEnoughData):
2146 obj.decode(obj.encode()[:-1])
2150 integers(min_value=1).map(tag_ctxc),
2152 def test_stripped_expl(self, value, tag_expl):
2153 obj = OctetString(value, expl=tag_expl)
2154 with self.assertRaises(NotEnoughData):
2155 obj.decode(obj.encode()[:-1])
2158 integers(min_value=31),
2159 integers(min_value=0),
2162 def test_bad_tag(self, tag, offset, decode_path):
2163 with self.assertRaises(DecodeError) as err:
2164 OctetString().decode(
2165 tag_encode(tag)[:-1],
2167 decode_path=decode_path,
2170 self.assertEqual(err.exception.offset, offset)
2171 self.assertEqual(err.exception.decode_path, decode_path)
2174 integers(min_value=128),
2175 integers(min_value=0),
2178 def test_bad_len(self, l, offset, decode_path):
2179 with self.assertRaises(DecodeError) as err:
2180 OctetString().decode(
2181 OctetString.tag_default + len_encode(l)[:-1],
2183 decode_path=decode_path,
2186 self.assertEqual(err.exception.offset, offset)
2187 self.assertEqual(err.exception.decode_path, decode_path)
2190 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
2191 integers(min_value=0),
2194 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
2195 value, bound_min = list(sorted(ints))
2197 class String(OctetString):
2198 bounds = (bound_min, bound_min)
2199 with self.assertRaises(DecodeError) as err:
2201 OctetString(b"\x00" * value).encode(),
2203 decode_path=decode_path,
2206 self.assertEqual(err.exception.offset, offset)
2207 self.assertEqual(err.exception.decode_path, decode_path)
2209 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2211 octet_string_values_strategy(),
2213 integers(min_value=1).map(tag_ctxc),
2214 integers(min_value=0),
2218 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2219 for klass in (OctetString, OctetStringInherited):
2220 _, _, _, _, default, optional, _decoded = values
2229 pprint(obj, big_blobs=True, with_decode_path=True)
2230 self.assertFalse(obj.expled)
2231 obj_encoded = obj.encode()
2232 self.assertEqual(encode2pass(obj), obj_encoded)
2233 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2234 obj_expled = obj(value, expl=tag_expl)
2235 self.assertTrue(obj_expled.expled)
2237 list(obj_expled.pps())
2238 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2239 obj_expled_encoded = obj_expled.encode()
2240 obj_expled_cer = encode_cer(obj_expled)
2241 self.assertNotEqual(obj_expled_cer, obj_encoded)
2242 self.assertSequenceEqual(
2243 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2246 ctx_copied = deepcopy(ctx_dummy)
2247 obj_decoded, tail = obj_expled.decode(
2248 obj_expled_encoded + tail_junk,
2252 self.assertDictEqual(ctx_copied, ctx_dummy)
2254 list(obj_decoded.pps())
2255 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2256 self.assertEqual(tail, tail_junk)
2257 self.assertEqual(obj_decoded, obj_expled)
2258 self.assertNotEqual(obj_decoded, obj)
2259 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
2260 self.assertEqual(bytes(obj_decoded), bytes(obj))
2261 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2262 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2263 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2265 obj_decoded.expl_llen,
2266 len(len_encode(len(obj_encoded))),
2268 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2269 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2272 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2274 self.assertEqual(obj_decoded.expl_offset, offset)
2275 assert_exceeding_data(
2277 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2281 evgens = list(obj_expled.decode_evgen(
2282 obj_expled_encoded + tail_junk,
2284 decode_path=decode_path,
2287 self.assertEqual(len(evgens), 1)
2288 _decode_path, obj, tail = evgens[0]
2289 self.assertSequenceEqual(tail, tail_junk)
2290 self.assertEqual(_decode_path, decode_path)
2291 self.assertEqual(obj.expl_offset, offset)
2295 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2297 integers(min_value=1, max_value=30),
2300 binary(min_size=1, max_size=5),
2302 binary(min_size=1, max_size=5),
2313 def test_constructed(self, impl, chunk_inputs, junk, decode_path):
2314 def chunk_constructed(contents):
2316 tag_encode(form=TagFormConstructed, num=4) +
2318 b"".join(OctetString(content).encode() for content in contents) +
2322 chunks_len_expected = []
2323 payload_expected = b""
2324 for chunk_input in chunk_inputs:
2325 if isinstance(chunk_input, binary_type):
2326 chunks.append(OctetString(chunk_input).encode())
2327 payload_expected += chunk_input
2328 chunks_len_expected.append(len(chunk_input))
2330 chunks.append(chunk_constructed(chunk_input))
2331 payload = b"".join(chunk_input)
2332 payload_expected += payload
2333 for c in chunk_input:
2334 chunks_len_expected.append(len(c))
2335 chunks_len_expected.append(len(chunks[-1]) - 1 - 1)
2336 encoded_indefinite = (
2337 tag_encode(form=TagFormConstructed, num=impl) +
2342 encoded_definite = (
2343 tag_encode(form=TagFormConstructed, num=impl) +
2344 len_encode(len(b"".join(chunks))) +
2347 with assertRaisesRegex(self, DecodeError, "unallowed BER"):
2348 OctetString(impl=tag_encode(impl)).decode(encoded_indefinite)
2349 for lenindef_expected, encoded in (
2350 (True, encoded_indefinite),
2351 (False, encoded_definite),
2353 obj, tail = OctetString(impl=tag_encode(impl)).decode(
2355 ctx={"bered": True},
2357 self.assertSequenceEqual(tail, junk)
2358 self.assertSequenceEqual(bytes(obj), payload_expected)
2359 self.assertTrue(obj.ber_encoded)
2360 self.assertEqual(obj.lenindef, lenindef_expected)
2361 self.assertTrue(obj.bered)
2363 self.assertTrue(obj.ber_encoded)
2364 self.assertEqual(obj.lenindef, lenindef_expected)
2365 self.assertTrue(obj.bered)
2366 self.assertEqual(len(encoded), obj.tlvlen)
2369 pprint(obj, big_blobs=True, with_decode_path=True)
2371 evgens = list(OctetString(impl=tag_encode(impl)).decode_evgen(
2373 decode_path=decode_path,
2374 ctx={"bered": True},
2376 self.assertEqual(len(evgens), len(chunks_len_expected) + 1)
2377 for chunk_len_expected, (dp, obj, _) in zip(chunks_len_expected, evgens):
2378 self.assertGreater(len(dp), len(decode_path))
2379 self.assertEqual(obj.vlen, chunk_len_expected)
2382 integers(min_value=0),
2385 def test_ber_definite_too_short(self, offset, decode_path):
2386 with assertRaisesRegex(self, DecodeError, "longer than data") as err:
2387 OctetString().decode(
2388 tag_encode(4, form=TagFormConstructed) + len_encode(1),
2390 decode_path=decode_path,
2391 ctx={"bered": True},
2393 self.assertEqual(err.exception.decode_path, decode_path)
2394 self.assertEqual(err.exception.offset, offset)
2397 integers(min_value=0),
2399 integers(min_value=1, max_value=3),
2401 def test_ber_indefinite_no_eoc(self, offset, decode_path, chunks):
2402 bs = OctetString(b"data").encode()
2403 with self.assertRaises(NotEnoughData) as err:
2404 OctetString().decode(
2405 tag_encode(4, form=TagFormConstructed) + LENINDEF + chunks * bs,
2407 decode_path=decode_path,
2408 ctx={"bered": True},
2410 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2411 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2414 integers(min_value=0),
2416 integers(min_value=1, max_value=3),
2418 def test_ber_definite_chunk_out_of_bounds(self, offset, decode_path, chunks):
2419 bs = OctetString(b"data").encode()
2420 bs_longer = OctetString(b"data-longer").encode()
2421 with assertRaisesRegex(self, DecodeError, "chunk out of bounds") as err:
2422 OctetString().decode(
2424 tag_encode(4, form=TagFormConstructed) +
2425 len_encode((chunks + 1) * len(bs)) +
2430 decode_path=decode_path,
2431 ctx={"bered": True},
2433 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
2434 self.assertEqual(err.exception.offset, offset + 1 + 1 + chunks * len(bs))
2436 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2437 @given(integers(min_value=1001, max_value=3000))
2438 def test_cer(self, data_len):
2439 data = urandom(data_len)
2440 encoded = encode_cer(OctetString(data))
2441 ctx = {"bered": True}
2442 self.assertSequenceEqual(bytes(OctetString().decod(encoded, ctx=ctx)), data)
2443 evgens = list(OctetString().decode_evgen(encoded, ctx=ctx))
2444 evgens_expected = data_len // 1000
2445 if evgens_expected * 1000 != data_len:
2446 evgens_expected += 1
2447 evgens_expected += 1
2448 self.assertEqual(len(evgens), evgens_expected)
2449 for (_, obj, _) in evgens[:-2]:
2450 self.assertEqual(obj.vlen, 1000)
2451 _, obj, _ = evgens[-2]
2452 self.assertEqual(obj.vlen, data_len - len(evgens[:-2]) * 1000)
2456 def null_values_strategy(draw, do_expl=False):
2460 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2462 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2463 optional = draw(one_of(none(), booleans()))
2465 draw(integers(min_value=0)),
2466 draw(integers(min_value=0)),
2467 draw(integers(min_value=0)),
2469 return (impl, expl, optional, _decoded)
2472 class NullInherited(Null):
2476 class TestNull(CommonMixin, TestCase):
2479 def test_ready(self):
2481 self.assertTrue(obj.ready)
2484 pprint(obj, big_blobs=True, with_decode_path=True)
2486 @given(binary(min_size=1), binary(min_size=1))
2487 def test_comparison(self, tag1, tag2):
2488 for klass in (Null, NullInherited):
2489 obj1 = klass(impl=tag1)
2490 obj2 = klass(impl=tag2)
2491 self.assertEqual(obj1 == obj2, tag1 == tag2)
2492 self.assertEqual(obj1 != obj2, tag1 != tag2)
2493 self.assertNotEqual(obj1, tag2)
2495 @given(data_strategy())
2496 def test_call(self, d):
2497 for klass in (Null, NullInherited):
2503 ) = d.draw(null_values_strategy())
2504 obj_initial = klass(
2507 optional=optional_initial or False,
2508 _decoded=_decoded_initial,
2515 ) = d.draw(null_values_strategy(do_expl=impl_initial is None))
2516 obj = obj_initial(impl=impl, expl=expl, optional=optional)
2517 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2518 self.assertEqual(obj.expl_tag, expl or expl_initial)
2519 optional = optional_initial if optional is None else optional
2520 optional = False if optional is None else optional
2521 self.assertEqual(obj.optional, optional)
2523 @given(null_values_strategy())
2524 def test_copy(self, values):
2525 for klass in (Null, NullInherited):
2526 impl, expl, optional, _decoded = values
2530 optional=optional or False,
2533 for copy_func in copy_funcs:
2534 obj_copied = copy_func(obj)
2535 self.assert_copied_basic_fields(obj, obj_copied)
2537 @given(integers(min_value=1).map(tag_encode))
2538 def test_stripped(self, tag_impl):
2539 obj = Null(impl=tag_impl)
2540 with self.assertRaises(NotEnoughData):
2541 obj.decode(obj.encode()[:-1])
2543 @given(integers(min_value=1).map(tag_ctxc))
2544 def test_stripped_expl(self, tag_expl):
2545 obj = Null(expl=tag_expl)
2546 with self.assertRaises(NotEnoughData):
2547 obj.decode(obj.encode()[:-1])
2550 integers(min_value=31),
2551 integers(min_value=0),
2554 def test_bad_tag(self, tag, offset, decode_path):
2555 with self.assertRaises(DecodeError) as err:
2557 tag_encode(tag)[:-1],
2559 decode_path=decode_path,
2562 self.assertEqual(err.exception.offset, offset)
2563 self.assertEqual(err.exception.decode_path, decode_path)
2566 integers(min_value=128),
2567 integers(min_value=0),
2570 def test_bad_len(self, l, offset, decode_path):
2571 with self.assertRaises(DecodeError) as err:
2573 Null.tag_default + len_encode(l)[:-1],
2575 decode_path=decode_path,
2578 self.assertEqual(err.exception.offset, offset)
2579 self.assertEqual(err.exception.decode_path, decode_path)
2581 @given(binary(min_size=1))
2582 def test_tag_mismatch(self, impl):
2583 assume(impl != Null.tag_default)
2584 with self.assertRaises(TagMismatch):
2585 Null(impl=impl).decode(Null().encode())
2588 null_values_strategy(),
2589 integers(min_value=1).map(tag_ctxc),
2590 integers(min_value=0),
2594 def test_symmetric(self, values, tag_expl, offset, tail_junk, decode_path):
2595 for klass in (Null, NullInherited):
2596 _, _, optional, _decoded = values
2597 obj = klass(optional=optional, _decoded=_decoded)
2600 pprint(obj, big_blobs=True, with_decode_path=True)
2601 self.assertFalse(obj.expled)
2602 obj_encoded = obj.encode()
2603 self.assertEqual(encode2pass(obj), obj_encoded)
2604 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2605 obj_expled = obj(expl=tag_expl)
2606 self.assertTrue(obj_expled.expled)
2608 list(obj_expled.pps())
2609 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2610 obj_expled_encoded = obj_expled.encode()
2611 obj_expled_cer = encode_cer(obj_expled)
2612 self.assertNotEqual(obj_expled_cer, obj_encoded)
2613 self.assertSequenceEqual(
2614 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2617 ctx_copied = deepcopy(ctx_dummy)
2618 obj_decoded, tail = obj_expled.decode(
2619 obj_expled_encoded + tail_junk,
2623 self.assertDictEqual(ctx_copied, ctx_dummy)
2625 list(obj_decoded.pps())
2626 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2627 self.assertEqual(tail, tail_junk)
2628 self.assertEqual(obj_decoded, obj_expled)
2629 self.assertNotEqual(obj_decoded, obj)
2630 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
2631 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
2632 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
2634 obj_decoded.expl_llen,
2635 len(len_encode(len(obj_encoded))),
2637 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
2638 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
2641 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
2643 self.assertEqual(obj_decoded.expl_offset, offset)
2644 assert_exceeding_data(
2646 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
2650 evgens = list(obj_expled.decode_evgen(
2651 obj_expled_encoded + tail_junk,
2653 decode_path=decode_path,
2656 self.assertEqual(len(evgens), 1)
2657 _decode_path, obj, tail = evgens[0]
2658 self.assertSequenceEqual(tail, tail_junk)
2659 self.assertEqual(_decode_path, decode_path)
2660 self.assertEqual(obj, obj_decoded)
2661 self.assertEqual(obj.expl_offset, offset)
2665 @given(integers(min_value=1))
2666 def test_invalid_len(self, l):
2667 with self.assertRaises(InvalidLength):
2668 Null().decode(b"".join((
2675 def oid_strategy(draw):
2676 first_arc = draw(integers(min_value=0, max_value=2))
2678 if first_arc in (0, 1):
2679 second_arc = draw(integers(min_value=0, max_value=39))
2681 second_arc = draw(integers(min_value=0))
2682 other_arcs = draw(lists(integers(min_value=0)))
2683 return tuple([first_arc, second_arc] + other_arcs)
2687 def oid_values_strategy(draw, do_expl=False):
2688 value = draw(one_of(none(), oid_strategy()))
2692 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2694 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
2695 default = draw(one_of(none(), oid_strategy()))
2696 optional = draw(one_of(none(), booleans()))
2698 draw(integers(min_value=0)),
2699 draw(integers(min_value=0)),
2700 draw(integers(min_value=0)),
2702 return (value, impl, expl, default, optional, _decoded)
2705 class ObjectIdentifierInherited(ObjectIdentifier):
2709 class TestObjectIdentifier(CommonMixin, TestCase):
2710 base_klass = ObjectIdentifier
2712 def test_invalid_value_type(self):
2713 with self.assertRaises(InvalidValueType) as err:
2714 ObjectIdentifier(123)
2718 def test_optional(self, optional):
2719 obj = ObjectIdentifier(default=ObjectIdentifier("1.2.3"), optional=optional)
2720 self.assertTrue(obj.optional)
2722 @given(oid_strategy())
2723 def test_ready(self, value):
2724 obj = ObjectIdentifier()
2725 self.assertFalse(obj.ready)
2728 pprint(obj, big_blobs=True, with_decode_path=True)
2729 with self.assertRaises(ObjNotReady) as err:
2732 with self.assertRaises(ObjNotReady) as err:
2734 obj = ObjectIdentifier(value)
2735 self.assertTrue(obj.ready)
2736 self.assertFalse(obj.ber_encoded)
2739 pprint(obj, big_blobs=True, with_decode_path=True)
2742 @given(oid_strategy(), oid_strategy(), binary(min_size=1), binary(min_size=1))
2743 def test_comparison(self, value1, value2, tag1, tag2):
2744 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2745 obj1 = klass(value1)
2746 obj2 = klass(value2)
2747 self.assertEqual(obj1 == obj2, value1 == value2)
2748 self.assertEqual(obj1 != obj2, value1 != value2)
2749 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
2750 self.assertEqual(str(obj1) == str(obj2), value1 == value2)
2751 obj1 = klass(value1, impl=tag1)
2752 obj2 = klass(value1, impl=tag2)
2753 self.assertEqual(obj1 == obj2, tag1 == tag2)
2754 self.assertEqual(obj1 != obj2, tag1 != tag2)
2756 @given(lists(oid_strategy()))
2757 def test_sorted_works(self, values):
2758 self.assertSequenceEqual(
2759 [tuple(v) for v in sorted(ObjectIdentifier(v) for v in values)],
2763 @given(data_strategy())
2764 def test_call(self, d):
2765 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2773 ) = d.draw(oid_values_strategy())
2774 obj_initial = klass(
2775 value=value_initial,
2778 default=default_initial,
2779 optional=optional_initial or False,
2780 _decoded=_decoded_initial,
2789 ) = d.draw(oid_values_strategy(do_expl=impl_initial is None))
2798 value_expected = default if value is None else value
2800 default_initial if value_expected is None
2803 self.assertEqual(obj, value_expected)
2804 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
2805 self.assertEqual(obj.expl_tag, expl or expl_initial)
2808 default_initial if default is None else default,
2810 if obj.default is None:
2811 optional = optional_initial if optional is None else optional
2812 optional = False if optional is None else optional
2815 self.assertEqual(obj.optional, optional)
2817 @given(oid_values_strategy())
2818 def test_copy(self, values):
2819 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2836 for copy_func in copy_funcs:
2837 obj_copied = copy_func(obj)
2838 self.assert_copied_basic_fields(obj, obj_copied)
2839 self.assertEqual(obj._value, obj_copied._value)
2841 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2844 integers(min_value=1).map(tag_encode),
2846 def test_stripped(self, value, tag_impl):
2847 obj = ObjectIdentifier(value, impl=tag_impl)
2848 with self.assertRaises(NotEnoughData):
2849 obj.decode(obj.encode()[:-1])
2853 integers(min_value=1).map(tag_ctxc),
2855 def test_stripped_expl(self, value, tag_expl):
2856 obj = ObjectIdentifier(value, expl=tag_expl)
2857 with self.assertRaises(NotEnoughData):
2858 obj.decode(obj.encode()[:-1])
2861 integers(min_value=31),
2862 integers(min_value=0),
2865 def test_bad_tag(self, tag, offset, decode_path):
2866 with self.assertRaises(DecodeError) as err:
2867 ObjectIdentifier().decode(
2868 tag_encode(tag)[:-1],
2870 decode_path=decode_path,
2873 self.assertEqual(err.exception.offset, offset)
2874 self.assertEqual(err.exception.decode_path, decode_path)
2877 integers(min_value=128),
2878 integers(min_value=0),
2881 def test_bad_len(self, l, offset, decode_path):
2882 with self.assertRaises(DecodeError) as err:
2883 ObjectIdentifier().decode(
2884 ObjectIdentifier.tag_default + len_encode(l)[:-1],
2886 decode_path=decode_path,
2889 self.assertEqual(err.exception.offset, offset)
2890 self.assertEqual(err.exception.decode_path, decode_path)
2892 def test_zero_oid(self):
2893 with self.assertRaises(NotEnoughData):
2894 ObjectIdentifier().decode(
2895 b"".join((ObjectIdentifier.tag_default, len_encode(0)))
2898 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2899 @given(oid_strategy())
2900 def test_unfinished_oid(self, value):
2901 assume(list(value)[-1] > 255)
2902 obj_encoded = ObjectIdentifier(value).encode()
2903 obj, _ = ObjectIdentifier().decode(obj_encoded)
2904 data = obj_encoded[obj.tlen + obj.llen:-1]
2906 ObjectIdentifier.tag_default,
2907 len_encode(len(data)),
2910 with assertRaisesRegex(self, DecodeError, "unfinished OID"):
2913 @given(integers(min_value=0))
2914 def test_invalid_short(self, value):
2915 with self.assertRaises(InvalidOID):
2916 ObjectIdentifier((value,))
2917 with self.assertRaises(InvalidOID):
2918 ObjectIdentifier("%d" % value)
2920 @given(integers(min_value=3), integers(min_value=0))
2921 def test_invalid_first_arc(self, first_arc, second_arc):
2922 with self.assertRaises(InvalidOID):
2923 ObjectIdentifier((first_arc, second_arc))
2924 with self.assertRaises(InvalidOID):
2925 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2927 @given(integers(min_value=0, max_value=1), integers(min_value=40))
2928 def test_invalid_second_arc(self, first_arc, second_arc):
2929 with self.assertRaises(InvalidOID):
2930 ObjectIdentifier((first_arc, second_arc))
2931 with self.assertRaises(InvalidOID):
2932 ObjectIdentifier("%d.%d" % (first_arc, second_arc))
2934 @given(text(alphabet=ascii_letters + ".", min_size=1))
2935 def test_junk(self, oid):
2936 with self.assertRaises(InvalidOID):
2937 ObjectIdentifier(oid)
2939 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2940 @given(oid_strategy())
2941 def test_validness(self, oid):
2942 obj = ObjectIdentifier(oid)
2943 self.assertEqual(obj, ObjectIdentifier(".".join(str(arc) for arc in oid)))
2946 pprint(obj, big_blobs=True, with_decode_path=True)
2948 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
2950 oid_values_strategy(),
2952 integers(min_value=1).map(tag_ctxc),
2953 integers(min_value=0),
2957 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
2958 for klass in (ObjectIdentifier, ObjectIdentifierInherited):
2959 _, _, _, default, optional, _decoded = values
2968 pprint(obj, big_blobs=True, with_decode_path=True)
2969 self.assertFalse(obj.expled)
2970 obj_encoded = obj.encode()
2971 self.assertEqual(encode2pass(obj), obj_encoded)
2972 self.assertSequenceEqual(encode_cer(obj), obj_encoded)
2973 obj_expled = obj(value, expl=tag_expl)
2974 self.assertTrue(obj_expled.expled)
2976 list(obj_expled.pps())
2977 pprint(obj_expled, big_blobs=True, with_decode_path=True)
2978 obj_expled_encoded = obj_expled.encode()
2979 obj_expled_cer = encode_cer(obj_expled)
2980 self.assertNotEqual(obj_expled_cer, obj_encoded)
2981 self.assertSequenceEqual(
2982 obj_expled.decod(obj_expled_cer, ctx={"bered": True}).encode(),
2985 ctx_copied = deepcopy(ctx_dummy)
2986 obj_decoded, tail = obj_expled.decode(
2987 obj_expled_encoded + tail_junk,
2991 self.assertDictEqual(ctx_copied, ctx_dummy)
2993 list(obj_decoded.pps())
2994 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
2995 self.assertEqual(tail, tail_junk)
2996 self.assertEqual(obj_decoded, obj_expled)
2997 self.assertNotEqual(obj_decoded, obj)
2998 self.assertEqual(tuple(obj_decoded), tuple(obj_expled))
2999 self.assertEqual(tuple(obj_decoded), tuple(obj))
3000 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3001 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3002 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3004 obj_decoded.expl_llen,
3005 len(len_encode(len(obj_encoded))),
3007 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3008 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3011 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3013 self.assertEqual(obj_decoded.expl_offset, offset)
3014 assert_exceeding_data(
3016 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3020 evgens = list(obj_expled.decode_evgen(
3021 obj_expled_encoded + tail_junk,
3023 decode_path=decode_path,
3026 self.assertEqual(len(evgens), 1)
3027 _decode_path, obj, tail = evgens[0]
3028 self.assertSequenceEqual(tail, tail_junk)
3029 self.assertEqual(_decode_path, decode_path)
3030 self.assertEqual(obj, obj_decoded)
3031 self.assertEqual(obj.expl_offset, offset)
3036 oid_strategy().map(ObjectIdentifier),
3037 oid_strategy().map(ObjectIdentifier),
3039 def test_add(self, oid1, oid2):
3040 oid_expect = ObjectIdentifier(str(oid1) + "." + str(oid2))
3041 for oid_to_add in (oid2, tuple(oid2)):
3042 self.assertEqual(oid1 + oid_to_add, oid_expect)
3043 with self.assertRaises(InvalidValueType):
3046 def test_go_vectors_valid(self):
3047 for data, expect in (
3049 (b"\x55\x02", (2, 5, 2)),
3050 (b"\x55\x02\xc0\x00", (2, 5, 2, 8192)),
3051 (b"\x81\x34\x03", (2, 100, 3)),
3054 ObjectIdentifier().decode(b"".join((
3055 ObjectIdentifier.tag_default,
3056 len_encode(len(data)),
3062 def test_go_vectors_invalid(self):
3063 data = b"\x55\x02\xc0\x80\x80\x80\x80"
3064 with self.assertRaises(DecodeError):
3065 ObjectIdentifier().decode(b"".join((
3066 Integer.tag_default,
3067 len_encode(len(data)),
3071 def test_x690_vector(self):
3073 ObjectIdentifier().decode(hexdec("0603883703"))[0],
3074 ObjectIdentifier((2, 999, 3)),
3077 def test_nonnormalized_first_arc(self):
3079 ObjectIdentifier.tag_default +
3082 ObjectIdentifier((1, 0)).encode()[-1:]
3084 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3085 self.assertTrue(obj.ber_encoded)
3086 self.assertTrue(obj.bered)
3088 self.assertTrue(obj.ber_encoded)
3089 self.assertTrue(obj.bered)
3090 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3091 ObjectIdentifier().decode(tampered)
3093 @given(data_strategy())
3094 def test_negative_arcs(self, d):
3095 oid = list(d.draw(oid_strategy()))
3098 idx = d.draw(integers(min_value=3, max_value=len(oid)))
3100 if oid[idx - 1] == 0:
3102 with self.assertRaises(InvalidOID):
3103 ObjectIdentifier(tuple(oid))
3104 with self.assertRaises(InvalidOID):
3105 ObjectIdentifier(".".join(str(i) for i in oid))
3107 @given(data_strategy())
3108 def test_plused_arcs(self, d):
3109 oid = [str(arc) for arc in d.draw(oid_strategy())]
3110 idx = d.draw(integers(min_value=0, max_value=len(oid)))
3111 oid[idx - 1] = "+" + oid[idx - 1]
3112 with self.assertRaises(InvalidOID):
3113 ObjectIdentifier(".".join(str(i) for i in oid))
3115 @given(data_strategy())
3116 def test_nonnormalized_arcs(self, d):
3117 arcs = d.draw(lists(
3118 integers(min_value=0, max_value=100),
3122 dered = ObjectIdentifier((1, 0) + tuple(arcs)).encode()
3123 _, _, lv = tag_strip(dered)
3124 _, _, v = len_decode(lv)
3125 v_no_first_arc = v[1:]
3126 idx_for_tamper = d.draw(integers(
3128 max_value=len(v_no_first_arc) - 1,
3130 tampered = list(bytearray(v_no_first_arc))
3131 for _ in range(d.draw(integers(min_value=1, max_value=3))):
3132 tampered.insert(idx_for_tamper, 0x80)
3133 tampered = bytes(bytearray(tampered))
3135 ObjectIdentifier.tag_default +
3136 len_encode(len(tampered)) +
3139 obj, _ = ObjectIdentifier().decode(tampered, ctx={"bered": True})
3140 self.assertTrue(obj.ber_encoded)
3141 self.assertTrue(obj.bered)
3143 self.assertTrue(obj.ber_encoded)
3144 self.assertTrue(obj.bered)
3145 with assertRaisesRegex(self, DecodeError, "non normalized arc encoding"):
3146 ObjectIdentifier().decode(tampered)
3150 def enumerated_values_strategy(draw, schema=None, do_expl=False):
3152 schema = list(draw(sets(text_printable, min_size=1, max_size=3)))
3153 values = list(draw(sets(
3155 min_size=len(schema),
3156 max_size=len(schema),
3158 schema = list(zip(schema, values))
3159 value = draw(one_of(none(), sampled_from([k for k, v in schema])))
3163 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3165 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3166 default = draw(one_of(none(), sampled_from([v for k, v in schema])))
3167 optional = draw(one_of(none(), booleans()))
3169 draw(integers(min_value=0)),
3170 draw(integers(min_value=0)),
3171 draw(integers(min_value=0)),
3173 return (schema, value, impl, expl, default, optional, _decoded)
3176 class TestEnumerated(CommonMixin, TestCase):
3177 class EWhatever(Enumerated):
3178 schema = (("whatever", 0),)
3180 base_klass = EWhatever
3182 def test_schema_required(self):
3183 with assertRaisesRegex(self, ValueError, "schema must be specified"):
3186 def test_invalid_value_type(self):
3187 with self.assertRaises(InvalidValueType) as err:
3188 self.base_klass((1, 2))
3191 @given(sets(text_letters(), min_size=2))
3192 def test_unknown_name(self, schema_input):
3193 missing = schema_input.pop()
3195 class E(Enumerated):
3196 schema = [(n, 123) for n in schema_input]
3197 with self.assertRaises(ObjUnknown) as err:
3202 sets(text_letters(), min_size=2),
3203 sets(integers(), min_size=2),
3205 def test_unknown_value(self, schema_input, values_input):
3207 missing_value = values_input.pop()
3208 _input = list(zip(schema_input, values_input))
3210 class E(Enumerated):
3212 with self.assertRaises(DecodeError) as err:
3217 def test_optional(self, optional):
3218 obj = self.base_klass(default="whatever", optional=optional)
3219 self.assertTrue(obj.optional)
3221 def test_ready(self):
3222 obj = self.base_klass()
3223 self.assertFalse(obj.ready)
3226 pprint(obj, big_blobs=True, with_decode_path=True)
3227 with self.assertRaises(ObjNotReady) as err:
3230 obj = self.base_klass("whatever")
3231 self.assertTrue(obj.ready)
3234 pprint(obj, big_blobs=True, with_decode_path=True)
3236 @given(integers(), integers(), binary(min_size=1), binary(min_size=1))
3237 def test_comparison(self, value1, value2, tag1, tag2):
3238 class E(Enumerated):
3240 ("whatever0", value1),
3241 ("whatever1", value2),
3244 class EInherited(E):
3246 for klass in (E, EInherited):
3247 obj1 = klass(value1)
3248 obj2 = klass(value2)
3249 self.assertEqual(obj1 == obj2, value1 == value2)
3250 self.assertEqual(obj1 != obj2, value1 != value2)
3251 self.assertEqual(obj1 == int(obj2), value1 == value2)
3252 obj1 = klass(value1, impl=tag1)
3253 obj2 = klass(value1, impl=tag2)
3254 self.assertEqual(obj1 == obj2, tag1 == tag2)
3255 self.assertEqual(obj1 != obj2, tag1 != tag2)
3257 @given(data_strategy())
3258 def test_call(self, d):
3267 ) = d.draw(enumerated_values_strategy())
3269 class E(Enumerated):
3270 schema = schema_initial
3272 value=value_initial,
3275 default=default_initial,
3276 optional=optional_initial or False,
3277 _decoded=_decoded_initial,
3287 ) = d.draw(enumerated_values_strategy(
3288 schema=schema_initial,
3289 do_expl=impl_initial is None,
3299 value_expected = default if value is None else value
3301 default_initial if value_expected is None
3306 dict(schema_initial).get(value_expected, value_expected),
3308 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3309 self.assertEqual(obj.expl_tag, expl or expl_initial)
3312 default_initial if default is None else default,
3314 if obj.default is None:
3315 optional = optional_initial if optional is None else optional
3316 optional = False if optional is None else optional
3319 self.assertEqual(obj.optional, optional)
3320 self.assertEqual(obj.specs, dict(schema_initial))
3322 @given(enumerated_values_strategy())
3323 def test_copy(self, values):
3324 schema_input, value, impl, expl, default, optional, _decoded = values
3326 class E(Enumerated):
3327 schema = schema_input
3337 for copy_func in copy_funcs:
3338 obj_copied = copy_func(obj)
3339 self.assert_copied_basic_fields(obj, obj_copied)
3340 self.assertEqual(obj.specs, obj_copied.specs)
3342 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
3343 @given(data_strategy())
3344 def test_symmetric(self, d):
3345 schema_input, _, _, _, default, optional, _decoded = d.draw(
3346 enumerated_values_strategy(),
3348 tag_expl = d.draw(integers(min_value=1).map(tag_ctxc))
3349 offset = d.draw(integers(min_value=0))
3350 value = d.draw(sampled_from(sorted([v for _, v in schema_input])))
3351 tail_junk = d.draw(binary(max_size=5))
3352 decode_path = d.draw(decode_path_strat)
3354 class E(Enumerated):
3355 schema = schema_input
3364 pprint(obj, big_blobs=True, with_decode_path=True)
3365 self.assertFalse(obj.expled)
3366 obj_encoded = obj.encode()
3367 self.assertEqual(encode2pass(obj), obj_encoded)
3368 obj_expled = obj(value, expl=tag_expl)
3369 self.assertTrue(obj_expled.expled)
3371 list(obj_expled.pps())
3372 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3373 obj_expled_encoded = obj_expled.encode()
3374 ctx_copied = deepcopy(ctx_dummy)
3375 obj_decoded, tail = obj_expled.decode(
3376 obj_expled_encoded + tail_junk,
3380 self.assertDictEqual(ctx_copied, ctx_dummy)
3382 list(obj_decoded.pps())
3383 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3384 self.assertEqual(tail, tail_junk)
3385 self.assertEqual(obj_decoded, obj_expled)
3386 self.assertNotEqual(obj_decoded, obj)
3387 self.assertEqual(int(obj_decoded), int(obj_expled))
3388 self.assertEqual(int(obj_decoded), int(obj))
3389 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3390 self.assertEqual(obj_decoded.expl_tag, tag_expl)
3391 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3393 obj_decoded.expl_llen,
3394 len(len_encode(len(obj_encoded))),
3396 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3397 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3400 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3402 self.assertEqual(obj_decoded.expl_offset, offset)
3403 assert_exceeding_data(
3405 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3409 evgens = list(obj_expled.decode_evgen(
3410 obj_expled_encoded + tail_junk,
3412 decode_path=decode_path,
3415 self.assertEqual(len(evgens), 1)
3416 _decode_path, obj, tail = evgens[0]
3417 self.assertSequenceEqual(tail, tail_junk)
3418 self.assertEqual(_decode_path, decode_path)
3419 self.assertEqual(obj, obj_decoded)
3420 self.assertEqual(obj.expl_offset, offset)
3426 def string_values_strategy(draw, alphabet, do_expl=False):
3427 bound_min, bound_max = sorted(draw(sets(
3428 integers(min_value=0, max_value=1 << 7),
3432 value = draw(one_of(
3434 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3436 default = draw(one_of(
3438 text(alphabet=alphabet, min_size=bound_min, max_size=bound_max),
3441 if draw(booleans()):
3442 bounds = (bound_min, bound_max)
3446 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3448 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
3449 optional = draw(one_of(none(), booleans()))
3451 draw(integers(min_value=0)),
3452 draw(integers(min_value=0)),
3453 draw(integers(min_value=0)),
3455 return (value, bounds, impl, expl, default, optional, _decoded)
3458 class StringMixin(object):
3459 def test_invalid_value_type(self):
3460 with self.assertRaises(InvalidValueType) as err:
3461 self.base_klass((1, 2))
3464 def text_alphabet(self):
3465 return "".join(six_unichr(c) for c in six_xrange(256))
3468 def test_optional(self, optional):
3469 obj = self.base_klass(default=self.base_klass(""), optional=optional)
3470 self.assertTrue(obj.optional)
3472 @given(data_strategy())
3473 def test_ready(self, d):
3474 obj = self.base_klass()
3475 self.assertFalse(obj.ready)
3478 pprint(obj, big_blobs=True, with_decode_path=True)
3480 with self.assertRaises(ObjNotReady) as err:
3483 with self.assertRaises(ObjNotReady) as err:
3485 value = d.draw(text(alphabet=self.text_alphabet()))
3486 obj = self.base_klass(value)
3487 self.assertTrue(obj.ready)
3490 pprint(obj, big_blobs=True, with_decode_path=True)
3493 @given(data_strategy())
3494 def test_comparison(self, d):
3495 value1 = d.draw(text(alphabet=self.text_alphabet()))
3496 value2 = d.draw(text(alphabet=self.text_alphabet()))
3497 tag1 = d.draw(binary(min_size=1))
3498 tag2 = d.draw(binary(min_size=1))
3499 obj1 = self.base_klass(value1)
3500 obj2 = self.base_klass(value2)
3501 self.assertEqual(obj1 == obj2, value1 == value2)
3502 self.assertEqual(obj1 != obj2, value1 != value2)
3503 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
3504 self.assertEqual(obj1 == text_type(obj2), value1 == value2)
3505 obj1 = self.base_klass(value1, impl=tag1)
3506 obj2 = self.base_klass(value1, impl=tag2)
3507 self.assertEqual(obj1 == obj2, tag1 == tag2)
3508 self.assertEqual(obj1 != obj2, tag1 != tag2)
3510 @given(data_strategy())
3511 def test_bounds_satisfied(self, d):
3512 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
3513 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3514 value = d.draw(text(
3515 alphabet=self.text_alphabet(),
3519 self.base_klass(value=value, bounds=(bound_min, bound_max))
3521 @given(data_strategy())
3522 def test_bounds_unsatisfied(self, d):
3523 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
3524 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
3525 value = d.draw(text(alphabet=self.text_alphabet(), max_size=bound_min - 1))
3526 with self.assertRaises(BoundsError) as err:
3527 self.base_klass(value=value, bounds=(bound_min, bound_max))
3529 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3530 self.base_klass(bounds=(bound_min, bound_max)).decode(
3531 self.base_klass(value).encode()
3534 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3535 self.base_klass(bounds=(bound_min, bound_max)).decode(
3536 encode2pass(self.base_klass(value))
3538 value = d.draw(text(alphabet=self.text_alphabet(), min_size=bound_max + 1))
3539 with self.assertRaises(BoundsError) as err:
3540 self.base_klass(value=value, bounds=(bound_min, bound_max))
3542 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3543 self.base_klass(bounds=(bound_min, bound_max)).decode(
3544 self.base_klass(value).encode()
3547 with assertRaisesRegex(self, DecodeError, "bounds") as err:
3548 self.base_klass(bounds=(bound_min, bound_max)).decode(
3549 encode2pass(self.base_klass(value))
3552 @given(data_strategy())
3553 def test_call(self, d):
3562 ) = d.draw(string_values_strategy(self.text_alphabet()))
3563 obj_initial = self.base_klass(
3569 optional_initial or False,
3580 ) = d.draw(string_values_strategy(
3581 self.text_alphabet(),
3582 do_expl=impl_initial is None,
3584 if (default is None) and (obj_initial.default is not None):
3587 (bounds is None) and
3588 (value is not None) and
3589 (bounds_initial is not None) and
3590 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
3594 (bounds is None) and
3595 (default is not None) and
3596 (bounds_initial is not None) and
3597 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
3600 obj = obj_initial(value, bounds, impl, expl, default, optional)
3602 value_expected = default if value is None else value
3604 default_initial if value_expected is None
3607 self.assertEqual(obj, value_expected)
3608 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
3609 self.assertEqual(obj.expl_tag, expl or expl_initial)
3612 default_initial if default is None else default,
3614 if obj.default is None:
3615 optional = optional_initial if optional is None else optional
3616 optional = False if optional is None else optional
3619 self.assertEqual(obj.optional, optional)
3621 (obj._bound_min, obj._bound_max),
3622 bounds or bounds_initial or (0, float("+inf")),
3625 @given(data_strategy())
3626 def test_copy(self, d):
3627 values = d.draw(string_values_strategy(self.text_alphabet()))
3628 obj = self.base_klass(*values)
3629 for copy_func in copy_funcs:
3630 obj_copied = copy_func(obj)
3631 self.assert_copied_basic_fields(obj, obj_copied)
3632 self.assertEqual(obj._bound_min, obj_copied._bound_min)
3633 self.assertEqual(obj._bound_max, obj_copied._bound_max)
3634 self.assertEqual(obj._value, obj_copied._value)
3636 @given(data_strategy())
3637 def test_stripped(self, d):
3638 value = d.draw(text(alphabet=self.text_alphabet()))
3639 tag_impl = tag_encode(d.draw(integers(min_value=1)))
3640 obj = self.base_klass(value, impl=tag_impl)
3641 with self.assertRaises(NotEnoughData):
3642 obj.decode(obj.encode()[:-1])
3644 @given(data_strategy())
3645 def test_stripped_expl(self, d):
3646 value = d.draw(text(alphabet=self.text_alphabet()))
3647 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3648 obj = self.base_klass(value, expl=tag_expl)
3649 with self.assertRaises(NotEnoughData):
3650 obj.decode(obj.encode()[:-1])
3653 integers(min_value=31),
3654 integers(min_value=0),
3657 def test_bad_tag(self, tag, offset, decode_path):
3658 with self.assertRaises(DecodeError) as err:
3659 self.base_klass().decode(
3660 tag_encode(tag)[:-1],
3662 decode_path=decode_path,
3665 self.assertEqual(err.exception.offset, offset)
3666 self.assertEqual(err.exception.decode_path, decode_path)
3669 integers(min_value=128),
3670 integers(min_value=0),
3673 def test_bad_len(self, l, offset, decode_path):
3674 with self.assertRaises(DecodeError) as err:
3675 self.base_klass().decode(
3676 self.base_klass.tag_default + len_encode(l)[:-1],
3678 decode_path=decode_path,
3681 self.assertEqual(err.exception.offset, offset)
3682 self.assertEqual(err.exception.decode_path, decode_path)
3685 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3686 integers(min_value=0),
3689 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3690 value, bound_min = list(sorted(ints))
3692 class String(self.base_klass):
3693 # Multiply this value by four, to satisfy UTF-32 bounds
3694 # (4 bytes per character) validation
3695 bounds = (bound_min * 4, bound_min * 4)
3696 with self.assertRaises(DecodeError) as err:
3698 self.base_klass(b"\x00\x00\x00\x00" * value).encode(),
3700 decode_path=decode_path,
3703 self.assertEqual(err.exception.offset, offset)
3704 self.assertEqual(err.exception.decode_path, decode_path)
3706 @given(data_strategy())
3707 def test_symmetric(self, d):
3708 values = d.draw(string_values_strategy(self.text_alphabet()))
3709 value = d.draw(text(alphabet=self.text_alphabet()))
3710 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
3711 offset = d.draw(integers(min_value=0))
3712 tail_junk = d.draw(binary(max_size=5))
3713 decode_path = d.draw(decode_path_strat)
3714 _, _, _, _, default, optional, _decoded = values
3715 obj = self.base_klass(
3723 pprint(obj, big_blobs=True, with_decode_path=True)
3724 self.assertFalse(obj.expled)
3725 obj_encoded = obj.encode()
3726 self.assertEqual(encode2pass(obj), obj_encoded)
3727 obj_expled = obj(value, expl=tag_expl)
3728 self.assertTrue(obj_expled.expled)
3730 list(obj_expled.pps())
3731 pprint(obj_expled, big_blobs=True, with_decode_path=True)
3732 obj_expled_encoded = obj_expled.encode()
3733 ctx_copied = deepcopy(ctx_dummy)
3734 obj_decoded, tail = obj_expled.decode(
3735 obj_expled_encoded + tail_junk,
3739 self.assertDictEqual(ctx_copied, ctx_dummy)
3741 list(obj_decoded.pps())
3742 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
3743 self.assertEqual(tail, tail_junk)
3744 self.assertEqual(obj_decoded, obj_expled)
3745 self.assertNotEqual(obj_decoded, obj)
3746 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
3747 self.assertEqual(bytes(obj_decoded), bytes(obj))
3748 self.assertEqual(text_type(obj_decoded), text_type(obj_expled))
3749 self.assertEqual(text_type(obj_decoded), text_type(obj))
3750 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
3751 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
3752 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
3754 obj_decoded.expl_llen,
3755 len(len_encode(len(obj_encoded))),
3757 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
3758 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
3761 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
3763 self.assertEqual(obj_decoded.expl_offset, offset)
3764 assert_exceeding_data(
3766 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
3770 evgens = list(obj_expled.decode_evgen(
3771 obj_expled_encoded + tail_junk,
3773 decode_path=decode_path,
3776 self.assertEqual(len(evgens), 1)
3777 _decode_path, obj, tail = evgens[0]
3778 self.assertSequenceEqual(tail, tail_junk)
3779 self.assertEqual(_decode_path, decode_path)
3780 if not getattr(self, "evgen_mode_skip_value", True):
3781 self.assertEqual(obj, obj_decoded)
3782 self.assertEqual(obj.expl_offset, offset)
3787 cyrillic_letters = text(
3788 alphabet="".join(six_unichr(i) for i in list(range(0x0410, 0x044f + 1))),
3794 class TestUTF8String(StringMixin, CommonMixin, TestCase):
3795 base_klass = UTF8String
3797 @given(cyrillic_letters)
3798 def test_byte_per_primitive(self, chars):
3800 char_raw = char.encode("utf-8")
3801 encoded = b"".join((
3802 self.base_klass().tag_constructed,
3804 OctetString(char_raw[:1]).encode(),
3805 OctetString(char_raw[1:2]).encode(),
3809 self.base_klass().decod(encoded, ctx={"bered": True}),
3814 class UnicodeDecodeErrorMixin(object):
3815 @given(cyrillic_letters)
3816 def test_unicode_decode_error(self, cyrillic_text):
3817 with self.assertRaises(DecodeError):
3818 self.base_klass(cyrillic_text)
3821 class TestNumericString(StringMixin, CommonMixin, TestCase):
3822 base_klass = NumericString
3824 def text_alphabet(self):
3827 @given(text(alphabet=ascii_letters, min_size=1, max_size=5))
3828 def test_non_numeric(self, non_numeric_text):
3829 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3830 self.base_klass(non_numeric_text)
3833 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3834 integers(min_value=0),
3837 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3838 value, bound_min = list(sorted(ints))
3840 class String(self.base_klass):
3841 bounds = (bound_min, bound_min)
3842 with self.assertRaises(DecodeError) as err:
3844 self.base_klass(b"1" * value).encode(),
3846 decode_path=decode_path,
3849 self.assertEqual(err.exception.offset, offset)
3850 self.assertEqual(err.exception.decode_path, decode_path)
3852 def test_byte_per_primitive(self):
3853 encoded = b"".join((
3854 self.base_klass().tag_constructed,
3856 OctetString(b"1").encode(),
3857 OctetString(b"2").encode(),
3861 self.base_klass().decod(encoded, ctx={"bered": True}),
3866 class TestPrintableString(
3867 UnicodeDecodeErrorMixin,
3872 base_klass = PrintableString
3874 def text_alphabet(self):
3875 return ascii_letters + digits + " '()+,-./:=?"
3877 @given(text(alphabet=sorted(set(whitespace) - set(" ")), min_size=1, max_size=5))
3878 def test_non_printable(self, non_printable_text):
3879 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3880 self.base_klass(non_printable_text)
3883 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
3884 integers(min_value=0),
3887 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
3888 value, bound_min = list(sorted(ints))
3890 class String(self.base_klass):
3891 bounds = (bound_min, bound_min)
3892 with self.assertRaises(DecodeError) as err:
3894 self.base_klass(b"1" * value).encode(),
3896 decode_path=decode_path,
3899 self.assertEqual(err.exception.offset, offset)
3900 self.assertEqual(err.exception.decode_path, decode_path)
3902 def test_allowable_invalid_chars(self):
3904 ("*", {"allow_asterisk": True}),
3905 ("&", {"allow_ampersand": True}),
3906 ("&*", {"allow_asterisk": True, "allow_ampersand": True}),
3909 obj = self.base_klass(s)
3910 for prop in kwargs.keys():
3911 self.assertFalse(getattr(obj, prop))
3913 with assertRaisesRegex(self, DecodeError, "alphabet value"):
3915 self.base_klass(s, **kwargs)
3916 klass = self.base_klass(**kwargs)
3918 for prop in kwargs.keys():
3919 self.assertTrue(getattr(obj, prop))
3922 for prop in kwargs.keys():
3923 self.assertTrue(getattr(obj, prop))
3926 class TestTeletexString(
3927 UnicodeDecodeErrorMixin,
3932 base_klass = TeletexString
3935 class TestVideotexString(
3936 UnicodeDecodeErrorMixin,
3941 base_klass = VideotexString
3944 class TestIA5String(
3945 UnicodeDecodeErrorMixin,
3950 base_klass = IA5String
3952 def text_alphabet(self):
3953 return "".join(six_unichr(c) for c in six_xrange(128))
3955 @given(integers(min_value=128, max_value=255))
3956 def test_alphabet_bad(self, code):
3957 with self.assertRaises(DecodeError):
3958 self.base_klass().decod(
3959 self.base_klass.tag_default +
3961 bytes(bytearray([code])),
3965 class TestGraphicString(
3966 UnicodeDecodeErrorMixin,
3971 base_klass = GraphicString
3974 class TestVisibleString(
3975 UnicodeDecodeErrorMixin,
3980 base_klass = VisibleString
3982 def text_alphabet(self):
3983 return " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
3985 def test_x690_vector(self):
3986 obj, tail = VisibleString().decode(hexdec("1A054A6F6E6573"))
3987 self.assertSequenceEqual(tail, b"")
3988 self.assertEqual(str(obj), "Jones")
3989 self.assertFalse(obj.ber_encoded)
3990 self.assertFalse(obj.lenindef)
3991 self.assertFalse(obj.bered)
3993 obj, tail = VisibleString().decode(
3994 hexdec("3A0904034A6F6E04026573"),
3995 ctx={"bered": True},
3997 self.assertSequenceEqual(tail, b"")
3998 self.assertEqual(str(obj), "Jones")
3999 self.assertTrue(obj.ber_encoded)
4000 self.assertFalse(obj.lenindef)
4001 self.assertTrue(obj.bered)
4003 self.assertTrue(obj.ber_encoded)
4004 self.assertFalse(obj.lenindef)
4005 self.assertTrue(obj.bered)
4007 obj, tail = VisibleString().decode(
4008 hexdec("3A8004034A6F6E040265730000"),
4009 ctx={"bered": True},
4011 self.assertSequenceEqual(tail, b"")
4012 self.assertEqual(str(obj), "Jones")
4013 self.assertTrue(obj.ber_encoded)
4014 self.assertTrue(obj.lenindef)
4015 self.assertTrue(obj.bered)
4017 self.assertTrue(obj.ber_encoded)
4018 self.assertTrue(obj.lenindef)
4019 self.assertTrue(obj.bered)
4022 integers(min_value=0, max_value=ord(" ") - 1),
4023 integers(min_value=ord("~") + 1, max_value=255),
4025 def test_alphabet_bad(self, code):
4026 with self.assertRaises(DecodeError):
4027 self.base_klass().decod(
4028 self.base_klass.tag_default +
4030 bytes(bytearray([code])),
4034 sets(integers(min_value=0, max_value=10), min_size=2, max_size=2),
4035 integers(min_value=0),
4038 def test_invalid_bounds_while_decoding(self, ints, offset, decode_path):
4039 value, bound_min = list(sorted(ints))
4041 class String(self.base_klass):
4042 bounds = (bound_min, bound_min)
4043 with self.assertRaises(DecodeError) as err:
4045 self.base_klass(b"1" * value).encode(),
4047 decode_path=decode_path,
4050 self.assertEqual(err.exception.offset, offset)
4051 self.assertEqual(err.exception.decode_path, decode_path)
4054 class TestGeneralString(
4055 UnicodeDecodeErrorMixin,
4060 base_klass = GeneralString
4063 class TestUniversalString(StringMixin, CommonMixin, TestCase):
4064 base_klass = UniversalString
4067 class TestBMPString(StringMixin, CommonMixin, TestCase):
4068 base_klass = BMPString
4072 def generalized_time_values_strategy(
4080 if draw(booleans()):
4081 value = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4083 value = value.replace(microsecond=0)
4085 if draw(booleans()):
4086 default = draw(datetimes(min_value=min_datetime, max_value=max_datetime))
4088 default = default.replace(microsecond=0)
4092 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4094 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
4095 optional = draw(one_of(none(), booleans()))
4097 draw(integers(min_value=0)),
4098 draw(integers(min_value=0)),
4099 draw(integers(min_value=0)),
4101 return (value, impl, expl, default, optional, _decoded)
4104 class TimeMixin(object):
4105 def test_invalid_value_type(self):
4106 with self.assertRaises(InvalidValueType) as err:
4107 self.base_klass(datetime.now().timetuple())
4110 @given(data_strategy())
4111 def test_optional(self, d):
4112 default = d.draw(datetimes(
4113 min_value=self.min_datetime,
4114 max_value=self.max_datetime,
4116 optional = d.draw(booleans())
4117 obj = self.base_klass(default=default, optional=optional)
4118 self.assertTrue(obj.optional)
4120 @given(data_strategy())
4121 def test_ready(self, d):
4122 obj = self.base_klass()
4123 self.assertFalse(obj.ready)
4126 pprint(obj, big_blobs=True, with_decode_path=True)
4127 with self.assertRaises(ObjNotReady) as err:
4130 with self.assertRaises(ObjNotReady) as err:
4132 value = d.draw(datetimes(
4133 min_value=self.min_datetime,
4134 max_value=self.max_datetime,
4136 obj = self.base_klass(value)
4137 self.assertTrue(obj.ready)
4140 pprint(obj, big_blobs=True, with_decode_path=True)
4142 @given(data_strategy())
4143 def test_comparison(self, d):
4144 value1 = d.draw(datetimes(
4145 min_value=self.min_datetime,
4146 max_value=self.max_datetime,
4148 value2 = d.draw(datetimes(
4149 min_value=self.min_datetime,
4150 max_value=self.max_datetime,
4152 tag1 = d.draw(binary(min_size=1))
4153 tag2 = d.draw(binary(min_size=1))
4155 value1 = value1.replace(microsecond=0)
4156 value2 = value2.replace(microsecond=0)
4157 obj1 = self.base_klass(value1)
4158 obj2 = self.base_klass(value2)
4159 self.assertEqual(obj1 == obj2, value1 == value2)
4160 self.assertEqual(obj1 != obj2, value1 != value2)
4161 self.assertEqual(obj1 == obj2.todatetime(), value1 == value2)
4162 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
4163 obj1 = self.base_klass(value1, impl=tag1)
4164 obj2 = self.base_klass(value1, impl=tag2)
4165 self.assertEqual(obj1 == obj2, tag1 == tag2)
4166 self.assertEqual(obj1 != obj2, tag1 != tag2)
4168 @given(data_strategy())
4169 def test_call(self, d):
4177 ) = d.draw(generalized_time_values_strategy(
4178 min_datetime=self.min_datetime,
4179 max_datetime=self.max_datetime,
4180 omit_ms=self.omit_ms,
4182 obj_initial = self.base_klass(
4183 value=value_initial,
4186 default=default_initial,
4187 optional=optional_initial or False,
4188 _decoded=_decoded_initial,
4197 ) = d.draw(generalized_time_values_strategy(
4198 min_datetime=self.min_datetime,
4199 max_datetime=self.max_datetime,
4200 omit_ms=self.omit_ms,
4201 do_expl=impl_initial is None,
4211 value_expected = default if value is None else value
4213 default_initial if value_expected is None
4216 self.assertEqual(obj, value_expected)
4217 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
4218 self.assertEqual(obj.expl_tag, expl or expl_initial)
4221 default_initial if default is None else default,
4223 if obj.default is None:
4224 optional = optional_initial if optional is None else optional
4225 optional = False if optional is None else optional
4228 self.assertEqual(obj.optional, optional)
4230 @given(data_strategy())
4231 def test_copy(self, d):
4232 values = d.draw(generalized_time_values_strategy(
4233 min_datetime=self.min_datetime,
4234 max_datetime=self.max_datetime,
4236 obj = self.base_klass(*values)
4237 for copy_func in copy_funcs:
4238 obj_copied = copy_func(obj)
4239 self.assert_copied_basic_fields(obj, obj_copied)
4240 self.assertEqual(obj._value, obj_copied._value)
4242 @given(data_strategy())
4243 def test_stripped(self, d):
4244 value = d.draw(datetimes(
4245 min_value=self.min_datetime,
4246 max_value=self.max_datetime,
4248 tag_impl = tag_encode(d.draw(integers(min_value=1)))
4249 obj = self.base_klass(value, impl=tag_impl)
4250 with self.assertRaises(NotEnoughData):
4251 obj.decode(obj.encode()[:-1])
4253 @given(data_strategy())
4254 def test_stripped_expl(self, d):
4255 value = d.draw(datetimes(
4256 min_value=self.min_datetime,
4257 max_value=self.max_datetime,
4259 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4260 obj = self.base_klass(value, expl=tag_expl)
4261 with self.assertRaises(NotEnoughData):
4262 obj.decode(obj.encode()[:-1])
4264 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4265 @given(data_strategy())
4266 def test_symmetric(self, d):
4267 values = d.draw(generalized_time_values_strategy(
4268 min_datetime=self.min_datetime,
4269 max_datetime=self.max_datetime,
4271 value = d.draw(datetimes(
4272 min_value=self.min_datetime,
4273 max_value=self.max_datetime,
4275 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
4276 offset = d.draw(integers(min_value=0))
4277 tail_junk = d.draw(binary(max_size=5))
4278 _, _, _, default, optional, _decoded = values
4279 obj = self.base_klass(
4287 pprint(obj, big_blobs=True, with_decode_path=True)
4288 self.assertFalse(obj.expled)
4289 obj_encoded = obj.encode()
4290 self.assertEqual(encode2pass(obj), obj_encoded)
4291 self.additional_symmetric_check(value, obj_encoded)
4292 obj_expled = obj(value, expl=tag_expl)
4293 self.assertTrue(obj_expled.expled)
4295 list(obj_expled.pps())
4296 pprint(obj_expled, big_blobs=True, with_decode_path=True)
4297 obj_expled_encoded = obj_expled.encode()
4298 ctx_copied = deepcopy(ctx_dummy)
4299 obj_decoded, tail = obj_expled.decode(
4300 obj_expled_encoded + tail_junk,
4304 self.assertDictEqual(ctx_copied, ctx_dummy)
4306 list(obj_decoded.pps())
4307 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
4308 self.assertEqual(tail, tail_junk)
4309 self.assertEqual(obj_decoded, obj_expled)
4310 self.assertEqual(obj_decoded.todatetime(), obj_expled.todatetime())
4311 self.assertEqual(obj_decoded.todatetime(), obj.todatetime())
4312 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
4313 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
4314 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
4316 obj_decoded.expl_llen,
4317 len(len_encode(len(obj_encoded))),
4319 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
4320 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
4323 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
4325 self.assertEqual(obj_decoded.expl_offset, offset)
4326 assert_exceeding_data(
4328 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
4333 class TestGeneralizedTime(TimeMixin, CommonMixin, TestCase):
4334 base_klass = GeneralizedTime
4336 min_datetime = datetime(1900, 1, 1)
4337 max_datetime = datetime(9999, 12, 31)
4338 evgen_mode_skip_value = False
4340 def additional_symmetric_check(self, value, obj_encoded):
4341 if value.microsecond > 0:
4342 self.assertFalse(obj_encoded.endswith(b"0Z"))
4344 def test_repr_not_ready(self):
4345 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4346 repr(GeneralizedTime())
4348 def test_x690_vector_valid(self):
4352 b"19920722132100.3Z",
4354 GeneralizedTime(data)
4356 def test_x690_vector_invalid(self):
4359 b"19920622123421.0Z",
4360 b"19920722132100.30Z",
4362 with self.assertRaises(DecodeError) as err:
4363 GeneralizedTime(data)
4366 def test_go_vectors_invalid(self):
4378 b"-20100102030410Z",
4379 b"2010-0102030410Z",
4380 b"2010-0002030410Z",
4381 b"201001-02030410Z",
4382 b"20100102-030410Z",
4383 b"2010010203-0410Z",
4384 b"201001020304-10Z",
4385 # These ones are INVALID in *DER*, but accepted
4386 # by Go's encoding/asn1
4387 b"20100102030405+0607",
4388 b"20100102030405-0607",
4390 with self.assertRaises(DecodeError) as err:
4391 GeneralizedTime(data)
4394 def test_go_vectors_valid(self):
4396 GeneralizedTime(b"20100102030405Z").todatetime(),
4397 datetime(2010, 1, 2, 3, 4, 5, 0),
4400 def test_go_vectors_valid_ber(self):
4402 b"20100102030405+0607",
4403 b"20100102030405-0607",
4405 GeneralizedTime(data, ctx={"bered": True})
4407 def test_utc_offsets(self):
4408 """Some know equal UTC offsets
4411 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4415 "200101011130-0700",
4416 "200101011500-03:30",
4419 self.assertEqual(dts[0], dts[1])
4420 self.assertEqual(dts[0], dts[2])
4421 self.assertEqual(dts[0], dts[3])
4423 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4424 @given(data_strategy())
4425 def test_valid_ber(self, d):
4426 min_year = 1901 if PY2 else 2
4427 year = d.draw(integers(min_value=min_year, max_value=9999))
4428 month = d.draw(integers(min_value=1, max_value=12))
4429 day = d.draw(integers(min_value=1, max_value=28))
4430 hours = d.draw(integers(min_value=0, max_value=23))
4431 data = "%04d%02d%02d%02d" % (year, month, day, hours)
4432 dt = datetime(year, month, day, hours)
4433 fractions_sign = d.draw(sampled_from(" ,."))
4435 if fractions_sign != " ":
4436 fractions = random()
4437 if d.draw(booleans()):
4438 minutes = d.draw(integers(min_value=0, max_value=59))
4439 data += "%02d" % minutes
4440 dt += timedelta(seconds=60 * minutes)
4441 if d.draw(booleans()):
4442 seconds = d.draw(integers(min_value=0, max_value=59))
4443 data += "%02d" % seconds
4444 dt += timedelta(seconds=seconds)
4445 if fractions is not None:
4446 dt += timedelta(microseconds=10**6 * fractions)
4447 elif fractions is not None:
4448 dt += timedelta(seconds=60 * fractions)
4449 elif fractions is not None:
4450 dt += timedelta(seconds=3600 * fractions)
4451 if fractions is not None:
4452 data += fractions_sign + str(fractions)[2:]
4453 if d.draw(booleans()):
4455 elif d.draw(booleans()):
4456 offset_hour = d.draw(integers(min_value=0, max_value=13))
4458 if d.draw(booleans()):
4463 dt -= timedelta(seconds=sign * 3600 * offset_hour)
4464 data += "%02d" % offset_hour
4465 minutes_separator = d.draw(sampled_from((None, "", ":")))
4466 if minutes_separator is not None:
4467 offset_minute = d.draw(integers(min_value=0, max_value=59))
4468 dt -= timedelta(seconds=sign * 60 * offset_minute)
4469 data += "%s%02d" % (minutes_separator, offset_minute)
4470 data = data.encode("ascii")
4471 data_der = GeneralizedTime.tag_default + len_encode(len(data)) + data
4473 GeneralizedTime().decod(data_der)
4478 obj = GeneralizedTime().decod(data_der, ctx={"bered": True})
4481 mktime(obj.todatetime().timetuple()),
4482 mktime(dt.timetuple()),
4485 self.assertEqual(obj.todatetime().timestamp(), dt.timestamp())
4486 self.assertEqual(obj.ber_encoded, not dered)
4487 self.assertEqual(obj.bered, not dered)
4488 self.assertEqual(obj.ber_raw, None if dered else data)
4489 self.assertEqual(obj.encode() == data_der, dered)
4494 def test_invalid_ber(self):
4496 # "00010203040506.07",
4497 "-0010203040506.07",
4498 "0001-203040506.07",
4499 "000102-3040506.07",
4500 "00010203-40506.07",
4501 "0001020304-506.07",
4502 "000102030405-6.07",
4503 "00010203040506.-7",
4504 "+0010203040506.07",
4505 "0001+203040506.07",
4506 "000102+3040506.07",
4507 "00010203+40506.07",
4508 "0001020304+506.07",
4509 "000102030405+6.07",
4510 "00010203040506.+7",
4511 " 0010203040506.07",
4512 "0001 203040506.07",
4513 "000102 3040506.07",
4514 "00010203 40506.07",
4515 "0001020304 506.07",
4516 "000102030405 6.07",
4517 "00010203040506. 7",
4518 "001 0203040506.07",
4519 "00012 03040506.07",
4520 "0001023 040506.07",
4521 "000102034 0506.07",
4522 "00010203045 06.07",
4523 "0001020304056 .07",
4524 "00010203040506.7 ",
4604 "00010203040506.07+15",
4605 "00010203040506.07-15",
4606 "00010203040506.07+14:60",
4607 "00010203040506.07+1460",
4608 "00010203040506.07-1460",
4609 "00010203040506.07+00:60",
4610 "00010203040506.07-00:60",
4612 "00010203040506+15",
4613 "00010203040506-15",
4614 "00010203040506+14:60",
4615 "00010203040506+1460",
4616 "00010203040506-1460",
4617 "00010203040506+00:60",
4618 "00010203040506-00:60",
4627 with self.assertRaises(DecodeError):
4628 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4629 data = data.replace(".", ",")
4630 with self.assertRaises(DecodeError):
4631 GeneralizedTime(data.encode("ascii"), ctx={"bered": True})
4635 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4636 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4638 binary(min_size=1, max_size=1),
4640 min_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4641 max_size=(LEN_YYYYMMDDHHMMSSZ - 1) // 2,
4644 def test_junk(self, part0, part1, part2):
4645 junk = part0 + part1 + part2
4646 assume(not (set(junk) <= set(digits.encode("ascii"))))
4647 with self.assertRaises(DecodeError):
4648 GeneralizedTime().decode(
4649 GeneralizedTime.tag_default +
4650 len_encode(len(junk)) +
4656 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4657 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4659 binary(min_size=1, max_size=1),
4661 min_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4662 max_size=(LEN_YYYYMMDDHHMMSSDMZ - 1) // 2,
4665 def test_junk_dm(self, part0, part1, part2):
4666 junk = part0 + part1 + part2
4667 assume(not (set(junk) <= set(digits.encode("ascii"))))
4668 with self.assertRaises(DecodeError):
4669 GeneralizedTime().decode(
4670 GeneralizedTime.tag_default +
4671 len_encode(len(junk)) +
4675 def test_ns_fractions(self):
4676 GeneralizedTime(b"20010101000000.000001Z")
4677 with assertRaisesRegex(self, DecodeError, "only microsecond fractions"):
4678 GeneralizedTime(b"20010101000000.0000001Z")
4680 def test_non_pure_integers(self):
4682 # b"20000102030405Z,
4689 b"20000102030405.+6Z",
4690 b"20000102030405.-6Z",
4697 b"20000102030405._6Z",
4698 b"20000102030405.6_Z",
4705 b"20000102030405. 6Z",
4712 b"20000102030405.6 Z",
4714 with self.assertRaises(DecodeError):
4715 GeneralizedTime(data)
4718 class TestUTCTime(TimeMixin, CommonMixin, TestCase):
4719 base_klass = UTCTime
4721 min_datetime = datetime(2000, 1, 1)
4722 max_datetime = datetime(2049, 12, 31)
4723 evgen_mode_skip_value = False
4725 def additional_symmetric_check(self, value, obj_encoded):
4728 def test_repr_not_ready(self):
4729 unicode(GeneralizedTime()) if PY2 else str(GeneralizedTime())
4732 def test_x690_vector_valid(self):
4740 def test_x690_vector_invalid(self):
4745 with self.assertRaises(DecodeError) as err:
4749 def test_go_vectors_invalid(self):
4775 # These ones are INVALID in *DER*, but accepted
4776 # by Go's encoding/asn1
4777 b"910506164540-0700",
4778 b"910506164540+0730",
4782 with self.assertRaises(DecodeError) as err:
4786 def test_go_vectors_valid(self):
4788 UTCTime(b"910506234540Z").todatetime(),
4789 datetime(1991, 5, 6, 23, 45, 40, 0),
4792 def test_non_pure_integers(self):
4821 with self.assertRaises(DecodeError):
4824 def test_x680_vector_valid_ber(self):
4826 (b"8201021200Z", datetime(1982, 1, 2, 12)),
4827 (b"8201020700-0500", datetime(1982, 1, 2, 12)),
4828 (b"0101021200Z", datetime(2001, 1, 2, 12)),
4829 (b"0101020700-0500", datetime(2001, 1, 2, 12)),
4831 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4832 obj = UTCTime().decod(data_der, ctx={"bered": True})
4833 self.assertEqual(obj, dt)
4834 self.assertEqual(obj.todatetime(), dt)
4835 self.assertTrue(obj.ber_encoded)
4836 self.assertTrue(obj.bered)
4837 self.assertEqual(obj.ber_raw, data)
4838 self.assertNotEqual(obj.encode(), data_der)
4841 def test_go_vectors_valid_ber(self):
4843 b"910506164540-0700",
4844 b"910506164540+0730",
4848 data = UTCTime.tag_default + len_encode(len(data)) + data
4849 obj = UTCTime().decod(data, ctx={"bered": True})
4850 self.assertTrue(obj.ber_encoded)
4851 self.assertTrue(obj.bered)
4852 self.assertNotEqual(obj.encode(), data)
4855 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
4856 @given(data_strategy())
4857 def test_valid_ber(self, d):
4858 year = d.draw(integers(min_value=0, max_value=99))
4859 month = d.draw(integers(min_value=1, max_value=12))
4860 day = d.draw(integers(min_value=1, max_value=28))
4861 hours = d.draw(integers(min_value=0, max_value=23))
4862 minute = d.draw(integers(min_value=0, max_value=59))
4863 data = "%02d%02d%02d%02d%02d" % (year, month, day, hours, minute)
4865 year + (2000 if year < 50 else 1900),
4872 if d.draw(booleans()):
4874 seconds = d.draw(integers(min_value=0, max_value=59))
4875 data += "%02d" % seconds
4876 dt += timedelta(seconds=seconds)
4877 if d.draw(booleans()):
4881 offset_hour = d.draw(integers(min_value=0, max_value=13))
4882 offset_minute = d.draw(integers(min_value=0, max_value=59))
4883 offset = timedelta(seconds=offset_hour * 3600 + offset_minute * 60)
4884 if d.draw(booleans()):
4890 data += "%02d%02d" % (offset_hour, offset_minute)
4891 data = data.encode("ascii")
4892 data_der = UTCTime.tag_default + len_encode(len(data)) + data
4893 obj = UTCTime().decod(data_der, ctx={"bered": True})
4894 self.assertEqual(obj, dt)
4895 self.assertEqual(obj.todatetime(), dt)
4896 self.assertEqual(obj.ber_encoded, not dered)
4897 self.assertEqual(obj.bered, not dered)
4898 self.assertEqual(obj.ber_raw, None if dered else data)
4899 self.assertEqual(obj.encode() == data_der, dered)
4904 def test_invalid_ber(self):
4945 b"0001020304+0000Z",
4954 with self.assertRaises(DecodeError):
4955 UTCTime(data, ctx={"bered": True})
4956 data = data[:8] + data[8+2:]
4957 with self.assertRaises(DecodeError):
4958 UTCTime(data, ctx={"bered": True})
5003 b"000102030405+000",
5004 b"000102030405+000Z",
5005 b"000102030405+0000Z",
5006 b"000102030405+-101",
5007 b"000102030405+01-1",
5008 b"000102030405+0060",
5009 b"000102030405+1401",
5010 b"500101000002+0003",
5012 with self.assertRaises(DecodeError):
5013 UTCTime(data, ctx={"bered": True})
5015 @given(integers(min_value=0, max_value=49))
5016 def test_pre50(self, year):
5018 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5022 @given(integers(min_value=50, max_value=99))
5023 def test_post50(self, year):
5025 UTCTime(("%02d1231235959Z" % year).encode("ascii")).todatetime().year,
5031 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5032 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5034 binary(min_size=1, max_size=1),
5036 min_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5037 max_size=(LEN_YYMMDDHHMMSSZ - 1) // 2,
5040 def test_junk(self, part0, part1, part2):
5041 junk = part0 + part1 + part2
5042 assume(not (set(junk) <= set(digits.encode("ascii"))))
5043 with self.assertRaises(DecodeError):
5045 UTCTime.tag_default +
5046 len_encode(len(junk)) +
5052 def tlv_value_strategy(draw):
5053 tag_num = draw(integers(min_value=1))
5054 data = draw(binary())
5055 return b"".join((tag_encode(tag_num), len_encode(len(data)), data))
5059 def any_values_strategy(draw, do_expl=False):
5060 value = draw(one_of(none(), tlv_value_strategy()))
5063 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5064 optional = draw(one_of(none(), booleans()))
5066 draw(integers(min_value=0)),
5067 draw(integers(min_value=0)),
5068 draw(integers(min_value=0)),
5070 return (value, expl, optional, _decoded)
5073 class AnyInherited(Any):
5077 class TestAny(CommonMixin, TestCase):
5080 def test_invalid_value_type(self):
5081 with self.assertRaises(InvalidValueType) as err:
5086 def test_optional(self, optional):
5087 obj = Any(optional=optional)
5088 self.assertEqual(obj.optional, optional)
5090 @given(tlv_value_strategy())
5091 def test_ready(self, value):
5093 self.assertFalse(obj.ready)
5096 pprint(obj, big_blobs=True, with_decode_path=True)
5097 with self.assertRaises(ObjNotReady) as err:
5100 with self.assertRaises(ObjNotReady) as err:
5103 self.assertTrue(obj.ready)
5106 pprint(obj, big_blobs=True, with_decode_path=True)
5109 def test_basic(self, value):
5110 integer_encoded = Integer(value).encode()
5112 Any(integer_encoded),
5113 Any(Integer(value)),
5114 Any(Any(Integer(value))),
5116 self.assertSequenceEqual(bytes(obj), integer_encoded)
5118 obj.decode(obj.encode())[0].vlen,
5119 len(integer_encoded),
5123 pprint(obj, big_blobs=True, with_decode_path=True)
5124 self.assertSequenceEqual(obj.encode(), integer_encoded)
5126 @given(tlv_value_strategy(), tlv_value_strategy())
5127 def test_comparison(self, value1, value2):
5128 for klass in (Any, AnyInherited):
5129 obj1 = klass(value1)
5130 obj2 = klass(value2)
5131 self.assertEqual(obj1 == obj2, value1 == value2)
5132 self.assertEqual(obj1 != obj2, value1 != value2)
5133 self.assertEqual(obj1 == bytes(obj2), value1 == value2)
5135 @given(data_strategy())
5136 def test_call(self, d):
5137 for klass in (Any, AnyInherited):
5143 ) = d.draw(any_values_strategy())
5144 obj_initial = klass(
5147 optional_initial or False,
5155 ) = d.draw(any_values_strategy(do_expl=True))
5156 obj = obj_initial(value, expl, optional)
5158 value_expected = None if value is None else value
5159 self.assertEqual(obj, value_expected)
5160 self.assertEqual(obj.expl_tag, expl or expl_initial)
5161 if obj.default is None:
5162 optional = optional_initial if optional is None else optional
5163 optional = False if optional is None else optional
5164 self.assertEqual(obj.optional, optional)
5166 def test_simultaneous_impl_expl(self):
5167 # override it, as Any does not have implicit tag
5170 def test_decoded(self):
5171 # override it, as Any does not have implicit tag
5174 @given(any_values_strategy())
5175 def test_copy(self, values):
5176 for klass in (Any, AnyInherited):
5177 obj = klass(*values)
5178 for copy_func in copy_funcs:
5179 obj_copied = copy_func(obj)
5180 self.assert_copied_basic_fields(obj, obj_copied)
5181 self.assertEqual(obj._value, obj_copied._value)
5183 @given(binary().map(OctetString))
5184 def test_stripped(self, value):
5186 with self.assertRaises(NotEnoughData):
5187 obj.decode(obj.encode()[:-1])
5190 tlv_value_strategy(),
5191 integers(min_value=1).map(tag_ctxc),
5193 def test_stripped_expl(self, value, tag_expl):
5194 obj = Any(value, expl=tag_expl)
5195 with self.assertRaises(NotEnoughData):
5196 obj.decode(obj.encode()[:-1])
5199 integers(min_value=31),
5200 integers(min_value=0),
5203 def test_bad_tag(self, tag, offset, decode_path):
5204 with self.assertRaises(DecodeError) as err:
5206 tag_encode(tag)[:-1],
5208 decode_path=decode_path,
5211 self.assertEqual(err.exception.offset, offset)
5212 self.assertEqual(err.exception.decode_path, decode_path)
5215 integers(min_value=128),
5216 integers(min_value=0),
5219 def test_bad_len(self, l, offset, decode_path):
5220 with self.assertRaises(DecodeError) as err:
5222 Any.tag_default + len_encode(l)[:-1],
5224 decode_path=decode_path,
5227 self.assertEqual(err.exception.offset, offset)
5228 self.assertEqual(err.exception.decode_path, decode_path)
5230 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5232 any_values_strategy(),
5233 integers().map(lambda x: Integer(x).encode()),
5234 integers(min_value=1).map(tag_ctxc),
5235 integers(min_value=0),
5239 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
5240 for klass in (Any, AnyInherited):
5241 _, _, optional, _decoded = values
5242 obj = klass(value=value, optional=optional, _decoded=_decoded)
5245 pprint(obj, big_blobs=True, with_decode_path=True)
5246 self.assertFalse(obj.expled)
5247 tag_class, _, tag_num = tag_decode(tag_strip(value)[0])
5248 self.assertEqual(obj.tag_order, (tag_class, tag_num))
5249 obj_encoded = obj.encode()
5250 self.assertEqual(encode2pass(obj), obj_encoded)
5251 obj_expled = obj(value, expl=tag_expl)
5252 self.assertTrue(obj_expled.expled)
5253 tag_class, _, tag_num = tag_decode(tag_expl)
5254 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5256 list(obj_expled.pps())
5257 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5258 obj_expled_encoded = obj_expled.encode()
5259 ctx_copied = deepcopy(ctx_dummy)
5260 obj_decoded, tail = obj_expled.decode(
5261 obj_expled_encoded + tail_junk,
5265 self.assertDictEqual(ctx_copied, ctx_dummy)
5267 list(obj_decoded.pps())
5268 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5269 self.assertEqual(tail, tail_junk)
5270 self.assertEqual(obj_decoded, obj_expled)
5271 self.assertEqual(bytes(obj_decoded), bytes(obj_expled))
5272 self.assertEqual(bytes(obj_decoded), bytes(obj))
5273 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5274 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5275 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5277 obj_decoded.expl_llen,
5278 len(len_encode(len(obj_encoded))),
5280 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5281 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5284 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5286 self.assertEqual(obj_decoded.expl_offset, offset)
5287 self.assertEqual(obj_decoded.tlen, 0)
5288 self.assertEqual(obj_decoded.llen, 0)
5289 self.assertEqual(obj_decoded.vlen, len(value))
5290 assert_exceeding_data(
5292 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5296 evgens = list(obj_expled.decode_evgen(
5297 obj_expled_encoded + tail_junk,
5299 decode_path=decode_path,
5302 self.assertEqual(len(evgens), 1)
5303 _decode_path, obj, tail = evgens[0]
5304 self.assertSequenceEqual(tail, tail_junk)
5305 self.assertEqual(_decode_path, decode_path)
5306 self.assertEqual(obj.expl_offset, offset)
5311 integers(min_value=1).map(tag_ctxc),
5312 integers(min_value=0, max_value=3),
5313 integers(min_value=0),
5317 def test_indefinite(self, expl, chunks, offset, decode_path, junk):
5318 chunk = Boolean(False, expl=expl).encode()
5320 OctetString.tag_default +
5322 b"".join([chunk] * chunks) +
5325 with self.assertRaises(LenIndefForm):
5329 decode_path=decode_path,
5331 obj, tail = Any().decode(
5334 decode_path=decode_path,
5335 ctx={"bered": True},
5337 self.assertSequenceEqual(tail, junk)
5338 self.assertEqual(obj.offset, offset)
5339 self.assertEqual(obj.tlvlen, len(encoded))
5340 self.assertTrue(obj.lenindef)
5341 self.assertFalse(obj.ber_encoded)
5342 self.assertTrue(obj.bered)
5344 self.assertTrue(obj.lenindef)
5345 self.assertFalse(obj.ber_encoded)
5346 self.assertTrue(obj.bered)
5349 pprint(obj, big_blobs=True, with_decode_path=True)
5350 with self.assertRaises(NotEnoughData) as err:
5354 decode_path=decode_path,
5355 ctx={"bered": True},
5357 self.assertEqual(err.exception.offset, offset + 1 + 1 + len(chunk) * chunks)
5358 self.assertEqual(err.exception.decode_path, decode_path + (str(chunks),))
5360 class SeqOf(SequenceOf):
5361 schema = Boolean(expl=expl)
5363 class Seq(Sequence):
5365 ("type", ObjectIdentifier(defines=((("value",), {
5366 ObjectIdentifier("1.2.3"): SeqOf(impl=OctetString.tag_default),
5371 ("type", ObjectIdentifier("1.2.3")),
5372 ("value", Any(encoded)),
5374 seq_encoded = seq.encode()
5375 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5376 self.assertIsNotNone(seq_decoded["value"].defined)
5378 list(seq_decoded.pps())
5379 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5380 self.assertTrue(seq_decoded.bered)
5381 self.assertFalse(seq_decoded["type"].bered)
5382 self.assertTrue(seq_decoded["value"].bered)
5384 chunk = chunk[:-1] + b"\x01"
5385 chunks = b"".join([chunk] * (chunks + 1))
5386 encoded = OctetString.tag_default + len_encode(len(chunks)) + chunks
5388 ("type", ObjectIdentifier("1.2.3")),
5389 ("value", Any(encoded)),
5391 seq_encoded = seq.encode()
5392 seq_decoded, _ = Seq().decode(seq_encoded, ctx={"bered": True})
5393 self.assertIsNotNone(seq_decoded["value"].defined)
5395 list(seq_decoded.pps())
5396 pprint(seq_decoded, big_blobs=True, with_decode_path=True)
5397 self.assertTrue(seq_decoded.bered)
5398 self.assertFalse(seq_decoded["type"].bered)
5399 self.assertTrue(seq_decoded["value"].bered)
5403 def choice_values_strategy(draw, value_required=False, schema=None, do_expl=False):
5405 names = list(draw(sets(text_letters(), min_size=1, max_size=5)))
5406 tags = [{tag_type: tag_value} for tag_type, tag_value in draw(sets(
5408 tuples(just("impl"), integers(min_value=0).map(tag_encode)),
5409 tuples(just("expl"), integers(min_value=0).map(tag_ctxp)),
5411 min_size=len(names),
5412 max_size=len(names),
5415 (name, Integer(**tag_kwargs))
5416 for name, tag_kwargs in zip(names, tags)
5419 if value_required or draw(booleans()):
5420 value = draw(tuples(
5421 sampled_from([name for name, _ in schema]),
5422 integers().map(Integer),
5426 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5427 default = draw(one_of(
5429 tuples(sampled_from([name for name, _ in schema]), integers().map(Integer)),
5431 optional = draw(one_of(none(), booleans()))
5433 draw(integers(min_value=0)),
5434 draw(integers(min_value=0)),
5435 draw(integers(min_value=0)),
5437 return (schema, value, expl, default, optional, _decoded)
5440 class ChoiceInherited(Choice):
5444 class TestChoice(CommonMixin, TestCase):
5446 schema = (("whatever", Boolean()),)
5449 def test_schema_required(self):
5450 with assertRaisesRegex(self, ValueError, "schema must be specified"):
5453 def test_impl_forbidden(self):
5454 with assertRaisesRegex(self, ValueError, "no implicit tag allowed"):
5455 Choice(impl=b"whatever")
5457 def test_invalid_value_type(self):
5458 with self.assertRaises(InvalidValueType) as err:
5459 self.base_klass(123)
5461 with self.assertRaises(ObjUnknown) as err:
5462 self.base_klass(("whenever", Boolean(False)))
5464 with self.assertRaises(InvalidValueType) as err:
5465 self.base_klass(("whatever", Integer(123)))
5469 def test_optional(self, optional):
5470 obj = self.base_klass(
5471 default=self.base_klass(("whatever", Boolean(False))),
5474 self.assertTrue(obj.optional)
5477 def test_ready(self, value):
5478 obj = self.base_klass()
5479 self.assertFalse(obj.ready)
5482 pprint(obj, big_blobs=True, with_decode_path=True)
5483 self.assertIsNone(obj["whatever"])
5484 with self.assertRaises(ObjNotReady) as err:
5487 with self.assertRaises(ObjNotReady) as err:
5489 obj["whatever"] = Boolean()
5490 self.assertFalse(obj.ready)
5493 pprint(obj, big_blobs=True, with_decode_path=True)
5494 obj["whatever"] = Boolean(value)
5495 self.assertTrue(obj.ready)
5498 pprint(obj, big_blobs=True, with_decode_path=True)
5500 @given(booleans(), booleans())
5501 def test_comparison(self, value1, value2):
5502 class WahlInherited(self.base_klass):
5504 for klass in (self.base_klass, WahlInherited):
5505 obj1 = klass(("whatever", Boolean(value1)))
5506 obj2 = klass(("whatever", Boolean(value2)))
5507 self.assertEqual(obj1 == obj2, value1 == value2)
5508 self.assertEqual(obj1 != obj2, value1 != value2)
5509 self.assertEqual(obj1 == obj2._value, value1 == value2)
5510 self.assertFalse(obj1 == obj2._value[1])
5512 @given(data_strategy())
5513 def test_call(self, d):
5514 for klass in (Choice, ChoiceInherited):
5522 ) = d.draw(choice_values_strategy())
5525 schema = schema_initial
5527 value=value_initial,
5529 default=default_initial,
5530 optional=optional_initial or False,
5531 _decoded=_decoded_initial,
5540 ) = d.draw(choice_values_strategy(schema=schema_initial, do_expl=True))
5541 obj = obj_initial(value, expl, default, optional)
5543 value_expected = default if value is None else value
5545 default_initial if value_expected is None
5548 self.assertEqual(obj.choice, value_expected[0])
5549 self.assertEqual(obj.value, int(value_expected[1]))
5550 self.assertEqual(obj.expl_tag, expl or expl_initial)
5551 default_expect = default_initial if default is None else default
5552 if default_expect is not None:
5553 self.assertEqual(obj.default.choice, default_expect[0])
5554 self.assertEqual(obj.default.value, int(default_expect[1]))
5555 if obj.default is None:
5556 optional = optional_initial if optional is None else optional
5557 optional = False if optional is None else optional
5560 self.assertEqual(obj.optional, optional)
5561 self.assertEqual(obj.specs, obj_initial.specs)
5563 def test_simultaneous_impl_expl(self):
5564 # override it, as Any does not have implicit tag
5567 def test_decoded(self):
5568 # override it, as Any does not have implicit tag
5571 @given(choice_values_strategy())
5572 def test_copy(self, values):
5573 _schema, value, expl, default, optional, _decoded = values
5575 class Wahl(self.base_klass):
5577 register_class(Wahl)
5582 optional=optional or False,
5585 for copy_func in copy_funcs:
5586 obj_copied = copy_func(obj)
5587 self.assertIsNone(obj.tag)
5588 self.assertIsNone(obj_copied.tag)
5589 # hack for assert_copied_basic_fields
5590 obj.tag = "whatever"
5591 obj_copied.tag = "whatever"
5592 self.assert_copied_basic_fields(obj, obj_copied)
5594 self.assertEqual(obj._value, obj_copied._value)
5595 self.assertEqual(obj.specs, obj_copied.specs)
5598 def test_stripped(self, value):
5599 obj = self.base_klass(("whatever", Boolean(value)))
5600 with self.assertRaises(NotEnoughData):
5601 obj.decode(obj.encode()[:-1])
5605 integers(min_value=1).map(tag_ctxc),
5607 def test_stripped_expl(self, value, tag_expl):
5608 obj = self.base_klass(("whatever", Boolean(value)), expl=tag_expl)
5609 with self.assertRaises(NotEnoughData):
5610 obj.decode(obj.encode()[:-1])
5612 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
5613 @given(data_strategy())
5614 def test_symmetric(self, d):
5615 _schema, value, _, default, optional, _decoded = d.draw(
5616 choice_values_strategy(value_required=True)
5618 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
5619 offset = d.draw(integers(min_value=0))
5620 tail_junk = d.draw(binary(max_size=5))
5621 decode_path = d.draw(decode_path_strat)
5623 class Wahl(self.base_klass):
5633 pprint(obj, big_blobs=True, with_decode_path=True)
5634 self.assertFalse(obj.expled)
5635 self.assertEqual(obj.tag_order, obj.value.tag_order)
5636 obj_encoded = obj.encode()
5637 self.assertEqual(encode2pass(obj), obj_encoded)
5638 obj_expled = obj(value, expl=tag_expl)
5639 self.assertTrue(obj_expled.expled)
5640 tag_class, _, tag_num = tag_decode(tag_expl)
5641 self.assertEqual(obj_expled.tag_order, (tag_class, tag_num))
5643 list(obj_expled.pps())
5644 pprint(obj_expled, big_blobs=True, with_decode_path=True)
5645 obj_expled_encoded = obj_expled.encode()
5646 ctx_copied = deepcopy(ctx_dummy)
5647 obj_decoded, tail = obj_expled.decode(
5648 obj_expled_encoded + tail_junk,
5652 self.assertDictEqual(ctx_copied, ctx_dummy)
5654 list(obj_decoded.pps())
5655 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
5656 self.assertEqual(tail, tail_junk)
5657 self.assertEqual(obj_decoded, obj_expled)
5658 self.assertEqual(obj_decoded.choice, obj_expled.choice)
5659 self.assertEqual(obj_decoded.value, obj_expled.value)
5660 self.assertEqual(obj_decoded.choice, obj.choice)
5661 self.assertEqual(obj_decoded.value, obj.value)
5662 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
5663 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
5664 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
5666 obj_decoded.expl_llen,
5667 len(len_encode(len(obj_encoded))),
5669 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
5670 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
5673 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
5675 self.assertEqual(obj_decoded.expl_offset, offset)
5676 self.assertSequenceEqual(
5678 obj_decoded.value.fulloffset - offset:
5679 obj_decoded.value.fulloffset + obj_decoded.value.fulllen - offset
5683 assert_exceeding_data(
5685 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
5689 evgens = list(obj_expled.decode_evgen(
5690 obj_expled_encoded + tail_junk,
5692 decode_path=decode_path,
5695 self.assertEqual(len(evgens), 2)
5696 _decode_path, obj, tail = evgens[0]
5697 self.assertEqual(_decode_path, decode_path + (obj_decoded.choice,))
5698 _decode_path, obj, tail = evgens[1]
5699 self.assertSequenceEqual(tail, tail_junk)
5700 self.assertEqual(_decode_path, decode_path)
5701 self.assertEqual(obj.expl_offset, offset)
5706 def test_set_get(self, value):
5709 ("erste", Boolean()),
5710 ("zweite", Integer()),
5713 with self.assertRaises(ObjUnknown) as err:
5714 obj["whatever"] = "whenever"
5715 with self.assertRaises(InvalidValueType) as err:
5716 obj["zweite"] = Boolean(False)
5717 obj["zweite"] = Integer(value)
5719 with self.assertRaises(ObjUnknown) as err:
5722 self.assertIsNone(obj["erste"])
5723 self.assertEqual(obj["zweite"], Integer(value))
5725 def test_tag_mismatch(self):
5728 ("erste", Boolean()),
5730 int_encoded = Integer(123).encode()
5731 bool_encoded = Boolean(False).encode()
5733 obj.decode(bool_encoded)
5734 with self.assertRaises(TagMismatch):
5735 obj.decode(int_encoded)
5737 def test_tag_mismatch_underlying(self):
5738 class SeqOfBoolean(SequenceOf):
5741 class SeqOfInteger(SequenceOf):
5746 ("erste", SeqOfBoolean()),
5749 int_encoded = SeqOfInteger((Integer(123),)).encode()
5750 bool_encoded = SeqOfBoolean((Boolean(False),)).encode()
5752 obj.decode(bool_encoded)
5753 with self.assertRaises(TagMismatch) as err:
5754 obj.decode(int_encoded)
5755 self.assertEqual(err.exception.decode_path, ("erste", "0"))
5759 def seq_values_strategy(draw, seq_klass, do_expl=False):
5761 if draw(booleans()):
5763 value._value = draw(dictionaries(
5766 booleans().map(Boolean),
5767 integers().map(Integer),
5771 if draw(booleans()):
5772 schema = list(draw(dictionaries(
5775 booleans().map(Boolean),
5776 integers().map(Integer),
5782 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5784 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
5786 if draw(booleans()):
5787 default = seq_klass()
5788 default._value = draw(dictionaries(
5791 booleans().map(Boolean),
5792 integers().map(Integer),
5795 optional = draw(one_of(none(), booleans()))
5797 draw(integers(min_value=0)),
5798 draw(integers(min_value=0)),
5799 draw(integers(min_value=0)),
5801 return (value, schema, impl, expl, default, optional, _decoded)
5805 def sequence_strategy(draw, seq_klass):
5806 inputs = draw(lists(
5808 tuples(just(Boolean), booleans(), one_of(none(), booleans())),
5809 tuples(just(Integer), integers(), one_of(none(), integers())),
5814 integers(min_value=1),
5815 min_size=len(inputs),
5816 max_size=len(inputs),
5819 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5820 for tag, expled in zip(tags, draw(lists(
5822 min_size=len(inputs),
5823 max_size=len(inputs),
5827 for i, optional in enumerate(draw(lists(
5828 sampled_from(("required", "optional", "empty")),
5829 min_size=len(inputs),
5830 max_size=len(inputs),
5832 if optional in ("optional", "empty"):
5833 inits[i]["optional"] = True
5834 if optional == "empty":
5836 empties = set(empties)
5837 names = list(draw(sets(
5839 min_size=len(inputs),
5840 max_size=len(inputs),
5843 for i, (klass, value, default) in enumerate(inputs):
5844 schema.append((names[i], klass(default=default, **inits[i])))
5845 seq_name = draw(text_letters())
5846 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5849 for i, (klass, value, default) in enumerate(inputs):
5856 "default_value": None if spec.default is None else default,
5860 expect["optional"] = True
5862 expect["presented"] = True
5863 expect["value"] = value
5865 expect["optional"] = True
5866 if default is not None and default == value:
5867 expect["presented"] = False
5868 seq[name] = klass(value)
5869 expects.append(expect)
5874 def sequences_strategy(draw, seq_klass):
5875 tags = draw(sets(integers(min_value=1), min_size=0, max_size=5))
5877 ({"expl": tag_ctxc(tag)} if expled else {"impl": tag_encode(tag)})
5878 for tag, expled in zip(tags, draw(lists(
5885 i for i, is_default in enumerate(draw(lists(
5891 names = list(draw(sets(
5896 seq_expectses = draw(lists(
5897 sequence_strategy(seq_klass=seq_klass),
5901 seqs = [seq for seq, _ in seq_expectses]
5903 for i, (name, seq) in enumerate(zip(names, seqs)):
5906 seq(default=(seq if i in defaulted else None), **inits[i]),
5908 seq_name = draw(text_letters())
5909 Seq = type(seq_name, (seq_klass,), {"schema": tuple(schema)})
5912 for name, (seq_inner, expects_inner) in zip(names, seq_expectses):
5915 "expects": expects_inner,
5918 seq_outer[name] = seq_inner
5919 if seq_outer.specs[name].default is None:
5920 expect["presented"] = True
5921 expect_outers.append(expect)
5922 return seq_outer, expect_outers
5925 class SeqMixing(object):
5926 def test_invalid_value_type(self):
5927 with self.assertRaises(InvalidValueType) as err:
5928 self.base_klass(123)
5931 def test_invalid_value_type_set(self):
5932 class Seq(self.base_klass):
5933 schema = (("whatever", Boolean()),)
5935 with self.assertRaises(InvalidValueType) as err:
5936 seq["whatever"] = Integer(123)
5940 def test_optional(self, optional):
5941 obj = self.base_klass(default=self.base_klass(), optional=optional)
5942 self.assertTrue(obj.optional)
5944 @given(data_strategy())
5945 def test_ready(self, d):
5947 str(i): v for i, v in enumerate(d.draw(lists(
5954 str(i + len(ready)): v for i, v in enumerate(d.draw(lists(
5961 for name in d.draw(permutations(
5962 list(ready.keys()) + list(non_ready.keys()),
5964 schema_input.append((name, Boolean()))
5966 class Seq(self.base_klass):
5967 schema = tuple(schema_input)
5969 for name in ready.keys():
5971 seq[name] = Boolean()
5972 self.assertFalse(seq.ready)
5975 pprint(seq, big_blobs=True, with_decode_path=True)
5976 for name, value in ready.items():
5977 seq[name] = Boolean(value)
5978 self.assertFalse(seq.ready)
5981 pprint(seq, big_blobs=True, with_decode_path=True)
5982 with self.assertRaises(ObjNotReady) as err:
5985 with self.assertRaises(ObjNotReady) as err:
5987 for name, value in non_ready.items():
5988 seq[name] = Boolean(value)
5989 self.assertTrue(seq.ready)
5992 pprint(seq, big_blobs=True, with_decode_path=True)
5994 @given(data_strategy())
5995 def test_call(self, d):
5996 class SeqInherited(self.base_klass):
5998 for klass in (self.base_klass, SeqInherited):
6007 ) = d.draw(seq_values_strategy(seq_klass=klass))
6008 obj_initial = klass(
6014 optional_initial or False,
6025 ) = d.draw(seq_values_strategy(
6027 do_expl=impl_initial is None,
6029 obj = obj_initial(value, impl, expl, default, optional)
6030 value_expected = default if value is None else value
6032 default_initial if value_expected is None
6035 self.assertEqual(obj._value, getattr(value_expected, "_value", {}))
6036 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6037 self.assertEqual(obj.expl_tag, expl or expl_initial)
6039 {} if obj.default is None else obj.default._value,
6040 getattr(default_initial if default is None else default, "_value", {}),
6042 if obj.default is None:
6043 optional = optional_initial if optional is None else optional
6044 optional = False if optional is None else optional
6047 self.assertEqual(list(obj.specs.items()), schema_initial or [])
6048 self.assertEqual(obj.optional, optional)
6050 @given(data_strategy())
6051 def test_copy(self, d):
6052 class SeqInherited(self.base_klass):
6054 register_class(SeqInherited)
6055 for klass in (self.base_klass, SeqInherited):
6056 values = d.draw(seq_values_strategy(seq_klass=klass))
6057 obj = klass(*values)
6058 for copy_func in copy_funcs:
6059 obj_copied = copy_func(obj)
6060 self.assert_copied_basic_fields(obj, obj_copied)
6061 self.assertEqual(obj.specs, obj_copied.specs)
6062 self.assertEqual(obj._value, obj_copied._value)
6064 @given(data_strategy())
6065 def test_stripped(self, d):
6066 value = d.draw(integers())
6067 tag_impl = tag_encode(d.draw(integers(min_value=1)))
6069 class Seq(self.base_klass):
6071 schema = (("whatever", Integer()),)
6073 seq["whatever"] = Integer(value)
6074 with self.assertRaises(NotEnoughData):
6075 seq.decode(seq.encode()[:-1])
6077 @given(data_strategy())
6078 def test_stripped_expl(self, d):
6079 value = d.draw(integers())
6080 tag_expl = tag_ctxc(d.draw(integers(min_value=1)))
6082 class Seq(self.base_klass):
6084 schema = (("whatever", Integer()),)
6086 seq["whatever"] = Integer(value)
6087 with self.assertRaises(NotEnoughData):
6088 seq.decode(seq.encode()[:-1])
6090 @given(integers(min_value=3), binary(min_size=2))
6091 def test_non_tag_mismatch_raised(self, junk_tag_num, junk):
6092 junk = tag_encode(junk_tag_num) + junk
6094 _, _, len_encoded = tag_strip(memoryview(junk))
6095 len_decode(len_encoded)
6101 class Seq(self.base_klass):
6103 ("whatever", Integer()),
6105 ("whenever", Integer()),
6108 seq["whatever"] = Integer(123)
6109 seq["junk"] = Any(junk)
6110 seq["whenever"] = Integer(123)
6111 with self.assertRaises(DecodeError):
6112 seq.decode(seq.encode())
6115 integers(min_value=31),
6116 integers(min_value=0),
6119 def test_bad_tag(self, tag, offset, decode_path):
6120 with self.assertRaises(DecodeError) as err:
6121 self.base_klass().decode(
6122 tag_encode(tag)[:-1],
6124 decode_path=decode_path,
6127 self.assertEqual(err.exception.offset, offset)
6128 self.assertEqual(err.exception.decode_path, decode_path)
6131 integers(min_value=128),
6132 integers(min_value=0),
6135 def test_bad_len(self, l, offset, decode_path):
6136 with self.assertRaises(DecodeError) as err:
6137 self.base_klass().decode(
6138 self.base_klass.tag_default + len_encode(l)[:-1],
6140 decode_path=decode_path,
6143 self.assertEqual(err.exception.offset, offset)
6144 self.assertEqual(err.exception.decode_path, decode_path)
6146 def _assert_expects(self, seq, expects):
6147 for expect in expects:
6149 seq.specs[expect["name"]].optional,
6152 if expect["default_value"] is not None:
6154 seq.specs[expect["name"]].default,
6155 expect["default_value"],
6157 if expect["presented"]:
6158 self.assertIn(expect["name"], seq)
6159 self.assertEqual(seq[expect["name"]], expect["value"])
6161 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6162 @given(data_strategy())
6163 def test_symmetric(self, d):
6164 seq, expects = d.draw(sequence_strategy(seq_klass=self.base_klass))
6165 tail_junk = d.draw(binary(max_size=5))
6166 decode_path = d.draw(decode_path_strat)
6167 self.assertTrue(seq.ready)
6168 self.assertFalse(seq.decoded)
6169 self._assert_expects(seq, expects)
6172 pprint(seq, big_blobs=True, with_decode_path=True)
6173 self.assertTrue(seq.ready)
6174 seq_encoded = seq.encode()
6175 self.assertEqual(encode2pass(seq), seq_encoded)
6176 seq_encoded_cer = encode_cer(seq)
6177 self.assertNotEqual(seq_encoded_cer, seq_encoded)
6178 self.assertSequenceEqual(
6179 seq.decod(seq_encoded_cer, ctx={"bered": True}).encode(),
6182 seq_decoded, tail = seq.decode(seq_encoded + tail_junk)
6183 self.assertFalse(seq_decoded.lenindef)
6184 self.assertFalse(seq_decoded.ber_encoded)
6185 self.assertFalse(seq_decoded.bered)
6187 t, _, lv = tag_strip(seq_encoded)
6188 _, _, v = len_decode(lv)
6189 seq_encoded_lenindef = t + LENINDEF + v + EOC
6190 with self.assertRaises(DecodeError):
6191 seq.decode(seq_encoded_lenindef)
6192 ctx_copied = deepcopy(ctx_dummy)
6193 ctx_copied["bered"] = True
6194 seq_decoded_lenindef, tail_lenindef = seq.decode(
6195 seq_encoded_lenindef + tail_junk,
6198 del ctx_copied["bered"]
6199 self.assertDictEqual(ctx_copied, ctx_dummy)
6200 self.assertTrue(seq_decoded_lenindef.lenindef)
6201 self.assertTrue(seq_decoded_lenindef.bered)
6202 seq_decoded_lenindef = copy(seq_decoded_lenindef)
6203 self.assertTrue(seq_decoded_lenindef.lenindef)
6204 self.assertTrue(seq_decoded_lenindef.bered)
6205 with self.assertRaises(DecodeError):
6206 seq.decode(seq_encoded_lenindef[:-1], ctx={"bered": True})
6207 with self.assertRaises(DecodeError):
6208 seq.decode(seq_encoded_lenindef[:-2], ctx={"bered": True})
6209 repr(seq_decoded_lenindef)
6210 list(seq_decoded_lenindef.pps())
6211 pprint(seq_decoded_lenindef, big_blobs=True, with_decode_path=True)
6212 self.assertTrue(seq_decoded_lenindef.ready)
6214 for decoded, decoded_tail, encoded in (
6215 (seq_decoded, tail, seq_encoded),
6216 (seq_decoded_lenindef, tail_lenindef, seq_encoded_lenindef),
6218 self.assertEqual(decoded_tail, tail_junk)
6219 self._assert_expects(decoded, expects)
6220 self.assertEqual(seq, decoded)
6221 self.assertEqual(decoded.encode(), seq_encoded)
6222 self.assertEqual(decoded.tlvlen, len(encoded))
6223 for expect in expects:
6224 if not expect["presented"]:
6225 self.assertNotIn(expect["name"], decoded)
6227 self.assertIn(expect["name"], decoded)
6228 obj = decoded[expect["name"]]
6229 self.assertTrue(obj.decoded)
6230 offset = obj.expl_offset if obj.expled else obj.offset
6231 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6232 self.assertSequenceEqual(
6233 seq_encoded[offset:offset + tlvlen],
6237 evgens = list(seq.decode_evgen(
6238 encoded + decoded_tail,
6239 decode_path=decode_path,
6240 ctx={"bered": True},
6242 self.assertEqual(len(evgens), len(list(decoded._values_for_encoding())) + 1)
6243 for _decode_path, obj, _ in evgens[:-1]:
6244 self.assertEqual(_decode_path[:-1], decode_path)
6247 _decode_path, obj, tail = evgens[-1]
6248 self.assertEqual(_decode_path, decode_path)
6252 assert_exceeding_data(
6254 lambda: seq.decod(seq_encoded_lenindef + tail_junk, ctx={"bered": True}),
6258 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6259 @given(data_strategy())
6260 def test_symmetric_with_seq(self, d):
6261 seq, expect_outers = d.draw(sequences_strategy(seq_klass=self.base_klass))
6262 self.assertTrue(seq.ready)
6263 seq_encoded = seq.encode()
6264 self.assertEqual(encode2pass(seq), seq_encoded)
6265 seq_decoded, tail = seq.decode(seq_encoded)
6266 self.assertEqual(tail, b"")
6267 self.assertTrue(seq.ready)
6268 self.assertEqual(seq, seq_decoded)
6269 self.assertEqual(seq_decoded.encode(), seq_encoded)
6270 for expect_outer in expect_outers:
6271 if not expect_outer["presented"]:
6272 self.assertNotIn(expect_outer["name"], seq_decoded)
6274 self.assertIn(expect_outer["name"], seq_decoded)
6275 obj = seq_decoded[expect_outer["name"]]
6276 self.assertTrue(obj.decoded)
6277 offset = obj.expl_offset if obj.expled else obj.offset
6278 tlvlen = obj.expl_tlvlen if obj.expled else obj.tlvlen
6279 self.assertSequenceEqual(
6280 seq_encoded[offset:offset + tlvlen],
6283 self._assert_expects(obj, expect_outer["expects"])
6285 @given(data_strategy())
6286 def test_default_disappears(self, d):
6287 _schema = list(d.draw(dictionaries(
6289 sets(integers(), min_size=2, max_size=2),
6293 class Seq(self.base_klass):
6295 (n, Integer(default=d))
6296 for n, (_, d) in _schema
6299 for name, (value, _) in _schema:
6300 seq[name] = Integer(value)
6301 self.assertEqual(len(seq._value), len(_schema))
6302 empty_seq = b"".join((self.base_klass.tag_default, len_encode(0)))
6303 self.assertGreater(len(seq.encode()), len(empty_seq))
6304 for name, (_, default) in _schema:
6305 seq[name] = Integer(default)
6306 self.assertEqual(len(seq._value), 0)
6307 self.assertSequenceEqual(seq.encode(), empty_seq)
6309 @given(data_strategy())
6310 def test_encoded_default_not_accepted(self, d):
6311 _schema = list(d.draw(dictionaries(
6316 tags = [tag_encode(tag) for tag in d.draw(sets(
6317 integers(min_value=1),
6318 min_size=len(_schema),
6319 max_size=len(_schema),
6323 schema = (("int", Integer()),)
6325 class SeqWithoutDefault(self.base_klass):
6328 for (n, _), t in zip(_schema, tags)
6330 seq_without_default = SeqWithoutDefault()
6331 for name, value in _schema:
6332 seq_without_default[name] = Wahl(("int", Integer(value)))
6333 seq_encoded = seq_without_default.encode()
6334 seq_without_default.decode(seq_encoded)
6336 len(list(seq_without_default.decode_evgen(seq_encoded))),
6337 len(_schema) * 2 + 1,
6340 class SeqWithDefault(self.base_klass):
6342 (n, Wahl(default=Wahl(("int", Integer(v))), expl=t))
6343 for (n, v), t in zip(_schema, tags)
6345 seq_with_default = SeqWithDefault()
6346 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6347 seq_with_default.decode(seq_encoded)
6348 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
6349 list(seq_with_default.decode_evgen(seq_encoded))
6350 for ctx in ({"bered": True}, {"allow_default_values": True}):
6351 seq_decoded, _ = seq_with_default.decode(seq_encoded, ctx=ctx)
6352 self.assertTrue(seq_decoded.ber_encoded)
6353 self.assertTrue(seq_decoded.bered)
6354 seq_decoded = copy(seq_decoded)
6355 self.assertTrue(seq_decoded.ber_encoded)
6356 self.assertTrue(seq_decoded.bered)
6357 for name, value in _schema:
6358 self.assertEqual(seq_decoded[name], seq_with_default[name])
6359 self.assertEqual(seq_decoded[name].value, value)
6361 len(list(seq_with_default.decode_evgen(seq_encoded, ctx=ctx))),
6365 seq_without_default = SeqWithoutDefault()
6366 for name, value in _schema:
6367 seq_without_default[name] = Wahl(("int", Integer(value + 1)))
6368 seq_encoded = seq_without_default.encode()
6369 seq_with_default.decode(seq_encoded)
6371 len(list(seq_with_default.decode_evgen(seq_encoded))),
6375 @given(data_strategy())
6376 def test_missing_from_spec(self, d):
6377 names = list(d.draw(sets(text_letters(), min_size=2)))
6378 tags = [tag_encode(tag) for tag in d.draw(sets(
6379 integers(min_value=1),
6380 min_size=len(names),
6381 max_size=len(names),
6383 names_tags = [(name, tag) for tag, name in sorted(zip(tags, names))]
6385 class SeqFull(self.base_klass):
6386 schema = [(n, Integer(impl=t)) for n, t in names_tags]
6387 seq_full = SeqFull()
6388 for i, name in enumerate(names):
6389 seq_full[name] = Integer(i)
6390 seq_encoded = seq_full.encode()
6391 altered = names_tags[:-2] + names_tags[-1:]
6393 class SeqMissing(self.base_klass):
6394 schema = [(n, Integer(impl=t)) for n, t in altered]
6395 seq_missing = SeqMissing()
6396 with self.assertRaises(TagMismatch):
6397 seq_missing.decode(seq_encoded)
6398 with self.assertRaises(TagMismatch):
6399 list(seq_missing.decode_evgen(seq_encoded))
6401 def test_bered(self):
6402 class Seq(self.base_klass):
6403 schema = (("underlying", Boolean()),)
6404 encoded = Boolean.tag_default + len_encode(1) + b"\x01"
6405 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6406 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6407 self.assertFalse(decoded.ber_encoded)
6408 self.assertFalse(decoded.lenindef)
6409 self.assertTrue(decoded.bered)
6410 decoded = copy(decoded)
6411 self.assertFalse(decoded.ber_encoded)
6412 self.assertFalse(decoded.lenindef)
6413 self.assertTrue(decoded.bered)
6415 class Seq(self.base_klass):
6416 schema = (("underlying", OctetString()),)
6418 tag_encode(form=TagFormConstructed, num=4) +
6420 OctetString(b"whatever").encode() +
6423 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6424 with self.assertRaises(DecodeError):
6425 Seq().decode(encoded)
6426 with self.assertRaises(DecodeError):
6427 list(Seq().decode_evgen(encoded))
6428 list(Seq().decode_evgen(encoded, ctx={"bered": True}))
6429 decoded, _ = Seq().decode(encoded, ctx={"bered": True})
6430 self.assertFalse(decoded.ber_encoded)
6431 self.assertFalse(decoded.lenindef)
6432 self.assertTrue(decoded.bered)
6433 decoded = copy(decoded)
6434 self.assertFalse(decoded.ber_encoded)
6435 self.assertFalse(decoded.lenindef)
6436 self.assertTrue(decoded.bered)
6439 class TestSequence(SeqMixing, CommonMixin, TestCase):
6440 base_klass = Sequence
6446 def test_remaining(self, value, junk):
6447 class Seq(Sequence):
6449 ("whatever", Integer()),
6451 int_encoded = Integer(value).encode()
6453 Sequence.tag_default,
6454 len_encode(len(int_encoded + junk)),
6457 with assertRaisesRegex(self, DecodeError, "remaining"):
6458 Seq().decode(junked)
6460 @given(sets(text_letters(), min_size=2))
6461 def test_obj_unknown(self, names):
6462 missing = names.pop()
6464 class Seq(Sequence):
6465 schema = [(n, Boolean()) for n in names]
6467 with self.assertRaises(ObjUnknown) as err:
6470 with self.assertRaises(ObjUnknown) as err:
6471 seq[missing] = Boolean()
6474 def test_x690_vector(self):
6475 class Seq(Sequence):
6477 ("name", IA5String()),
6480 seq = Seq().decode(hexdec("300A1605536d6974680101FF"))[0]
6481 self.assertEqual(seq["name"], "Smith")
6482 self.assertEqual(seq["ok"], True)
6485 class TestSet(SeqMixing, CommonMixin, TestCase):
6488 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6489 @given(data_strategy())
6490 def test_sorted(self, d):
6491 class DummySeq(Sequence):
6492 schema = (("null", Null()),)
6494 tag_nums = d.draw(sets(integers(min_value=1), min_size=1, max_size=50))
6495 _, _, dummy_seq_tag_num = tag_decode(DummySeq.tag_default)
6496 assume(any(i > dummy_seq_tag_num for i in tag_nums))
6497 tag_nums -= set([dummy_seq_tag_num])
6498 _schema = [(str(i), OctetString(impl=tag_encode(i))) for i in tag_nums]
6499 _schema.append(("seq", DummySeq()))
6502 schema = d.draw(permutations(_schema))
6504 for name, _ in _schema:
6506 seq[name] = OctetString(name.encode("ascii"))
6507 seq["seq"] = DummySeq((("null", Null()),))
6509 seq_encoded = seq.encode()
6510 seq_decoded, _ = seq.decode(seq_encoded)
6511 seq_encoded_expected = []
6512 for tag_num in sorted(tag_nums | set([dummy_seq_tag_num])):
6513 if tag_num == dummy_seq_tag_num:
6514 seq_encoded_expected.append(seq["seq"].encode())
6516 seq_encoded_expected.append(seq[str(tag_num)].encode())
6517 self.assertSequenceEqual(
6518 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
6519 b"".join(seq_encoded_expected),
6522 encoded = b"".join(seq[str(i)].encode() for i in tag_nums)
6523 encoded += seq["seq"].encode()
6524 seq_encoded = b"".join((
6526 len_encode(len(encoded)),
6529 with assertRaisesRegex(self, DecodeError, "unordered SET"):
6530 seq.decode(seq_encoded)
6531 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
6532 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
6533 self.assertTrue(seq_decoded.ber_encoded)
6534 self.assertTrue(seq_decoded.bered)
6535 seq_decoded = copy(seq_decoded)
6536 self.assertTrue(seq_decoded.ber_encoded)
6537 self.assertTrue(seq_decoded.bered)
6539 def test_same_value_twice(self):
6542 ("bool", Boolean()),
6546 encoded = b"".join((
6547 Integer(123).encode(),
6548 Integer(234).encode(),
6549 Boolean(True).encode(),
6551 encoded = Seq.tag_default + len_encode(len(encoded)) + encoded
6552 with self.assertRaises(TagMismatch):
6553 Seq().decod(encoded, ctx={"allow_unordered_set": True})
6557 def seqof_values_strategy(draw, schema=None, do_expl=False):
6559 schema = draw(sampled_from((Boolean(), Integer())))
6560 bound_min, bound_max = sorted(draw(sets(
6561 integers(min_value=0, max_value=10),
6565 if isinstance(schema, Boolean):
6566 values_generator = booleans().map(Boolean)
6567 elif isinstance(schema, Integer):
6568 values_generator = integers().map(Integer)
6569 values_generator = lists(
6574 values = draw(one_of(none(), values_generator))
6578 expl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6580 impl = draw(one_of(none(), integers(min_value=1).map(tag_encode)))
6581 default = draw(one_of(none(), values_generator))
6582 optional = draw(one_of(none(), booleans()))
6584 draw(integers(min_value=0)),
6585 draw(integers(min_value=0)),
6586 draw(integers(min_value=0)),
6591 (bound_min, bound_max),
6600 class SeqOfMixing(object):
6601 def test_invalid_value_type(self):
6602 with self.assertRaises(InvalidValueType) as err:
6603 self.base_klass(123)
6606 def test_invalid_values_type(self):
6607 class SeqOf(self.base_klass):
6609 with self.assertRaises(InvalidValueType) as err:
6610 SeqOf([Integer(123), Boolean(False), Integer(234)])
6613 def test_schema_required(self):
6614 with assertRaisesRegex(self, ValueError, "schema must be specified"):
6615 self.base_klass.__mro__[1]()
6617 @given(booleans(), booleans(), binary(min_size=1), binary(min_size=1))
6618 def test_comparison(self, value1, value2, tag1, tag2):
6619 class SeqOf(self.base_klass):
6621 obj1 = SeqOf([Boolean(value1)])
6622 obj2 = SeqOf([Boolean(value2)])
6623 self.assertEqual(obj1 == obj2, value1 == value2)
6624 self.assertEqual(obj1 != obj2, value1 != value2)
6625 self.assertEqual(obj1 == list(obj2), value1 == value2)
6626 self.assertEqual(obj1 == tuple(obj2), value1 == value2)
6627 obj1 = SeqOf([Boolean(value1)], impl=tag1)
6628 obj2 = SeqOf([Boolean(value1)], impl=tag2)
6629 self.assertEqual(obj1 == obj2, tag1 == tag2)
6630 self.assertEqual(obj1 != obj2, tag1 != tag2)
6632 @given(lists(booleans()))
6633 def test_iter(self, values):
6634 class SeqOf(self.base_klass):
6636 obj = SeqOf([Boolean(value) for value in values])
6637 self.assertEqual(len(obj), len(values))
6638 for i, value in enumerate(obj):
6639 self.assertEqual(value, values[i])
6641 @given(data_strategy())
6642 def test_ready(self, d):
6643 ready = [Integer(v) for v in d.draw(lists(
6650 range(d.draw(integers(min_value=1, max_value=5)))
6653 class SeqOf(self.base_klass):
6655 values = d.draw(permutations(ready + non_ready))
6657 for value in values:
6659 self.assertFalse(seqof.ready)
6662 pprint(seqof, big_blobs=True, with_decode_path=True)
6663 with self.assertRaises(ObjNotReady) as err:
6666 with self.assertRaises(ObjNotReady) as err:
6668 for i, value in enumerate(values):
6669 self.assertEqual(seqof[i], value)
6670 if not seqof[i].ready:
6671 seqof[i] = Integer(i)
6672 self.assertTrue(seqof.ready)
6675 pprint(seqof, big_blobs=True, with_decode_path=True)
6677 def test_spec_mismatch(self):
6678 class SeqOf(self.base_klass):
6681 seqof.append(Integer(123))
6682 with self.assertRaises(ValueError):
6683 seqof.append(Boolean(False))
6684 with self.assertRaises(ValueError):
6685 seqof[0] = Boolean(False)
6687 @given(data_strategy())
6688 def test_bounds_satisfied(self, d):
6689 class SeqOf(self.base_klass):
6691 bound_min = d.draw(integers(min_value=0, max_value=1 << 7))
6692 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6693 value = [Boolean()] * d.draw(integers(min_value=bound_min, max_value=bound_max))
6694 SeqOf(value=value, bounds=(bound_min, bound_max))
6696 @given(data_strategy())
6697 def test_bounds_unsatisfied(self, d):
6698 class SeqOf(self.base_klass):
6700 bound_min = d.draw(integers(min_value=1, max_value=1 << 7))
6701 bound_max = d.draw(integers(min_value=bound_min, max_value=1 << 7))
6702 value = [Boolean(False)] * d.draw(integers(max_value=bound_min - 1))
6703 with self.assertRaises(BoundsError) as err:
6704 SeqOf(value=value, bounds=(bound_min, bound_max))
6706 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6707 SeqOf(bounds=(bound_min, bound_max)).decode(
6708 SeqOf(value).encode()
6711 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6712 SeqOf(bounds=(bound_min, bound_max)).decode(
6713 encode2pass(SeqOf(value))
6715 value = [Boolean(True)] * d.draw(integers(
6716 min_value=bound_max + 1,
6717 max_value=bound_max + 10,
6719 with self.assertRaises(BoundsError) as err:
6720 SeqOf(value=value, bounds=(bound_min, bound_max))
6722 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6723 SeqOf(bounds=(bound_min, bound_max)).decode(
6724 SeqOf(value).encode()
6727 with assertRaisesRegex(self, DecodeError, "bounds") as err:
6728 SeqOf(bounds=(bound_min, bound_max)).decode(
6729 encode2pass(SeqOf(value))
6732 @given(integers(min_value=1, max_value=10))
6733 def test_out_of_bounds(self, bound_max):
6734 class SeqOf(self.base_klass):
6736 bounds = (0, bound_max)
6738 for _ in range(bound_max):
6739 seqof.append(Integer(123))
6740 with self.assertRaises(BoundsError):
6741 seqof.append(Integer(123))
6743 @given(data_strategy())
6744 def test_call(self, d):
6754 ) = d.draw(seqof_values_strategy())
6756 class SeqOf(self.base_klass):
6757 schema = schema_initial
6758 obj_initial = SeqOf(
6759 value=value_initial,
6760 bounds=bounds_initial,
6763 default=default_initial,
6764 optional=optional_initial or False,
6765 _decoded=_decoded_initial,
6776 ) = d.draw(seqof_values_strategy(
6777 schema=schema_initial,
6778 do_expl=impl_initial is None,
6780 if (default is None) and (obj_initial.default is not None):
6783 (bounds is None) and
6784 (value is not None) and
6785 (bounds_initial is not None) and
6786 not (bounds_initial[0] <= len(value) <= bounds_initial[1])
6790 (bounds is None) and
6791 (default is not None) and
6792 (bounds_initial is not None) and
6793 not (bounds_initial[0] <= len(default) <= bounds_initial[1])
6805 value_expected = default if value is None else value
6807 default_initial if value_expected is None
6810 value_expected = () if value_expected is None else value_expected
6811 self.assertEqual(obj, value_expected)
6812 self.assertEqual(obj.tag, impl or impl_initial or obj.tag_default)
6813 self.assertEqual(obj.expl_tag, expl or expl_initial)
6816 default_initial if default is None else default,
6818 if obj.default is None:
6819 optional = optional_initial if optional is None else optional
6820 optional = False if optional is None else optional
6823 self.assertEqual(obj.optional, optional)
6825 (obj._bound_min, obj._bound_max),
6826 bounds or bounds_initial or (0, float("+inf")),
6829 @given(seqof_values_strategy())
6830 def test_copy(self, values):
6831 _schema, value, bounds, impl, expl, default, optional, _decoded = values
6833 class SeqOf(self.base_klass):
6835 register_class(SeqOf)
6842 optional=optional or False,
6845 for copy_func in copy_funcs:
6846 obj_copied = copy_func(obj)
6847 self.assert_copied_basic_fields(obj, obj_copied)
6848 self.assertEqual(obj._bound_min, obj_copied._bound_min)
6849 self.assertEqual(obj._bound_max, obj_copied._bound_max)
6850 self.assertEqual(obj._value, obj_copied._value)
6854 integers(min_value=1).map(tag_encode),
6856 def test_stripped(self, values, tag_impl):
6857 class SeqOf(self.base_klass):
6858 schema = OctetString()
6859 obj = SeqOf([OctetString(v) for v in values], impl=tag_impl)
6860 with self.assertRaises(NotEnoughData):
6861 obj.decode(obj.encode()[:-1])
6865 integers(min_value=1).map(tag_ctxc),
6867 def test_stripped_expl(self, values, tag_expl):
6868 class SeqOf(self.base_klass):
6869 schema = OctetString()
6870 obj = SeqOf([OctetString(v) for v in values], expl=tag_expl)
6871 with self.assertRaises(NotEnoughData):
6872 obj.decode(obj.encode()[:-1])
6875 integers(min_value=31),
6876 integers(min_value=0),
6879 def test_bad_tag(self, tag, offset, decode_path):
6880 with self.assertRaises(DecodeError) as err:
6881 self.base_klass().decode(
6882 tag_encode(tag)[:-1],
6884 decode_path=decode_path,
6887 self.assertEqual(err.exception.offset, offset)
6888 self.assertEqual(err.exception.decode_path, decode_path)
6891 integers(min_value=128),
6892 integers(min_value=0),
6895 def test_bad_len(self, l, offset, decode_path):
6896 with self.assertRaises(DecodeError) as err:
6897 self.base_klass().decode(
6898 self.base_klass.tag_default + len_encode(l)[:-1],
6900 decode_path=decode_path,
6903 self.assertEqual(err.exception.offset, offset)
6904 self.assertEqual(err.exception.decode_path, decode_path)
6906 @given(binary(min_size=1))
6907 def test_tag_mismatch(self, impl):
6908 assume(impl != self.base_klass.tag_default)
6909 with self.assertRaises(TagMismatch):
6910 self.base_klass(impl=impl).decode(self.base_klass().encode())
6912 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
6914 seqof_values_strategy(schema=Integer()),
6915 lists(integers().map(Integer)),
6916 integers(min_value=1).map(tag_ctxc),
6917 integers(min_value=0),
6921 def test_symmetric(self, values, value, tag_expl, offset, tail_junk, decode_path):
6922 _, _, _, _, _, default, optional, _decoded = values
6924 class SeqOf(self.base_klass):
6934 pprint(obj, big_blobs=True, with_decode_path=True)
6935 self.assertFalse(obj.expled)
6936 obj_encoded = obj.encode()
6937 self.assertEqual(encode2pass(obj), obj_encoded)
6938 obj_encoded_cer = encode_cer(obj)
6939 self.assertNotEqual(obj_encoded_cer, obj_encoded)
6940 self.assertSequenceEqual(
6941 obj.decod(obj_encoded_cer, ctx={"bered": True}).encode(),
6944 obj_expled = obj(value, expl=tag_expl)
6945 self.assertTrue(obj_expled.expled)
6947 list(obj_expled.pps())
6948 pprint(obj_expled, big_blobs=True, with_decode_path=True)
6949 obj_expled_encoded = obj_expled.encode()
6950 ctx_copied = deepcopy(ctx_dummy)
6951 obj_decoded, tail = obj_expled.decode(
6952 obj_expled_encoded + tail_junk,
6956 self.assertDictEqual(ctx_copied, ctx_dummy)
6958 list(obj_decoded.pps())
6959 pprint(obj_decoded, big_blobs=True, with_decode_path=True)
6960 self.assertEqual(tail, tail_junk)
6961 self._test_symmetric_compare_objs(obj_decoded, obj_expled)
6962 self.assertSequenceEqual(obj_decoded.encode(), obj_expled_encoded)
6963 self.assertSequenceEqual(obj_decoded.expl_tag, tag_expl)
6964 self.assertEqual(obj_decoded.expl_tlen, len(tag_expl))
6966 obj_decoded.expl_llen,
6967 len(len_encode(len(obj_encoded))),
6969 self.assertEqual(obj_decoded.tlvlen, len(obj_encoded))
6970 self.assertEqual(obj_decoded.expl_vlen, len(obj_encoded))
6973 offset + obj_decoded.expl_tlen + obj_decoded.expl_llen,
6975 self.assertEqual(obj_decoded.expl_offset, offset)
6976 for obj_inner in obj_decoded:
6977 self.assertIn(obj_inner, obj_decoded)
6978 self.assertSequenceEqual(
6981 obj_inner.offset - offset:
6982 obj_inner.offset + obj_inner.tlvlen - offset
6986 t, _, lv = tag_strip(obj_encoded)
6987 _, _, v = len_decode(lv)
6988 obj_encoded_lenindef = t + LENINDEF + v + EOC
6989 with self.assertRaises(DecodeError):
6990 obj.decode(obj_encoded_lenindef)
6991 obj_decoded_lenindef, tail_lenindef = obj.decode(
6992 obj_encoded_lenindef + tail_junk,
6993 ctx={"bered": True},
6995 self.assertTrue(obj_decoded_lenindef.lenindef)
6996 self.assertTrue(obj_decoded_lenindef.bered)
6997 obj_decoded_lenindef = copy(obj_decoded_lenindef)
6998 self.assertTrue(obj_decoded_lenindef.lenindef)
6999 self.assertTrue(obj_decoded_lenindef.bered)
7000 repr(obj_decoded_lenindef)
7001 list(obj_decoded_lenindef.pps())
7002 pprint(obj_decoded_lenindef, big_blobs=True, with_decode_path=True)
7003 self.assertEqual(tail_lenindef, tail_junk)
7004 self.assertEqual(obj_decoded_lenindef.tlvlen, len(obj_encoded_lenindef))
7005 with self.assertRaises(DecodeError):
7006 obj.decode(obj_encoded_lenindef[:-1], ctx={"bered": True})
7007 with self.assertRaises(DecodeError):
7008 obj.decode(obj_encoded_lenindef[:-2], ctx={"bered": True})
7010 evgens = list(obj.decode_evgen(
7011 obj_encoded_lenindef + tail_junk,
7012 decode_path=decode_path,
7013 ctx={"bered": True},
7015 self.assertEqual(len(evgens), len(obj_decoded_lenindef) + 1)
7016 for i, (_decode_path, obj, _) in enumerate(evgens[:-1]):
7017 self.assertEqual(_decode_path, decode_path + (str(i),))
7020 _decode_path, obj, tail = evgens[-1]
7021 self.assertEqual(_decode_path, decode_path)
7025 assert_exceeding_data(
7027 lambda: obj_expled.decod(obj_expled_encoded + tail_junk),
7031 def test_bered(self):
7032 class SeqOf(self.base_klass):
7034 encoded = Boolean(False).encode()
7035 encoded += Boolean.tag_default + len_encode(1) + b"\x01"
7036 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7037 with self.assertRaises(DecodeError):
7038 SeqOf().decode(encoded)
7039 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7040 self.assertFalse(decoded.ber_encoded)
7041 self.assertFalse(decoded.lenindef)
7042 self.assertTrue(decoded.bered)
7043 decoded = copy(decoded)
7044 self.assertFalse(decoded.ber_encoded)
7045 self.assertFalse(decoded.lenindef)
7046 self.assertTrue(decoded.bered)
7048 class SeqOf(self.base_klass):
7049 schema = OctetString()
7050 encoded = OctetString(b"whatever").encode()
7052 tag_encode(form=TagFormConstructed, num=4) +
7054 OctetString(b"whatever").encode() +
7057 encoded = SeqOf.tag_default + len_encode(len(encoded)) + encoded
7058 with self.assertRaises(DecodeError):
7059 SeqOf().decode(encoded)
7060 decoded, _ = SeqOf().decode(encoded, ctx={"bered": True})
7061 self.assertFalse(decoded.ber_encoded)
7062 self.assertFalse(decoded.lenindef)
7063 self.assertTrue(decoded.bered)
7064 decoded = copy(decoded)
7065 self.assertFalse(decoded.ber_encoded)
7066 self.assertFalse(decoded.lenindef)
7067 self.assertTrue(decoded.bered)
7070 class TestSequenceOf(SeqOfMixing, CommonMixin, TestCase):
7071 class SeqOf(SequenceOf):
7075 def _test_symmetric_compare_objs(self, obj1, obj2):
7076 self.assertEqual(obj1, obj2)
7077 self.assertSequenceEqual(list(obj1), list(obj2))
7079 def test_iterator_pickling(self):
7080 class SeqOf(SequenceOf):
7082 register_class(SeqOf)
7085 seqof = seqof(iter(six_xrange(10)))
7086 with assertRaisesRegex(self, ValueError, "iterator"):
7089 def test_iterator_bounds(self):
7090 class SeqOf(SequenceOf):
7096 for i in six_xrange(n):
7099 seqof = SeqOf(gen(n))
7100 self.assertTrue(seqof.ready)
7101 with self.assertRaises(BoundsError):
7103 self.assertFalse(seqof.ready)
7104 seqof = seqof(gen(n))
7105 self.assertTrue(seqof.ready)
7106 with self.assertRaises(BoundsError):
7108 self.assertFalse(seqof.ready)
7110 def test_iterator_twice(self):
7111 class SeqOf(SequenceOf):
7113 bounds = (1, float("+inf"))
7116 for i in six_xrange(10):
7118 seqof = SeqOf(gen())
7119 self.assertTrue(seqof.ready)
7121 self.assertFalse(seqof.ready)
7122 register_class(SeqOf)
7125 def test_iterator_2pass(self):
7126 class SeqOf(SequenceOf):
7128 bounds = (1, float("+inf"))
7131 for i in six_xrange(10):
7133 seqof = SeqOf(gen())
7134 self.assertTrue(seqof.ready)
7135 _, state = seqof.encode1st()
7136 self.assertFalse(seqof.ready)
7137 seqof = seqof(gen())
7138 self.assertTrue(seqof.ready)
7140 seqof.encode2nd(buf.write, iter(state))
7141 self.assertSequenceEqual(
7142 [int(i) for i in seqof.decod(buf.getvalue())],
7146 def test_non_ready_bound_min(self):
7147 class SeqOf(SequenceOf):
7149 bounds = (1, float("+inf"))
7151 self.assertFalse(seqof.ready)
7154 class TestSetOf(SeqOfMixing, CommonMixin, TestCase):
7159 def _test_symmetric_compare_objs(self, obj1, obj2):
7160 self.assertSetEqual(
7161 set(int(v) for v in obj1),
7162 set(int(v) for v in obj2),
7165 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7166 @given(data_strategy())
7167 def test_sorted(self, d):
7168 values = [OctetString(v) for v in d.draw(lists(binary()))]
7171 schema = OctetString()
7173 seq_encoded = seq.encode()
7174 seq_decoded, _ = seq.decode(seq_encoded)
7175 self.assertSequenceEqual(
7176 seq_encoded[seq_decoded.tlen + seq_decoded.llen:],
7177 b"".join(sorted([v.encode() for v in values])),
7180 @settings(max_examples=LONG_TEST_MAX_EXAMPLES)
7181 @given(data_strategy())
7182 def test_unsorted(self, d):
7183 values = [OctetString(v).encode() for v in d.draw(sets(
7184 binary(min_size=1, max_size=5),
7188 values = d.draw(permutations(values))
7189 assume(values != sorted(values))
7190 encoded = b"".join(values)
7191 seq_encoded = b"".join((
7193 len_encode(len(encoded)),
7198 schema = OctetString()
7200 with assertRaisesRegex(self, DecodeError, "unordered SET OF"):
7201 seq.decode(seq_encoded)
7203 for ctx in ({"bered": True}, {"allow_unordered_set": True}):
7204 seq_decoded, _ = Seq().decode(seq_encoded, ctx=ctx)
7205 self.assertTrue(seq_decoded.ber_encoded)
7206 self.assertTrue(seq_decoded.bered)
7207 seq_decoded = copy(seq_decoded)
7208 self.assertTrue(seq_decoded.ber_encoded)
7209 self.assertTrue(seq_decoded.bered)
7210 self.assertSequenceEqual(
7211 [obj.encode() for obj in seq_decoded],
7216 class TestGoMarshalVectors(TestCase):
7218 self.assertSequenceEqual(Integer(10).encode(), hexdec("02010a"))
7219 self.assertSequenceEqual(Integer(127).encode(), hexdec("02017f"))
7220 self.assertSequenceEqual(Integer(128).encode(), hexdec("02020080"))
7221 self.assertSequenceEqual(Integer(-128).encode(), hexdec("020180"))
7222 self.assertSequenceEqual(Integer(-129).encode(), hexdec("0202ff7f"))
7224 class Seq(Sequence):
7226 ("erste", Integer()),
7227 ("zweite", Integer(optional=True))
7230 seq["erste"] = Integer(64)
7231 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7232 seq["erste"] = Integer(0x123456)
7233 self.assertSequenceEqual(seq.encode(), hexdec("30050203123456"))
7234 seq["erste"] = Integer(64)
7235 seq["zweite"] = Integer(65)
7236 self.assertSequenceEqual(seq.encode(), hexdec("3006020140020141"))
7238 class NestedSeq(Sequence):
7242 seq["erste"] = Integer(127)
7243 seq["zweite"] = None
7244 nested = NestedSeq()
7245 nested["nest"] = seq
7246 self.assertSequenceEqual(nested.encode(), hexdec("3005300302017f"))
7248 self.assertSequenceEqual(
7249 OctetString(b"\x01\x02\x03").encode(),
7250 hexdec("0403010203"),
7253 class Seq(Sequence):
7255 ("erste", Integer(impl=tag_encode(5, klass=TagClassContext))),
7258 seq["erste"] = Integer(64)
7259 self.assertSequenceEqual(seq.encode(), hexdec("3003850140"))
7261 class Seq(Sequence):
7263 ("erste", Integer(expl=tag_ctxc(5))),
7266 seq["erste"] = Integer(64)
7267 self.assertSequenceEqual(seq.encode(), hexdec("3005a503020140"))
7269 class Seq(Sequence):
7272 impl=tag_encode(0, klass=TagClassContext),
7277 seq["erste"] = Null()
7278 self.assertSequenceEqual(seq.encode(), hexdec("30028000"))
7280 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7282 self.assertSequenceEqual(
7283 UTCTime(datetime(1970, 1, 1, 0, 0)).encode(),
7284 hexdec("170d3730303130313030303030305a"),
7286 self.assertSequenceEqual(
7287 UTCTime(datetime(2009, 11, 15, 22, 56, 16)).encode(),
7288 hexdec("170d3039313131353232353631365a"),
7290 self.assertSequenceEqual(
7291 GeneralizedTime(datetime(2100, 4, 5, 12, 1, 1)).encode(),
7292 hexdec("180f32313030303430353132303130315a"),
7295 class Seq(Sequence):
7297 ("erste", GeneralizedTime()),
7300 seq["erste"] = GeneralizedTime(datetime(2009, 11, 15, 22, 56, 16))
7301 self.assertSequenceEqual(
7303 hexdec("3011180f32303039313131353232353631365a"),
7306 self.assertSequenceEqual(
7307 BitString((1, b"\x80")).encode(),
7310 self.assertSequenceEqual(
7311 BitString((12, b"\x81\xF0")).encode(),
7312 hexdec("03030481f0"),
7315 self.assertSequenceEqual(
7316 ObjectIdentifier("1.2.3.4").encode(),
7317 hexdec("06032a0304"),
7319 self.assertSequenceEqual(
7320 ObjectIdentifier("1.2.840.133549.1.1.5").encode(),
7321 hexdec("06092a864888932d010105"),
7323 self.assertSequenceEqual(
7324 ObjectIdentifier("2.100.3").encode(),
7325 hexdec("0603813403"),
7328 self.assertSequenceEqual(
7329 PrintableString("test").encode(),
7330 hexdec("130474657374"),
7332 self.assertSequenceEqual(
7333 PrintableString("x" * 127).encode(),
7334 hexdec("137F" + "78" * 127),
7336 self.assertSequenceEqual(
7337 PrintableString("x" * 128).encode(),
7338 hexdec("138180" + "78" * 128),
7340 self.assertSequenceEqual(UTF8String("Σ").encode(), hexdec("0c02cea3"))
7342 class Seq(Sequence):
7344 ("erste", IA5String()),
7347 seq["erste"] = IA5String("test")
7348 self.assertSequenceEqual(seq.encode(), hexdec("3006160474657374"))
7350 class Seq(Sequence):
7352 ("erste", PrintableString()),
7355 seq["erste"] = PrintableString("test")
7356 self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374"))
7357 # Asterisk is actually not allowable
7358 PrintableString._allowable_chars |= set(b"*")
7359 seq["erste"] = PrintableString("test*")
7360 self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a"))
7361 PrintableString._allowable_chars -= set(b"*")
7363 class Seq(Sequence):
7365 ("erste", Any(optional=True)),
7366 ("zweite", Integer()),
7369 seq["zweite"] = Integer(64)
7370 self.assertSequenceEqual(seq.encode(), hexdec("3003020140"))
7375 seq.append(Integer(10))
7376 self.assertSequenceEqual(seq.encode(), hexdec("310302010a"))
7378 class _SeqOf(SequenceOf):
7379 schema = PrintableString()
7381 class SeqOf(SequenceOf):
7384 _seqof.append(PrintableString("1"))
7386 seqof.append(_seqof)
7387 self.assertSequenceEqual(seqof.encode(), hexdec("30053003130131"))
7389 class Seq(Sequence):
7391 ("erste", Integer(default=1)),
7394 seq["erste"] = Integer(0)
7395 self.assertSequenceEqual(seq.encode(), hexdec("3003020100"))
7396 seq["erste"] = Integer(1)
7397 self.assertSequenceEqual(seq.encode(), hexdec("3000"))
7398 seq["erste"] = Integer(2)
7399 self.assertSequenceEqual(seq.encode(), hexdec("3003020102"))
7402 class TestPP(TestCase):
7403 @given(data_strategy())
7404 def test_oid_printing(self, d):
7406 str(ObjectIdentifier(k)): v * 2
7407 for k, v in d.draw(dictionaries(oid_strategy(), text_letters())).items()
7409 chosen = d.draw(sampled_from(sorted(oids)))
7410 chosen_id = oids[chosen]
7411 pp = _pp(asn1_type_name=ObjectIdentifier.asn1_type_name, value=chosen)
7412 self.assertNotIn(chosen_id, pp_console_row(pp))
7415 pp_console_row(pp, oid_maps=[{'whatever': 'whenever'}, oids]),
7419 class TestAutoAddSlots(TestCase):
7421 class Inher(Integer):
7424 with self.assertRaises(AttributeError):
7426 inher.unexistent = "whatever"
7429 class TestOIDDefines(TestCase):
7430 @given(data_strategy())
7431 def runTest(self, d):
7432 value_names = list(d.draw(sets(text_letters(), min_size=1, max_size=10)))
7433 value_name_chosen = d.draw(sampled_from(value_names))
7435 ObjectIdentifier(oid)
7436 for oid in d.draw(sets(oid_strategy(), min_size=2, max_size=10))
7438 oid_chosen = d.draw(sampled_from(oids))
7439 values = d.draw(lists(
7441 min_size=len(value_names),
7442 max_size=len(value_names),
7444 for definable_class in (Any, OctetString, BitString):
7446 ("type", ObjectIdentifier(defines=(((value_name_chosen,), {
7447 oid: Integer() for oid in oids[:-1]
7450 for i, value_name in enumerate(value_names):
7451 _schema.append((value_name, definable_class(expl=tag_ctxp(i))))
7453 class Seq(Sequence):
7456 for value_name, value in zip(value_names, values):
7457 seq[value_name] = definable_class(Integer(value).encode())
7458 seq["type"] = oid_chosen
7459 seq, _ = Seq().decode(seq.encode())
7460 for value_name in value_names:
7461 if value_name == value_name_chosen:
7463 self.assertIsNone(seq[value_name].defined)
7464 if value_name_chosen in oids[:-1]:
7465 self.assertIsNotNone(seq[value_name_chosen].defined)
7466 self.assertEqual(seq[value_name_chosen].defined[0], oid_chosen)
7467 self.assertIsInstance(seq[value_name_chosen].defined[1], Integer)
7470 pprint(seq, big_blobs=True, with_decode_path=True)
7473 class TestDefinesByPath(TestCase):
7474 def test_generated(self):
7475 class Seq(Sequence):
7477 ("type", ObjectIdentifier()),
7478 ("value", OctetString(expl=tag_ctxc(123))),
7481 class SeqInner(Sequence):
7483 ("typeInner", ObjectIdentifier()),
7484 ("valueInner", Any()),
7487 class PairValue(SetOf):
7490 class Pair(Sequence):
7492 ("type", ObjectIdentifier()),
7493 ("value", PairValue()),
7496 class Pairs(SequenceOf):
7503 type_octet_stringed,
7505 ObjectIdentifier(oid)
7506 for oid in sets(oid_strategy(), min_size=4, max_size=4).example()
7508 seq_integered = Seq()
7509 seq_integered["type"] = type_integered
7510 seq_integered["value"] = OctetString(Integer(123).encode())
7511 seq_integered_raw = seq_integered.encode()
7515 (type_octet_stringed, OctetString(b"whatever")),
7516 (type_integered, Integer(123)),
7517 (type_octet_stringed, OctetString(b"whenever")),
7518 (type_integered, Integer(234)),
7520 for t, v in pairs_input:
7523 ("value", PairValue((Any(v),))),
7525 seq_inner = SeqInner()
7526 seq_inner["typeInner"] = type_innered
7527 seq_inner["valueInner"] = Any(pairs)
7528 seq_sequenced = Seq()
7529 seq_sequenced["type"] = type_sequenced
7530 seq_sequenced["value"] = OctetString(seq_inner.encode())
7531 seq_sequenced_raw = seq_sequenced.encode()
7533 list(seq_sequenced.pps())
7534 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7536 defines_by_path = []
7537 ctx_copied = deepcopy(ctx_dummy)
7538 seq_integered, _ = Seq().decode(
7542 self.assertDictEqual(ctx_copied, ctx_dummy)
7543 self.assertIsNone(seq_integered["value"].defined)
7544 defines_by_path.append(
7545 (("type",), ((("value",), {
7546 type_integered: Integer(),
7547 type_sequenced: SeqInner(),
7550 ctx_copied["defines_by_path"] = defines_by_path
7551 seq_integered, _ = Seq().decode(
7555 del ctx_copied["defines_by_path"]
7556 self.assertDictEqual(ctx_copied, ctx_dummy)
7557 self.assertIsNotNone(seq_integered["value"].defined)
7558 self.assertEqual(seq_integered["value"].defined[0], type_integered)
7559 self.assertEqual(seq_integered["value"].defined[1], Integer(123))
7560 self.assertTrue(seq_integered_raw[
7561 seq_integered["value"].defined[1].offset:
7562 ].startswith(Integer(123).encode()))
7564 list(seq_integered.pps())
7565 pprint(seq_integered, big_blobs=True, with_decode_path=True)
7567 ctx_copied["defines_by_path"] = defines_by_path
7568 seq_sequenced, _ = Seq().decode(
7572 del ctx_copied["defines_by_path"]
7573 self.assertDictEqual(ctx_copied, ctx_dummy)
7574 self.assertIsNotNone(seq_sequenced["value"].defined)
7575 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7576 seq_inner = seq_sequenced["value"].defined[1]
7577 self.assertIsNone(seq_inner["valueInner"].defined)
7579 list(seq_sequenced.pps())
7580 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7582 defines_by_path.append((
7583 ("value", DecodePathDefBy(type_sequenced), "typeInner"),
7584 ((("valueInner",), {type_innered: Pairs()}),),
7586 ctx_copied["defines_by_path"] = defines_by_path
7587 seq_sequenced, _ = Seq().decode(
7591 del ctx_copied["defines_by_path"]
7592 self.assertDictEqual(ctx_copied, ctx_dummy)
7593 self.assertIsNotNone(seq_sequenced["value"].defined)
7594 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7595 seq_inner = seq_sequenced["value"].defined[1]
7596 self.assertIsNotNone(seq_inner["valueInner"].defined)
7597 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7598 pairs = seq_inner["valueInner"].defined[1]
7600 self.assertIsNone(pair["value"][0].defined)
7602 list(seq_sequenced.pps())
7603 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7605 defines_by_path.append((
7608 DecodePathDefBy(type_sequenced),
7610 DecodePathDefBy(type_innered),
7615 type_integered: Integer(),
7616 type_octet_stringed: OctetString(),
7619 ctx_copied["defines_by_path"] = defines_by_path
7620 seq_sequenced, _ = Seq().decode(
7624 del ctx_copied["defines_by_path"]
7625 self.assertDictEqual(ctx_copied, ctx_dummy)
7626 self.assertIsNotNone(seq_sequenced["value"].defined)
7627 self.assertEqual(seq_sequenced["value"].defined[0], type_sequenced)
7628 seq_inner = seq_sequenced["value"].defined[1]
7629 self.assertIsNotNone(seq_inner["valueInner"].defined)
7630 self.assertEqual(seq_inner["valueInner"].defined[0], type_innered)
7631 pairs_got = seq_inner["valueInner"].defined[1]
7632 for pair_input, pair_got in zip(pairs_input, pairs_got):
7633 self.assertEqual(pair_got["value"][0].defined[0], pair_input[0])
7634 self.assertEqual(pair_got["value"][0].defined[1], pair_input[1])
7636 list(seq_sequenced.pps())
7637 pprint(seq_sequenced, big_blobs=True, with_decode_path=True)
7639 @given(oid_strategy(), integers())
7640 def test_simple(self, oid, tgt):
7641 class Inner(Sequence):
7643 ("oid", ObjectIdentifier(defines=((("..", "tgt"), {
7644 ObjectIdentifier(oid): Integer(),
7648 class Outer(Sequence):
7651 ("tgt", OctetString()),
7655 inner["oid"] = ObjectIdentifier(oid)
7657 outer["inner"] = inner
7658 outer["tgt"] = OctetString(Integer(tgt).encode())
7659 decoded, _ = Outer().decode(outer.encode())
7660 self.assertEqual(decoded["tgt"].defined[1], Integer(tgt))
7662 def test_remaining_data(self):
7663 oid = ObjectIdentifier("1.2.3")
7665 class Seq(Sequence):
7667 ("oid", ObjectIdentifier(defines=((("tgt",), {
7670 ("tgt", OctetString()),
7675 ("tgt", OctetString(Integer(123).encode() + b"junk")),
7677 with assertRaisesRegex(self, DecodeError, "remaining data"):
7678 Seq().decode(seq.encode())
7680 def test_remaining_data_seqof(self):
7681 oid = ObjectIdentifier("1.2.3")
7684 schema = OctetString()
7686 class Seq(Sequence):
7688 ("oid", ObjectIdentifier(defines=((("tgt",), {
7696 ("tgt", SeqOf([OctetString(Integer(123).encode() + b"junk")])),
7698 with assertRaisesRegex(self, DecodeError, "remaining data"):
7699 Seq().decode(seq.encode())
7702 class TestAbsDecodePath(TestCase):
7704 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7705 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7707 def test_concat(self, decode_path, rel_path):
7708 dp = abs_decode_path(decode_path, rel_path)
7709 self.assertSequenceEqual(dp, decode_path + rel_path)
7713 lists(text(alphabet=ascii_letters, min_size=1)).map(tuple),
7714 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7716 def test_abs(self, decode_path, rel_path):
7717 self.assertSequenceEqual(
7718 abs_decode_path(decode_path, ("/",) + rel_path),
7723 lists(text(alphabet=ascii_letters, min_size=1), min_size=5).map(tuple),
7724 integers(min_value=1, max_value=3),
7725 lists(text(alphabet=ascii_letters, min_size=1), min_size=1).map(tuple),
7727 def test_dots(self, decode_path, number_of_dots, rel_path):
7728 self.assertSequenceEqual(
7729 abs_decode_path(decode_path, tuple([".."] * number_of_dots) + rel_path),
7730 decode_path[:-number_of_dots] + rel_path,
7734 class TestStrictDefaultExistence(TestCase):
7735 @given(data_strategy())
7736 def runTest(self, d):
7737 count = d.draw(integers(min_value=1, max_value=10))
7738 chosen = d.draw(integers(min_value=0, max_value=count - 1))
7740 ("int%d" % i, Integer(expl=tag_ctxc(i + 1)))
7741 for i in range(count)
7743 for klass in (Sequence, Set):
7747 for i in range(count):
7748 seq["int%d" % i] = Integer(123)
7750 chosen_choice = "int%d" % chosen
7751 seq.specs[chosen_choice] = seq.specs[chosen_choice](default=123)
7752 with assertRaisesRegex(self, DecodeError, "DEFAULT value met"):
7754 decoded, _ = seq.decode(raw, ctx={"allow_default_values": True})
7755 self.assertTrue(decoded.ber_encoded)
7756 self.assertTrue(decoded.bered)
7757 decoded = copy(decoded)
7758 self.assertTrue(decoded.ber_encoded)
7759 self.assertTrue(decoded.bered)
7760 decoded, _ = seq.decode(raw, ctx={"bered": True})
7761 self.assertTrue(decoded.ber_encoded)
7762 self.assertTrue(decoded.bered)
7763 decoded = copy(decoded)
7764 self.assertTrue(decoded.ber_encoded)
7765 self.assertTrue(decoded.bered)
7768 class TestX690PrefixedType(TestCase):
7770 self.assertSequenceEqual(
7771 VisibleString("Jones").encode(),
7772 hexdec("1A054A6F6E6573"),
7776 self.assertSequenceEqual(
7779 impl=tag_encode(3, klass=TagClassApplication),
7781 hexdec("43054A6F6E6573"),
7785 self.assertSequenceEqual(
7789 impl=tag_encode(3, klass=TagClassApplication),
7793 hexdec("A20743054A6F6E6573"),
7797 self.assertSequenceEqual(
7801 impl=tag_encode(3, klass=TagClassApplication),
7803 impl=tag_encode(7, form=TagFormConstructed, klass=TagClassApplication),
7805 hexdec("670743054A6F6E6573"),
7809 self.assertSequenceEqual(
7810 VisibleString("Jones", impl=tag_ctxp(2)).encode(),
7811 hexdec("82054A6F6E6573"),
7815 class TestExplOOB(TestCase):
7817 expl = tag_ctxc(123)
7818 raw = Integer(123).encode() + Integer(234).encode()
7819 raw = b"".join((expl, len_encode(len(raw)), raw))
7820 with assertRaisesRegex(self, DecodeError, "explicit tag out-of-bound"):
7821 Integer(expl=expl).decode(raw)
7822 Integer(expl=expl).decode(raw, ctx={"allow_expl_oob": True})
7825 class TestPickleDifferentVersion(TestCase):
7827 pickled = pickle_dumps(Integer(123), pickle_proto)
7829 version_orig = pyderasn.__version__
7830 pyderasn.__version__ += "different"
7831 with assertRaisesRegex(self, ValueError, "different PyDERASN version"):
7832 pickle_loads(pickled)
7833 pyderasn.__version__ = version_orig
7834 pickle_loads(pickled)
7837 class TestCERSetOrdering(TestCase):
7838 def test_vectors(self):
7839 """Taken from X.690-201508
7843 ("c", Integer(impl=tag_ctxp(2))),
7844 ("d", Integer(impl=tag_ctxp(4))),
7849 ("g", Integer(impl=tag_ctxp(5))),
7850 ("h", Integer(impl=tag_ctxp(6))),
7855 ("j", Integer(impl=tag_ctxp(0))),
7866 ("a", Integer(impl=tag_ctxp(3))),
7867 ("b", B(expl=tag_ctxc(1))),
7872 ("a", Integer(123)),
7873 ("b", B(("d", Integer(234)))),
7874 ("e", E(("f", F(("g", Integer(345)))))),
7876 order = sorted(a._values_for_encoding(), key=attrgetter("tag_order_cer"))
7877 self.assertSequenceEqual(
7878 [i.__class__.__name__ for i in order],
7879 ("E", "B", "Integer"),